diff options
Diffstat (limited to 'storage/innobase/dict/dict0mem.cc')
-rw-r--r-- | storage/innobase/dict/dict0mem.cc | 163 |
1 files changed, 151 insertions, 12 deletions
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 885627a61bc..58781fce1d4 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -35,6 +35,7 @@ Created 1/8/1996 Heikki Tuuri #include "mach0data.h" #include "dict0dict.h" #include "fts0priv.h" +#include "ut0crc32.h" #ifndef UNIV_HOTBACKUP # include "ha_prototypes.h" /* innobase_casedn_str(), innobase_get_lower_case_table_names */ @@ -44,6 +45,7 @@ Created 1/8/1996 Heikki Tuuri #ifdef UNIV_BLOB_DEBUG # include "ut0rbt.h" #endif /* UNIV_BLOB_DEBUG */ +#include <iostream> #define DICT_HEAP_SIZE 100 /*!< initial memory heap size when creating a table or index object */ @@ -53,6 +55,18 @@ Created 1/8/1996 Heikki Tuuri UNIV_INTERN mysql_pfs_key_t autoinc_mutex_key; #endif /* UNIV_PFS_MUTEX */ +/** System databases */ +static const char* innobase_system_databases[] = { + "mysql/", + "information_schema/", + "performance_schema/", + NullS +}; + +/** An interger randomly initialized at startup used to make a temporary +table name as unique as possible. */ +static ib_uint32_t dict_temp_file_num; + /**********************************************************************//** Creates a table memory object. @return own: table object */ @@ -85,6 +99,7 @@ dict_mem_table_create( table->flags2 = (unsigned int) flags2; table->name = static_cast<char*>(ut_malloc(strlen(name) + 1)); memcpy(table->name, name, strlen(name) + 1); + table->is_system_db = dict_mem_table_is_system(table->name); table->space = (unsigned int) space; table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); @@ -131,6 +146,36 @@ dict_mem_table_create( } /****************************************************************//** +Determines if a table belongs to a system database +@return */ +UNIV_INTERN +bool +dict_mem_table_is_system( +/*================*/ + char *name) /*!< in: table name */ +{ + ut_ad(name); + + /* table has the following format: database/table + and some system table are of the form SYS_* */ + if (strchr(name, '/')) { + int table_len = strlen(name); + const char *system_db; + int i = 0; + while ((system_db = innobase_system_databases[i++]) + && (system_db != NullS)) { + int len = strlen(system_db); + if (table_len > len && !strncmp(name, system_db, len)) { + return true; + } + } + return false; + } else { + return true; + } +} + +/****************************************************************//** Free a table memory object. */ UNIV_INTERN void @@ -614,26 +659,120 @@ dict_mem_index_free( mem_heap_free(index->heap); } -/*******************************************************************//** -Create a temporary tablename. -@return temporary tablename suitable for InnoDB use */ +/** Create a temporary tablename like "#sql-ibtid-inc where + tid = the Table ID + inc = a randomly initialized number that is incremented for each file +The table ID is a 64 bit integer, can use up to 20 digits, and is +initialized at bootstrap. The second number is 32 bits, can use up to 10 +digits, and is initialized at startup to a randomly distributed number. +It is hoped that the combination of these two numbers will provide a +reasonably unique temporary file name. +@param[in] heap A memory heap +@param[in] dbtab Table name in the form database/table name +@param[in] id Table id +@return A unique temporary tablename suitable for InnoDB use */ UNIV_INTERN char* dict_mem_create_temporary_tablename( -/*================================*/ - mem_heap_t* heap, /*!< in: memory heap */ - const char* dbtab, /*!< in: database/table name */ - table_id_t id) /*!< in: InnoDB table id */ + mem_heap_t* heap, + const char* dbtab, + table_id_t id) { - const char* dbend = strchr(dbtab, '/'); + size_t size; + char* name; + const char* dbend = strchr(dbtab, '/'); ut_ad(dbend); - size_t dblen = dbend - dbtab + 1; - size_t size = tmp_file_prefix_length + 4 + 9 + 9 + dblen; + size_t dblen = dbend - dbtab + 1; - char* name = static_cast<char*>(mem_heap_alloc(heap, size)); +#ifdef HAVE_ATOMIC_BUILTINS + /* Increment a randomly initialized number for each temp file. */ + os_atomic_increment_uint32(&dict_temp_file_num, 1); +#else /* HAVE_ATOMIC_BUILTINS */ + dict_temp_file_num++; +#endif /* HAVE_ATOMIC_BUILTINS */ + + size = tmp_file_prefix_length + 3 + 20 + 1 + 10 + dblen; + name = static_cast<char*>(mem_heap_alloc(heap, size)); memcpy(name, dbtab, dblen); ut_snprintf(name + dblen, size - dblen, - tmp_file_prefix "-ib" UINT64PF, id); + TEMP_FILE_PREFIX_INNODB UINT64PF "-" UINT32PF, + id, dict_temp_file_num); + return(name); } +/** Initialize dict memory variables */ + +void +dict_mem_init(void) +{ + /* Initialize a randomly distributed temporary file number */ + ib_uint32_t now = static_cast<ib_uint32_t>(ut_time()); + + const byte* buf = reinterpret_cast<const byte*>(&now); + ut_ad(ut_crc32 != NULL); + + dict_temp_file_num = ut_crc32(buf, sizeof(now)); + + DBUG_PRINT("dict_mem_init", + ("Starting Temporary file number is " UINT32PF, + dict_temp_file_num)); +} + +/** Validate the search order in the foreign key set. +@param[in] fk_set the foreign key set to be validated +@return true if search order is fine in the set, false otherwise. */ +bool +dict_foreign_set_validate( + const dict_foreign_set& fk_set) +{ + dict_foreign_not_exists not_exists(fk_set); + + dict_foreign_set::iterator it = std::find_if( + fk_set.begin(), fk_set.end(), not_exists); + + if (it == fk_set.end()) { + return(true); + } + + dict_foreign_t* foreign = *it; + std::cerr << "Foreign key lookup failed: " << *foreign; + std::cerr << fk_set; + ut_ad(0); + return(false); +} + +/** Validate the search order in the foreign key sets of the table +(foreign_set and referenced_set). +@param[in] table table whose foreign key sets are to be validated +@return true if foreign key sets are fine, false otherwise. */ +bool +dict_foreign_set_validate( + const dict_table_t& table) +{ + return(dict_foreign_set_validate(table.foreign_set) + && dict_foreign_set_validate(table.referenced_set)); +} + +std::ostream& +operator<< (std::ostream& out, const dict_foreign_t& foreign) +{ + out << "[dict_foreign_t: id='" << foreign.id << "'"; + + if (foreign.foreign_table_name != NULL) { + out << ",for: '" << foreign.foreign_table_name << "'"; + } + + out << "]"; + return(out); +} + +std::ostream& +operator<< (std::ostream& out, const dict_foreign_set& fk_set) +{ + out << "[dict_foreign_set:"; + std::for_each(fk_set.begin(), fk_set.end(), dict_foreign_print(out)); + out << "]" << std::endl; + return(out); +} + |