Ejemplo n.º 1
0
/********************************************************//**
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);
}
Ejemplo n.º 2
0
/********************************************************//**
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);
}
Ejemplo n.º 3
0
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);
}	
Ejemplo n.º 4
0
/********************************************************//**
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
/********************************************************//**
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
/* 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;
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
/**********************************************************************//**
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);
	}
}
Ejemplo n.º 11
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);
		/* 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);
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
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);
}