my_bool my_thread_init() { struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return TRUE; /* cannot proceed with unintialized library */ if (mysys_thread_var()) return FALSE; #ifdef _MSC_VER install_sigabrt_handler(); #endif if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp)))) return TRUE; mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend); tmp->stack_ends_here= (char*)&tmp + STACK_DIRECTION * (long)my_thread_stack_size; mysql_mutex_lock(&THR_LOCK_threads); tmp->id= ++thread_id; ++THR_thread_count; mysql_mutex_unlock(&THR_LOCK_threads); set_mysys_thread_var(tmp); return FALSE; }
audit_log_buffer_t *audit_log_buffer_init(size_t size, int drop_if_full, audit_log_write_func write_func, void *data) { audit_log_buffer_t *log= (audit_log_buffer_t*) calloc(sizeof(audit_log_buffer_t) + size, 1); #ifdef HAVE_PSI_INTERFACE if(PSI_server) { PSI_server->register_mutex("server_audit", mutex_key_list, array_elements(mutex_key_list)); PSI_server->register_cond("server_audit", cond_key_list, array_elements(cond_key_list)); } #endif /* HAVE_PSI_INTERFACE */ if (log != NULL) { log->buf= ((char*) log + sizeof(audit_log_buffer_t)); log->drop_if_full= drop_if_full; log->write_func= write_func; log->write_func_data= data; log->size= size; mysql_mutex_init(key_log_mutex, &log->mutex, MY_MUTEX_INIT_FAST); mysql_cond_init(key_log_flushed_cond, &log->flushed_cond, NULL); mysql_cond_init(key_log_written_cond, &log->written_cond, NULL); pthread_create(&log->flush_worker_thread, NULL, audit_log_flush_worker, log); } return log; }
static void my_thread_init_common_mutex(void) { mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW); #endif }
my_bool my_thread_init(void) { struct st_my_thread_var *tmp; my_bool error=0; if (!my_thread_global_init_done) return 1; /* cannot proceed with unintialized library */ #ifdef EXTRA_DEBUG_THREADS my_message_local(INFORMATION_LEVEL, "my_thread_init(): thread_id: 0x%lx", (ulong) pthread_self()); #endif if (_my_thread_var()) { #ifdef EXTRA_DEBUG_THREADS my_message_local(WARNING_LEVEL, "my_thread_init() called more than once in thread 0x%lx", (long) pthread_self()); #endif goto end; } #ifdef _MSC_VER install_sigabrt_handler(); #endif if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp)))) { error= 1; goto end; } set_mysys_var(tmp); tmp->pthread_self= pthread_self(); mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); tmp->stack_ends_here= (char*)&tmp + STACK_DIRECTION * (long)my_thread_stack_size; mysql_mutex_lock(&THR_LOCK_threads); tmp->id= ++thread_id; ++THR_thread_count; mysql_mutex_unlock(&THR_LOCK_threads); tmp->init= 1; #ifndef DBUG_OFF /* Generate unique name for thread */ (void) my_thread_name(); #endif end: return error; }
void thr_lock_init(THR_LOCK *lock) { DBUG_ENTER("thr_lock_init"); bzero((char*) lock,sizeof(*lock)); mysql_mutex_init(key_THR_LOCK_mutex, &lock->mutex, MY_MUTEX_INIT_FAST); lock->read.last= &lock->read.data; lock->read_wait.last= &lock->read_wait.data; lock->write_wait.last= &lock->write_wait.data; lock->write.last= &lock->write.data; mysql_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ lock->list.data=(void*) lock; thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list); mysql_mutex_unlock(&THR_LOCK_lock); DBUG_VOID_RETURN; }
MRN_LONG_TERM_SHARE *mrn_get_long_term_share(const char *table_name, uint table_name_length, int *error) { MRN_LONG_TERM_SHARE *long_term_share; char *tmp_name; MRN_DBUG_ENTER_FUNCTION(); DBUG_PRINT("info", ("mroonga: table_name=%s", table_name)); mrn::Lock lock(&mrn_long_term_share_mutex); if (!(long_term_share = (MRN_LONG_TERM_SHARE*) my_hash_search(&mrn_long_term_share, (uchar*) table_name, table_name_length))) { if (!(long_term_share = (MRN_LONG_TERM_SHARE *) mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &long_term_share, sizeof(*long_term_share), &tmp_name, table_name_length + 1, NullS)) ) { *error = HA_ERR_OUT_OF_MEM; goto error_alloc_long_term_share; } long_term_share->table_name = tmp_name; long_term_share->table_name_length = table_name_length; memcpy(long_term_share->table_name, table_name, table_name_length); if (mysql_mutex_init(mrn_long_term_share_auto_inc_mutex_key, &long_term_share->auto_inc_mutex, MY_MUTEX_INIT_FAST) != 0) { *error = HA_ERR_OUT_OF_MEM; goto error_init_auto_inc_mutex; } if (my_hash_insert(&mrn_long_term_share, (uchar*) long_term_share)) { *error = HA_ERR_OUT_OF_MEM; goto error_hash_insert; } } DBUG_RETURN(long_term_share); error_hash_insert: mysql_mutex_destroy(&long_term_share->auto_inc_mutex); error_init_auto_inc_mutex: my_free(long_term_share); error_alloc_long_term_share: DBUG_RETURN(NULL); }
my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) { char *end, *copy; char buff[FN_REFLEN]; DBUG_ENTER("init_tmpdir"); DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); mysql_mutex_init(key_TMPDIR_mutex, &tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) goto err; if (!pathlist || !pathlist[0]) { /* Get default temporary directory */ pathlist=getenv("TMPDIR"); /* Use this if possible */ #if defined(_WIN32) if (!pathlist) pathlist=getenv("TEMP"); if (!pathlist) pathlist=getenv("TMP"); #endif if (!pathlist || !pathlist[0]) pathlist=(char*) P_tmpdir; } do { size_t length; end=strcend(pathlist, DELIM); strmake(buff, pathlist, (uint) (end-pathlist)); length= cleanup_dirname(buff, buff); if (!(copy= my_strndup(key_memory_MY_TMPDIR_full_list, buff, length, MYF(MY_WME))) || insert_dynamic(&tmpdir->full_list, ©)) DBUG_RETURN(TRUE); pathlist=end+1; } while (*end); freeze_size(&tmpdir->full_list); tmpdir->list=(char **)tmpdir->full_list.buffer; tmpdir->max=tmpdir->full_list.elements-1; tmpdir->cur=0; DBUG_RETURN(FALSE); err: delete_dynamic(&tmpdir->full_list); /* Safe to free */ mysql_mutex_destroy(&tmpdir->mutex); DBUG_RETURN(TRUE); }
/** Re-initialize components initialized early with @c my_thread_global_init. Some mutexes were initialized before the instrumentation. Destroy + create them again, now that the instrumentation is in place. This is safe, since this function() is called before creating new threads, so the mutexes are not in use. */ void my_thread_global_reinit(void) { struct st_my_thread_var *tmp; DBUG_ASSERT(my_thread_global_init_done); #ifdef HAVE_PSI_INTERFACE my_init_mysys_psi_keys(); #endif mysql_mutex_destroy(&THR_LOCK_heap); mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); mysql_mutex_destroy(&THR_LOCK_net); mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); mysql_mutex_destroy(&THR_LOCK_myisam); mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); mysql_mutex_destroy(&THR_LOCK_malloc); mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); mysql_mutex_destroy(&THR_LOCK_open); mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); mysql_mutex_destroy(&THR_LOCK_charset); mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); mysql_mutex_destroy(&THR_LOCK_threads); mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); mysql_cond_destroy(&THR_COND_threads); mysql_cond_init(key_THR_COND_threads, &THR_COND_threads); tmp= mysys_thread_var(); DBUG_ASSERT(tmp); mysql_mutex_destroy(&tmp->mutex); mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); mysql_cond_destroy(&tmp->suspend); mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend); }
LOGGER_HANDLE *logger_open(const char *path, unsigned long long size_limit, unsigned int rotations) { LOGGER_HANDLE new_log, *l_perm; /* I don't think we ever need more rotations, but if it's so, the rotation procedure should be adapted to it. */ if (rotations > 999) return 0; new_log.rotations= rotations; new_log.size_limit= size_limit; new_log.path_len= strlen(fn_format(new_log.path, path, mysql_data_home, "", MY_UNPACK_FILENAME)); if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN) { errno= ENAMETOOLONG; /* File path too long */ return 0; } if ((new_log.file= my_open(new_log.path, LOG_FLAGS, MYF(0))) < 0) { errno= my_errno; /* Check errno for the cause */ return 0; } if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) { my_close(new_log.file, MYF(0)); new_log.file= -1; return 0; /* End of memory */ } *l_perm= new_log; mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST); return l_perm; }
int main(int argc __attribute__((unused)), char **argv) { MY_INIT("thd_template"); if (argv[1] && *argv[1]) DBUG_SET_INITIAL(argv[1]); mysql_mutex_init(0, &mutex, 0); mysql_cond_init(0, &cond, 0); pthread_attr_init(&thr_attr); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); #ifdef MY_ATOMIC_MODE_RWLOCKS #if defined(HPUX11) || defined(__POWERPC__) /* showed to be very slow (scheduler-related) */ #define CYCLES 300 #else #define CYCLES 3000 #endif #else #define CYCLES 3000 #endif #define THREADS 30 diag("N CPUs: %d, atomic ops: %s", my_getncpus(), MY_ATOMIC_MODE); do_tests(); /* workaround until we know why it crashes randomly on some machine (BUG#22320). */ sleep(2); mysql_mutex_destroy(&mutex); mysql_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); my_end(0); return exit_status(); }
static void my_thread_init_thr_mutex(struct st_my_thread_var *var) { mysql_mutex_init(key_my_thread_var_mutex, &var->mutex, MY_MUTEX_INIT_FAST); mysql_cond_init(key_my_thread_var_suspend, &var->suspend, NULL); }
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,errpos=0; uint files= 0, i, dir_length, length, UNINIT_VAR(key_parts), min_keys= 0; ulonglong file_offset=0; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO *m_info=0; File fd; IO_CACHE file; MI_INFO *isam=0; uint found_merge_insert_method= 0; size_t name_buff_length; my_bool bad_children= FALSE; DBUG_ENTER("myrg_open"); memset(&file, 0, sizeof(file)); if ((fd= mysql_file_open(rg_key_file_MRG, fn_format(name_buff, name, "", MYRG_NAME_EXT, MY_UNPACK_FILENAME|MY_APPEND_EXT), O_RDONLY | O_SHARE, MYF(0))) < 0) goto err; errpos=1; if (init_io_cache(&file, fd, 4*IO_SIZE, READ_CACHE, 0, 0, MYF(MY_WME | MY_NABP))) goto err; errpos=2; dir_length=dirname_part(name_buff, name, &name_buff_length); while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) { if ((end=buff+length)[-1] == '\n') end[-1]='\0'; if (buff[0] && buff[0] != '#') files++; } my_b_seek(&file, 0); while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) { if ((end=buff+length)[-1] == '\n') *--end='\0'; if (!buff[0]) continue; /* Skip empty lines */ if (buff[0] == '#') { if (!strncmp(buff+1,"INSERT_METHOD=",14)) { /* Lookup insert method */ int tmp= find_type(buff + 15, &merge_insert_method, FIND_TYPE_BASIC); found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); } continue; /* Skip comments */ } if (!has_path(buff)) { (void) strmake(name_buff+dir_length,buff, sizeof(name_buff)-1-dir_length); (void) cleanup_dirname(buff,name_buff); } else fn_format(buff, buff, "", "", 0); if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) { if (handle_locking & HA_OPEN_FOR_REPAIR) { myrg_print_wrong_table(buff); bad_children= TRUE; continue; } goto bad_children; } if (!m_info) /* First file */ { key_parts=isam->s->base.key_parts; if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + files*sizeof(MYRG_TABLE) + key_parts*sizeof(long), MYF(MY_WME|MY_ZEROFILL)))) goto err; DBUG_ASSERT(files); m_info->open_tables=(MYRG_TABLE *) (m_info+1); m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); m_info->tables= files; files= 0; m_info->reclength=isam->s->base.reclength; min_keys= isam->s->base.keys; errpos=3; } m_info->open_tables[files].table= isam; m_info->open_tables[files].file_offset=(my_off_t) file_offset; file_offset+=isam->state->data_file_length; files++; if (m_info->reclength != isam->s->base.reclength) { if (handle_locking & HA_OPEN_FOR_REPAIR) { myrg_print_wrong_table(buff); bad_children= TRUE; continue; } goto bad_children; } m_info->options|= isam->s->options; m_info->records+= isam->state->records; m_info->del+= isam->state->del; m_info->data_file_length+= isam->state->data_file_length; if (min_keys > isam->s->base.keys) min_keys= isam->s->base.keys; for (i=0; i < key_parts; i++) m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] / m_info->tables); } if (bad_children) goto bad_children; if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), MYF(MY_WME | MY_ZEROFILL)))) goto err; /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); m_info->merge_insert_method= found_merge_insert_method; if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) { my_errno=HA_ERR_RECORD_FILE_FULL; goto err; } m_info->keys= min_keys; memset(&m_info->by_key, 0, sizeof(m_info->by_key)); /* this works ok if the table list is empty */ m_info->end_table=m_info->open_tables+files; m_info->last_used_table=m_info->open_tables; m_info->children_attached= TRUE; (void) mysql_file_close(fd, MYF(0)); end_io_cache(&file); mysql_mutex_init(rg_key_mutex_MYRG_INFO_mutex, &m_info->mutex, MY_MUTEX_INIT_FAST); m_info->open_list.data=(void*) m_info; mysql_mutex_lock(&THR_LOCK_open); myrg_open_list=list_add(myrg_open_list,&m_info->open_list); mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(m_info); bad_children: my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; err: save_errno=my_errno; switch (errpos) { case 3: while (files) (void) mi_close(m_info->open_tables[--files].table); my_free(m_info); /* Fall through */ case 2: end_io_cache(&file); /* Fall through */ case 1: (void) mysql_file_close(fd, MYF(0)); } my_errno=save_errno; DBUG_RETURN (NULL); }
my_bool my_thread_global_init(void) { int pth_ret; if (my_thread_global_init_done) return 0; my_thread_global_init_done= 1; #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP /* Set mutex type to "fast" a.k.a "adaptive" In this case the thread may steal the mutex from some other thread that is waiting for the same mutex. This will save us some context switches but may cause a thread to 'starve forever' while waiting for the mutex (not likely if the code within the mutex is short). */ pthread_mutexattr_init(&my_fast_mutexattr); pthread_mutexattr_settype(&my_fast_mutexattr, PTHREAD_MUTEX_ADAPTIVE_NP); #endif #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* Set mutex type to "errorcheck" */ pthread_mutexattr_init(&my_errorcheck_mutexattr); pthread_mutexattr_settype(&my_errorcheck_mutexattr, PTHREAD_MUTEX_ERRORCHECK); #endif DBUG_ASSERT(! THR_KEY_mysys_initialized); if ((pth_ret= my_create_thread_local_key(&THR_KEY_mysys, NULL)) != 0) { /* purecov: begin inspected */ my_message_local(ERROR_LEVEL, "Can't initialize threads: error %d", pth_ret); /* purecov: end */ return 1; } THR_KEY_mysys_initialized= TRUE; mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); if (my_thread_init()) return 1; mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); mysql_cond_init(key_THR_COND_threads, &THR_COND_threads); #ifdef _MSC_VER install_sigabrt_handler(); #endif return 0; }
static void my_thread_init_internal_mutex(void) { mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); }
int heap_create(const char *name, HP_CREATE_INFO *create_info, HP_SHARE **res, my_bool *created_new_share) { uint i, j, key_segs, max_length, length; HP_SHARE *share= 0; HA_KEYSEG *keyseg; HP_KEYDEF *keydef= create_info->keydef; uint reclength= create_info->reclength; uint keys= create_info->keys; ulong min_records= create_info->min_records; ulong max_records= create_info->max_records; DBUG_ENTER("heap_create"); if (!create_info->internal_table) { mysql_mutex_lock(&THR_LOCK_heap); share= hp_find_named_heap(name); if (share && share->open_count == 0) { hp_free(share); share= 0; } } *created_new_share= (share == NULL); if (!share) { HP_KEYDEF *keyinfo; DBUG_PRINT("info",("Initializing new table")); /* We have to store sometimes uchar* del_link in records, so the record length should be at least sizeof(uchar*) */ set_if_bigger(reclength, sizeof (uchar*)); for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++) { memset(&keyinfo->block, 0, sizeof(keyinfo->block)); memset(&keyinfo->rb_tree, 0, sizeof(keyinfo->rb_tree)); for (j= length= 0; j < keyinfo->keysegs; j++) { length+= keyinfo->seg[j].length; if (keyinfo->seg[j].null_bit) { length++; if (!(keyinfo->flag & HA_NULL_ARE_EQUAL)) keyinfo->flag|= HA_NULL_PART_KEY; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) keyinfo->rb_tree.size_of_element++; } switch (keyinfo->seg[j].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: keyinfo->seg[j].flag|= HA_SWAP_KEY; break; case HA_KEYTYPE_VARBINARY1: /* Case-insensitiveness is handled in coll->hash_sort */ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1; /* fall_through */ case HA_KEYTYPE_VARTEXT1: keyinfo->flag|= HA_VAR_LENGTH_KEY; length+= 2; /* Save number of bytes used to store length */ keyinfo->seg[j].bit_start= 1; break; case HA_KEYTYPE_VARBINARY2: /* Case-insensitiveness is handled in coll->hash_sort */ /* fall_through */ case HA_KEYTYPE_VARTEXT2: keyinfo->flag|= HA_VAR_LENGTH_KEY; length+= 2; /* Save number of bytes used to store length */ keyinfo->seg[j].bit_start= 2; /* Make future comparison simpler by only having to check for one type */ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1; break; default: break; } } keyinfo->length= length; length+= keyinfo->rb_tree.size_of_element + ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(uchar*) : 0); if (length > max_length) max_length= length; key_segs+= keyinfo->keysegs; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { key_segs++; /* additional HA_KEYTYPE_END segment */ if (keyinfo->flag & HA_VAR_LENGTH_KEY) keyinfo->get_key_length= hp_rb_var_key_length; else if (keyinfo->flag & HA_NULL_PART_KEY) keyinfo->get_key_length= hp_rb_null_key_length; else keyinfo->get_key_length= hp_rb_key_length; } } if (!(share= (HP_SHARE*) my_malloc(hp_key_memory_HP_SHARE, (uint) sizeof(HP_SHARE)+ keys*sizeof(HP_KEYDEF)+ key_segs*sizeof(HA_KEYSEG), MYF(MY_ZEROFILL)))) goto err; share->keydef= (HP_KEYDEF*) (share + 1); share->key_stat_version= 1; keyseg= (HA_KEYSEG*) (share->keydef + keys); init_block(&share->block, reclength + 1, min_records, max_records); /* Fix keys */ memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys)); for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++) { keyinfo->seg= keyseg; memcpy(keyseg, keydef[i].seg, (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs)); keyseg+= keydef[i].keysegs; if (keydef[i].algorithm == HA_KEY_ALG_BTREE) { /* additional HA_KEYTYPE_END keyseg */ keyseg->type= HA_KEYTYPE_END; keyseg->length= sizeof(uchar*); keyseg->flag= 0; keyseg->null_bit= 0; keyseg++; init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*), (qsort_cmp2)keys_compare, 1, NULL, NULL); keyinfo->delete_key= hp_rb_delete_key; keyinfo->write_key= hp_rb_write_key; } else { init_block(&keyinfo->block, sizeof(HASH_INFO), min_records, max_records); keyinfo->delete_key= hp_delete_key; keyinfo->write_key= hp_write_key; keyinfo->hash_buckets= 0; } if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment) share->auto_key= i + 1; } share->min_records= min_records; share->max_records= max_records; share->max_table_size= create_info->max_table_size; share->data_length= share->index_length= 0; share->reclength= reclength; share->blength= 1; share->keys= keys; share->max_key_length= max_length; share->changed= 0; share->auto_key= create_info->auto_key; share->auto_key_type= create_info->auto_key_type; share->auto_increment= create_info->auto_increment; share->create_time= (long) time((time_t*) 0); /* Must be allocated separately for rename to work */ if (!(share->name= my_strdup(hp_key_memory_HP_SHARE, name, MYF(0)))) { my_free(share); goto err; } thr_lock_init(&share->lock); mysql_mutex_init(hp_key_mutex_HP_SHARE_intern_lock, &share->intern_lock, MY_MUTEX_INIT_FAST); if (!create_info->internal_table) { share->open_list.data= (void*) share; heap_share_list= list_add(heap_share_list,&share->open_list); } else share->delete_on_close= 1; } if (!create_info->internal_table) { if (create_info->pin_share) ++share->open_count; mysql_mutex_unlock(&THR_LOCK_heap); } *res= share; DBUG_RETURN(0); err: if (!create_info->internal_table) mysql_mutex_unlock(&THR_LOCK_heap); DBUG_RETURN(1); } /* heap_create */
MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) { MRN_SHARE *share; char *tmp_name, **index_table, **key_tokenizer, **col_flags, **col_type; uint length, *wrap_key_nr, *index_table_length; uint *key_tokenizer_length, *col_flags_length, *col_type_length, i, j; KEY *wrap_key_info; TABLE_SHARE *wrap_table_share; MRN_DBUG_ENTER_FUNCTION(); length = (uint) strlen(table_name); mrn::Lock lock(&mrn_open_tables_mutex); if (!(share = (MRN_SHARE*) my_hash_search(&mrn_open_tables, (uchar*) table_name, length))) { if (!(share = (MRN_SHARE *) mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &share, sizeof(*share), &tmp_name, length + 1, &index_table, sizeof(char *) * table->s->keys, &index_table_length, sizeof(uint) * table->s->keys, &key_tokenizer, sizeof(char *) * table->s->keys, &key_tokenizer_length, sizeof(uint) * table->s->keys, &col_flags, sizeof(char *) * table->s->fields, &col_flags_length, sizeof(uint) * table->s->fields, &col_type, sizeof(char *) * table->s->fields, &col_type_length, sizeof(uint) * table->s->fields, &wrap_key_nr, sizeof(*wrap_key_nr) * table->s->keys, &wrap_key_info, sizeof(*wrap_key_info) * table->s->keys, &wrap_table_share, sizeof(*wrap_table_share), NullS)) ) { *error = HA_ERR_OUT_OF_MEM; goto error_alloc_share; } share->use_count = 0; share->table_name_length = length; share->table_name = tmp_name; share->index_table = index_table; share->index_table_length = index_table_length; share->key_tokenizer = key_tokenizer; share->key_tokenizer_length = key_tokenizer_length; share->col_flags = col_flags; share->col_flags_length = col_flags_length; share->col_type = col_type; share->col_type_length = col_type_length; mrn_my_stpmov(share->table_name, table_name); share->table_share = table->s; if ( (*error = mrn_parse_table_param(share, table)) || (*error = mrn_parse_column_param(share, table)) || (*error = mrn_parse_index_param(share, table)) ) goto error_parse_table_param; if (share->wrapper_mode) { j = 0; for (i = 0; i < table->s->keys; i++) { if (table->s->key_info[i].algorithm != HA_KEY_ALG_FULLTEXT && !mrn_is_geo_key(&table->s->key_info[i])) { wrap_key_nr[i] = j; memcpy(&wrap_key_info[j], &table->s->key_info[i], sizeof(*wrap_key_info)); j++; } else { wrap_key_nr[i] = MAX_KEY; } } share->wrap_keys = j; share->base_keys = table->s->keys; share->base_key_info = table->s->key_info; share->base_primary_key = table->s->primary_key; if (i) { share->wrap_key_nr = wrap_key_nr; share->wrap_key_info = wrap_key_info; if (table->s->primary_key == MAX_KEY) share->wrap_primary_key = MAX_KEY; else share->wrap_primary_key = wrap_key_nr[table->s->primary_key]; } else { share->wrap_key_nr = NULL; share->wrap_key_info = NULL; share->wrap_primary_key = MAX_KEY; } memcpy(wrap_table_share, table->s, sizeof(*wrap_table_share)); mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root)); wrap_table_share->keys = share->wrap_keys; wrap_table_share->key_info = share->wrap_key_info; wrap_table_share->primary_key = share->wrap_primary_key; wrap_table_share->keys_in_use.init(share->wrap_keys); wrap_table_share->keys_for_keyread.init(share->wrap_keys); #ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE # ifdef WIN32 mysql_mutex_init(*mrn_table_share_lock_share, &(wrap_table_share->LOCK_share), MY_MUTEX_INIT_SLOW); # else mysql_mutex_init(key_TABLE_SHARE_LOCK_share, &(wrap_table_share->LOCK_share), MY_MUTEX_INIT_SLOW); # endif #endif #ifdef WIN32 mysql_mutex_init(*mrn_table_share_lock_ha_data, &(wrap_table_share->LOCK_ha_data), MY_MUTEX_INIT_FAST); #else mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, &(wrap_table_share->LOCK_ha_data), MY_MUTEX_INIT_FAST); #endif share->wrap_table_share = wrap_table_share; } if (mysql_mutex_init(mrn_share_mutex_key, &share->record_mutex, MY_MUTEX_INIT_FAST) != 0) { *error = HA_ERR_OUT_OF_MEM; goto error_init_mutex; } thr_lock_init(&share->lock); if (!(share->long_term_share = mrn_get_long_term_share(table_name, length, error))) { goto error_get_long_term_share; } if (my_hash_insert(&mrn_open_tables, (uchar*) share)) { *error = HA_ERR_OUT_OF_MEM; goto error_hash_insert; } } share->use_count++; DBUG_RETURN(share); error_hash_insert: error_get_long_term_share: mysql_mutex_destroy(&share->record_mutex); error_init_mutex: error_parse_table_param: mrn_free_share_alloc(share); my_free(share); error_alloc_share: DBUG_RETURN(NULL); }
MYRG_INFO *myrg_parent_open(const char *parent_name, int (*callback)(void*, const char*), void *callback_param) { MYRG_INFO *UNINIT_VAR(m_info); int rc; int errpos; int save_errno; int insert_method; uint length; uint child_count; File fd; IO_CACHE file_cache; char parent_name_buff[FN_REFLEN * 2]; char child_name_buff[FN_REFLEN]; DBUG_ENTER("myrg_parent_open"); rc= 1; errpos= 0; memset(&file_cache, 0, sizeof(file_cache)); /* Open MERGE meta file. */ if ((fd= mysql_file_open(rg_key_file_MRG, fn_format(parent_name_buff, parent_name, "", MYRG_NAME_EXT, MY_UNPACK_FILENAME|MY_APPEND_EXT), O_RDONLY | O_SHARE, MYF(0))) < 0) goto err; /* purecov: inspected */ errpos= 1; if (init_io_cache(&file_cache, fd, 4 * IO_SIZE, READ_CACHE, 0, 0, MYF(MY_WME | MY_NABP))) goto err; /* purecov: inspected */ errpos= 2; /* Count children. Determine insert method. */ child_count= 0; insert_method= 0; while ((length= my_b_gets(&file_cache, child_name_buff, FN_REFLEN - 1))) { /* Remove line terminator. */ if (child_name_buff[length - 1] == '\n') child_name_buff[--length]= '\0'; /* Skip empty lines. */ if (!child_name_buff[0]) continue; /* purecov: inspected */ /* Skip comments, but evaluate insert method. */ if (child_name_buff[0] == '#') { if (!strncmp(child_name_buff + 1, "INSERT_METHOD=", 14)) { /* Compare buffer with global methods list: merge_insert_method. */ insert_method= find_type(child_name_buff + 15, &merge_insert_method, FIND_TYPE_BASIC); } continue; } /* Count the child. */ child_count++; } /* Allocate MERGE parent table structure. */ if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + child_count * sizeof(MYRG_TABLE), MYF(MY_WME | MY_ZEROFILL)))) goto err; /* purecov: inspected */ errpos= 3; m_info->open_tables= (MYRG_TABLE*) (m_info + 1); m_info->tables= child_count; m_info->merge_insert_method= insert_method > 0 ? insert_method : 0; /* This works even if the table list is empty. */ m_info->end_table= m_info->open_tables + child_count; if (!child_count) { /* Do not attach/detach an empty child list. */ m_info->children_attached= TRUE; } /* Call callback for each child. */ my_b_seek(&file_cache, 0); while ((length= my_b_gets(&file_cache, child_name_buff, FN_REFLEN - 1))) { /* Remove line terminator. */ if (child_name_buff[length - 1] == '\n') child_name_buff[--length]= '\0'; /* Skip empty lines and comments. */ if (!child_name_buff[0] || (child_name_buff[0] == '#')) continue; DBUG_PRINT("info", ("child: '%s'", child_name_buff)); /* Callback registers child with handler table. */ if ((rc= (*callback)(callback_param, child_name_buff))) goto err; /* purecov: inspected */ } end_io_cache(&file_cache); (void) mysql_file_close(fd, MYF(0)); mysql_mutex_init(rg_key_mutex_MYRG_INFO_mutex, &m_info->mutex, MY_MUTEX_INIT_FAST); m_info->open_list.data= (void*) m_info; mysql_mutex_lock(&THR_LOCK_open); myrg_open_list= list_add(myrg_open_list, &m_info->open_list); mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(m_info); /* purecov: begin inspected */ err: save_errno= my_errno; switch (errpos) { case 3: my_free(m_info); /* Fall through */ case 2: end_io_cache(&file_cache); /* Fall through */ case 1: (void) mysql_file_close(fd, MYF(0)); } my_errno= save_errno; DBUG_RETURN (NULL); /* purecov: end */ }
int heap_create(const char *name, HP_CREATE_INFO *create_info, HP_SHARE **res, my_bool *created_new_share) { uint i, j, key_segs, max_length, length; HP_SHARE *share= 0; HA_KEYSEG *keyseg; HP_KEYDEF *keydef= create_info->keydef; uint reclength= create_info->reclength; uint keys= create_info->keys; ulong min_records= create_info->min_records; ulong max_records= create_info->max_records; ulong max_rows_for_stated_memory; DBUG_ENTER("heap_create"); if (!create_info->internal_table) { mysql_mutex_lock(&THR_LOCK_heap); share= hp_find_named_heap(name); if (share && share->open_count == 0) { hp_free(share); share= 0; } } *created_new_share= (share == NULL); if (!share) { uint chunk_dataspace_length, chunk_length, is_variable_size; uint fixed_data_length, fixed_column_count; HP_KEYDEF *keyinfo; DBUG_PRINT("info",("Initializing new table")); if (create_info->max_chunk_size) { uint configured_chunk_size= create_info->max_chunk_size; /* User requested variable-size records, let's see if they're possible */ if (configured_chunk_size < create_info->fixed_data_size) { /* The resulting chunk_size cannot be smaller than fixed data part at the start of the first chunk which allows faster copying with a single memcpy(). */ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "key_block_size"); goto err; } if (reclength > configured_chunk_size + VARIABLE_REC_OVERHEAD || create_info->blobs > 0) { /* Allow variable size only if we're saving some space, i.e. if a fixed-size record would take more space than variable-size one plus the variable-size overhead. There has to be at least one field after indexed fields. Note that NULL bits are already included in key_part_size. */ is_variable_size= 1; chunk_dataspace_length= configured_chunk_size; } else { /* max_chunk_size is near the full reclength, let's use fixed size */ is_variable_size= 0; chunk_dataspace_length= reclength; } } else if ((create_info->is_dynamic && reclength > 256 + VARIABLE_REC_OVERHEAD) || create_info->blobs > 0) { /* User asked for dynamic records - use 256 as the chunk size, if that will may save some memory. Otherwise revert to fixed size format. */ if ((create_info->fixed_data_size + VARIABLE_REC_OVERHEAD) > 256) chunk_dataspace_length= create_info->fixed_data_size; else chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD; is_variable_size= 1; } else { /* If max_chunk_size is not specified, put the whole record in one chunk */ is_variable_size= 0; chunk_dataspace_length= reclength; } if (is_variable_size) { /* Check whether we have any variable size records past key data */ uint has_variable_fields= 0; fixed_data_length= create_info->fixed_data_size; fixed_column_count= create_info->fixed_key_fieldnr; for (i= create_info->fixed_key_fieldnr; i < create_info->columns; i++) { HP_COLUMNDEF *column= create_info->columndef + i; if ((column->type == MYSQL_TYPE_VARCHAR && (column->length - column->length_bytes) >= 32) || column->type == MYSQL_TYPE_BLOB) { /* The field has to be either blob or >= 5.0.3 true VARCHAR and have substantial length. TODO: do we want to calculate minimum length? */ has_variable_fields= 1; break; } if (has_variable_fields) { break; } if ((column->offset + column->length) <= chunk_dataspace_length) { /* Still no variable-size columns, add one fixed-length */ fixed_column_count= i + 1; fixed_data_length= column->offset + column->length; } } if (!has_variable_fields && create_info->blobs == 0) { /* There is no need to use variable-size records without variable-size columns. Reset sizes if it's not variable size anymore. */ is_variable_size= 0; chunk_dataspace_length= reclength; fixed_data_length= reclength; fixed_column_count= create_info->columns; } } else { fixed_data_length= reclength; fixed_column_count= create_info->columns; } /* We store uchar* del_link inside the data area of deleted records, so the data length should be at least sizeof(uchar*) */ set_if_bigger(chunk_dataspace_length, sizeof (uchar **)); if (is_variable_size) { chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD; } else { chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD; } /* Align chunk length to the next pointer */ chunk_length= (uint) (chunk_length + sizeof(uchar **) - 1) & ~(sizeof(uchar **) - 1); for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++) { bzero((char*) &keyinfo->block,sizeof(keyinfo->block)); bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree)); for (j= length= 0; j < keyinfo->keysegs; j++) { length+= keyinfo->seg[j].length; if (keyinfo->seg[j].null_bit) { length++; if (!(keyinfo->flag & HA_NULL_ARE_EQUAL)) keyinfo->flag|= HA_NULL_PART_KEY; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) keyinfo->rb_tree.size_of_element++; } switch (keyinfo->seg[j].type) { case HA_KEYTYPE_VARBINARY1: case HA_KEYTYPE_VARTEXT1: case HA_KEYTYPE_VARBINARY2: case HA_KEYTYPE_VARTEXT2: length+= 2; break; default: break; } } keyinfo->length= length; length+= keyinfo->rb_tree.size_of_element + ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(uchar*) : 0); if (length > max_length) max_length= length; key_segs+= keyinfo->keysegs; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { key_segs++; /* additional HA_KEYTYPE_END segment */ if (keyinfo->flag & HA_VAR_LENGTH_KEY) keyinfo->get_key_length= hp_rb_var_key_length; else if (keyinfo->flag & HA_NULL_PART_KEY) keyinfo->get_key_length= hp_rb_null_key_length; else keyinfo->get_key_length= hp_rb_key_length; } } if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+ keys*sizeof(HP_KEYDEF)+ (create_info->columns * sizeof(HP_COLUMNDEF)) + key_segs*sizeof(HA_KEYSEG), MYF(MY_ZEROFILL)))) goto err; /* Max_records is used for estimating block sizes and for enforcement. Calculate the very maximum number of rows (if everything was one chunk) and then take either that value or configured max_records (pick smallest one). */ max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size / (create_info->keys_memory_size + chunk_length)); max_records = ((max_records && max_records < max_rows_for_stated_memory) ? max_records : max_rows_for_stated_memory); share->column_defs= (HP_COLUMNDEF*) (share + 1); memcpy(share->column_defs, create_info->columndef, (size_t) (sizeof(create_info->columndef[0]) * create_info->columns)); share->keydef= (HP_KEYDEF*) (share->column_defs + create_info->columns); share->key_stat_version= 1; keyseg= (HA_KEYSEG*) (share->keydef + keys); init_block(&share->recordspace.block, chunk_length, min_records, max_records); /* Fix keys */ memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys)); for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++) { keyinfo->seg= keyseg; memcpy(keyseg, keydef[i].seg, (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs)); keyseg+= keydef[i].keysegs; if (keydef[i].algorithm == HA_KEY_ALG_BTREE) { /* additional HA_KEYTYPE_END keyseg */ keyseg->type= HA_KEYTYPE_END; keyseg->length= sizeof(uchar*); keyseg->flag= 0; keyseg->null_bit= 0; keyseg++; init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*), (qsort_cmp2)keys_compare, 1, NULL, NULL); keyinfo->delete_key= hp_rb_delete_key; keyinfo->write_key= hp_rb_write_key; } else { init_block(&keyinfo->block, sizeof(HASH_INFO), min_records, max_records); keyinfo->delete_key= hp_delete_key; keyinfo->write_key= hp_write_key; keyinfo->hash_buckets= 0; } if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment) share->auto_key= i + 1; } share->min_records= min_records; share->max_records= max_records; share->max_table_size= create_info->max_table_size; share->index_length= 0; share->blength= 1; share->keys= keys; share->max_key_length= max_length; share->column_count= create_info->columns; share->changed= 0; share->auto_key= create_info->auto_key; share->auto_key_type= create_info->auto_key_type; share->auto_increment= create_info->auto_increment; share->create_time= (long) time((time_t*) 0); share->fixed_data_length= fixed_data_length; share->fixed_column_count= fixed_column_count; share->blobs= create_info->blobs; share->recordspace.chunk_length= chunk_length; share->recordspace.chunk_dataspace_length= chunk_dataspace_length; share->recordspace.is_variable_size= is_variable_size; share->recordspace.total_data_length= 0; if (is_variable_size) { share->recordspace.offset_link= chunk_dataspace_length; share->recordspace.offset_status= share->recordspace.offset_link + sizeof(uchar **); } else { /* Make it likely to fail if anyone uses this offset */ share->recordspace.offset_link= 1 << 22; share->recordspace.offset_status= chunk_dataspace_length; } /* Must be allocated separately for rename to work */ if (!(share->name= my_strdup(name,MYF(0)))) { my_free(share); goto err; } thr_lock_init(&share->lock); mysql_mutex_init(hp_key_mutex_HP_SHARE_intern_lock, &share->intern_lock, MY_MUTEX_INIT_FAST); if (!create_info->internal_table) { share->open_list.data= (void*) share; heap_share_list= list_add(heap_share_list,&share->open_list); } else share->delete_on_close= 1; } if (!create_info->internal_table) { if (create_info->pin_share) ++share->open_count; mysql_mutex_unlock(&THR_LOCK_heap); } *res= share; DBUG_RETURN(0); err: if (!create_info->internal_table) mysql_mutex_unlock(&THR_LOCK_heap); DBUG_RETURN(1); } /* heap_create */
void do_tests() { DBUG_ENTER("do_tests"); skip_all(": this module is not used in MySQL"); plan(12); compile_time_assert(THREADS >= 4); DBUG_PRINT("wt", ("================= initialization ===================")); bad= my_atomic_initialize(); ok(!bad, "my_atomic_initialize() returned %d", bad); mysql_cond_init(0, &thread_sync, 0); mysql_mutex_init(0, &lock, 0); wt_init(); for (cnt=0; cnt < THREADS; cnt++) mysql_mutex_init(0, & thds[cnt].lock, 0); { WT_RESOURCE_ID resid[4]; for (i=0; i < array_elements(resid); i++) { wt_thd_lazy_init(& thds[i].thd, & wt_deadlock_search_depth_short, & wt_timeout_short, & wt_deadlock_search_depth_long, & wt_timeout_long); resid[i].value= i+1; resid[i].type= &restype; } DBUG_PRINT("wt", ("================= manual test ===================")); #define ok_wait(X,Y, R) \ ok(wt_thd_will_wait_for(& thds[X].thd, & thds[Y].thd, &resid[R]) == 0, \ "thd[" #X "] will wait for thd[" #Y "]") #define ok_deadlock(X,Y,R) \ ok(wt_thd_will_wait_for(& thds[X].thd, & thds[Y].thd, &resid[R]) == WT_DEADLOCK, \ "thd[" #X "] will wait for thd[" #Y "] - deadlock") ok_wait(0,1,0); ok_wait(0,2,0); ok_wait(0,3,0); mysql_mutex_lock(&lock); bad= wt_thd_cond_timedwait(& thds[0].thd, &lock); mysql_mutex_unlock(&lock); ok(bad == WT_TIMEOUT, "timeout test returned %d", bad); ok_wait(0,1,0); ok_wait(1,2,1); ok_deadlock(2,0,2); mysql_mutex_lock(&lock); ok(wt_thd_cond_timedwait(& thds[0].thd, &lock) == WT_TIMEOUT, "as always"); ok(wt_thd_cond_timedwait(& thds[1].thd, &lock) == WT_TIMEOUT, "as always"); wt_thd_release_all(& thds[0].thd); wt_thd_release_all(& thds[1].thd); wt_thd_release_all(& thds[2].thd); wt_thd_release_all(& thds[3].thd); for (i=0; i < array_elements(resid); i++) { wt_thd_release_all(& thds[i].thd); wt_thd_destroy(& thds[i].thd); } mysql_mutex_unlock(&lock); } wt_deadlock_search_depth_short=6; wt_timeout_short=1000; wt_timeout_long= 100; wt_deadlock_search_depth_long=16; DBUG_PRINT("wt", ("================= stress test ===================")); diag("timeout_short=%lu us, deadlock_search_depth_short=%lu", wt_timeout_short, wt_deadlock_search_depth_short); diag("timeout_long=%lu us, deadlock_search_depth_long=%lu", wt_timeout_long, wt_deadlock_search_depth_long); #define test_kill_strategy(X) \ diag("kill strategy: " #X); \ DBUG_EXECUTE("reset_file", \ { rewind(DBUG_FILE); my_chsize(fileno(DBUG_FILE), 0, 0, MYF(0)); }); \ DBUG_PRINT("info", ("kill strategy: " #X)); \ kill_strategy=X; \ do_one_test(); test_kill_strategy(LATEST); test_kill_strategy(RANDOM); /* these two take looong time on sol10-amd64-a the server doesn't use this code now, so we disable these tests test_kill_strategy(YOUNGEST); test_kill_strategy(LOCKS); */ DBUG_PRINT("wt", ("================= cleanup ===================")); for (cnt=0; cnt < THREADS; cnt++) mysql_mutex_destroy(& thds[cnt].lock); wt_end(); mysql_mutex_destroy(&lock); mysql_cond_destroy(&thread_sync); DBUG_VOID_RETURN; }