summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/heap.h17
-rw-r--r--sql/lock.cc3
-rw-r--r--sql/repl_failsafe.cc1
-rw-r--r--sql/sql_base.cc104
-rw-r--r--sql/sql_base.h1
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h10
-rw-r--r--sql/sql_plugin.cc9
-rw-r--r--sql/sql_udf.cc2
-rw-r--r--sql/table.h1
-rw-r--r--sql/tztime.cc5
-rwxr-xr-xstorage/heap/CMakeLists.txt6
-rw-r--r--storage/heap/ha_heap.cc123
-rw-r--r--storage/heap/hp_create.c20
-rw-r--r--storage/heap/hp_open.c21
-rw-r--r--storage/heap/hp_test1.c11
-rw-r--r--storage/heap/hp_test2.c17
17 files changed, 207 insertions, 146 deletions
diff --git a/include/heap.h b/include/heap.h
index 27aefb5beda..a585371e18f 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -184,12 +184,22 @@ typedef struct st_heap_info
typedef struct st_heap_create_info
{
+ HP_KEYDEF *keydef;
+ ulong max_records;
+ ulong min_records;
uint auto_key; /* keynr [1 - maxkey] for auto key */
uint auto_key_type;
+ uint keys;
+ uint reclength;
ulonglong max_table_size;
ulonglong auto_increment;
my_bool with_auto_increment;
my_bool internal_table;
+ /*
+ TRUE if heap_create should 'pin' the created share by setting
+ open_count to 1. Is only looked at if not internal_table.
+ */
+ my_bool pin_share;
} HP_CREATE_INFO;
/* Prototypes for heap-functions */
@@ -197,6 +207,7 @@ typedef struct st_heap_create_info
extern HP_INFO *heap_open(const char *name, int mode);
extern HP_INFO *heap_open_from_share(HP_SHARE *share, int mode);
extern HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode);
+extern void heap_release_share(HP_SHARE *share, my_bool internal_table);
extern int heap_close(HP_INFO *info);
extern int heap_write(HP_INFO *info,const uchar *buff);
extern int heap_update(HP_INFO *info,const uchar *old,const uchar *newdata);
@@ -205,9 +216,9 @@ extern int heap_scan_init(HP_INFO *info);
extern int heap_scan(register HP_INFO *info, uchar *record);
extern int heap_delete(HP_INFO *info,const uchar *buff);
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
-extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
- uint reclength, ulong max_records, ulong min_records,
- HP_CREATE_INFO *create_info, HP_SHARE **share);
+extern int heap_create(const char *name,
+ HP_CREATE_INFO *create_info, HP_SHARE **share,
+ my_bool *created_new_share);
extern int heap_delete_table(const char *name);
extern void heap_drop_table(HP_INFO *info);
extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
diff --git a/sql/lock.cc b/sql/lock.cc
index d35f2c359fb..52d97a2422b 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1298,7 +1298,8 @@ wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
"Waiting for release of readlock");
while (must_wait && ! thd->killed &&
- (!abort_on_refresh || thd->version == refresh_version))
+ (!abort_on_refresh || !thd->open_tables ||
+ thd->open_tables->s->version == refresh_version))
{
DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index cddf798aac0..81366d55fc6 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -102,7 +102,6 @@ static int init_failsafe_rpl_thread(THD* thd)
thd->mem_root->free= thd->mem_root->used= 0;
thd_proc_info(thd, "Thread initialized");
- thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c227fd12f5b..78862985e97 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1589,10 +1589,18 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
*table_ptr=table->next;
mysql_mutex_unlock(&thd->LOCK_thd_data);
+ if (! table->needs_reopen())
+ {
+ /* Avoid having MERGE tables with attached children in unused_tables. */
+ table->file->extra(HA_EXTRA_DETACH_CHILDREN);
+ /* Free memory and reset for next loop. */
+ free_field_buffers_larger_than(table, MAX_TDC_BLOB_SIZE);
+ table->file->ha_reset();
+ }
+
mysql_mutex_lock(&LOCK_open);
- if (table->s->needs_reopen() ||
- thd->version != refresh_version || table->needs_reopen() ||
+ if (table->s->needs_reopen() || table->needs_reopen() ||
table_def_shutdown_in_progress)
{
free_cache_entry(table);
@@ -1600,14 +1608,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
else
{
- /* Avoid to have MERGE tables with attached children in unused_tables. */
DBUG_ASSERT(table->file);
- table->file->extra(HA_EXTRA_DETACH_CHILDREN);
-
- /* Free memory and reset for next loop */
- free_field_buffers_larger_than(table,MAX_TDC_BLOB_SIZE);
-
- table->file->ha_reset();
table_def_unuse_table(table);
/*
We free the least used table, not the subject table,
@@ -2305,7 +2306,7 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond)
@param[out] exists Out parameter which is set to TRUE if table
exists and to FALSE otherwise.
- @note This function assumes that caller owns LOCK_open mutex.
+ @note This function acquires LOCK_open internally.
It also assumes that the fact that there are no exclusive
metadata locks on the table was checked beforehand.
@@ -2313,28 +2314,30 @@ void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond)
of engines (e.g. it was created on another node of NDB cluster)
this function will fetch and create proper .FRM file for it.
- @retval TRUE Some error occured
+ @retval TRUE Some error occurred
@retval FALSE No error. 'exists' out parameter set accordingly.
*/
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
{
char path[FN_REFLEN + 1];
- int rc;
+ int rc= 0;
DBUG_ENTER("check_if_table_exists");
- mysql_mutex_assert_owner(&LOCK_open);
+ mysql_mutex_assert_not_owner(&LOCK_open);
*exists= TRUE;
+ mysql_mutex_lock(&LOCK_open);
+
if (get_cached_table_share(table->db, table->table_name))
- DBUG_RETURN(FALSE);
+ goto end;
build_table_filename(path, sizeof(path) - 1, table->db, table->table_name,
reg_ext, 0);
if (!access(path, F_OK))
- DBUG_RETURN(FALSE);
+ goto end;
/* .FRM file doesn't exist. Check if some engine can provide it. */
@@ -2344,19 +2347,17 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
{
/* Table does not exists in engines as well. */
*exists= FALSE;
- DBUG_RETURN(FALSE);
- }
- else if (!rc)
- {
- /* Table exists in some engine and .FRM for it was created. */
- DBUG_RETURN(FALSE);
+ rc= 0;
}
- else /* (rc > 0) */
+ else if (rc)
{
my_printf_error(ER_UNKNOWN_ERROR, "Failed to open '%-.64s', error while "
"unpacking from engine", MYF(0), table->table_name);
- DBUG_RETURN(TRUE);
}
+
+end:
+ mysql_mutex_unlock(&LOCK_open);
+ DBUG_RETURN(test(rc));
}
@@ -2651,7 +2652,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if (thd->global_read_lock.wait_if_global_read_lock(thd, 1, 1))
DBUG_RETURN(TRUE);
- if (thd->version != refresh_version)
+ if (thd->open_tables && thd->open_tables->s->version != refresh_version)
{
(void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC,
NULL);
@@ -2848,48 +2849,24 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
- mysql_mutex_lock(&LOCK_open);
- /*
- If it's the first table from a list of tables used in a query,
- remember refresh_version (the version of open_cache state).
- If the version changes while we're opening the remaining tables,
- we will have to back off, close all the tables opened-so-far,
- and try to reopen them.
- Note: refresh_version is currently changed only during FLUSH TABLES.
- */
- if (!thd->open_tables)
- thd->version=refresh_version;
- else if ((thd->version != refresh_version) &&
- ! (flags & MYSQL_OPEN_IGNORE_FLUSH))
- {
- /* Someone did a refresh while thread was opening tables */
- mysql_mutex_unlock(&LOCK_open);
- (void) ot_ctx->request_backoff_action(Open_table_context::OT_WAIT_TDC,
- NULL);
- DBUG_RETURN(TRUE);
- }
if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS)
{
bool exists;
if (check_if_table_exists(thd, table_list, &exists))
- goto err_unlock2;
+ DBUG_RETURN(TRUE);
if (!exists)
- {
- mysql_mutex_unlock(&LOCK_open);
DBUG_RETURN(FALSE);
- }
+
/* Table exists. Let us try to open it. */
}
else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB)
- {
- mysql_mutex_unlock(&LOCK_open);
DBUG_RETURN(FALSE);
- }
+ mysql_mutex_lock(&LOCK_open);
#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL
if (!(share= (TABLE_SHARE *) mdl_ticket->get_cached_object()))
#endif
@@ -2911,7 +2888,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
my_error(ER_WRONG_MRG_TABLE, MYF(0));
goto err_unlock;
}
-
+
/*
This table is a view. Validate its metadata version: in particular,
that it was a view when the statement was prepared.
@@ -2980,7 +2957,15 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
#endif
- if (share->needs_reopen())
+
+ /*
+ If the version changes while we're opening the tables,
+ we have to back off, close all the tables opened-so-far,
+ and try to reopen them. Note: refresh_version is currently
+ changed only during FLUSH TABLES.
+ */
+ if (share->needs_reopen() ||
+ (thd->open_tables && thd->open_tables->s->version != share->version))
{
if (!(flags & MYSQL_OPEN_IGNORE_FLUSH))
{
@@ -3000,8 +2985,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
NULL);
DBUG_RETURN(TRUE);
}
- /* Force close at once after usage */
- thd->version= share->version;
}
if (!share->free_tables.is_empty())
@@ -3017,9 +3000,11 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
while (table_cache_count > table_cache_size && unused_tables)
free_cache_entry(unused_tables);
+ mysql_mutex_unlock(&LOCK_open);
+
/* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
- goto err_unlock;
+ goto err_lock;
error= open_table_from_share(thd, share, alias,
(uint) (HA_OPEN_KEYFILE |
@@ -3041,16 +3026,17 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
(void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR,
table_list);
- goto err_unlock;
+ goto err_lock;
}
if (open_table_entry_fini(thd, share, table))
{
closefrm(table, 0);
my_free((uchar*)table, MYF(0));
- goto err_unlock;
+ goto err_lock;
}
+ mysql_mutex_lock(&LOCK_open);
/* Add table to the share's used tables list. */
table_def_add_used_table(thd, table);
}
@@ -3112,6 +3098,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->file->extra(HA_EXTRA_DETACH_CHILDREN);
DBUG_RETURN(FALSE);
+err_lock:
+ mysql_mutex_lock(&LOCK_open);
err_unlock:
release_table_share(share);
err_unlock2:
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 38194f94a37..20a068e27d7 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -267,6 +267,7 @@ TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
const char *table_name,
bool no_error);
void mark_tmp_table_for_reuse(TABLE *table);
+bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
extern uint table_cache_count;
extern TABLE *unused_tables;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b5d38bebd73..03d365115cf 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -592,7 +592,7 @@ THD::THD()
*scramble= '\0';
/* Call to init() below requires fully initialized Open_tables_state. */
- init_open_tables_state(this, refresh_version);
+ reset_open_tables_state(this);
init();
#if defined(ENABLED_PROFILING)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6cc22b22d6c..44af0b7d66e 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1006,7 +1006,6 @@ public:
of the main statement is called.
*/
enum enum_locked_tables_mode locked_tables_mode;
- ulong version;
uint current_tablenr;
enum enum_flags {
@@ -1025,15 +1024,6 @@ public:
*/
Open_tables_state() : state_flags(0U) { }
- /**
- Prepare Open_tables_state instance for operations dealing with tables.
- */
- void init_open_tables_state(THD *thd, ulong version_arg)
- {
- reset_open_tables_state(thd);
- version= version_arg;
- }
-
void set_open_tables_state(Open_tables_state *state)
{
*this= *state;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 0282053ce7e..bd6ff3a951d 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -261,11 +261,6 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
static void reap_plugins(void);
-#ifdef EMBEDDED_LIBRARY
-/* declared in sql_base.cc */
-extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
-#endif /* EMBEDDED_LIBRARY */
-
static void report_error(int where_to, uint error, ...)
{
va_list args;
@@ -1475,10 +1470,8 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
When building an embedded library, if the mysql.plugin table
does not exist, we silently ignore the missing table
*/
- mysql_mutex_lock(&LOCK_open);
if (check_if_table_exists(new_thd, &tables, &table_exists))
table_exists= FALSE;
- mysql_mutex_unlock(&LOCK_open);
if (!table_exists)
goto end;
#endif /* EMBEDDED_LIBRARY */
@@ -1519,7 +1512,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
if (error > 0)
sql_print_error(ER(ER_GET_ERRNO), my_errno);
end_read_record(&read_record_info);
- new_thd->version--; // Force close to free memory
+ table->m_needs_reopen= TRUE; // Force close to free memory
end:
close_thread_tables(new_thd);
/* Remember that we don't have a THD */
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 9ec17a67533..3d197303fb1 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -248,7 +248,7 @@ void udf_init()
if (error > 0)
sql_print_error("Got unknown error: %d", my_errno);
end_read_record(&read_record_info);
- new_thd->version--; // Force close to free memory
+ table->m_needs_reopen= TRUE; // Force close to free memory
end:
close_thread_tables(new_thd);
diff --git a/sql/table.h b/sql/table.h
index 30cac15f8d1..1307770d8e1 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -590,7 +590,6 @@ struct TABLE_SHARE
enum enum_ha_unused unused2;
uint ref_count; /* How many TABLE objects uses this */
- uint open_count; /* Number of tables in open list */
uint blob_ptr_size; /* 4 or 8 */
uint key_block_size; /* create key_block_size, if used */
uint null_bytes, last_null_bit_pos;
diff --git a/sql/tztime.cc b/sql/tztime.cc
index b23456b5465..79f3b83553e 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1692,7 +1692,11 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
}
for (TABLE_LIST *tl= tz_tables; tl; tl= tl->next_global)
+ {
tl->table->use_all_columns();
+ /* Force close at the end of the function to free memory. */
+ tl->table->m_needs_reopen= TRUE;
+ }
/*
Now we are going to load leap seconds descriptions that are shared
@@ -1781,7 +1785,6 @@ end_with_setting_default_tz:
end_with_close:
if (time_zone_tables_exist)
{
- thd->version--; /* Force close to free memory */
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
}
diff --git a/storage/heap/CMakeLists.txt b/storage/heap/CMakeLists.txt
index 32359759abc..32510ba0c79 100755
--- a/storage/heap/CMakeLists.txt
+++ b/storage/heap/CMakeLists.txt
@@ -23,3 +23,9 @@ SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create
hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c)
MYSQL_ADD_PLUGIN(heap ${HEAP_SOURCES} STORAGE_ENGINE MANDATORY RECOMPILE_FOR_EMBEDDED)
+
+ADD_EXECUTABLE(hp_test1 hp_test1.c)
+TARGET_LINK_LIBRARIES(hp_test1 mysys heap)
+
+ADD_EXECUTABLE(hp_test2 hp_test2.c)
+TARGET_LINK_LIBRARIES(hp_test2 mysys heap)
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index 3abffc7087f..541650bd5e8 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -29,6 +29,10 @@
static handler *heap_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
+static int
+heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
+ HP_CREATE_INFO *hp_create_info);
+
int heap_panic(handlerton *hton, ha_panic_function flag)
{
@@ -96,43 +100,48 @@ const char **ha_heap::bas_ext() const
int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
- if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) ||
- (!(file= heap_open(name, mode)) && my_errno == ENOENT))
+ internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
+ if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
{
- HA_CREATE_INFO create_info;
- internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
- bzero(&create_info, sizeof(create_info));
+ HP_CREATE_INFO create_info;
+ my_bool created_new_share;
+ int rc;
file= 0;
- if (!create(name, table, &create_info))
+ if (heap_prepare_hp_create_info(table, internal_table, &create_info))
+ goto end;
+ create_info.pin_share= TRUE;
+
+ rc= heap_create(name, &create_info, &internal_share, &created_new_share);
+ my_free((uchar*) create_info.keydef, MYF(0));
+ if (rc)
+ goto end;
+
+ implicit_emptied= test(created_new_share);
+ if (internal_table)
+ file= heap_open_from_share(internal_share, mode);
+ else
+ file= heap_open_from_share_and_register(internal_share, mode);
+
+ if (!file)
{
- file= internal_table ?
- heap_open_from_share(internal_share, mode) :
- heap_open_from_share_and_register(internal_share, mode);
- if (!file)
- {
- /* Couldn't open table; Remove the newly created table */
- mysql_mutex_lock(&THR_LOCK_heap);
- hp_free(internal_share);
- mysql_mutex_unlock(&THR_LOCK_heap);
- }
- implicit_emptied= 1;
+ heap_release_share(internal_share, internal_table);
+ goto end;
}
}
+
ref_length= sizeof(HEAP_PTR);
- if (file)
- {
- /* Initialize variables for the opened table */
- set_keys_for_scanning();
- /*
- We cannot run update_key_stats() here because we do not have a
- lock on the table. The 'records' count might just be changed
- temporarily at this moment and we might get wrong statistics (Bug
- #10178). Instead we request for update. This will be done in
- ha_heap::info(), which is always called before key statistics are
- used.
+ /* Initialize variables for the opened table */
+ set_keys_for_scanning();
+ /*
+ We cannot run update_key_stats() here because we do not have a
+ lock on the table. The 'records' count might just be changed
+ temporarily at this moment and we might get wrong statistics (Bug
+ #10178). Instead we request for update. This will be done in
+ ha_heap::info(), which is always called before key statistics are
+ used.
*/
- key_stat_version= file->s->key_stat_version-1;
- }
+ key_stat_version= file->s->key_stat_version-1;
+end:
return (file ? 0 : 1);
}
@@ -624,18 +633,20 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
}
-int ha_heap::create(const char *name, TABLE *table_arg,
- HA_CREATE_INFO *create_info)
+static int
+heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
+ HP_CREATE_INFO *hp_create_info)
{
uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
uint auto_key= 0, auto_key_type= 0;
ha_rows max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
- int error;
TABLE_SHARE *share= table_arg->s;
bool found_real_auto_increment= 0;
+ bzero(hp_create_info, sizeof(*hp_create_info));
+
for (key= parts= 0; key < keys; key++)
parts+= table_arg->key_info[key].key_parts;
@@ -715,29 +726,45 @@ int ha_heap::create(const char *name, TABLE *table_arg,
}
}
mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
- max_rows = (ha_rows) (table_arg->in_use->variables.max_heap_table_size /
- (ulonglong) mem_per_row);
if (table_arg->found_next_number_field)
{
keydef[share->next_number_index].flag|= HA_AUTO_KEY;
found_real_auto_increment= share->next_number_key_offset == 0;
}
+ hp_create_info->auto_key= auto_key;
+ hp_create_info->auto_key_type= auto_key_type;
+ hp_create_info->max_table_size=current_thd->variables.max_heap_table_size;
+ hp_create_info->with_auto_increment= found_real_auto_increment;
+ hp_create_info->internal_table= internal_table;
+
+ max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row);
+ if (share->max_rows && share->max_rows < max_rows)
+ max_rows= share->max_rows;
+
+ hp_create_info->max_records= (ulong) max_rows;
+ hp_create_info->min_records= (ulong) share->min_rows;
+ hp_create_info->keys= share->keys;
+ hp_create_info->reclength= share->reclength;
+ hp_create_info->keydef= keydef;
+ return 0;
+}
+
+
+int ha_heap::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int error;
+ my_bool created;
HP_CREATE_INFO hp_create_info;
- hp_create_info.auto_key= auto_key;
- hp_create_info.auto_key_type= auto_key_type;
+
+ error= heap_prepare_hp_create_info(table_arg, internal_table,
+ &hp_create_info);
+ if (error)
+ return error;
hp_create_info.auto_increment= (create_info->auto_increment_value ?
create_info->auto_increment_value - 1 : 0);
- hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
- hp_create_info.with_auto_increment= found_real_auto_increment;
- hp_create_info.internal_table= internal_table;
- max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row);
- error= heap_create(name,
- keys, keydef, share->reclength,
- (ulong) ((share->max_rows < max_rows &&
- share->max_rows) ?
- share->max_rows : max_rows),
- (ulong) share->min_rows, &hp_create_info, &internal_share);
- my_free((uchar*) keydef, MYF(0));
+ error= heap_create(name, &hp_create_info, &internal_share, &created);
+ my_free((uchar*) hp_create_info.keydef, MYF(0));
DBUG_ASSERT(file == 0);
return (error);
}
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index 85e632e5aad..cf0f5d5ba6d 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -21,24 +21,30 @@ static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
/* Create a heap table */
-int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
- uint reclength, ulong max_records, ulong min_records,
- HP_CREATE_INFO *create_info, HP_SHARE **res)
+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);
- if ((share= hp_find_named_heap(name)) && share->open_count == 0)
+ share= hp_find_named_heap(name);
+ if (share && share->open_count == 0)
{
hp_free(share);
share= 0;
}
- }
+ }
+ *created_new_share= (share == NULL);
if (!share)
{
@@ -200,7 +206,11 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
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);
diff --git a/storage/heap/hp_open.c b/storage/heap/hp_open.c
index feafa5d5cf1..ef2ce15f9b3 100644
--- a/storage/heap/hp_open.c
+++ b/storage/heap/hp_open.c
@@ -74,12 +74,33 @@ HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode)
{
info->open_list.data= (void*) info;
heap_open_list= list_add(heap_open_list,&info->open_list);
+ /* Unpin the share, it is now pinned by the file. */
+ share->open_count--;
}
mysql_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(info);
}
+/**
+ Dereference a HEAP share and free it if it's not referenced.
+ We don't check open_count for internal tables since they
+ are always thread-local, i.e. referenced by a single thread.
+*/
+void heap_release_share(HP_SHARE *share, my_bool internal_table)
+{
+ /* Couldn't open table; Remove the newly created table */
+ if (internal_table)
+ hp_free(share);
+ else
+ {
+ mysql_mutex_lock(&THR_LOCK_heap);
+ if (--share->open_count == 0)
+ hp_free(share);
+ mysql_mutex_unlock(&THR_LOCK_heap);
+ }
+}
+
/*
Open heap table based on name
diff --git a/storage/heap/hp_test1.c b/storage/heap/hp_test1.c
index 911e3a285a2..535db60e237 100644
--- a/storage/heap/hp_test1.c
+++ b/storage/heap/hp_test1.c
@@ -38,6 +38,7 @@ int main(int argc, char **argv)
HA_KEYSEG keyseg[4];
HP_CREATE_INFO hp_create_info;
HP_SHARE *tmp_share;
+ my_bool unused;
MY_INIT(argv[0]);
filename= "test1";
@@ -45,6 +46,11 @@ int main(int argc, char **argv)
bzero(&hp_create_info, sizeof(hp_create_info));
hp_create_info.max_table_size= 1024L*1024L;
+ hp_create_info.keys= 1;
+ hp_create_info.keydef= keyinfo;
+ hp_create_info.reclength= 30;
+ hp_create_info.max_records= (ulong) flag*100000L;
+ hp_create_info.min_records= 10UL;
keyinfo[0].keysegs=1;
keyinfo[0].seg=keyseg;
@@ -55,13 +61,12 @@ int main(int argc, char **argv)
keyinfo[0].seg[0].charset= &my_charset_latin1;
keyinfo[0].seg[0].null_bit= 0;
keyinfo[0].flag = HA_NOSAME;
-
+
deleted=0;
bzero((uchar*) flags,sizeof(flags));
printf("- Creating heap-file\n");
- if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000L,10L,
- &hp_create_info, &tmp_share) ||
+ if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
!(file= heap_open(filename, 2)))
goto err;
printf("- Writing records:s\n");
diff --git a/storage/heap/hp_test2.c b/storage/heap/hp_test2.c
index 8216c7360b4..733dff40c1a 100644
--- a/storage/heap/hp_test2.c
+++ b/storage/heap/hp_test2.c
@@ -65,15 +65,21 @@ int main(int argc, char *argv[])
HEAP_PTR UNINIT_VAR(position);
HP_CREATE_INFO hp_create_info;
CHARSET_INFO *cs= &my_charset_latin1;
+ my_bool unused;
MY_INIT(argv[0]); /* init my_sys library & pthreads */
filename= "test2";
filename2= "test2_2";
file=file2=0;
get_options(argc,argv);
-
+
bzero(&hp_create_info, sizeof(hp_create_info));
hp_create_info.max_table_size= 1024L*1024L;
+ hp_create_info.keys= keys;
+ hp_create_info.keydef= keyinfo;
+ hp_create_info.reclength= reclength;
+ hp_create_info.max_records= (ulong) flag*100000L;
+ hp_create_info.min_records= (ulong) recant/2;
write_count=update=opt_delete=0;
key_check=0;
@@ -125,8 +131,7 @@ int main(int argc, char *argv[])
bzero((char*) key3,sizeof(key3));
printf("- Creating heap-file\n");
- if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L,
- (ulong) recant/2, &hp_create_info, &tmp_share) ||
+ if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
!(file= heap_open(filename, 2)))
goto err;
signal(SIGINT,endprog);
@@ -563,8 +568,10 @@ int main(int argc, char *argv[])
heap_close(file2);
printf("- Creating output heap-file 2\n");
- if (heap_create(filename2, 1, keyinfo, reclength, 0L, 0L, &hp_create_info,
- &tmp_share) ||
+ hp_create_info.keys= 1;
+ hp_create_info.max_records= 0;
+ hp_create_info.min_records= 0;
+ if (heap_create(filename2, &hp_create_info, &tmp_share, &unused) ||
!(file2= heap_open_from_share_and_register(tmp_share, 2)))
goto err;