static int check_ptr(const char *where, byte *ptr, const char *sFile, uint uLine) { if (!ptr) { fprintf (stderr, "%s NULL pointer at line %d, '%s'\n", where,uLine, sFile); DBUG_PRINT("safe",("Null pointer at line %d '%s'", uLine, sFile)); (void) fflush(stderr); return 1; } #ifndef _MSC_VER if ((long) ptr & (MY_ALIGN(1,sizeof(char *))-1)) { fprintf (stderr, "%s wrong aligned pointer at line %d, '%s'\n", where,uLine, sFile); DBUG_PRINT("safe",("Wrong aligned pointer at line %d, '%s'", uLine,sFile)); (void) fflush(stderr); return 1; } #endif if (ptr < sf_min_adress || ptr > sf_max_adress) { fprintf (stderr, "%s pointer out of range at line %d, '%s'\n", where,uLine, sFile); DBUG_PRINT("safe",("Pointer out of range at line %d '%s'", uLine,sFile)); (void) fflush(stderr); return 1; } return 0; }
static Bigint *Balloc(int k, Stack_alloc *alloc) { Bigint *rv; DBUG_ASSERT(k <= Kmax); if (k <= Kmax && alloc->freelist[k]) { rv= alloc->freelist[k]; alloc->freelist[k]= rv->p.next; } else { int x, len; x= 1 << k; len= MY_ALIGN(sizeof(Bigint) + x * sizeof(ULong), SIZEOF_CHARP); if (alloc->free + len <= alloc->end) { rv= (Bigint*) alloc->free; alloc->free+= len; } else rv= (Bigint*) malloc(len); rv->k= k; rv->maxwds= x; } rv->sign= rv->wds= 0; rv->p.x= (ULong*) (rv + 1); return rv; }
static char *dtoa_alloc(int i, Stack_alloc *alloc) { char *rv; int aligned_size= MY_ALIGN(i, SIZEOF_CHARP); if (alloc->free + aligned_size <= alloc->end) { rv= alloc->free; alloc->free+= aligned_size; } else rv= malloc(i); return rv; }
void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, int size, qsort_cmp2 compare, my_bool with_delete, tree_element_free free_element, const void *custom_arg) { DBUG_ENTER("init_tree"); DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size)); if (default_alloc_size < DEFAULT_ALLOC_SIZE) default_alloc_size= DEFAULT_ALLOC_SIZE; default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE); memset(&tree->null_element, 0, sizeof(tree->null_element)); tree->root= &tree->null_element; tree->compare=compare; tree->size_of_element=size > 0 ? (uint) size : 0; tree->memory_limit=memory_limit; tree->free=free_element; tree->allocated=0; tree->elements_in_tree=0; tree->custom_arg = custom_arg; tree->null_element.colour=BLACK; tree->null_element.left=tree->null_element.right=0; tree->flag= 0; if (!free_element && size >= 0 && ((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1)))) { /* We know that the data doesn't have to be aligned (like if the key contains a double), so we can store the data combined with the TREE_ELEMENT. */ tree->offset_to_key=sizeof(TREE_ELEMENT); /* Put key after element */ /* Fix allocation size so that we don't lose any memory */ default_alloc_size/=(sizeof(TREE_ELEMENT)+size); if (!default_alloc_size) default_alloc_size=1; default_alloc_size*=(sizeof(TREE_ELEMENT)+size); } else { tree->offset_to_key=0; /* use key through pointer */ tree->size_of_element+=sizeof(void*); } if (!(tree->with_delete=with_delete)) { init_alloc_root(key_memory_TREE, &tree->mem_root, (uint) default_alloc_size, 0); tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element); } DBUG_VOID_RETURN; }
uchar* my_large_malloc_int(size_t size, myf my_flags) { int shmid; uchar* ptr; struct shmid_ds buf; DBUG_ENTER("my_large_malloc_int"); /* Align block size to my_large_page_size */ size= MY_ALIGN(size, (size_t) my_large_page_size); shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) { if (my_flags & MY_WME) /* purecov: begin inspected */ my_message_local(WARNING_LEVEL, "Failed to allocate %lu bytes from HugeTLB memory." " errno %d", (ulong) size, errno); /* purecov: end */ DBUG_RETURN(NULL); } ptr = (uchar*) shmat(shmid, NULL, 0); if (ptr == (uchar *) -1) { if (my_flags& MY_WME) /* purecov: begin inspected */ my_message_local(WARNING_LEVEL, "Failed to attach shared memory segment," " errno %d", errno); /* purecov: end */ shmctl(shmid, IPC_RMID, &buf); DBUG_RETURN(NULL); } /* Remove the shared memory segment so that it will be automatically freed after memory is detached or process exits */ shmctl(shmid, IPC_RMID, &buf); DBUG_RETURN(ptr); }
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uint columns, MI_COLUMNDEF *recinfo, uint uniques, MI_UNIQUEDEF *uniquedefs, MI_CREATE_INFO *ci,uint flags) { register uint i,j; File UNINIT_VAR(dfile), UNINIT_VAR(file); int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; uint fields,length,max_key_length,packed,pointer,real_length_diff, key_length,info_length,key_segs,options,min_key_length_skip, base_pos,long_varchar_count,varchar_length, max_key_block_length,unique_key_parts,fulltext_keys,offset; uint aligned_key_start, block_length; uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; enum en_fieldtype type; MYISAM_SHARE share; MI_KEYDEF *keydef,tmp_keydef; MI_UNIQUEDEF *uniquedef; HA_KEYSEG *keyseg,tmp_keyseg; MI_COLUMNDEF *rec; ulong *rec_per_key_part; my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; MI_CREATE_INFO tmp_create_info; DBUG_ENTER("mi_create"); DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", keys, columns, uniques, flags)); if (!ci) { memset(&tmp_create_info, 0, sizeof(tmp_create_info)); ci=&tmp_create_info; } if (keys + uniques > MI_MAX_KEY || columns == 0) { DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION); } errpos=0; options=0; memset(&share, 0, sizeof(share)); if (flags & HA_DONT_TOUCH_DATA) { if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD)) options=ci->old_options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); else options=ci->old_options & (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); } if (ci->reloc_rows > ci->max_rows) ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */ if (!(rec_per_key_part= (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long), MYF(MY_WME | MY_ZEROFILL)))) DBUG_RETURN(my_errno); /* Start by checking fields and field-types used */ reclength=varchar_length=long_varchar_count=packed= min_pack_length=pack_reclength=0; for (rec=recinfo, fields=0 ; fields != columns ; rec++,fields++) { reclength+=rec->length; if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL && type != FIELD_CHECK) { packed++; if (type == FIELD_BLOB) { share.base.blobs++; if (pack_reclength != INT_MAX32) { if (rec->length == 4+portable_sizeof_char_ptr) pack_reclength= INT_MAX32; else pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */ } } else if (type == FIELD_SKIP_PRESPACE || type == FIELD_SKIP_ENDSPACE) { if (pack_reclength != INT_MAX32) pack_reclength+= rec->length > 255 ? 2 : 1; min_pack_length++; } else if (type == FIELD_VARCHAR) { varchar_length+= rec->length-1; /* Used for min_pack_length */ packed--; pack_reclength++; min_pack_length++; /* We must test for 257 as length includes pack-length */ if (test(rec->length >= 257)) { long_varchar_count++; pack_reclength+= 2; /* May be packed on 3 bytes */ } } else if (type != FIELD_SKIP_ZERO) { min_pack_length+=rec->length; packed--; /* Not a pack record type */ } } else /* FIELD_NORMAL */ min_pack_length+=rec->length; } if ((packed & 7) == 1) { /* Bad packing, try to remove a zero-field */ while (rec != recinfo) { rec--; if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1) { /* NOTE1: here we change a field type FIELD_SKIP_ZERO -> FIELD_NORMAL */ rec->type=(int) FIELD_NORMAL; packed--; min_pack_length++; break; } } } if (packed || (flags & HA_PACK_RECORD)) options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ /* We can't use checksum with static length rows */ if (!(options & HA_OPTION_PACK_RECORD)) options&= ~HA_OPTION_CHECKSUM; if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) min_pack_length+= varchar_length; if (flags & HA_CREATE_TMP_TABLE) { options|= HA_OPTION_TMP_TABLE; create_mode|= O_EXCL | O_NOFOLLOW; } if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { options|= HA_OPTION_CHECKSUM; min_pack_length++; } if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) options|= HA_OPTION_RELIES_ON_SQL_LAYER; packed=(packed+7)/8; if (pack_reclength != INT_MAX32) pack_reclength+= reclength+packed + test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_OPTION_PACK_RECORD)); min_pack_length+=packed; if (!ci->data_file_length && ci->max_rows) { if (pack_reclength == INT_MAX32 || (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) ci->data_file_length= ~(ulonglong) 0; else ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; } else if (!ci->max_rows) ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length + ((options & HA_OPTION_PACK_RECORD) ? 3 : 0))); if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)) pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size); else pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size); if (!(max_rows=(ulonglong) ci->max_rows)) max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length); real_reclength=reclength; if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))) { if (reclength <= pointer) reclength=pointer+1; /* reserve place for delete link */ } else reclength+= long_varchar_count; /* We need space for varchar! */ max_key_length=0; tot_length=0 ; key_segs=0; fulltext_keys=0; max_key_block_length=0; share.state.rec_per_key_part=rec_per_key_part; share.state.key_root=key_root; share.state.key_del=key_del; if (uniques) { max_key_block_length= myisam_block_size; max_key_length= MI_UNIQUE_HASH_LENGTH + pointer; } for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) { share.state.key_root[i]= HA_OFFSET_ERROR; min_key_length_skip=length=real_length_diff=0; key_length=pointer; if (keydef->flag & HA_SPATIAL) { #ifdef HAVE_SPATIAL /* BAR TODO to support 3D and more dimensions in the future */ uint sp_segs=SPDIMS*2; keydef->flag=HA_SPATIAL; if (flags & HA_DONT_TOUCH_DATA) { /* called by myisamchk - i.e. table structure was taken from MYI file and SPATIAL key *does have* additional sp_segs keysegs. keydef->seg here points right at the GEOMETRY segment, so we only need to decrease keydef->keysegs. (see recreate_table() in mi_check.c) */ keydef->keysegs-=sp_segs-1; } for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ; j++, keyseg++) { if (keyseg->type != HA_KEYTYPE_BINARY && keyseg->type != HA_KEYTYPE_VARBINARY1 && keyseg->type != HA_KEYTYPE_VARBINARY2) { my_errno=HA_WRONG_CREATE_OPTION; goto err_no_lock; } } keydef->keysegs+=sp_segs; key_length+=SPLEN*sp_segs; length++; /* At least one length byte */ min_key_length_skip+=SPLEN*2*SPDIMS; #else my_errno= HA_ERR_UNSUPPORTED; goto err_no_lock; #endif /*HAVE_SPATIAL*/ } else if (keydef->flag & HA_FULLTEXT) { keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY; options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ; j++, keyseg++) { if (keyseg->type != HA_KEYTYPE_TEXT && keyseg->type != HA_KEYTYPE_VARTEXT1 && keyseg->type != HA_KEYTYPE_VARTEXT2) { my_errno=HA_WRONG_CREATE_OPTION; goto err_no_lock; } if (!(keyseg->flag & HA_BLOB_PART) && (keyseg->type == HA_KEYTYPE_VARTEXT1 || keyseg->type == HA_KEYTYPE_VARTEXT2)) { /* Make a flag that this is a VARCHAR */ keyseg->flag|= HA_VAR_LENGTH_PART; /* Store in bit_start number of bytes used to pack the length */ keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)? 1 : 2); } } fulltext_keys++; key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN; length++; /* At least one length byte */ min_key_length_skip+=HA_FT_MAXBYTELEN; real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT; } else { /* Test if prefix compression */ if (keydef->flag & HA_PACK_KEY) { /* Can't use space_compression on number keys */ if ((keydef->seg[0].flag & HA_SPACE_PACK) && keydef->seg[0].type == (int) HA_KEYTYPE_NUM) keydef->seg[0].flag&= ~HA_SPACE_PACK; /* Only use HA_PACK_KEY when first segment is a variable length key */ if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))) { /* pack relative to previous key */ keydef->flag&= ~HA_PACK_KEY; keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY; } else { keydef->seg[0].flag|=HA_PACK_KEY; /* for easyer intern test */ keydef->flag|=HA_VAR_LENGTH_KEY; options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ } } if (keydef->flag & HA_BINARY_PACK_KEY) options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment) share.base.auto_key=i+1; for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++) { /* numbers are stored with high by first to make compression easier */ switch (keyseg->type) { case HA_KEYTYPE_SHORT_INT: case HA_KEYTYPE_LONG_INT: case HA_KEYTYPE_FLOAT: case HA_KEYTYPE_DOUBLE: case HA_KEYTYPE_USHORT_INT: case HA_KEYTYPE_ULONG_INT: case HA_KEYTYPE_LONGLONG: case HA_KEYTYPE_ULONGLONG: case HA_KEYTYPE_INT24: case HA_KEYTYPE_UINT24: case HA_KEYTYPE_INT8: keyseg->flag|= HA_SWAP_KEY; break; case HA_KEYTYPE_VARTEXT1: case HA_KEYTYPE_VARTEXT2: case HA_KEYTYPE_VARBINARY1: case HA_KEYTYPE_VARBINARY2: if (!(keyseg->flag & HA_BLOB_PART)) { /* Make a flag that this is a VARCHAR */ keyseg->flag|= HA_VAR_LENGTH_PART; /* Store in bit_start number of bytes used to pack the length */ keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 || keyseg->type == HA_KEYTYPE_VARBINARY1) ? 1 : 2); } break; default: break; } if (keyseg->flag & HA_SPACE_PACK) { DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART)); keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY; options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ length++; /* At least one length byte */ min_key_length_skip+=keyseg->length; if (keyseg->length >= 255) { /* prefix may be 3 bytes */ min_key_length_skip+=2; length+=2; } } if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART)) { DBUG_ASSERT(!test_all_bits(keyseg->flag, (HA_VAR_LENGTH_PART | HA_BLOB_PART))); keydef->flag|=HA_VAR_LENGTH_KEY; length++; /* At least one length byte */ options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ min_key_length_skip+=keyseg->length; if (keyseg->length >= 255) { /* prefix may be 3 bytes */ min_key_length_skip+=2; length+=2; } } key_length+= keyseg->length; if (keyseg->null_bit) { key_length++; options|=HA_OPTION_PACK_KEYS; keyseg->flag|=HA_NULL_PART; keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY; } } } /* if HA_FULLTEXT */ key_segs+=keydef->keysegs; if (keydef->keysegs > MI_MAX_KEY_SEG) { my_errno=HA_WRONG_CREATE_OPTION; goto err_no_lock; } /* key_segs may be 0 in the case when we only want to be able to add on row into the table. This can happen with some DISTINCT queries in MySQL */ if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME && key_segs) share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; /* Get block length for key, if defined by user */ block_length= (keydef->block_length ? my_round_up_to_next_power(keydef->block_length) : myisam_block_size); block_length= MY_MAX(block_length, MI_MIN_KEY_BLOCK_LENGTH); block_length= MY_MIN(block_length, MI_MAX_KEY_BLOCK_LENGTH); keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff, pointer,MI_MAX_KEYPTR_SIZE, block_length); if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH || length >= MI_MAX_KEY_BUFF) { my_errno=HA_WRONG_CREATE_OPTION; goto err_no_lock; } set_if_bigger(max_key_block_length,keydef->block_length); keydef->keylength= (uint16) key_length; keydef->minlength= (uint16) (length-min_key_length_skip); keydef->maxlength= (uint16) length; if (length > max_key_length) max_key_length= length; tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/ (length*2)))* (ulong) keydef->block_length; } for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) key_del[i]=HA_OFFSET_ERROR; unique_key_parts=0; for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++) { uniquedef->key=keys+i; unique_key_parts+=uniquedef->keysegs; share.state.key_root[keys+i]= HA_OFFSET_ERROR; tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/ ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))* (ulong) myisam_block_size; } keys+=uniques; /* Each unique has 1 key */ key_segs+=uniques; /* Each unique has 1 key seg */ base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE + max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH* MI_STATE_KEYBLOCK_SIZE+ key_segs*MI_STATE_KEYSEG_SIZE); info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+ keys * MI_KEYDEF_SIZE+ uniques * MI_UNIQUEDEF_SIZE + (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ columns*MI_COLUMNDEF_SIZE); DBUG_PRINT("info", ("info_length: %u", info_length)); /* There are only 16 bits for the total header length. */ if (info_length > 65535) { my_printf_error(0, "MyISAM table '%s' has too many columns and/or " "indexes and/or unique constraints.", MYF(0), name + dirname_length(name)); my_errno= HA_WRONG_CREATE_OPTION; goto err_no_lock; } bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4); ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? HA_OPTION_COMPRESS_RECORD | HA_OPTION_TEMP_COMPRESS_RECORD: 0); mi_int2store(share.state.header.options,ci->old_options); mi_int2store(share.state.header.header_length,info_length); mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE); mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE); mi_int2store(share.state.header.base_pos,base_pos); share.state.header.language= (ci->language ? ci->language : default_charset_info->number); share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH; share.state.dellink = HA_OFFSET_ERROR; share.state.process= (ulong) getpid(); share.state.unique= (ulong) 0; share.state.update_count=(ulong) 0; share.state.version= (ulong) time((time_t*) 0); share.state.sortkey= (ushort) ~0; share.state.auto_increment=ci->auto_increment; share.options=options; share.base.rec_reflength=pointer; /* Get estimate for index file length (this may be wrong for FT keys) */ tmp= (tot_length + max_key_block_length * keys * MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH; /* use maximum of key_file_length we calculated and key_file_length value we got from MYI file header (see also myisampack.c:save_state) */ share.base.key_reflength= mi_get_pointer_length(MY_MAX(ci->key_file_length, tmp), 3); share.base.keys= share.state.header.keys= keys; share.state.header.uniques= uniques; share.state.header.fulltext_keys= fulltext_keys; mi_int2store(share.state.header.key_parts,key_segs); mi_int2store(share.state.header.unique_key_parts,unique_key_parts); mi_set_all_keys_active(share.state.key_map, keys); aligned_key_start= my_round_up_to_next_power(max_key_block_length ? max_key_block_length : myisam_block_size); share.base.keystart= share.state.state.key_file_length= MY_ALIGN(info_length, aligned_key_start); share.base.max_key_block_length=max_key_block_length; share.base.max_key_length=ALIGN_SIZE(max_key_length+4); share.base.records=ci->max_rows; share.base.reloc= ci->reloc_rows; share.base.reclength=real_reclength; share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; share.base.pack_bits=packed; share.base.fields=fields; share.base.pack_fields=packed; /* max_data_file_length and max_key_file_length are recalculated on open */ if (options & HA_OPTION_TMP_TABLE) share.base.max_data_file_length=(my_off_t) ci->data_file_length; share.base.min_block_length= (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH && ! share.base.blobs) ? MY_MAX(share.base.pack_reclength, MI_MIN_BLOCK_LENGTH) : MI_EXTEND_BLOCK_LENGTH; if (! (flags & HA_DONT_TOUCH_DATA)) share.state.create_time= (long) time((time_t*) 0); if (!internal_table) mysql_mutex_lock(&THR_LOCK_myisam); /* NOTE: For test_if_reopen() we need a real path name. Hence we need MY_RETURN_REAL_PATH for every fn_format(filename, ...). */ if (ci->index_file_name) { char *iext= strrchr(ci->index_file_name, '.'); int have_iext= iext && !strcmp(iext, MI_NAME_IEXT); if (options & HA_OPTION_TMP_TABLE) { char *path; /* chop off the table name, tempory tables use generated name */ if ((path= strrchr(ci->index_file_name, FN_LIBCHAR))) *path= '\0'; fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT, MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | MY_APPEND_EXT); } else { fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); } fn_format(linkname, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME|MY_APPEND_EXT); linkname_ptr=linkname; /* Don't create the table if the link or file exists to ensure that one doesn't accidently destroy another table. */ create_flag=0; } else { char *iext= strrchr(name, '.'); int have_iext= iext && !strcmp(iext, MI_NAME_IEXT); fn_format(filename, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH | (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT)); linkname_ptr=0; /* Replace the current file */ create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD; } /* If a MRG_MyISAM table is in use, the mapped MyISAM tables are open, but no entry is made in the table cache for them. A TRUNCATE command checks for the table in the cache only and could be fooled to believe, the table is not open. Pull the emergency brake in this situation. (Bug #8306) NOTE: The filename is compared against unique_file_name of every open table. Hence we need a real path here. */ if (!internal_table && test_if_reopen(filename)) { my_printf_error(0, "MyISAM table '%s' is in use " "(most likely by a MERGE table). Try FLUSH TABLES.", MYF(0), name + dirname_length(name)); my_errno= HA_ERR_TABLE_EXIST; goto err; } if ((file= mysql_file_create_with_symlink(mi_key_file_kfile, linkname_ptr, filename, 0, create_mode, MYF(MY_WME | create_flag))) < 0) goto err; errpos=1; if (!(flags & HA_DONT_TOUCH_DATA)) { { if (ci->data_file_name) { char *dext= strrchr(ci->data_file_name, '.'); int have_dext= dext && !strcmp(dext, MI_NAME_DEXT); if (options & HA_OPTION_TMP_TABLE) { char *path; /* chop off the table name, tempory tables use generated name */ if ((path= strrchr(ci->data_file_name, FN_LIBCHAR))) *path= '\0'; fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT, MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT); } else { fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT, MY_UNPACK_FILENAME | (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT)); } fn_format(linkname, name, "",MI_NAME_DEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT); linkname_ptr=linkname; create_flag=0; } else { fn_format(filename,name,"", MI_NAME_DEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT); linkname_ptr=0; create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD; } if ((dfile= mysql_file_create_with_symlink(mi_key_file_dfile, linkname_ptr, filename, 0, create_mode, MYF(MY_WME | create_flag))) < 0) goto err; } errpos=3; } DBUG_PRINT("info", ("write state info and base info")); if (mi_state_info_write(file, &share.state, 2) || mi_base_info_write(file, &share.base)) goto err; #ifndef DBUG_OFF if ((uint) mysql_file_tell(file, MYF(0)) != base_pos + MI_BASE_INFO_SIZE) { uint pos=(uint) mysql_file_tell(file, MYF(0)); DBUG_PRINT("warning",("base_length: %d != used_length: %d", base_pos+ MI_BASE_INFO_SIZE, pos)); } #endif /* Write key and keyseg definitions */ DBUG_PRINT("info", ("write key and keyseg definitions")); for (i=0 ; i < share.base.keys - uniques; i++) { uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0; if (mi_keydef_write(file, &keydefs[i])) goto err; for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++) if (mi_keyseg_write(file, &keydefs[i].seg[j])) goto err; #ifdef HAVE_SPATIAL for (j=0 ; j < sp_segs ; j++) { HA_KEYSEG sseg; sseg.type=SPTYPE; sseg.language= 7; /* Binary */ sseg.null_bit=0; sseg.bit_start=0; sseg.bit_end=0; sseg.bit_length= 0; sseg.bit_pos= 0; sseg.length=SPLEN; sseg.null_pos=0; sseg.start=j*SPLEN; sseg.flag= HA_SWAP_KEY; if (mi_keyseg_write(file, &sseg)) goto err; } #endif } /* Create extra keys for unique definitions */ offset= real_reclength - uniques * MI_UNIQUE_HASH_LENGTH; memset(&tmp_keydef, 0, sizeof(tmp_keydef)); memset(&tmp_keyseg, 0, sizeof(tmp_keyseg)); for (i=0; i < uniques ; i++) { tmp_keydef.keysegs=1; tmp_keydef.flag= HA_UNIQUE_CHECK; tmp_keydef.block_length= (uint16)myisam_block_size; tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer; tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength; tmp_keyseg.type= MI_UNIQUE_HASH_TYPE; tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH; tmp_keyseg.start= offset; offset+= MI_UNIQUE_HASH_LENGTH; if (mi_keydef_write(file,&tmp_keydef) || mi_keyseg_write(file,(&tmp_keyseg))) goto err; } /* Save unique definition */ DBUG_PRINT("info", ("write unique definitions")); for (i=0 ; i < share.state.header.uniques ; i++) { HA_KEYSEG *keyseg_end; keyseg= uniquedefs[i].seg; if (mi_uniquedef_write(file, &uniquedefs[i])) goto err; for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs; keyseg < keyseg_end; keyseg++) { switch (keyseg->type) { case HA_KEYTYPE_VARTEXT1: case HA_KEYTYPE_VARTEXT2: case HA_KEYTYPE_VARBINARY1: case HA_KEYTYPE_VARBINARY2: if (!(keyseg->flag & HA_BLOB_PART)) { keyseg->flag|= HA_VAR_LENGTH_PART; keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 || keyseg->type == HA_KEYTYPE_VARBINARY1) ? 1 : 2); } break; default: break; } if (mi_keyseg_write(file, keyseg)) goto err; } } DBUG_PRINT("info", ("write field definitions")); for (i=0 ; i < share.base.fields ; i++) if (mi_recinfo_write(file, &recinfo[i])) goto err; #ifndef DBUG_OFF if ((uint) mysql_file_tell(file, MYF(0)) != info_length) { uint pos= (uint) mysql_file_tell(file, MYF(0)); DBUG_PRINT("warning",("info_length: %d != used_length: %d", info_length, pos)); } #endif /* Enlarge files */ DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart)); if (mysql_file_chsize(file, (ulong) share.base.keystart, 0, MYF(0))) goto err; if (! (flags & HA_DONT_TOUCH_DATA)) { #ifdef USE_RELOC if (mysql_file_chsize(dfile, share.base.min_pack_length*ci->reloc_rows, 0, MYF(0))) goto err; #endif errpos=2; if (mysql_file_close(dfile, MYF(0))) goto err; } errpos=0; if (!internal_table) mysql_mutex_unlock(&THR_LOCK_myisam); if (mysql_file_close(file, MYF(0))) goto err_no_lock; my_free(rec_per_key_part); DBUG_RETURN(0); err: if (!internal_table) mysql_mutex_unlock(&THR_LOCK_myisam); err_no_lock: save_errno=my_errno; switch (errpos) { case 3: (void) mysql_file_close(dfile, MYF(0)); /* fall through */ case 2: if (! (flags & HA_DONT_TOUCH_DATA)) mysql_file_delete_with_symlink(mi_key_file_dfile, fn_format(filename, name, "", MI_NAME_DEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT), MYF(0)); /* fall through */ case 1: (void) mysql_file_close(file, MYF(0)); if (! (flags & HA_DONT_TOUCH_DATA)) mysql_file_delete_with_symlink(mi_key_file_kfile, fn_format(filename, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT), MYF(0)); } my_free(rec_per_key_part); DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */ }
/* my_ascii_to_lattice - ASCII字符转换成点阵 fontdata:点阵字库指针 character_width:点阵宽度(比如32*32的点阵,宽度是32) strings:字符串 lattice:转换后的点阵数据 w/h:转换后的点阵数据的宽、高 注:fontdata取模是' '开始(前32个字符是不可打印字符),使用PCtoLCD2002.exe软件,取模方式:逐列式,低位在前 */ static void my_ascii_to_lattice(unsigned char* fontdata, int char_width, char* strings, unsigned char* lattice, int* w, int* h) { #define MY_ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) // 字节对齐(此处点阵只使用8字节对齐) unsigned char tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; int offset_byte = 0; // 点阵所占字节偏移 char* q = NULL; int i,j, k; int len = 0; int width = 0; int height = 0; int half_width = char_width / 2; // 半角 int char_height = MY_ALIGN(char_width, 8); // 高(必须是8的整数倍) int char_halfwidth_size = MY_ALIGN(char_width, 8)*char_width/2/8; // 半角点阵总大小 if (fontdata == NULL || strings == NULL || lattice == NULL || w == NULL || h == NULL) return; len = (int)strlen((const char *)strings); width = len * half_width; height = char_height; q = (char*)lattice; *w = width; *h = height; // 多少个字符 for ( i = 0; i < len; ++i ) { // 前面32(0x20)个是不可打印字符,故要减去0x20 unsigned char* p = fontdata + ((strings[i] - 0x20) * char_halfwidth_size); // 每个字符宽是半角 for ( j = 0; j < half_width; ++j ) { // 每个字符高有多少个字节 for (k = 0; k < char_height/8; k++) { offset_byte = k * 8; // 分解点阵一个字节所有的位 // 注: 低位在前 tmp1 = (*p & 0x01) >> 0; tmp2 = (*p & 0x02) >> 1; tmp3 = (*p & 0x04) >> 2; tmp4 = (*p & 0x08) >> 3; tmp5 = (*p & 0x10) >> 4; tmp6 = (*p & 0x20) >> 5; tmp7 = (*p & 0x40) >> 6; tmp8 = (*p & 0x80) >> 7; // height/8个字节 q[width * (0+offset_byte) + half_width * i + j] = tmp1; q[width * (1+offset_byte) + half_width * i + j] = tmp2; q[width * (2+offset_byte) + half_width * i + j] = tmp3; q[width * (3+offset_byte) + half_width * i + j] = tmp4; q[width * (4+offset_byte) + half_width * i + j] = tmp5; q[width * (5+offset_byte) + half_width * i + j] = tmp6; q[width * (6+offset_byte) + half_width * i + j] = tmp7; q[width * (7+offset_byte) + half_width * i + j] = tmp8; p++; } } } }
static void get_options( int argc, char *argv[]) { char *pos,*progname; DEBUGGER_OFF; progname= argv[0]; while (--argc >0 && *(pos = *(++argv)) == '-' ) { switch(*++pos) { case 'b': if (*++pos) nisam_block_size= MY_ALIGN(atoi(pos),512); set_if_bigger(nisam_block_size,8192); /* Max block size */ set_if_smaller(nisam_block_size,1024); break; case 'B': use_blob=1; break; case 'K': /* Use key cacheing */ key_cacheing=1; break; case 'W': /* Use write cacheing */ write_cacheing=1; if (*++pos) my_default_record_cache_size=atoi(pos); break; case 'i': if (*++pos) srand(atoi(pos)); break; case 'l': use_log=1; break; case 'L': locking=1; break; case 'A': /* use asyncron io */ async_io=1; if (*++pos) my_default_record_cache_size=atoi(pos); break; case 'v': /* verbose */ verbose=1; break; case 'm': /* records */ recant=atoi(++pos); break; case 'f': if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS) first_key=0; break; case 'k': if ((keys=(uint) atoi(++pos)) < 1 || keys > (uint) (NISAM_KEYS-first_key)) keys=NISAM_KEYS-first_key; break; case 'P': pack_type=0; /* Don't use DIFF_LENGTH */ break; case 'R': /* Length of record pointer */ rec_pointer_size=atoi(++pos); if (rec_pointer_size > 3) rec_pointer_size=0; break; case 'S': pack_fields=0; /* Static-length-records */ break; case 't': testflag=atoi(++pos); /* testmod */ break; case '?': case 'I': case 'V': printf("%s Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); puts("TCX Datakonsult AB, by Monty, for your professional use\n"); printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname); exit(0); case '#': DEBUGGER_ON; DBUG_PUSH (++pos); break; default: printf("Illegal option: '%c'\n",*pos); break; } } return; } /* get options */
int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo, N_RECINFO *recinfo, ulong records,ulong reloc, uint flags,uint old_options, ulong data_file_length) { register uint i,j; File dfile,file; int errpos,save_errno; uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length, key_length,info_length,key_segs,options,min_key_length_skipp,max_block, base_pos; char buff[max(FN_REFLEN,512)]; ulong tot_length,pack_reclength; enum en_fieldtype type; ISAM_SHARE share; N_KEYDEF *keydef; N_KEYSEG *keyseg; N_RECINFO *rec; DBUG_ENTER("nisam_create"); LINT_INIT(dfile); pthread_mutex_lock(&THR_LOCK_isam); errpos=0; options=0; base_pos=512; /* Enough for N_STATE_INFO */ bzero((byte*) &share,sizeof(share)); if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) goto err; errpos=1; VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4)); if (!(flags & HA_DONT_TOUCH_DATA)) { if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) goto err; errpos=2; } else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD)) options=old_options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD); if (reloc > records) reloc=records; /* Check if wrong parameter */ /* Start by checking fields and field-types used */ reclength=0; for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L; rec->base.type != (int) FIELD_LAST; rec++,fields++) { reclength+=rec->base.length; if ((type=(enum en_fieldtype) rec->base.type)) { packed++; if (type == FIELD_BLOB) { share.base.blobs++; rec->base.length-= sizeof(char*); /* Don't calc pointer */ if (pack_reclength != NI_POS_ERROR) { if (rec->base.length == 4) pack_reclength= (ulong) NI_POS_ERROR; else pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8)); } } else if (type == FIELD_SKIP_PRESPACE || type == FIELD_SKIP_ENDSPACE) { if (pack_reclength != NI_POS_ERROR) pack_reclength+= rec->base.length > 255 ? 2 : 1; min_pack_length++; } else if (type == FIELD_ZERO) packed--; else if (type != FIELD_SKIP_ZERO) { min_pack_length+=rec->base.length; packed--; /* Not a pack record type */ } } else min_pack_length+=rec->base.length; } if ((packed & 7) == 1) { /* Bad packing, try to remove a zero-field */ while (rec != recinfo) { rec--; if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1) { rec->base.type=(int) FIELD_NORMAL; packed--; min_pack_length++; break; } } } if (packed && !(options & HA_OPTION_COMPRESS_RECORD)) options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ packed=(packed+7)/8; if (pack_reclength != NI_POS_ERROR) pack_reclength+= reclength+packed; min_pack_length+=packed; if (options & HA_OPTION_COMPRESS_RECORD) { if (data_file_length >= (1L << 24)) pointer=4; else if (data_file_length >= (1L << 16)) pointer=3; else pointer=2; } else if (((records == 0L && pack_reclength < 255) || options & HA_OPTION_PACK_RECORD) || records >= (ulong) 16000000L || pack_reclength == (ulong) NI_POS_ERROR || ((options & HA_OPTION_PACK_RECORD) && pack_reclength+4 >= (ulong) 14000000L/records)) pointer=4; else if (records == 0L || records >= (ulong) 65000L || ((options & HA_OPTION_PACK_RECORD) && pack_reclength+4 >= (ulong) 60000L/records)) pointer=3; else pointer=2; max_block=max_key_length=0; tot_length=key_segs=0; for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++) { share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR; share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L; min_key_length_skipp=length=0; key_length=pointer; if (keydef->base.flag & HA_PACK_KEY && keydef->seg[0].base.length > 127) keydef->base.flag&= ~HA_PACK_KEY; /* Can't pack long keys */ if (keydef->base.flag & HA_PACK_KEY) { if ((keydef->seg[0].base.flag & HA_SPACE_PACK) && keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM) keydef->seg[0].base.flag&= ~HA_SPACE_PACK; if (!(keydef->seg[0].base.flag & HA_SPACE_PACK)) length++; keydef->seg[0].base.flag|=HA_PACK_KEY; /* for easyer intern test */ options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ if (!(keydef->seg[0].base.flag & HA_SPACE_PACK)) min_key_length_skipp+=keydef->seg[0].base.length; } keydef->base.keysegs=0; for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++) { keydef->base.keysegs++; if (keyseg->base.length > 127) keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY); if (keyseg->base.flag & HA_SPACE_PACK) { keydef->base.flag |= HA_SPACE_PACK_USED; options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ length++; min_key_length_skipp+=keyseg->base.length; } key_length+= keyseg->base.length; } bzero((gptr) keyseg,sizeof(keyseg[0])); keyseg->base.length=(uint16) pointer; /* Last key part is pointer */ key_segs+=keydef->base.keysegs; length+=key_length; keydef->base.block_length=nisam_block_size; keydef->base.keylength= (uint16) key_length; keydef->base.minlength= (uint16) (length-min_key_length_skipp); keydef->base.maxlength= (uint16) length; if ((uint) keydef->base.block_length > max_block) max_block=(uint) keydef->base.block_length; if (length > max_key_length) max_key_length= length; tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/ (length*2)))* (ulong) keydef->base.block_length; } info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+ (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+ fields*sizeof(N_SAVE_RECINFO)); bmove(share.state.header.file_version,(byte*) nisam_file_magic,4); old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? HA_OPTION_COMPRESS_RECORD | HA_OPTION_TEMP_COMPRESS_RECORD: 0); int2store(share.state.header.options,old_options); int2store(share.state.header.header_length,info_length); int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO)); int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO)); int2store(share.state.header.base_pos,base_pos); share.state.dellink = NI_POS_ERROR; share.state.process= (ulong) getpid(); share.state.uniq= (ulong) file; share.state.loop= 0; share.state.version= (ulong) time((time_t*) 0); share.base.options=options; share.base.rec_reflength=pointer; share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 : tot_length > 120000L ? 2 : 1); share.base.keys= share.state.keys = keys; share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length, nisam_block_size); share.base.max_block=max_block; share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4); share.base.records=records; share.base.reloc=reloc; share.base.reclength=reclength; share.base.pack_reclength= (uint) (reclength+packed-share.base.blobs*sizeof(char*)); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; share.base.pack_bits=packed; share.base.fields=fields; share.base.pack_fields=packed; share.base.sortkey= (ushort) ~0; share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L : (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? (ulong) (1L << (pointer*8)) : (pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR : ((ulong) reclength * (1L << (pointer*8))); share.base.max_key_file_length= (share.base.key_reflength == 3 ? NI_POS_ERROR : (ulong) (1L << (share.base.key_reflength*8))*512); share.base.min_block_length= (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH && ! share.base.blobs) ? max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) : N_EXTEND_BLOCK_LENGTH; if (! (flags & HA_DONT_TOUCH_DATA)) share.base.create_time= (long) time((time_t*) 0); bzero(buff,base_pos); if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) || my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) || my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP))) goto err; for (i=0 ; i < share.base.keys ; i++) { if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF), MYF(MY_NABP))) goto err; for (j=0 ; j <= keyinfo[i].base.keysegs ; j++) { if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG), MYF(MY_NABP))) goto err; } } for (i=0 ; i < share.base.fields ; i++) if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO), MYF(MY_NABP))) goto err; /* Enlarge files */ if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0))) goto err; if (! (flags & HA_DONT_TOUCH_DATA)) { #ifdef USE_RELOC if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0))) goto err; #endif errpos=1; if (my_close(dfile,MYF(0))) goto err; } errpos=0; pthread_mutex_unlock(&THR_LOCK_isam); if (my_close(file,MYF(0))) goto err; DBUG_RETURN(0); err: pthread_mutex_unlock(&THR_LOCK_isam); save_errno=my_errno; switch (errpos) { case 2: VOID(my_close(dfile,MYF(0))); /* fall through */ case 1: VOID(my_close(file,MYF(0))); } my_errno=save_errno; /* R{tt felkod tillbaka */ DBUG_RETURN(-1); } /* nisam_create */