Drizzled Public API Documentation

myisam_priv.h
00001 /* Copyright (C) 2000-2006 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /* This file is included by all internal myisam files */
00017 
00018 #pragma once
00019 
00020 #include <config.h>
00021 
00022 #include "myisam.h"     /* Structs & some defines */
00023 #include "myisampack.h"     /* packing of keys */
00024 #include <drizzled/tree.h>
00025 #include <drizzled/internal/my_pthread.h>
00026 #include <drizzled/thr_lock.h>
00027 #include <drizzled/common.h>
00028 #include <drizzled/enum.h>
00029 #include <drizzled/dynamic_array.h>
00030 
00031 #include <assert.h>
00032 #include <fcntl.h>
00033 #include <string.h>
00034 #include <list>
00035 
00036 #include <boost/thread/mutex.hpp>
00037 
00038 #if defined(my_write)
00039 #undef my_write       /* undef map from my_nosys; We need test-if-disk full */
00040 #endif
00041 
00042 /* Typical key cash */
00043 static const uint32_t KEY_CACHE_SIZE= 8*1024*1024;
00044 
00045 /* Default size of a key cache block  */
00046 static const uint32_t KEY_CACHE_BLOCK_SIZE= 1024;
00047 
00048 typedef struct st_mi_status_info
00049 {
00050   drizzled::ha_rows records;      /* Rows in table */
00051   drizzled::ha_rows del;        /* Removed rows */
00052   drizzled::internal::my_off_t empty;     /* lost space in datafile */
00053   drizzled::internal::my_off_t key_empty;     /* lost space in indexfile */
00054   drizzled::internal::my_off_t key_file_length;
00055   drizzled::internal::my_off_t data_file_length;
00056   drizzled::internal::ha_checksum checksum;
00057 } MI_STATUS_INFO;
00058 
00059 typedef struct st_mi_state_info
00060 {
00061   struct {        /* Fileheader */
00062     unsigned char file_version[4];
00063     unsigned char options[2];
00064     unsigned char header_length[2];
00065     unsigned char state_info_length[2];
00066     unsigned char base_info_length[2];
00067     unsigned char base_pos[2];
00068     unsigned char key_parts[2];     /* Key parts */
00069     unsigned char unique_key_parts[2];    /* Key parts + unique parts */
00070     unsigned char keys;       /* number of keys in file */
00071     unsigned char uniques;      /* number of UNIQUE definitions */
00072     unsigned char language;     /* Language for indexes */
00073     unsigned char max_block_size_index;   /* max keyblock size */
00074     unsigned char fulltext_keys;
00075     unsigned char not_used;                     /* To align to 8 */
00076   } header;
00077 
00078   MI_STATUS_INFO state;
00079   drizzled::ha_rows split;      /* number of split blocks */
00080   drizzled::internal::my_off_t dellink;     /* Link to next removed block */
00081   uint64_t auto_increment;
00082   ulong process;      /* process that updated table last */
00083   ulong unique;       /* Unique number for this process */
00084   ulong update_count;     /* Updated for each write lock */
00085   ulong status;
00086   ulong *rec_per_key_part;
00087   drizzled::internal::my_off_t *key_root;     /* Start of key trees */
00088   drizzled::internal::my_off_t *key_del;      /* delete links for trees */
00089   drizzled::internal::my_off_t rec_per_key_rows;    /* Rows when calculating rec_per_key */
00090 
00091   ulong sec_index_changed;    /* Updated when new sec_index */
00092   ulong sec_index_used;     /* which extra index are in use */
00093   uint64_t key_map;     /* Which keys are in use */
00094   drizzled::internal::ha_checksum checksum;                 /* Table checksum */
00095   ulong version;      /* timestamp of create */
00096   time_t create_time;     /* Time when created database */
00097   time_t recover_time;      /* Time for last recover */
00098   time_t check_time;      /* Time for last check */
00099   uint  sortkey;      /* sorted by this key  (not used) */
00100   uint32_t open_count;
00101   uint8_t changed;      /* Changed since myisamchk */
00102 
00103   /* the following isn't saved on disk */
00104   uint32_t state_diff_length;   /* Should be 0 */
00105   uint  state_length;     /* Length of state header in file */
00106   ulong *key_info;
00107 } MI_STATE_INFO;
00108 
00109 #define MI_STATE_INFO_SIZE  (24+14*8+7*4+2*2+8)
00110 #define MI_STATE_KEY_SIZE 8
00111 #define MI_STATE_KEYBLOCK_SIZE  8
00112 #define MI_STATE_KEYSEG_SIZE  4
00113 #define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*MI_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE)
00114 #define MI_KEYDEF_SIZE    (2+ 5*2)
00115 #define MI_UNIQUEDEF_SIZE (2+1+1)
00116 #define HA_KEYSEG_SIZE    (6+ 2*2 + 4*2)
00117 #define MI_COLUMNDEF_SIZE (2*3+1)
00118 #define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16)
00119 #define MI_INDEX_BLOCK_MARGIN 16  /* Safety margin for .MYI tables */
00120 
00121 typedef struct st_mi_base_info
00122 {
00123   drizzled::internal::my_off_t keystart;      /* Start of keys */
00124   drizzled::internal::my_off_t max_data_file_length;
00125   drizzled::internal::my_off_t max_key_file_length;
00126   drizzled::internal::my_off_t margin_key_file_length;
00127   drizzled::ha_rows records,reloc;    /* Create information */
00128   ulong mean_row_length;    /* Create information */
00129   ulong reclength;      /* length of unpacked record */
00130   ulong pack_reclength;     /* Length of full packed rec. */
00131   ulong min_pack_length;
00132   ulong max_pack_length;    /* Max possibly length of packed rec.*/
00133   ulong min_block_length;
00134   ulong fields,       /* fields in table */
00135        pack_fields;     /* packed fields in table */
00136   uint32_t rec_reflength;     /* = 2-8 */
00137   uint32_t key_reflength;     /* = 2-8 */
00138   uint32_t keys;        /* same as in state.header */
00139   uint32_t auto_key;      /* Which key-1 is a auto key */
00140   uint32_t blobs;       /* Number of blobs */
00141   uint32_t pack_bits;     /* Length of packed bits */
00142   uint32_t max_key_block_length;    /* Max block length */
00143   uint32_t max_key_length;      /* Max key length */
00144   /* Extra allocation when using dynamic record format */
00145   uint32_t extra_alloc_bytes;
00146   uint32_t extra_alloc_procent;
00147   /* Info about raid */
00148   uint32_t raid_type,raid_chunks;
00149   uint32_t raid_chunksize;
00150   /* The following are from the header */
00151   uint32_t key_parts,all_key_parts;
00152 } MI_BASE_INFO;
00153 
00154 
00155   /* Structs used intern in database */
00156 
00157 typedef struct st_mi_blob   /* Info of record */
00158 {
00159   ulong offset;       /* Offset to blob in record */
00160   uint32_t pack_length;     /* Type of packed length */
00161   ulong length;       /* Calc:ed for each record */
00162 } MI_BLOB;
00163 
00164 
00165 typedef struct st_mi_isam_pack {
00166   ulong header_length;
00167   uint32_t ref_length;
00168   unsigned char version;
00169 } MI_PACK;
00170 
00171 #define MAX_NONMAPPED_INSERTS 1000
00172 
00173 namespace drizzled { class Session; }
00174 
00175 typedef struct st_mi_isam_share { /* Shared between opens */
00176   MI_STATE_INFO state;
00177   MI_BASE_INFO base;
00178   MI_KEYDEF  ft2_keyinfo;   /* Second-level ft-key definition */
00179   MI_KEYDEF  *keyinfo;      /* Key definitions */
00180   MI_UNIQUEDEF *uniqueinfo;   /* unique definitions */
00181   HA_KEYSEG *keyparts;      /* key part info */
00182   drizzled::MI_COLUMNDEF *rec;      /* Pointer to field information */
00183   MI_PACK    pack;      /* Data about packed records */
00184   MI_BLOB    *blobs;      /* Pointer to blobs */
00185   std::list<drizzled::Session *> *in_use;         /* List of threads using this table */
00186   char  *unique_file_name;    /* realpath() of index file */
00187   char  *data_file_name,    /* Resolved path names from symlinks */
00188         *index_file_name;
00189   unsigned char *file_map;      /* mem-map of file if possible */
00190 private:
00191   drizzled::KEY_CACHE key_cache;      /* ref to the current key cache */
00192 public:
00193   drizzled::KEY_CACHE *getKeyCache()
00194   {
00195     return &key_cache;
00196   }
00197 
00198   void setKeyCache();
00199 
00200   MI_DECODE_TREE *decode_trees;
00201   uint16_t *decode_tables;
00202   int (*read_record)(struct st_myisam_info*, drizzled::internal::my_off_t, unsigned char*);
00203   int (*write_record)(struct st_myisam_info*, const unsigned char*);
00204   int (*update_record)(struct st_myisam_info*, drizzled::internal::my_off_t, const unsigned char*);
00205   int (*delete_record)(struct st_myisam_info*);
00206   int (*read_rnd)(struct st_myisam_info*, unsigned char*, drizzled::internal::my_off_t, bool);
00207   int (*compare_record)(struct st_myisam_info*, const unsigned char *);
00208   /* Function to use for a row checksum. */
00209   drizzled::internal::ha_checksum (*calc_checksum)(struct st_myisam_info*, const unsigned char *);
00210   int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
00211       const unsigned char *record, drizzled::internal::my_off_t pos);
00212   size_t (*file_read)(MI_INFO *, unsigned char *, size_t, drizzled::internal::my_off_t, drizzled::myf);
00213   size_t (*file_write)(MI_INFO *, const unsigned char *, size_t, drizzled::internal::my_off_t, drizzled::myf);
00214   ulong this_process;     /* processid */
00215   ulong last_process;     /* For table-change-check */
00216   ulong last_version;     /* Version on start */
00217   uint64_t options;     /* Options used */
00218   ulong min_pack_length;    /* Theese are used by packed data */
00219   ulong max_pack_length;
00220   ulong state_diff_length;
00221   uint  rec_reflength;      /* rec_reflength in use now */
00222   uint32_t  unique_name_length;
00223   int kfile;        /* Shared keyfile */
00224   int data_file;      /* Shared data file */
00225   int mode;       /* mode of file on open */
00226   uint  reopen;       /* How many times reopened */
00227   uint  w_locks,r_locks,tot_locks;  /* Number of read/write locks */
00228   uint  blocksize;      /* blocksize of keyfile */
00229   drizzled::myf write_flag;
00230   enum drizzled::data_file_type data_file_type;
00231   /* Below flag is needed to make log tables work with concurrent insert */
00232   bool is_log_table;
00233 
00234   bool  changed,      /* If changed since lock */
00235     global_changed,     /* If changed since open */
00236     not_flushed,
00237     temporary,delay_key_write,
00238     concurrent_insert;
00239   drizzled::internal::my_off_t mmaped_length;
00240   uint32_t     nonmmaped_inserts;           /* counter of writing in non-mmaped
00241                                            area */
00242 } MYISAM_SHARE;
00243 
00244 
00245 typedef uint32_t mi_bit_type;
00246 
00247 typedef struct st_mi_bit_buff {   /* Used for packing of record */
00248   mi_bit_type current_byte;
00249   uint32_t bits;
00250   unsigned char *pos,*end,*blob_pos,*blob_end;
00251   uint32_t error;
00252 } MI_BIT_BUFF;
00253 
00254 
00255 typedef bool (*index_cond_func_t)(void *param);
00256 
00257 struct st_myisam_info {
00258   MYISAM_SHARE *s;      /* Shared between open:s */
00259   MI_STATUS_INFO *state,save_state;
00260   MI_BLOB     *blobs;     /* Pointer to blobs */
00261   MI_BIT_BUFF  bit_buff;
00262   /* accumulate indexfile changes between write's */
00263   drizzled::TREE          *bulk_insert;
00264   drizzled::Session *in_use;                      /* Thread using this table          */
00265   char *filename;     /* parameter to open filename       */
00266   unsigned char *buff,        /* Temp area for key                */
00267   *lastkey,*lastkey2;   /* Last used search key             */
00268   unsigned char *first_mbr_key;     /* Searhed spatial key              */
00269   unsigned char *rec_buff;      /* Tempbuff for recordpack          */
00270   unsigned char *int_keypos,      /* Save position for next/previous  */
00271         *int_maxpos;      /*  -""-  */
00272   uint32_t  int_nod_flag;     /*  -""-  */
00273   uint32_t int_keytree_version;   /*  -""-  */
00274   int (*read_record)(struct st_myisam_info*, drizzled::internal::my_off_t, unsigned char*);
00275   ulong this_unique;      /* uniq filenumber or thread */
00276   ulong last_unique;      /* last unique number */
00277   ulong this_loop;      /* counter for this open */
00278   ulong last_loop;      /* last used counter */
00279   drizzled::internal::my_off_t lastpos,     /* Last record position */
00280   nextpos;      /* Position to next record */
00281   drizzled::internal::my_off_t save_lastpos;
00282   drizzled::internal::my_off_t pos;       /* Intern variable */
00283   drizzled::internal::my_off_t last_keypage;    /* Last key page read */
00284   drizzled::internal::my_off_t last_search_keypage;   /* Last keypage when searching */
00285   drizzled::internal::my_off_t dupp_key_pos;
00286   drizzled::internal::ha_checksum checksum;                 /* Temp storage for row checksum */
00287   /* QQ: the folloing two xxx_length fields should be removed,
00288      as they are not compatible with parallel repair */
00289   ulong packed_length,blob_length;  /* Length of found, packed record */
00290   int  dfile;       /* The datafile */
00291   uint32_t opt_flag;      /* Optim. for space/speed */
00292   uint32_t update;        /* If file changed since open */
00293   int lastinx;      /* Last used index */
00294   uint  lastkey_length;     /* Length of key in lastkey */
00295   uint  last_rkey_length;   /* Last length in mi_rkey() */
00296   enum drizzled::ha_rkey_function last_key_func;  /* CONTAIN, OVERLAP, etc */
00297   uint32_t  save_lastkey_length;
00298   uint32_t  pack_key_length;                /* For MYISAMMRG */
00299   uint16_t last_used_keyseg;              /* For MyISAMMRG */
00300   int errkey;       /* Got last error on this key */
00301   int   lock_type;      /* How database was locked */
00302   int   tmp_lock_type;      /* When locked by readinfo */
00303   uint  data_changed;     /* Somebody has changed data */
00304   uint  save_update;      /* When using KEY_READ */
00305   int save_lastinx;
00306   drizzled::internal::IO_CACHE rec_cache;     /* When cacheing records */
00307   uint32_t  preload_buff_size;              /* When preloading indexes */
00308   drizzled::myf lock_wait;      /* is 0 or MY_DONT_WAIT */
00309   bool was_locked;      /* Was locked in panic */
00310   bool append_insert_at_end;    /* Set if concurrent insert */
00311   bool quick_mode;
00312   bool page_changed;    /* If info->buff can't be used for rnext */
00313   bool buff_used;   /* If info->buff has to be reread for rnext */
00314   bool once_flags;           /* For MYISAMMRG */
00315 
00316   index_cond_func_t index_cond_func;   /* Index condition function */
00317   void *index_cond_func_arg;           /* parameter for the func */
00318   drizzled::THR_LOCK_DATA lock;
00319   unsigned char  *rtree_recursion_state;  /* For RTREE */
00320   int     rtree_recursion_depth;
00321 };
00322 
00323 typedef struct st_buffpek {
00324   off_t file_pos;                    /* Where we are in the sort file */
00325   unsigned char *base,*key;                     /* Key pointers */
00326   drizzled::ha_rows count;                        /* Number of rows in table */
00327   ulong mem_count;                      /* numbers of keys in memory */
00328   ulong max_keys;                       /* Max keys in buffert */
00329 } BUFFPEK;
00330 
00331 typedef struct st_mi_sort_param
00332 {
00333   pthread_t  thr;
00334   drizzled::internal::IO_CACHE read_cache, tempfile, tempfile_for_exceptions;
00335   drizzled::DYNAMIC_ARRAY buffpek;
00336   MI_BIT_BUFF   bit_buff;               /* For parallel repair of packrec. */
00337 
00338   /*
00339     The next two are used to collect statistics, see update_key_parts for
00340     description.
00341   */
00342   uint64_t unique[MI_MAX_KEY_SEG+1];
00343   uint64_t notnull[MI_MAX_KEY_SEG+1];
00344 
00345   drizzled::internal::my_off_t pos,max_pos,filepos,start_recpos;
00346   uint32_t key, key_length,real_key_length,sortbuff_size;
00347   uint32_t maxbuffers, keys, find_length, sort_keys_length;
00348   bool fix_datafile, master;
00349   bool calc_checksum;                /* calculate table checksum */
00350   MI_KEYDEF *keyinfo;
00351   HA_KEYSEG *seg;
00352   SORT_INFO *sort_info;
00353   unsigned char **sort_keys;
00354   unsigned char *rec_buff;
00355   void *wordlist, *wordptr;
00356   drizzled::memory::Root wordroot;
00357   unsigned char *record;
00358   int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *);
00359   int (*key_read)(struct st_mi_sort_param *,void *);
00360   int (*key_write)(struct st_mi_sort_param *, const void *);
00361   void (*lock_in_memory)(MI_CHECK *);
00362   int (*write_keys)(struct st_mi_sort_param *, register unsigned char **,
00363                      uint32_t , struct st_buffpek *, drizzled::internal::IO_CACHE *);
00364   unsigned int (*read_to_buffer)(drizzled::internal::IO_CACHE *,struct st_buffpek *, uint);
00365   int (*write_key)(struct st_mi_sort_param *, drizzled::internal::IO_CACHE *,unsigned char *,
00366                        uint, uint);
00367 } MI_SORT_PARAM;
00368 
00369   /* Some defines used by isam-funktions */
00370 
00371 #define USE_WHOLE_KEY MI_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */
00372 #define F_EXTRA_LCK -1
00373 
00374   /* bits in opt_flag */
00375 #define MEMMAP_USED 32
00376 #define REMEMBER_OLD_POS 64
00377 
00378 #define WRITEINFO_UPDATE_KEYFILE  1
00379 #define WRITEINFO_NO_UNLOCK   2
00380 
00381         /* once_flags */
00382 #define USE_PACKED_KEYS         1
00383 #define RRND_PRESERVE_LASTINX   2
00384 
00385   /* bits in state.changed */
00386 
00387 #define STATE_CHANGED   1
00388 #define STATE_CRASHED   2
00389 #define STATE_CRASHED_ON_REPAIR 4
00390 #define STATE_NOT_ANALYZED  8
00391 #define STATE_NOT_OPTIMIZED_KEYS 16
00392 #define STATE_NOT_SORTED_PAGES  32
00393 
00394   /* options to mi_read_cache */
00395 
00396 #define READING_NEXT  1
00397 #define READING_HEADER  2
00398 
00399 
00400 #define mi_getint(x)  ((uint) mi_uint2korr(x) & 32767)
00401 #define mi_putint(x,y,nod) { uint16_t boh=(nod ? (uint16_t) 32768 : 0) + (uint16_t) (y);\
00402         mi_int2store(x,boh); }
00403 #define mi_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
00404 #define mi_report_crashed(A, B) _mi_report_crashed((A), (B), __FILE__, __LINE__)
00405 #define mi_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \
00406                               mi_report_crashed((x), 0); \
00407                            }while(0)
00408 #define mi_mark_crashed_on_repair(x) do{(x)->s->state.changed|= \
00409                                         STATE_CRASHED|STATE_CRASHED_ON_REPAIR; \
00410                                         (x)->update|= HA_STATE_CHANGED; \
00411                                      }while(0)
00412 #define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED)
00413 #define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR)
00414 #define mi_print_error(SHARE, ERRNO)                     \
00415         mi_report_error((ERRNO), (SHARE)->index_file_name)
00416 
00417 /* Functions to store length of space packed keys, VARCHAR or BLOB keys */
00418 
00419 #define store_key_length(key,length) \
00420 { if ((length) < 255) \
00421   { *(key)=(length); } \
00422   else \
00423   { *(key)=255; mi_int2store((key)+1,(length)); } \
00424 }
00425 
00426 #define get_key_full_length(length,key) \
00427 { if ((unsigned char) *(key) != 255) \
00428     length= ((uint) (unsigned char) *((key)++))+1; \
00429   else \
00430   { length=mi_uint2korr((key)+1)+3; (key)+=3; } \
00431 }
00432 
00433 #define get_key_full_length_rdonly(length,key) \
00434 { if ((unsigned char) *(key) != 255) \
00435     length= ((uint) (unsigned char) *((key)))+1; \
00436   else \
00437   { length=mi_uint2korr((key)+1)+3; } \
00438 }
00439 
00440 #define get_pack_length(length) ((length) >= 255 ? 3 : 1)
00441 
00442 #define MI_MIN_BLOCK_LENGTH 20  /* Because of delete-link */
00443 #define MI_EXTEND_BLOCK_LENGTH  20  /* Don't use to small record-blocks */
00444 #define MI_SPLIT_LENGTH ((MI_EXTEND_BLOCK_LENGTH+4)*2)
00445 #define MI_MAX_DYN_BLOCK_HEADER 20  /* Max prefix of record-block */
00446 #define MI_BLOCK_INFO_HEADER_LENGTH 20
00447 #define MI_DYN_DELETE_BLOCK_HEADER 20 /* length of delete-block-header */
00448 #define MI_DYN_MAX_BLOCK_LENGTH ((1L << 24)-4L)
00449 #define MI_DYN_MAX_ROW_LENGTH (MI_DYN_MAX_BLOCK_LENGTH - MI_SPLIT_LENGTH)
00450 #define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
00451 #define MI_MAX_DYN_HEADER_BYTE  13  /* max header byte for dynamic rows */
00452 #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1)))
00453 #define MI_REC_BUFF_OFFSET      ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32_t))
00454 
00455 #define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
00456 
00457 #define PACK_TYPE_SELECTED  1 /* Bits in field->pack_type */
00458 #define PACK_TYPE_SPACE_FIELDS  2
00459 #define PACK_TYPE_ZERO_FILL 4
00460 #define MI_FOUND_WRONG_KEY 32738  /* Impossible value from ha_key_cmp */
00461 
00462 #define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
00463 #define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size))
00464 #define MI_MAX_KEYPTR_SIZE  5        /* For calculating block lengths */
00465 #define MI_MIN_KEYBLOCK_LENGTH  50         /* When to split delete blocks */
00466 
00467 #define MI_MIN_SIZE_BULK_INSERT_TREE 16384             /* this is per key */
00468 #define MI_MIN_ROWS_TO_USE_BULK_INSERT 100
00469 #define MI_MIN_ROWS_TO_DISABLE_INDEXES 100
00470 #define MI_MIN_ROWS_TO_USE_WRITE_CACHE 10
00471 
00472 /* The UNIQUE check is done with a hashed long key */
00473 
00474 #define MI_UNIQUE_HASH_TYPE HA_KEYTYPE_ULONG_INT
00475 #define mi_unique_store(A,B)    mi_int4store((A),(B))
00476 
00477 extern boost::mutex THR_LOCK_myisam;
00478 
00479   /* Some extern variables */
00480 
00481 extern std::list<MI_INFO *> myisam_open_list;
00482 extern unsigned char  myisam_file_magic[], myisam_pack_file_magic[];
00483 extern uint32_t  myisam_read_vec[], myisam_readnext_vec[];
00484 extern uint32_t myisam_quick_table_bits;
00485 extern ulong myisam_pid;
00486 
00487   /* This is used by _mi_calc_xxx_key_length och _mi_store_key */
00488 
00489 typedef struct st_mi_s_param
00490 {
00491   uint  ref_length,key_length,
00492   n_ref_length,
00493   n_length,
00494   totlength,
00495   part_of_prev_key,prev_length,pack_marker;
00496   unsigned char *key, *prev_key,*next_key_pos;
00497   bool store_not_null;
00498 } MI_KEY_PARAM;
00499 
00500   /* Prototypes for intern functions */
00501 
00502 extern int _mi_read_dynamic_record(MI_INFO *info,drizzled::internal::my_off_t filepos,unsigned char *buf);
00503 extern int _mi_write_dynamic_record(MI_INFO*, const unsigned char*);
00504 extern int _mi_update_dynamic_record(MI_INFO*, drizzled::internal::my_off_t, const unsigned char*);
00505 extern int _mi_delete_dynamic_record(MI_INFO *info);
00506 extern int _mi_cmp_dynamic_record(MI_INFO *info,const unsigned char *record);
00507 extern int _mi_read_rnd_dynamic_record(MI_INFO *, unsigned char *,drizzled::internal::my_off_t, bool);
00508 extern int _mi_write_blob_record(MI_INFO*, const unsigned char*);
00509 extern int _mi_update_blob_record(MI_INFO*, drizzled::internal::my_off_t, const unsigned char*);
00510 extern int _mi_read_static_record(MI_INFO *info, drizzled::internal::my_off_t filepos,unsigned char *buf);
00511 extern int _mi_write_static_record(MI_INFO*, const unsigned char*);
00512 extern int _mi_update_static_record(MI_INFO*, drizzled::internal::my_off_t, const unsigned char*);
00513 extern int _mi_delete_static_record(MI_INFO *info);
00514 extern int _mi_cmp_static_record(MI_INFO *info,const unsigned char *record);
00515 extern int _mi_read_rnd_static_record(MI_INFO*, unsigned char *,drizzled::internal::my_off_t, bool);
00516 extern int _mi_ck_write(MI_INFO *info,uint32_t keynr,unsigned char *key,uint32_t length);
00517 extern int _mi_ck_real_write_btree(MI_INFO *info, MI_KEYDEF *keyinfo,
00518                                    unsigned char *key, uint32_t key_length,
00519                                    drizzled::internal::my_off_t *root, uint32_t comp_flag);
00520 extern int _mi_enlarge_root(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key, drizzled::internal::my_off_t *root);
00521 extern int _mi_insert(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,
00522           unsigned char *anc_buff,unsigned char *key_pos,unsigned char *key_buff,
00523           unsigned char *father_buff, unsigned char *father_keypos,
00524           drizzled::internal::my_off_t father_page, bool insert_last);
00525 extern int _mi_split_page(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,
00526         unsigned char *buff,unsigned char *key_buff, bool insert_last);
00527 extern unsigned char *_mi_find_half_pos(uint32_t nod_flag,MI_KEYDEF *keyinfo,unsigned char *page,
00528         unsigned char *key,uint32_t *return_key_length,
00529         unsigned char **after_key);
00530 extern int _mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
00531               unsigned char *key_pos, unsigned char *org_key,
00532               unsigned char *key_buff,
00533               unsigned char *key, MI_KEY_PARAM *s_temp);
00534 extern int _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
00535            unsigned char *key_pos, unsigned char *org_key,
00536            unsigned char *key_buff,
00537            unsigned char *key, MI_KEY_PARAM *s_temp);
00538 extern int _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
00539           unsigned char *key_pos, unsigned char *org_key,
00540           unsigned char *prev_key,
00541           unsigned char *key, MI_KEY_PARAM *s_temp);
00542 extern int _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
00543           unsigned char *key_pos,unsigned char *org_key,
00544           unsigned char *prev_key,
00545           unsigned char *key, MI_KEY_PARAM *s_temp);
00546 void _mi_store_static_key(MI_KEYDEF *keyinfo,  unsigned char *key_pos,
00547          MI_KEY_PARAM *s_temp);
00548 void _mi_store_var_pack_key(MI_KEYDEF *keyinfo,  unsigned char *key_pos,
00549            MI_KEY_PARAM *s_temp);
00550 #ifdef NOT_USED
00551 void _mi_store_pack_key(MI_KEYDEF *keyinfo,  unsigned char *key_pos,
00552        MI_KEY_PARAM *s_temp);
00553 #endif
00554 void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo,  unsigned char *key_pos,
00555           MI_KEY_PARAM *s_temp);
00556 
00557 extern int _mi_ck_delete(MI_INFO *info,uint32_t keynr,unsigned char *key,uint32_t key_length);
00558 int _mi_readinfo(MI_INFO *info,int lock_flag,int check_keybuffer);
00559 extern int _mi_writeinfo(MI_INFO *info,uint32_t options);
00560 extern int _mi_test_if_changed(MI_INFO *info);
00561 extern int _mi_mark_file_changed(MI_INFO *info);
00562 extern int _mi_decrement_open_count(MI_INFO *info);
00563 extern int _mi_check_index(MI_INFO *info,int inx);
00564 extern int _mi_search(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,uint32_t key_len,
00565           uint32_t nextflag,drizzled::internal::my_off_t pos);
00566 extern int _mi_bin_search(struct st_myisam_info *info,MI_KEYDEF *keyinfo,
00567         unsigned char *page,unsigned char *key,uint32_t key_len,uint32_t comp_flag,
00568         unsigned char * *ret_pos,unsigned char *buff, bool *was_last_key);
00569 extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *page,
00570         unsigned char *key,uint32_t key_len,uint32_t comp_flag,
00571         unsigned char **ret_pos,unsigned char *buff, bool *was_last_key);
00572 extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *page,
00573         unsigned char *key,uint32_t key_len,uint32_t comp_flag,
00574         unsigned char **ret_pos,unsigned char *buff, bool *was_last_key);
00575 extern drizzled::internal::my_off_t _mi_kpos(uint32_t nod_flag,unsigned char *after_key);
00576 extern void _mi_kpointer(MI_INFO *info,unsigned char *buff,drizzled::internal::my_off_t pos);
00577 extern drizzled::internal::my_off_t _mi_dpos(MI_INFO *info, uint32_t nod_flag,unsigned char *after_key);
00578 extern drizzled::internal::my_off_t _mi_rec_pos(MYISAM_SHARE *info, unsigned char *ptr);
00579 void _mi_dpointer(MI_INFO *info, unsigned char *buff,drizzled::internal::my_off_t pos);
00580 extern uint32_t _mi_get_static_key(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char * *page,
00581              unsigned char *key);
00582 extern uint32_t _mi_get_pack_key(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char * *page,
00583            unsigned char *key);
00584 extern uint32_t _mi_get_binary_pack_key(MI_KEYDEF *keyinfo, uint32_t nod_flag,
00585             unsigned char **page_pos, unsigned char *key);
00586 extern unsigned char *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *keypos,
00587              unsigned char *lastkey,unsigned char *endpos,
00588              uint32_t *return_key_length);
00589 extern unsigned char *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
00590         unsigned char *key, unsigned char *keypos, uint32_t *return_key_length);
00591 extern uint32_t _mi_keylength(MI_KEYDEF *keyinfo,unsigned char *key);
00592 extern uint32_t _mi_keylength_part(MI_KEYDEF *keyinfo, register unsigned char *key,
00593              HA_KEYSEG *end);
00594 extern unsigned char *_mi_move_key(MI_KEYDEF *keyinfo,unsigned char *to,unsigned char *from);
00595 extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,
00596          uint32_t key_length,uint32_t nextflag,drizzled::internal::my_off_t pos);
00597 extern int _mi_search_first(MI_INFO *info,MI_KEYDEF *keyinfo,drizzled::internal::my_off_t pos);
00598 extern int _mi_search_last(MI_INFO *info,MI_KEYDEF *keyinfo,drizzled::internal::my_off_t pos);
00599 extern unsigned char *_mi_fetch_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,drizzled::internal::my_off_t page,
00600         int level,unsigned char *buff,int return_buffer);
00601 extern int _mi_write_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,drizzled::internal::my_off_t page,
00602            int level, unsigned char *buff);
00603 extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,drizzled::internal::my_off_t pos,
00604                       int level);
00605 extern drizzled::internal::my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level);
00606 extern uint32_t _mi_make_key(MI_INFO *info,uint32_t keynr,unsigned char *key,
00607        const unsigned char *record,drizzled::internal::my_off_t filepos);
00608 extern uint32_t _mi_pack_key(register MI_INFO *info, uint32_t keynr, unsigned char *key,
00609                          unsigned char *old, drizzled::key_part_map keypart_map,
00610                          HA_KEYSEG **last_used_keyseg);
00611 extern int _mi_read_key_record(MI_INFO *info,drizzled::internal::my_off_t filepos,unsigned char *buf);
00612 extern int _mi_read_cache(drizzled::internal::IO_CACHE *info,unsigned char *buff,drizzled::internal::my_off_t pos,
00613         uint32_t length,int re_read_if_possibly);
00614 extern uint64_t retrieve_auto_increment(MI_INFO *info,const unsigned char *record);
00615 
00616 unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf);
00617 #define mi_get_rec_buff_ptr(info,buf)                              \
00618         ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \
00619         (buf) - MI_REC_BUFF_OFFSET : (buf))
00620 #define mi_get_rec_buff_len(info,buf)                              \
00621         (*((uint32_t *)(mi_get_rec_buff_ptr(info,buf))))
00622 
00623 extern ulong _mi_rec_unpack(MI_INFO *info,unsigned char *to,unsigned char *from,
00624           ulong reclength);
00625 extern bool _mi_rec_check(MI_INFO *info,const unsigned char *record, unsigned char *packpos,
00626                              ulong packed_length, bool with_checkum);
00627 extern int _mi_write_part_record(MI_INFO *info,drizzled::internal::my_off_t filepos,ulong length,
00628          drizzled::internal::my_off_t next_filepos,unsigned char **record,
00629          ulong *reclength,int *flag);
00630 extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const unsigned char *key,
00631         uint32_t length);
00632 extern bool _mi_read_pack_info(MI_INFO *info,bool fix_keys);
00633 extern int _mi_read_pack_record(MI_INFO *info,drizzled::internal::my_off_t filepos,unsigned char *buf);
00634 extern int _mi_read_rnd_pack_record(MI_INFO*, unsigned char *,drizzled::internal::my_off_t, bool);
00635 extern int _mi_pack_rec_unpack(MI_INFO *info, MI_BIT_BUFF *bit_buff,
00636                                unsigned char *to, unsigned char *from, ulong reclength);
00637 
00638 struct st_sort_info;
00639 
00640 
00641 typedef struct st_mi_block_info { /* Parameter to _mi_get_block_info */
00642   unsigned char header[MI_BLOCK_INFO_HEADER_LENGTH];
00643   ulong rec_len;
00644   ulong data_len;
00645   ulong block_len;
00646   ulong blob_len;
00647   drizzled::internal::my_off_t filepos;
00648   drizzled::internal::my_off_t next_filepos;
00649   drizzled::internal::my_off_t prev_filepos;
00650   uint32_t second_read;
00651   uint32_t offset;
00652 } MI_BLOCK_INFO;
00653 
00654   /* bits in return from _mi_get_block_info */
00655 
00656 #define BLOCK_FIRST 1
00657 #define BLOCK_LAST  2
00658 #define BLOCK_DELETED 4
00659 #define BLOCK_ERROR 8 /* Wrong data */
00660 #define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */
00661 #define BLOCK_FATAL_ERROR 32  /* hardware-error */
00662 
00663 #define NEED_MEM  ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
00664 #define MAXERR      20
00665 #define BUFFERS_WHEN_SORTING  16    /* Alloc for sort-key-tree */
00666 #define WRITE_COUNT   1000
00667 #define INDEX_TMP_EXT   ".TMM"
00668 #define DATA_TMP_EXT    ".TMD"
00669 
00670 #define UPDATE_TIME   1
00671 #define UPDATE_STAT   2
00672 #define UPDATE_SORT   4
00673 #define UPDATE_AUTO_INC   8
00674 #define UPDATE_OPEN_COUNT 16
00675 
00676 #define USE_BUFFER_INIT   (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE)
00677 #define READ_BUFFER_INIT  (1024L*256L-MALLOC_OVERHEAD)
00678 #define SORT_BUFFER_INIT  (2048L*1024L-MALLOC_OVERHEAD)
00679 #define MIN_SORT_BUFFER   (4096-MALLOC_OVERHEAD)
00680 
00681 #define fast_mi_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _mi_writeinfo((INFO),0)
00682 #define fast_mi_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _mi_readinfo((INFO),F_RDLCK,1)
00683 
00684 extern uint32_t _mi_get_block_info(MI_BLOCK_INFO *,int, drizzled::internal::my_off_t);
00685 extern uint32_t _mi_rec_pack(MI_INFO *info,unsigned char *to,const unsigned char *from);
00686 extern uint32_t _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff,
00687                                     MI_BLOCK_INFO *info, unsigned char **rec_buff_p,
00688                                     int file, drizzled::internal::my_off_t filepos);
00689 extern void _my_store_blob_length(unsigned char *pos,uint32_t pack_length,uint32_t length);
00690 extern void mi_report_error(int errcode, const char *file_name);
00691 extern void mi_report_error(drizzled::error_t errcode, const char *file_name);
00692 extern size_t mi_mmap_pread(MI_INFO *info, unsigned char *Buffer,
00693                             size_t Count, drizzled::internal::my_off_t offset, drizzled::myf MyFlags);
00694 extern size_t mi_mmap_pwrite(MI_INFO *info, const unsigned char *Buffer,
00695                              size_t Count, drizzled::internal::my_off_t offset, drizzled::myf MyFlags);
00696 extern size_t mi_nommap_pread(MI_INFO *info, unsigned char *Buffer,
00697                               size_t Count, drizzled::internal::my_off_t offset, drizzled::myf MyFlags);
00698 extern size_t mi_nommap_pwrite(MI_INFO *info, const unsigned char *Buffer,
00699                                size_t Count, drizzled::internal::my_off_t offset, drizzled::myf MyFlags);
00700 
00701 uint32_t mi_state_info_write(int file, MI_STATE_INFO *state, uint32_t pWrite);
00702 uint32_t mi_state_info_read_dsk(int file, MI_STATE_INFO *state, bool pRead);
00703 uint32_t mi_base_info_write(int file, MI_BASE_INFO *base);
00704 int mi_keyseg_write(int file, const HA_KEYSEG *keyseg);
00705 uint32_t mi_keydef_write(int file, MI_KEYDEF *keydef);
00706 uint32_t mi_uniquedef_write(int file, MI_UNIQUEDEF *keydef);
00707 uint32_t mi_recinfo_write(int file, drizzled::MI_COLUMNDEF *recinfo);
00708 extern int mi_disable_indexes(MI_INFO *info);
00709 extern int mi_enable_indexes(MI_INFO *info);
00710 extern int mi_indexes_are_disabled(MI_INFO *info);
00711 ulong _my_calc_total_blob_length(MI_INFO *info, const unsigned char *record);
00712 drizzled::internal::ha_checksum mi_checksum(MI_INFO *info, const unsigned char *buf);
00713 drizzled::internal::ha_checksum mi_static_checksum(MI_INFO *info, const unsigned char *buf);
00714 bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, unsigned char *record,
00715          drizzled::internal::ha_checksum unique_hash, drizzled::internal::my_off_t pos);
00716 drizzled::internal::ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const unsigned char *buf);
00717 int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
00718          const unsigned char *record, drizzled::internal::my_off_t pos);
00719 int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
00720          const unsigned char *record, drizzled::internal::my_off_t pos);
00721 int mi_unique_comp(MI_UNIQUEDEF *def, const unsigned char *a, const unsigned char *b,
00722        bool null_are_equal);
00723 
00724 extern MI_INFO *test_if_reopen(char *filename);
00725 bool check_table_is_closed(const char *name, const char *where);
00726 int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, int file_to_dup);
00727 int mi_open_keyfile(MYISAM_SHARE *share);
00728 void mi_setup_functions(register MYISAM_SHARE *share);
00729 bool mi_dynmap_file(MI_INFO *info, drizzled::internal::my_off_t size);
00730 void mi_remap_file(MI_INFO *info, drizzled::internal::my_off_t size);
00731 
00732 int mi_check_index_cond(register MI_INFO *info, uint32_t keynr, unsigned char *record);
00733 
00734     /* Functions needed by mi_check */
00735 volatile int *killed_ptr(MI_CHECK *param);
00736 void mi_check_print_error(MI_CHECK *param, const char *fmt,...);
00737 void mi_check_print_warning(MI_CHECK *param, const char *fmt,...);
00738 void mi_check_print_info(MI_CHECK *param, const char *fmt,...);
00739 int flush_pending_blocks(MI_SORT_PARAM *param);
00740 int thr_write_keys(MI_SORT_PARAM *sort_param);
00741 int flush_blocks(MI_CHECK *param, drizzled::KEY_CACHE *key_cache, int file);
00742 
00743 int sort_write_record(MI_SORT_PARAM *sort_param);
00744 int _create_index_by_sort(MI_SORT_PARAM *info,bool no_messages, size_t);
00745 
00746 extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
00747                                    void *func_arg);
00748 /* Just for myisam legacy */
00749 extern size_t my_pwrite(int Filedes,const unsigned char *Buffer,size_t Count,
00750                         drizzled::internal::my_off_t offset,drizzled::myf MyFlags);
00751 extern size_t my_pread(int Filedes,unsigned char *Buffer,size_t Count,drizzled::internal::my_off_t offset,
00752                        drizzled::myf MyFlags);
00753 
00754 /* Needed for handler */
00755 void mi_disable_non_unique_index(MI_INFO *info, drizzled::ha_rows rows);
00756 void _mi_report_crashed(MI_INFO *file, const char *message, const char *sfile,
00757                         uint32_t sline);
00758