void buf_flush_init_for_writing( /*=======================*/ byte* page, /* in: page */ dulint newest_lsn, /* in: newest modification lsn to the page */ ulint space, /* in: space id */ ulint page_no) /* in: page number */ { /* Write the newest modification lsn to the page header and trailer */ mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn); mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, newest_lsn); /* Write the page number and the space id */ mach_write_to_4(page + FIL_PAGE_OFFSET, page_no); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space); /* Store the new formula checksum */ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums ? buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC); /* We overwrite the first 4 bytes of the end lsn field to store the old formula checksum. Since it depends also on the field FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the new formula checksum. */ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, srv_use_checksums ? buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC); }
/********************************************************//** Writes 8 bytes to a file page buffered in the buffer pool. Writes the corresponding log record to the mini-transaction log. */ UNIV_INTERN void mlog_write_dulint( /*==============*/ byte* ptr, /*!< in: pointer where to write */ dulint val, /*!< in: value to write */ mtr_t* mtr) /*!< in: mini-transaction handle */ { byte* log_ptr; ut_ad(ptr && mtr); mach_write_to_8(ptr, val); log_ptr = mlog_open(mtr, 11 + 2 + 9); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES, log_ptr, mtr); mach_write_to_2(log_ptr, page_offset(ptr)); log_ptr += 2; log_ptr += mach_dulint_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); }
void mlog_write_dulint( /*==============*/ byte* ptr, /* in: pointer where to write */ dulint val, /* in: value to write */ mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero) || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) { fprintf(stderr, "InnoDB: Error: trying to write to" " a stray memory location %p\n", (void*) ptr); ut_error; } ut_ad(ptr && mtr); mach_write_to_8(ptr, val); log_ptr = mlog_open(mtr, 11 + 2 + 9); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES, log_ptr, mtr); mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; log_ptr += mach_dulint_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); }
/********************************************************//** Parses a log record written by mlog_write_ulint or mlog_write_dulint. @return parsed record end, NULL if not a complete record or a corrupt record */ UNIV_INTERN byte* mlog_parse_nbytes( /*==============*/ ulint type, /*!< in: log record type: MLOG_1BYTE, ... */ byte* ptr, /*!< in: buffer */ byte* end_ptr,/*!< in: buffer end */ byte* page, /*!< in: page where to apply the log record, or NULL */ void* page_zip)/*!< in/out: compressed page, or NULL */ { ulint offset; ulint val; dulint dval; ut_a(type <= MLOG_8BYTES); ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX); if (end_ptr < ptr + 2) { return(NULL); } offset = mach_read_from_2(ptr); ptr += 2; if (offset >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; return(NULL); } if (type == MLOG_8BYTES) { ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval); if (ptr == NULL) { return(NULL); } if (page) { if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_8 (((page_zip_des_t*) page_zip)->data + offset, dval); } mach_write_to_8(page + offset, dval); } return(ptr); } ptr = mach_parse_compressed(ptr, end_ptr, &val); if (ptr == NULL) { return(NULL); } switch (type) { case MLOG_1BYTE: if (UNIV_UNLIKELY(val > 0xFFUL)) { goto corrupt; } if (page) { if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_1 (((page_zip_des_t*) page_zip)->data + offset, val); } mach_write_to_1(page + offset, val); } break; case MLOG_2BYTES: if (UNIV_UNLIKELY(val > 0xFFFFUL)) { goto corrupt; } if (page) { if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_2 (((page_zip_des_t*) page_zip)->data + offset, val); } mach_write_to_2(page + offset, val); } break; case MLOG_4BYTES: if (page) { if (UNIV_LIKELY_NULL(page_zip)) { mach_write_to_4 (((page_zip_des_t*) page_zip)->data + offset, val); } mach_write_to_4(page + offset, val); } break; default: corrupt: recv_sys->found_corrupt_log = TRUE; ptr = NULL; } return(ptr); }
/********************************************************************* Based on an index object, this function builds the entry to be inserted in the SYS_FIELDS system table. */ static dtuple_t* dict_create_sys_fields_tuple( /*=========================*/ /* out: the tuple which should be inserted */ dict_index_t* index, /* in: index */ ulint i, /* in: field number */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_fields; dtuple_t* entry; dict_field_t* field; dfield_t* dfield; byte* ptr; ibool index_contains_column_prefix_field = FALSE; ulint j; ut_ad(index && heap); for (j = 0; j < index->n_fields; j++) { if (dict_index_get_nth_field(index, j)->prefix_len > 0) { index_contains_column_prefix_field = TRUE; } } field = dict_index_get_nth_field(index, i); sys_fields = dict_sys->sys_fields; entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS); /* 0: INDEX_ID -----------------------*/ dfield = dtuple_get_nth_field(entry, 0); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, index->id); dfield_set_data(dfield, ptr, 8); /* 1: POS + PREFIX LENGTH ----------------------------*/ dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 4); if (index_contains_column_prefix_field) { /* If there are column prefix fields in the index, then we store the number of the field to the 2 HIGH bytes and the prefix length to the 2 low bytes, */ mach_write_to_4(ptr, (i << 16) + field->prefix_len); } else { /* Else we store the number of the field to the 2 LOW bytes. This is to keep the storage format compatible with InnoDB versions < 4.0.14. */ mach_write_to_4(ptr, i); } dfield_set_data(dfield, ptr, 4); /* 4: COL_NAME -------------------------*/ dfield = dtuple_get_nth_field(entry, 2); dfield_set_data(dfield, field->name, ut_strlen(field->name)); /*---------------------------------*/ dict_table_copy_types(entry, sys_fields); return(entry); }
/********************************************************************* Based on a table object, this function builds the entry to be inserted in the SYS_TABLES system table. */ static dtuple_t* dict_create_sys_tables_tuple( /*=========================*/ /* out: the tuple which should be inserted */ dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_tables; dtuple_t* entry; dfield_t* dfield; byte* ptr; ut_ad(table && heap); sys_tables = dict_sys->sys_tables; entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS); /* 0: NAME -----------------------------*/ dfield = dtuple_get_nth_field(entry, 0); dfield_set_data(dfield, table->name, ut_strlen(table->name)); /* 3: ID -------------------------------*/ dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, table->id); dfield_set_data(dfield, ptr, 8); /* 4: N_COLS ---------------------------*/ dfield = dtuple_get_nth_field(entry, 2); #if DICT_TF_COMPACT != 1 #error #endif ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, table->n_def | ((table->flags & DICT_TF_COMPACT) << 31)); dfield_set_data(dfield, ptr, 4); /* 5: TYPE -----------------------------*/ dfield = dtuple_get_nth_field(entry, 3); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, DICT_TABLE_ORDINARY); dfield_set_data(dfield, ptr, 4); /* 6: MIX_ID (obsolete) ---------------------------*/ dfield = dtuple_get_nth_field(entry, 4); ptr = mem_heap_alloc(heap, 8); memset(ptr, 0, 8); dfield_set_data(dfield, ptr, 8); /* 7: MIX_LEN (obsolete) --------------------------*/ dfield = dtuple_get_nth_field(entry, 5); ptr = mem_heap_alloc(heap, 4); memset(ptr, 0, 4); dfield_set_data(dfield, ptr, 4); /* 8: CLUSTER_NAME ---------------------*/ dfield = dtuple_get_nth_field(entry, 6); dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */ /* 9: SPACE ----------------------------*/ dfield = dtuple_get_nth_field(entry, 7); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, table->space); dfield_set_data(dfield, ptr, 4); /*----------------------------------*/ dict_table_copy_types(entry, sys_tables); return(entry); }
/********************************************************************* Based on an index object, this function builds the entry to be inserted in the SYS_INDEXES system table. */ static dtuple_t* dict_create_sys_indexes_tuple( /*==========================*/ /* out: the tuple which should be inserted */ dict_index_t* index, /* in: index */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_indexes; dict_table_t* table; dtuple_t* entry; dfield_t* dfield; byte* ptr; ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(index && heap); sys_indexes = dict_sys->sys_indexes; table = dict_table_get_low(index->table_name); entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS); /* 0: TABLE_ID -----------------------*/ dfield = dtuple_get_nth_field(entry, 0); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, table->id); dfield_set_data(dfield, ptr, 8); /* 1: ID ----------------------------*/ dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, index->id); dfield_set_data(dfield, ptr, 8); /* 4: NAME --------------------------*/ dfield = dtuple_get_nth_field(entry, 2); dfield_set_data(dfield, index->name, ut_strlen(index->name)); /* 5: N_FIELDS ----------------------*/ dfield = dtuple_get_nth_field(entry, 3); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, index->n_fields); dfield_set_data(dfield, ptr, 4); /* 6: TYPE --------------------------*/ dfield = dtuple_get_nth_field(entry, 4); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, index->type); dfield_set_data(dfield, ptr, 4); /* 7: SPACE --------------------------*/ #if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7 #error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7" #endif dfield = dtuple_get_nth_field(entry, 5); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, index->space); dfield_set_data(dfield, ptr, 4); /* 8: PAGE_NO --------------------------*/ #if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8 #error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8" #endif dfield = dtuple_get_nth_field(entry, 6); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, FIL_NULL); dfield_set_data(dfield, ptr, 4); /*--------------------------------*/ dict_table_copy_types(entry, sys_indexes); return(entry); }
/********************************************************************* Based on a table object, this function builds the entry to be inserted in the SYS_COLUMNS system table. */ static dtuple_t* dict_create_sys_columns_tuple( /*==========================*/ /* out: the tuple which should be inserted */ dict_table_t* table, /* in: table */ ulint i, /* in: column number */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_columns; dtuple_t* entry; const dict_col_t* column; dfield_t* dfield; byte* ptr; const char* col_name; ut_ad(table && heap); column = dict_table_get_nth_col(table, i); sys_columns = dict_sys->sys_columns; entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS); /* 0: TABLE_ID -----------------------*/ dfield = dtuple_get_nth_field(entry, 0); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, table->id); dfield_set_data(dfield, ptr, 8); /* 1: POS ----------------------------*/ dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, i); dfield_set_data(dfield, ptr, 4); /* 4: NAME ---------------------------*/ dfield = dtuple_get_nth_field(entry, 2); col_name = dict_table_get_col_name(table, i); dfield_set_data(dfield, col_name, ut_strlen(col_name)); /* 5: MTYPE --------------------------*/ dfield = dtuple_get_nth_field(entry, 3); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, column->mtype); dfield_set_data(dfield, ptr, 4); /* 6: PRTYPE -------------------------*/ dfield = dtuple_get_nth_field(entry, 4); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, column->prtype); dfield_set_data(dfield, ptr, 4); /* 7: LEN ----------------------------*/ dfield = dtuple_get_nth_field(entry, 5); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, column->len); dfield_set_data(dfield, ptr, 4); /* 8: PREC ---------------------------*/ dfield = dtuple_get_nth_field(entry, 6); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, 0/* unused */); dfield_set_data(dfield, ptr, 4); /*---------------------------------*/ dict_table_copy_types(entry, sys_columns); return(entry); }
byte* mlog_parse_nbytes( /*==============*/ /* out: parsed record end, NULL if not a complete record or a corrupt record */ ulint type, /* in: log record type: MLOG_1BYTE, ... */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ byte* page) /* in: page where to apply the log record, or NULL */ { ulint offset; ulint val; dulint dval; ut_a(type <= MLOG_8BYTES); if (end_ptr < ptr + 2) { return(NULL); } offset = mach_read_from_2(ptr); ptr += 2; if (offset >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; return(NULL); } if (type == MLOG_8BYTES) { ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval); if (ptr == NULL) { return(NULL); } if (page) { mach_write_to_8(page + offset, dval); } return(ptr); } ptr = mach_parse_compressed(ptr, end_ptr, &val); if (ptr == NULL) { return(NULL); } if (type == MLOG_1BYTE) { if (val > 0xFFUL) { recv_sys->found_corrupt_log = TRUE; return(NULL); } } else if (type == MLOG_2BYTES) { if (val > 0xFFFFUL) { recv_sys->found_corrupt_log = TRUE; return(NULL); } } else { if (type != MLOG_4BYTES) { recv_sys->found_corrupt_log = TRUE; return(NULL); } } if (page) { if (type == MLOG_1BYTE) { mach_write_to_1(page + offset, val); } else if (type == MLOG_2BYTES) { mach_write_to_2(page + offset, val); } else { ut_a(type == MLOG_4BYTES); mach_write_to_4(page + offset, val); } } return(ptr); }
/*****************************************************************//** Based on a table object, this function builds the entry to be inserted in the SYS_TABLES system table. @return the tuple which should be inserted */ static dtuple_t* dict_create_sys_tables_tuple( /*=========================*/ const dict_table_t* table, /*!< in: table */ mem_heap_t* heap) /*!< in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_tables; dtuple_t* entry; dfield_t* dfield; byte* ptr; ut_ad(table); ut_ad(heap); sys_tables = dict_sys->sys_tables; entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS); dict_table_copy_types(entry, sys_tables); /* 0: NAME -----------------------------*/ dfield = dtuple_get_nth_field(entry, 0/*NAME*/); dfield_set_data(dfield, table->name, ut_strlen(table->name)); /* 3: ID -------------------------------*/ dfield = dtuple_get_nth_field(entry, 1/*ID*/); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, table->id); dfield_set_data(dfield, ptr, 8); /* 4: N_COLS ---------------------------*/ dfield = dtuple_get_nth_field(entry, 2/*N_COLS*/); #if DICT_TF_COMPACT != 1 #error #endif ptr = mem_heap_alloc(heap, 4); if (dict_table_is_gcs(table)) /* ±í¶¨ÒåÐÞ¸Ä */ { ut_ad(dict_table_is_comp(table)); mach_write_to_4(ptr, table->n_def | (1 << 31) | (1 << 30)); } else { mach_write_to_4(ptr, table->n_def | ((table->flags & DICT_TF_COMPACT) << 31)); } dfield_set_data(dfield, ptr, 4); /* 5: TYPE -----------------------------*/ dfield = dtuple_get_nth_field(entry, 3/*TYPE*/); ptr = mem_heap_alloc(heap, 4); if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) { ut_a(table->flags & DICT_TF_COMPACT); ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP); ut_a((table->flags & DICT_TF_ZSSIZE_MASK) <= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT)); ut_a(!(table->flags & (~0 << DICT_TF2_BITS))); mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS)); } else { mach_write_to_4(ptr, DICT_TABLE_ORDINARY); } dfield_set_data(dfield, ptr, 4); /* 6: MIX_ID (obsolete) ---------------------------*/ dfield = dtuple_get_nth_field(entry, 4/*MIX_ID*/); ptr = mem_heap_zalloc(heap, 8); dfield_set_data(dfield, ptr, 8); /* 7: MIX_LEN (additional flags) --------------------------*/ dfield = dtuple_get_nth_field(entry, 5/*MIX_LEN*/); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT); ut_ad(table->n_cols_before_alter_table == 0); dfield_set_data(dfield, ptr, 4); /* 8: CLUSTER_NAME ---------------------*/ dfield = dtuple_get_nth_field(entry, 6/*CLUSTER_NAME*/); dfield_set_null(dfield); /* not supported */ /* 9: SPACE ----------------------------*/ dfield = dtuple_get_nth_field(entry, 7/*SPACE*/); ptr = mem_heap_alloc(heap, 4); mach_write_to_4(ptr, table->space); dfield_set_data(dfield, ptr, 4); /*----------------------------------*/ return(entry); }
/************************************************************************ Loads definitions for index fields. */ static void dict_load_fields( /*=============*/ dict_table_t* table, /* in: table */ dict_index_t* index, /* in: index whose fields to load */ mem_heap_t* heap) /* in: memory heap for temporary storage */ { dict_table_t* sys_fields; dict_index_t* sys_index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; char* col_name; rec_t* rec; byte* field; ulint len; byte* buf; ulint i; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); UT_NOT_USED(table); mtr_start(&mtr); sys_fields = dict_table_get_low("SYS_FIELDS"); sys_index = UT_LIST_GET_FIRST(sys_fields->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); buf = mem_heap_alloc(heap, 8); mach_write_to_8(buf, index->id); dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (i = 0; i < index->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); ut_a(ut_memcmp(buf, field, len) == 0); field = rec_get_nth_field(rec, 1, &len); ut_ad(len == 4); ut_a(i == mach_read_from_4(field)); ut_a(0 == ut_strcmp("COL_NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_fields), 4))->name)); field = rec_get_nth_field(rec, 4, &len); col_name = mem_heap_alloc(heap, len + 1); ut_memcpy(col_name, field, len); col_name[len] = '\0'; dict_mem_index_add_field(index, col_name, 0); btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
/************************************************************************ Loads definitions for table indexes. Adds them to the data dictionary cache. */ static void dict_load_indexes( /*==============*/ dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap for temporary storage */ { dict_table_t* sys_indexes; dict_index_t* sys_index; dict_index_t* index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; rec_t* rec; byte* field; ulint len; ulint name_len; char* name_buf; ulint type; ulint space; ulint page_no; ulint n_fields; byte* buf; ibool is_sys_table; dulint id; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); if ((ut_dulint_get_high(table->id) == 0) && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { is_sys_table = TRUE; } else { is_sys_table = FALSE; } mtr_start(&mtr); sys_indexes = dict_table_get_low("SYS_INDEXES"); sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); buf = mem_heap_alloc(heap, 8); mach_write_to_8(buf, table->id); dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (;;) { if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { break; } rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); if (ut_memcmp(buf, field, len) != 0) { break; } ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 1, &len); ut_ad(len == 8); id = mach_read_from_8(field); ut_a(0 == ut_strcmp("NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_indexes), 4))->name)); field = rec_get_nth_field(rec, 4, &name_len); name_buf = mem_heap_alloc(heap, name_len + 1); ut_memcpy(name_buf, field, name_len); name_buf[name_len] = '\0'; field = rec_get_nth_field(rec, 5, &len); n_fields = mach_read_from_4(field); field = rec_get_nth_field(rec, 6, &len); type = mach_read_from_4(field); field = rec_get_nth_field(rec, 7, &len); space = mach_read_from_4(field); ut_a(0 == ut_strcmp("PAGE_NO", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_indexes), 8))->name)); field = rec_get_nth_field(rec, 8, &len); page_no = mach_read_from_4(field); if (is_sys_table && ((type & DICT_CLUSTERED) || ((table == dict_sys->sys_tables) && (name_len == ut_strlen("ID_IND")) && (0 == ut_memcmp(name_buf, "ID_IND", name_len))))) { /* The index was created in memory already in booting */ } else { index = dict_mem_index_create(table->name, name_buf, space, type, n_fields); index->page_no = page_no; index->id = id; dict_load_fields(table, index, heap); dict_index_add_to_cache(table, index); } btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
/************************************************************************ Loads definitions for table columns. */ static void dict_load_columns( /*==============*/ dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap for temporary storage */ { dict_table_t* sys_columns; dict_index_t* sys_index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; rec_t* rec; byte* field; ulint len; byte* buf; char* name_buf; char* name; ulint mtype; ulint prtype; ulint col_len; ulint prec; ulint i; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); mtr_start(&mtr); sys_columns = dict_table_get_low("SYS_COLUMNS"); sys_index = UT_LIST_GET_FIRST(sys_columns->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); buf = mem_heap_alloc(heap, 8); mach_write_to_8(buf, table->id); dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0); field = rec_get_nth_field(rec, 1, &len); ut_ad(len == 4); ut_a(i == mach_read_from_4(field)); ut_a(0 == ut_strcmp("NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_columns), 4))->name)); field = rec_get_nth_field(rec, 4, &len); name_buf = mem_heap_alloc(heap, len + 1); ut_memcpy(name_buf, field, len); name_buf[len] = '\0'; name = name_buf; field = rec_get_nth_field(rec, 5, &len); mtype = mach_read_from_4(field); field = rec_get_nth_field(rec, 6, &len); prtype = mach_read_from_4(field); field = rec_get_nth_field(rec, 7, &len); col_len = mach_read_from_4(field); ut_a(0 == ut_strcmp("PREC", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_columns), 8))->name)); field = rec_get_nth_field(rec, 8, &len); prec = mach_read_from_4(field); dict_mem_table_add_col(table, name, mtype, prtype, col_len, prec); btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
dict_table_t* dict_load_table_on_id( /*==================*/ /* out: table; NULL if table does not exist */ dulint table_id) /* in: table id */ { byte id_buf[8]; btr_pcur_t pcur; mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sys_table_ids; dict_table_t* sys_tables; rec_t* rec; byte* field; ulint len; dict_table_t* table; char* name; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); /* NOTE that the operation of this function is protected by the dictionary mutex, and therefore no deadlocks can occur with other dictionary operations. */ mtr_start(&mtr); /*---------------------------------------------------*/ /* Get the secondary index based on ID for table SYS_TABLES */ sys_tables = dict_sys->sys_tables; sys_table_ids = dict_table_get_next_index( dict_table_get_first_index(sys_tables)); heap = mem_heap_create(256); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); /* Write the table id in byte format to id_buf */ mach_write_to_8(id_buf, table_id); dfield_set_data(dfield, id_buf, 8); dict_index_copy_types(tuple, sys_table_ids, 1); btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec)) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } /*---------------------------------------------------*/ /* Now we have the record in the secondary index containing the table ID and NAME */ rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); /* Check if the table id in record is the one searched for */ if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) { btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } /* Now we get the table name from the record */ field = rec_get_nth_field(rec, 1, &len); name = mem_heap_alloc(heap, len + 1); ut_memcpy(name, field, len); name[len] = '\0'; /* Load the table definition to memory */ table = dict_load_table(name); ut_a(table); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(table); }