📄 fil0fil.c
字号:
voidfil_ibuf_init_at_db_start(void)/*===========================*/{ fil_space_t* space; space = UT_LIST_GET_FIRST(fil_system->space_list); ut_a(space); ut_a(space->purpose == FIL_TABLESPACE); space->ibuf_data = ibuf_data_init_for_space(space->id);}/********************************************************************Writes the flushed lsn and the latest archived log number to the page headerof the first page of a data file. */staticulintfil_write_lsn_and_arch_no_to_file(/*==============================*/ ulint space_id, /* in: space number */ ulint sum_of_sizes, /* in: combined size of previous files in space, in database pages */ dulint lsn, /* in: lsn to write */ ulint arch_log_no /* in: archived log number to write */ __attribute__((unused))){ byte* buf1; byte* buf; buf1 = mem_alloc(2 * UNIV_PAGE_SIZE); buf = ut_align(buf1, UNIV_PAGE_SIZE); fil_read(TRUE, space_id, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL); mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN, lsn); fil_write(TRUE, space_id, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL); return(DB_SUCCESS); }/********************************************************************Writes the flushed lsn and the latest archived log number to the pageheader of the first page of each data file in the system tablespace. */ulintfil_write_flushed_lsn_to_data_files(/*================================*/ /* out: DB_SUCCESS or error number */ dulint lsn, /* in: lsn to write */ ulint arch_log_no) /* in: latest archived log file number */{ fil_space_t* space; fil_node_t* node; ulint sum_of_sizes; ulint err; mutex_enter(&(fil_system->mutex)); space = UT_LIST_GET_FIRST(fil_system->space_list); while (space) { /* We only write the lsn to all existing data files which have been open during the lifetime of the mysqld process; they are represented by the space objects in the tablespace memory cache. Note that all data files in the system tablespace 0 are always open. */ if (space->purpose == FIL_TABLESPACE && space->id == 0) { sum_of_sizes = 0; node = UT_LIST_GET_FIRST(space->chain); while (node) { mutex_exit(&(fil_system->mutex)); err = fil_write_lsn_and_arch_no_to_file( space->id, sum_of_sizes, lsn, arch_log_no); if (err != DB_SUCCESS) { return(err); } mutex_enter(&(fil_system->mutex)); sum_of_sizes += node->size; node = UT_LIST_GET_NEXT(chain, node); } } space = UT_LIST_GET_NEXT(space_list, space); } mutex_exit(&(fil_system->mutex)); return(DB_SUCCESS);}/***********************************************************************Reads the flushed lsn and arch no fields from a data file at databasestartup. */voidfil_read_flushed_lsn_and_arch_log_no(/*=================================*/ os_file_t data_file, /* in: open data file */ ibool one_read_already, /* in: TRUE if min and max parameters below already contain sensible data */#ifdef UNIV_LOG_ARCHIVE ulint* min_arch_log_no, /* in/out: */ ulint* max_arch_log_no, /* in/out: */#endif /* UNIV_LOG_ARCHIVE */ dulint* min_flushed_lsn, /* in/out: */ dulint* max_flushed_lsn) /* in/out: */{ byte* buf; byte* buf2; dulint flushed_lsn; buf2 = ut_malloc(2 * UNIV_PAGE_SIZE); /* Align the memory for a possible read from a raw device */ buf = ut_align(buf2, UNIV_PAGE_SIZE); os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE); flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN); ut_free(buf2); if (!one_read_already) { *min_flushed_lsn = flushed_lsn; *max_flushed_lsn = flushed_lsn;#ifdef UNIV_LOG_ARCHIVE *min_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no;#endif /* UNIV_LOG_ARCHIVE */ return; } if (ut_dulint_cmp(*min_flushed_lsn, flushed_lsn) > 0) { *min_flushed_lsn = flushed_lsn; } if (ut_dulint_cmp(*max_flushed_lsn, flushed_lsn) < 0) { *max_flushed_lsn = flushed_lsn; }#ifdef UNIV_LOG_ARCHIVE if (*min_arch_log_no > arch_log_no) { *min_arch_log_no = arch_log_no; } if (*max_arch_log_no < arch_log_no) { *max_arch_log_no = arch_log_no; }#endif /* UNIV_LOG_ARCHIVE */}/*================ SINGLE-TABLE TABLESPACES ==========================*//***********************************************************************Increments the count of pending insert buffer page merges, if space is notbeing deleted. */iboolfil_inc_pending_ibuf_merges(/*========================*/ /* out: TRUE if being deleted, and ibuf merges should be skipped */ ulint id) /* in: space id */{ fil_system_t* system = fil_system; fil_space_t* space; mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); if (space == NULL) { fprintf(stderr,"InnoDB: Error: trying to do ibuf merge to a dropped tablespace %lu\n", (ulong) id); } if (space == NULL || space->stop_ibuf_merges) { mutex_exit(&(system->mutex)); return(TRUE); } space->n_pending_ibuf_merges++; mutex_exit(&(system->mutex)); return(FALSE);}/***********************************************************************Decrements the count of pending insert buffer page merges. */voidfil_decr_pending_ibuf_merges(/*========================*/ ulint id) /* in: space id */{ fil_system_t* system = fil_system; fil_space_t* space; mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); if (space == NULL) { fprintf(stderr,"InnoDB: Error: decrementing ibuf merge of a dropped tablespace %lu\n", (ulong) id); } if (space != NULL) { space->n_pending_ibuf_merges--; } mutex_exit(&(system->mutex));}/************************************************************Creates the database directory for a table if it does not exist yet. */staticvoidfil_create_directory_for_tablename(/*===============================*/ const char* name) /* in: name in the standard 'databasename/tablename' format */{ const char* namend; char* path; ulint len; len = strlen(fil_path_to_mysql_datadir); namend = strchr(name, '/'); ut_a(namend); path = mem_alloc(len + (namend - name) + 2); memcpy(path, fil_path_to_mysql_datadir, len); path[len] = '/'; memcpy(path + len + 1, name, namend - name); path[len + (namend - name) + 1] = 0; srv_normalize_path_for_win(path); ut_a(os_file_create_directory(path, FALSE)); mem_free(path);}#ifndef UNIV_HOTBACKUP/************************************************************Writes a log record about an .ibd file create/rename/delete. */staticvoidfil_op_write_log(/*=============*/ ulint type, /* in: MLOG_FILE_CREATE, MLOG_FILE_DELETE, or MLOG_FILE_RENAME */ ulint space_id, /* in: space id */ const char* name, /* in: table name in the familiar 'databasename/tablename' format, or the file path in the case of MLOG_FILE_DELETE */ const char* new_name, /* in: if type is MLOG_FILE_RENAME, the new table name in the 'databasename/tablename' format */ mtr_t* mtr) /* in: mini-transaction handle */{ byte* log_ptr; ulint len; log_ptr = mlog_open(mtr, 11 + 2); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: in that case mlog_open returns NULL */ return; } log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0, log_ptr, mtr); /* Let us store the strings as null-terminated for easier readability and handling */ len = strlen(name) + 1; mach_write_to_2(log_ptr, len); log_ptr += 2; mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, (byte*) name, len); if (type == MLOG_FILE_RENAME) { ulint len = strlen(new_name) + 1; log_ptr = mlog_open(mtr, 2 + len); ut_a(log_ptr); mach_write_to_2(log_ptr, len); log_ptr += 2; mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, (byte*) new_name, len); }}#endif/***********************************************************************Parses the body of a log record written about an .ibd file operation. That is,the log record part after the standard (type, space id, page no) header of thelog record.If desired, also replays the delete or rename operation if the .ibd fileexists and the space id in it matches. Replays the create operation if a fileat that path does not exist yet. If the database directory for the file to becreated does not exist, then we create the directory, too.Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to thedatadir that we should use in replaying the file operations. */byte*fil_op_log_parse_or_replay(/*=======================*/ /* out: end of log record, or NULL if the record was not completely contained between ptr and end_ptr */ byte* ptr, /* in: buffer containing the log record body, or an initial segment of it, if the record does not fir completely between ptr and end_ptr */ byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ ibool do_replay, /* in: TRUE if we want to replay the operation, and not just parse the log record */ ulint space_id) /* in: if do_replay is TRUE, the space id of the tablespace in question; otherwise ignored */{ ulint name_len; ulint new_name_len; const char* name; const char* new_name = NULL; if (end_ptr < ptr + 2) { return(NULL); } name_len = mach_read_from_2(ptr); ptr += 2; if (end_ptr < ptr + name_len) { return(NULL); } name = (const char*) ptr; ptr += name_len; if (type == MLOG_FILE_RENAME) { if (end_ptr < ptr + 2) { return(NULL); } new_name_len = mach_read_from_2(ptr); ptr += 2; if (end_ptr < ptr + new_name_len) { return(NULL); } new_name = (const char*) ptr; ptr += new_name_len; } /* We managed to parse a full log record body *//* printf("Parsed log rec of type %lu space %lu\n" "name %s\n", type, space_id, name); if (type == MLOG_FILE_RENAME) { printf("new name %s\n", new_name); }*/ if (do_replay == FALSE) { return(ptr); } /* Let us try to perform the file operation, if sensible. Note that ibbackup has at this stage already read in all space id info to the fil0fil.c data structures. NOTE that our algorithm is not guaranteed to work correctly if there were renames of tables during the backup. See ibbackup code for more on the problem. */ if (type == MLOG_FILE_DELETE) { if (fil_tablespace_exists_in_mem(space_id)) { ut_a(fil_delete_tablespace(space_id)); } } else if (type == MLOG_FILE_RENAME) { /* We do the rename based on space id, not old file name; this should guarantee that after the log replay each .ibd file has the correct name for the latest log sequence number; the proof is left as an exercise :) */ if (fil_tablespace_exists_in_mem(space_id)) { /* Create the database directory for the new name, if it does not exist yet */ fil_create_directory_for_tablename(new_name); /* Rename the table if there is not yet a tablespace with the same name */ if (fil_get_space_id_for_table(new_name) == ULINT_UNDEFINED) { /* We do not care of the old name, that is why we pass NULL as the first argument */ ut_a(fil_rename_tablespace(NULL, space_id, new_name)); } } } else { ut_a(type == MLOG_FILE_CREATE); if (fil_tablespace_exists_in_mem(space_id)) { /* Do nothing */ } else if (fil_get_space_id_for_table(name) != ULINT_UNDEFINED) { /* Do nothing */ } else { /* Create the database directory for name, if it does not exist yet */ fil_create_directory_for_tablename(name); ut_a(space_id != 0); ut_a(DB_SUCCESS == fil_create_new_single_table_tablespace( &space_id, name, FALSE, FIL_IBD_FILE_INITIAL_SIZE)); } } return(ptr);}/***********************************************************************Deletes a single-table tablespace. The tablespace must be cached in thememory cache. */iboolfil_delete_tablespace(/*==================*/ /* out: TRUE if success */ ulint id) /* in: space id */{ fil_system_t* system = fil_system; ibool success; fil_space_t* space; fil_node_t* node; ulint count = 0; char* path; ut_a(id != 0);stop_ibuf_merges: mutex_enter(&(system->mutex)); HASH_SEARCH(hash, system->spaces, id, space, space->id == id); if (space != NULL) { space->stop_ibuf_merges = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -