/********************************************************//** Writes the initial part of a log record consisting of one-byte item type and four-byte space and page numbers. Also pushes info to the mtr memo that a buffer page has been modified. */ UNIV_INTERN void mlog_write_initial_log_record( /*==========================*/ const byte* ptr, /*!< in: pointer to (inside) a buffer frame holding the file page where modification is made */ byte type, /*!< in: log item type: MLOG_1BYTE, ... */ mtr_t* mtr) /*!< in: mini-transaction handle */ { byte* log_ptr; ut_ad(type <= MLOG_BIGGEST_TYPE); ut_ad(type > MLOG_8BYTES); log_ptr = mlog_open(mtr, 11); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr); mlog_close(mtr, log_ptr); }
/********************************************************//** Logs a write of a string to a file page buffered in the buffer pool. Writes the corresponding log record to the mini-transaction log. */ UNIV_INTERN void mlog_log_string( /*============*/ byte* ptr, /*!< in: pointer written to */ ulint len, /*!< in: string length */ mtr_t* mtr) /*!< in: mini-transaction handle */ { byte* log_ptr; ut_ad(ptr && mtr); ut_ad(len <= UNIV_PAGE_SIZE); log_ptr = mlog_open(mtr, 30); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING, log_ptr, mtr); mach_write_to_2(log_ptr, page_offset(ptr)); log_ptr += 2; mach_write_to_2(log_ptr, len); log_ptr += 2; mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, ptr, len); }
void mlog_write_initial_log_record( /*==========================*/ byte* ptr, /* in: pointer to (inside) a buffer frame holding the file page where modification is made */ byte type, /* in: log item type: MLOG_1BYTE, ... */ mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; ut_ad(type <= MLOG_BIGGEST_TYPE); ut_ad(type > MLOG_8BYTES); if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) { fprintf(stderr, "InnoDB: Error: trying to write to a stray memory location %p\n", ptr); ut_error; } log_ptr = mlog_open(mtr, 11); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr); mlog_close(mtr, log_ptr); }
/********************************************************//** 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_ulint( /*=============*/ byte* ptr, /* in: pointer where to write */ ulint val, /* in: value to write */ byte type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) { fprintf(stderr, "InnoDB: Error: trying to write to" " a stray memory location %p\n", (void*) ptr); ut_error; } if (type == MLOG_1BYTE) { mach_write_to_1(ptr, val); } else if (type == MLOG_2BYTES) { mach_write_to_2(ptr, val); } else { ut_ad(type == MLOG_4BYTES); mach_write_to_4(ptr, val); } log_ptr = mlog_open(mtr, 11 + 2 + 5); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr); mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; log_ptr += mach_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); }
/********************************************************//** Writes 1 - 4 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_ulint( /*=============*/ byte* ptr, /*!< in: pointer where to write */ ulint val, /*!< in: value to write */ byte type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ mtr_t* mtr) /*!< in: mini-transaction handle */ { byte* log_ptr; switch (type) { case MLOG_1BYTE: mach_write_to_1(ptr, val); break; case MLOG_2BYTES: mach_write_to_2(ptr, val); break; case MLOG_4BYTES: mach_write_to_4(ptr, val); break; default: ut_error; } log_ptr = mlog_open(mtr, 11 + 2 + 5); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr); mach_write_to_2(log_ptr, page_offset(ptr)); log_ptr += 2; log_ptr += mach_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); }
void mlog_write_string( /*==============*/ byte* ptr, /* in: pointer where to write */ const byte* str, /* in: string to write */ ulint len, /* in: string length */ 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); ut_a(len < UNIV_PAGE_SIZE); ut_memcpy(ptr, str, len); log_ptr = mlog_open(mtr, 30); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING, log_ptr, mtr); mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; mach_write_to_2(log_ptr, len); log_ptr += 2; mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, str, len); }
/* name : prog_init * parameters : none, global parameters * description: some program initialisation * returns : 0 if ok, -1 on error * remarks : */ int prog_init ( void ) { /* daemon */ if ( (g_par.flags&PROBE_DAEMON) && (daemon ( 0, 0 ) < 0) ) { errorf ( "[%s] failed to run as daemon!\n\n", g_par.progname ); return -1; } #if 0 if ( chdir ( "/tmp" ) <0 ) mlogf( 0, "[%s] ERROR cannot change working dir: %s\n", g_par.progname, strerror(errno) ); #endif /* open logfile */ mlog_set_vlevel( g_par.vlevel ); if ( g_par.logfile ) (void) mlog_open( g_par.logfile, NULL ); mlogf( 1, "\nIPFIX probe (%s)\n\n", __DATE__ ); /* signal handler */ signal( SIGKILL, exit_func ); signal( SIGTERM, exit_func ); signal( SIGINT, exit_func ); /* init exporter */ if ( export_init( &g_probe ) <0 ) { return -1; } /* init pcap sniffing */ if ( input_init( &g_probe, g_par.flags ) <0 ) { return -1; } return 0; }
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); }
/**********************************************************************//** Writes the mtr log entry of the inserted undo log record on the undo log page. */ UNIV_INLINE void trx_undof_page_add_undo_rec_log( /*============================*/ page_t* undo_page, /*!< in: undo log page */ ulint old_free, /*!< in: start offset of the inserted entry */ ulint new_free, /*!< in: end offset of the entry */ mtr_t* mtr) /*!< in: mtr */ { byte* log_ptr; const byte* log_end; ulint len; log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN); if (log_ptr == NULL) { return; } log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN]; log_ptr = mlog_write_initial_log_record_fast( undo_page, MLOG_UNDO_INSERT, log_ptr, mtr); len = new_free - old_free - 4; mach_write_to_2(log_ptr, len); log_ptr += 2; if (log_ptr + len <= log_end) { memcpy(log_ptr, undo_page + old_free + 2, len); mlog_close(mtr, log_ptr + len); } else { mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, undo_page + old_free + 2, len); } }
/********************************************************//** Opens a buffer for mlog, writes the initial log record and, if needed, the field lengths of an index. @return buffer, NULL if log mode MTR_LOG_NONE */ UNIV_INTERN byte* mlog_open_and_write_index( /*======================*/ mtr_t* mtr, /*!< in: mtr */ const byte* rec, /*!< in: index record or page */ dict_index_t* index, /*!< in: record descriptor */ byte type, /*!< in: log item type */ ulint size) /*!< in: requested buffer size in bytes (if 0, calls mlog_close() and returns NULL) */ { byte* log_ptr; const byte* log_start; const byte* log_end; ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); if (!page_rec_is_comp(rec)) { log_start = log_ptr = mlog_open(mtr, 11 + size); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_ptr = mlog_write_initial_log_record_fast(rec, type, log_ptr, mtr); log_end = log_ptr + 11 + size; } else { ulint i; ulint n = dict_index_get_n_fields(index); /* total size needed */ ulint total = 11 + size + (n + 2) * 2; ulint alloc = total; /* allocate at most DYN_ARRAY_DATA_SIZE at a time */ if (alloc > DYN_ARRAY_DATA_SIZE) { alloc = DYN_ARRAY_DATA_SIZE; } log_start = log_ptr = mlog_open(mtr, alloc); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_end = log_ptr + alloc; log_ptr = mlog_write_initial_log_record_fast(rec, type, log_ptr, mtr); mach_write_to_2(log_ptr, n); log_ptr += 2; mach_write_to_2(log_ptr, dict_index_get_n_unique_in_tree(index)); log_ptr += 2; for (i = 0; i < n; i++) { dict_field_t* field; const dict_col_t* col; ulint len; field = dict_index_get_nth_field(index, i); col = dict_field_get_col(field); len = field->fixed_len; ut_ad(len < 0x7fff); if (len == 0 && (col->len > 255 || col->mtype == DATA_BLOB)) { /* variable-length field with maximum length > 255 */ len = 0x7fff; } if (col->prtype & DATA_NOT_NULL) { len |= 0x8000; } if (log_ptr + 2 > log_end) { mlog_close(mtr, log_ptr); ut_a(total > (ulint) (log_ptr - log_start)); total -= log_ptr - log_start; alloc = total; if (alloc > DYN_ARRAY_DATA_SIZE) { alloc = DYN_ARRAY_DATA_SIZE; } log_start = log_ptr = mlog_open(mtr, alloc); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_end = log_ptr + alloc; } mach_write_to_2(log_ptr, len); log_ptr += 2; } } if (size == 0) { mlog_close(mtr, log_ptr); log_ptr = NULL; } else if (log_ptr + size > log_end) { mlog_close(mtr, log_ptr); log_ptr = mlog_open(mtr, size); } return(log_ptr); }
void row_upd_index_write_log( /*====================*/ upd_t* update, /* in: update vector */ byte* log_ptr,/* in: pointer to mlog buffer: must contain at least MLOG_BUF_MARGIN bytes of free space; the buffer is closed within this function */ mtr_t* mtr) /* in: mtr into whose log to write */ { upd_field_t* upd_field; dfield_t* new_val; ulint len; ulint n_fields; byte* buf_end; ulint i; n_fields = upd_get_n_fields(update); buf_end = log_ptr + MLOG_BUF_MARGIN; mach_write_to_1(log_ptr, update->info_bits); log_ptr++; log_ptr += mach_write_compressed(log_ptr, n_fields); for (i = 0; i < n_fields; i++) { ut_ad(MLOG_BUF_MARGIN > 30); if (log_ptr + 30 > buf_end) { mlog_close(mtr, log_ptr); log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); buf_end = log_ptr + MLOG_BUF_MARGIN; } upd_field = upd_get_nth_field(update, i); new_val = &(upd_field->new_val); len = new_val->len; log_ptr += mach_write_compressed(log_ptr, upd_field->field_no); log_ptr += mach_write_compressed(log_ptr, len); if (len != UNIV_SQL_NULL) { if (log_ptr + len < buf_end) { ut_memcpy(log_ptr, new_val->data, len); log_ptr += len; } else { mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, new_val->data, len); log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); buf_end = log_ptr + MLOG_BUF_MARGIN; } } } mlog_close(mtr, log_ptr); }
int main (int argc, char *argv[]) { char arg; /* short options: character */ int loptidx=0; /* long options: arg==0 and index */ char opt[] = "64stuhl:p:vo:f:"; #ifdef HAVE_GETOPT_LONG struct option lopt[] = { { "dbhost", 1, 0, 0}, { "dbname", 1, 0, 0}, { "dbuser", 1, 0, 0}, { "dbpw", 1, 0, 0}, { "db", 0, 0, 0}, { "ssl", 0, 0, 0}, { "key", 1, 0, 0}, { "cert", 1, 0, 0}, { "cafile", 1, 0, 0}, { "cadir", 1, 0, 0}, { "help", 0, 0, 0}, { 0, 0, 0, 0 } }; #endif /** set default options */ par.tcp = 0; par.udp = 0; par.sctp = 0; par.ssl = 0; par.cafile = CAFILE; par.cadir = CADIR; par.keyfile = KEYFILE; par.certfile= CERTFILE; par.port = 0; par.family = AF_UNSPEC; par.logfile = NULL; par.maxcon = 10; par.datadir = NULL; par.datafile = NULL; par.dbexport = 0; par.dbhost = DFLT_MYSQL_HOST; par.dbname = DFLT_MYSQL_DBNAME; par.dbuser = DFLT_MYSQL_USER; par.dbpw = DFLT_MYSQL_PASSWORD; snprintf( par.progname, sizeof(par.progname), "%s", basename( argv[0]) ); /* --- command line parsing --- */ #ifdef HAVE_GETOPT_LONG while ((arg=getopt_long( argc, argv, opt, lopt, &loptidx)) >=0 ) #else while( (arg=getopt( argc, argv, opt )) != EOF ) #endif { switch (arg) { case 0: switch (loptidx) { case 0: /* dbhost */ par.dbhost = optarg; break; case 1: /* dbname */ par.dbname = optarg; break; case 2: /* dbuser */ par.dbuser = optarg; break; case 3: /* dbpw */ par.dbpw = optarg; break; case 4: /* db */ par.dbexport = 1; break; case 5: /* ssl */ par.ssl = 1; break; case 6: /* key */ par.keyfile = optarg; break; case 7: /* cert */ par.certfile = optarg; break; case 8: /* cafile */ par.cafile = optarg; break; case 9: /* cadir */ par.cadir = optarg; break; case 10: usage(par.progname); exit(1); } break; case '4': #ifdef INET6 par.family = (par.family==AF_INET6)? AF_UNSPEC : AF_INET; break; case '6': par.family = (par.family==AF_INET)? AF_UNSPEC : AF_INET6; #endif break; case 'd': par.dbexport = 1; break; case 'l': par.logfile = optarg; break; case 's': par.sctp ++; break; case 't': par.tcp ++; break; case 'u': par.udp ++; break; case 'o': par.datadir = optarg; if ( access( optarg, W_OK|X_OK ) <0 ) { fprintf( stderr, "cannot access dir '%s': %s!\n", optarg, strerror(errno) ); exit(1); } break; case 'f': par.datafile = optarg; break; case 'p': if ((par.port=atoi(optarg)) <0) { fprintf( stderr, "Invalid -p argument!\n" ); exit(1); } break; case 'v': verbose_level ++; break; case 'h': default: usage(par.progname); exit(1); } } if ( !par.udp && !par.tcp && !par.sctp ) par.tcp++; if ( !par.dbexport && !par.datadir ) { fprintf( stderr, "info: message dump, no data storage.\n" ); fflush( stderr ); } if ( par.port==0 ) { par.port = par.ssl?IPFIX_TLS_PORTNO:IPFIX_PORTNO; } /** init loggin */ mlog_set_vlevel( verbose_level ); if ( par.logfile ) (void) mlog_open( par.logfile, NULL ); if ( (!par.dbexport && !par.datadir) || (verbose_level >2) ) (void) ipfix_col_start_msglog( stderr ); mlogf( 1, "[%s] listen on port %d, write to %s ...\n", par.progname, par.port, par.dbexport?"database":par.datadir?"files":"stdout" ); /** init ipfix lib */ if ( ipfix_init() <0 ) { fprintf( stderr, "ipfix_init() failed: %s\n", strerror(errno) ); exit(1); } if ( ipfix_add_vendor_information_elements( ipfix_ft_fokus ) <0 ) { fprintf( stderr, "ipfix_add_ie() failed: %s\n", strerror(errno) ); exit(1); } /** signal handler signal( SIGSEGV, sig_func ); */ signal( SIGKILL, sig_func ); signal( SIGTERM, sig_func ); signal( SIGINT, sig_func ); /** do the work */ if ( do_collect() <0 ) exit_func(1); exit_func(0); return 0; }
/********************************************************//** Opens a buffer for mlog, writes the initial log record and, if needed, the field lengths of an index. @return buffer, NULL if log mode MTR_LOG_NONE */ UNIV_INTERN byte* mlog_open_and_write_index( /*======================*/ mtr_t* mtr, /*!< in: mtr */ const byte* rec, /*!< in: index record or page */ dict_index_t* index, /*!< in: record descriptor */ byte type, /*!< in: log item type */ ulint size) /*!< in: requested buffer size in bytes (if 0, calls mlog_close() and returns NULL) */ { byte* log_ptr; const byte* log_start; const byte* log_end; ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); if (!page_rec_is_comp(rec)) { log_start = log_ptr = mlog_open(mtr, 11 + size); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_ptr = mlog_write_initial_log_record_fast(rec, type, log_ptr, mtr); log_end = log_ptr + 11 + size; } else { ulint i; ulint n = dict_index_get_n_fields(index); ibool is_gcs_cluster = dict_index_is_gcs_clust_after_alter_table(index); /* total size needed */ /* redo日志有可能需要多两字节,total需要根据实际情况分配空间! */ ulint total = 11 + size + (n + 2 + (is_gcs_cluster ? 1 : 0)) * 2; ulint alloc = total; /* allocate at most DYN_ARRAY_DATA_SIZE at a time */ if (alloc > DYN_ARRAY_DATA_SIZE) { alloc = DYN_ARRAY_DATA_SIZE; } log_start = log_ptr = mlog_open(mtr, alloc); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_end = log_ptr + alloc; log_ptr = mlog_write_initial_log_record_fast(rec, type, log_ptr, mtr); /* 在第一次alter table前,所有gcs表可以当成compact表,即使是redo过程,这样redo log也兼容! */ if (is_gcs_cluster) { //ut_ad(rec_is_gcs(rec) || rec == page_align(rec) || rec_get_status(rec) & REC_STATUS_NODE_PTR); /* rec有可能就是页头,如日志MLOG_COMP_LIST_END_COPY_CREATED */ mach_write_to_2(log_ptr, n | 0x8000); /* 标记是gcs表 */ } else { ut_ad(rec == page_align(rec) || !rec_is_gcs(rec)); mach_write_to_2(log_ptr, n); } /* 对于gcs聚集索引,记录第一次alter table前聚集索引的字段数 */ if (is_gcs_cluster) { log_ptr += 2; mach_write_to_2(log_ptr, (ulint)index->n_fields_before_alter); ut_ad(!index->n_fields_before_alter == !dict_index_is_gcs_clust_after_alter_table(index)); } log_ptr += 2; mach_write_to_2(log_ptr, dict_index_get_n_unique_in_tree(index)); log_ptr += 2; for (i = 0; i < n; i++) { dict_field_t* field; const dict_col_t* col; ulint len; field = dict_index_get_nth_field(index, i); col = dict_field_get_col(field); len = field->fixed_len; ut_ad(len < 0x7fff); if (len == 0 && (col->len > 255 || col->mtype == DATA_BLOB)) { /* variable-length field with maximum length > 255 */ len = 0x7fff; } if (col->prtype & DATA_NOT_NULL) { len |= 0x8000; } if (log_ptr + 2 > log_end) { mlog_close(mtr, log_ptr); ut_a(total > (ulint) (log_ptr - log_start)); total -= log_ptr - log_start; alloc = total; if (alloc > DYN_ARRAY_DATA_SIZE) { alloc = DYN_ARRAY_DATA_SIZE; } log_start = log_ptr = mlog_open(mtr, alloc); if (!log_ptr) { return(NULL); /* logging is disabled */ } log_end = log_ptr + alloc; } mach_write_to_2(log_ptr, len); log_ptr += 2; } } if (size == 0) { mlog_close(mtr, log_ptr); log_ptr = NULL; } else if (log_ptr + size > log_end) { mlog_close(mtr, log_ptr); log_ptr = mlog_open(mtr, size); } return(log_ptr); }