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