64 # define ROW_LOG_APPLY_PRINT
67 #ifdef ROW_LOG_APPLY_PRINT
69 static bool row_log_apply_print;
73 #define ROW_LOG_HEADER_SIZE 2
95 old_offset (0), free_offset (offset_arg),
96 offset (BLOB_FREED) {}
99 offset (BLOB_FREED) {}
110 ut_ad(offset < offset_arg);
111 ut_ad(offset != BLOB_FREED);
112 ut_d(old_offset = offset);
113 ut_d(free_offset = offset_arg);
119 ut_ad(free_offset <= offset_arg);
120 ut_d(old_offset = offset);
129 ut_ad(offset_arg > 0);
131 ut_ad(offset_arg < BLOB_FREED);
132 return(offset_arg < offset);
136 static const ulonglong BLOB_FREED = ~0ULL;
139 ulonglong old_offset;
141 ulonglong free_offset;
217 ut_ad(dtuple_validate(tuple));
219 #ifdef UNIV_SYNC_DEBUG
236 ut_ad(size >= extra_size);
237 ut_ad(size <= sizeof log->tail.buf);
240 + (extra_size >= 0x80) + size
241 + (trx_id ? DATA_TRX_ID_LEN : 0);
244 mutex_enter(&log->
mutex);
255 if (mrec_size > avail_size) {
264 b += DATA_TRX_ID_LEN;
269 if (extra_size < 0x80) {
270 *b++ = (byte) extra_size;
272 ut_ad(extra_size < 0x8000);
273 *b++ = (byte) (0x80 | (extra_size >> 8));
274 *b++ = (byte) extra_size;
281 if (mrec_size >= avail_size) {
291 if (mrec_size == avail_size) {
300 "(modification log)",
313 mrec_size - avail_size);
314 log->
tail.
bytes = mrec_size - avail_size;
321 mutex_exit(&log->
mutex);
342 static __attribute__((nonnull, warn_unused_result))
350 mutex_enter(&log->mutex);
352 UNIV_MEM_INVALID(log->tail.buf,
sizeof log->tail.buf);
354 if (log->error != DB_SUCCESS) {
355 mutex_exit(&log->mutex);
363 return(log->tail.buf);
365 return(log->tail.block + log->tail.bytes);
371 static __attribute__((nonnull))
373 row_log_table_close_func(
382 ut_ad(mutex_own(&log->mutex));
397 ut_ad(b == log->tail.buf + size);
398 memcpy(log->tail.block + log->tail.bytes,
399 log->tail.buf, avail);
403 "(modification log)",
412 memcpy(log->tail.block, log->tail.buf + avail, size - avail);
413 log->tail.bytes = size - avail;
415 log->tail.bytes +=
size;
416 ut_ad(b == log->tail.block + log->tail.bytes);
419 log->tail.total +=
size;
420 UNIV_MEM_INVALID(log->tail.buf,
sizeof log->tail.buf);
421 mutex_exit(&log->mutex);
425 # define row_log_table_close(log, b, size, avail) \
426 row_log_table_close_func(log, b, size, avail)
428 # define row_log_table_close(log, b, size, avail) \
429 row_log_table_close_func(log, size, avail)
448 ulint old_pk_extra_size;
458 ut_ad(rec_offs_validate(rec, index, offsets));
461 #ifdef UNIV_SYNC_DEBUG
462 ut_ad(rw_lock_own(&index->
lock, RW_LOCK_SHARED)
463 || rw_lock_own(&index->
lock, RW_LOCK_EX));
473 dict_index_t* new_index = dict_table_get_first_index(new_table);
488 + DTUPLE_EST_ALLOC(new_index->
n_uniq + 1));
493 for (ulint
i = 0;
i < new_index->
n_uniq;
i++) {
495 const void* field = rec_get_nth_field(
496 rec, offsets,
i, &len);
497 dfield_t* dfield = dtuple_get_nth_field(
499 ut_ad(len != UNIV_SQL_NULL);
504 db_trx_id =
static_cast<byte*
>(
509 db_trx_id, DATA_TRX_ID_LEN);
526 const_cast<ulint&
>(old_pk->
n_fields)--;
529 dfield = dtuple_get_nth_field(old_pk, new_index->
n_uniq);
530 ut_ad(dfield_get_type(dfield)->mtype == DATA_SYS);
531 ut_ad(dfield_get_type(dfield)->prtype
532 == (DATA_NOT_NULL | DATA_TRX_ID));
539 ut_ad(DATA_TRX_ID_LEN == dtuple_get_nth_field(
540 old_pk, old_pk->
n_fields - 1)->len);
544 ut_ad(old_pk_extra_size < 0x100);
546 mrec_size = 4 + old_pk_size;
559 offsets, NULL, NULL, NULL, &ext, heap);
564 + ext->
n_ext *
sizeof(ulint)
565 + (ext->
n_ext - 1) *
sizeof ext->
len;
566 mrec_size += ext_size;
570 if (byte* b = row_log_table_open(index->
online_log,
571 mrec_size, &avail_size)) {
573 *b++ =
static_cast<byte
>(old_pk_extra_size);
580 b + old_pk_extra_size, new_index,
586 ulint cur_ext_size =
sizeof(*ext)
587 + (ext->
n_ext - 1) *
sizeof ext->
len;
589 memcpy(b, ext, cur_ext_size);
595 if (
const ulint* col_map =
597 for (ulint
i = 0;
i < ext->
n_ext;
i++) {
598 const_cast<ulint&
>(ext->
ext[
i]) =
599 col_map[ext->
ext[
i]];
603 memcpy(b, ext->
ext, ext->
n_ext *
sizeof(*ext->
ext));
604 b += ext->
n_ext *
sizeof(*ext->
ext);
606 ext_size -= cur_ext_size
608 memcpy(b, ext->
buf, ext_size);
623 row_log_table_low_redundant(
640 ulint old_pk_extra_size;
665 dfield = dtuple_get_nth_field(tuple,
i);
666 field = rec_get_nth_field_old(rec,
i, &len);
676 dfield = dtuple_get_nth_field(tuple,
i);
677 field = rec_get_nth_field_old(rec,
i, &len);
694 old_pk_extra_size = old_pk_size = 0;
698 ut_ad(DATA_TRX_ID_LEN == dtuple_get_nth_field(
699 old_pk, old_pk->
n_fields - 2)->len);
700 ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
701 old_pk, old_pk->
n_fields - 1)->len);
706 ut_ad(old_pk_extra_size < 0x100);
707 mrec_size += 1 + old_pk_size;
710 if (byte* b = row_log_table_open(index->
online_log,
711 mrec_size, &avail_size)) {
715 *b++ =
static_cast<byte
>(old_pk_extra_size);
718 b + old_pk_extra_size, new_index,
723 if (extra_size < 0x80) {
724 *b++ =
static_cast<byte
>(extra_size);
726 ut_ad(extra_size < 0x8000);
727 *b++ =
static_cast<byte
>(0x80 | (extra_size >> 8));
728 *b++ =
static_cast<byte
>(extra_size);
744 static __attribute__((nonnull(1,2,3)))
752 const ulint* offsets,
759 ulint old_pk_extra_size;
763 const dict_index_t* new_index = dict_table_get_first_index(
764 index->online_log->table);
768 ut_ad(rec_offs_validate(rec, index, offsets));
771 #ifdef UNIV_SYNC_DEBUG
772 ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
773 || rw_lock_own(&index->lock, RW_LOCK_EX));
781 || index->online_log->error != DB_SUCCESS) {
786 row_log_table_low_redundant(
787 rec, index, insert, old_pk, new_index);
794 omit_size = REC_N_NEW_EXTRA_BYTES;
801 if (insert || index->online_log->same_pk) {
803 old_pk_extra_size = old_pk_size = 0;
806 ut_ad(old_pk->n_fields == 2 + old_pk->n_fields_cmp);
807 ut_ad(DATA_TRX_ID_LEN == dtuple_get_nth_field(
808 old_pk, old_pk->n_fields - 2)->len);
809 ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
810 old_pk, old_pk->n_fields - 1)->len);
813 new_index, old_pk->
fields, old_pk->n_fields,
815 ut_ad(old_pk_extra_size < 0x100);
816 mrec_size += 1 + old_pk_size;
819 if (byte* b = row_log_table_open(index->online_log,
820 mrec_size, &avail_size)) {
824 *b++ =
static_cast<byte
>(old_pk_extra_size);
827 b + old_pk_extra_size, new_index,
828 old_pk->
fields, old_pk->n_fields);
832 if (extra_size < 0x80) {
833 *b++ =
static_cast<byte
>(extra_size);
835 ut_ad(extra_size < 0x8000);
836 *b++ =
static_cast<byte
>(0x80 | (extra_size >> 8));
837 *b++ =
static_cast<byte
>(extra_size);
846 index->online_log, b, mrec_size, avail_size);
861 const ulint* offsets,
865 row_log_table_low(rec, index, offsets,
false, old_pk);
875 row_log_table_get_pk_old_col(
878 const ulint* col_map,
881 for (ulint
i = 0;
i < table->
n_cols;
i++) {
882 if (col_no == col_map[
i]) {
883 return(dict_table_get_nth_col(table, i));
904 row_log_table_get_pk_col(
911 const ulint* offsets,
921 field = rec_get_nth_field(rec, offsets, i, &len);
923 if (len == UNIV_SQL_NULL) {
934 field_len = max_len + 1;
938 blob_field =
static_cast<byte*
>(
942 blob_field, field_len, zip_size, field, len);
943 if (len >= max_len + 1) {
968 const ulint* offsets,
976 ut_ad(!offsets || rec_offs_validate(rec, index, offsets));
977 #ifdef UNIV_SYNC_DEBUG
978 ut_ad(rw_lock_own(&index->
lock, RW_LOCK_SHARED)
979 || rw_lock_own(&index->
lock, RW_LOCK_EX));
990 mutex_enter(&log->
mutex);
993 if (log->
error == DB_SUCCESS) {
996 = dict_table_get_first_index(new_table);
997 const ulint new_n_uniq
1004 size += (1 + REC_OFFS_HEADER_SIZE
1009 for (ulint i = 0; i < new_n_uniq; i++) {
1015 DTUPLE_EST_ALLOC(new_n_uniq + 2) + size);
1019 offsets = rec_get_offsets(rec, index, NULL,
1020 ULINT_UNDEFINED, heap);
1030 for (ulint new_i = 0; new_i < new_n_uniq; new_i++) {
1036 ifield = dict_index_get_nth_field(new_index, new_i);
1037 dfield = dtuple_get_nth_field(tuple, new_i);
1043 = row_log_table_get_pk_old_col(
1047 if (i == ULINT_UNDEFINED) {
1053 log->
error = row_log_table_get_pk_col(
1054 col, ifield, dfield, *heap,
1055 rec, offsets, i, zip_size, max_len);
1057 if (log->
error != DB_SUCCESS) {
1082 prtype, mbminmaxlen,
1085 static_cast<const char*>(
1086 dfield_get_data(dfield)));
1093 const byte* trx_roll = rec
1097 trx_roll, DATA_TRX_ID_LEN);
1099 trx_roll + DATA_TRX_ID_LEN, DATA_ROLL_PTR_LEN);
1103 mutex_exit(&log->
mutex);
1118 const ulint* offsets)
1120 row_log_table_low(rec, index, offsets,
true, NULL);
1134 #ifdef UNIV_SYNC_DEBUG
1135 ut_ad(rw_lock_own(&index->
lock, RW_LOCK_EX));
1155 const page_no_map::value_type v(page_no,
1158 std::pair<page_no_map::iterator,bool> p = blobs->insert(v);
1162 ut_ad(p.first->first == page_no);
1163 p.first->second.blob_free(log_pos);
1179 #ifdef UNIV_SYNC_DEBUG
1180 ut_ad(rw_lock_own(&index->
lock, RW_LOCK_EX));
1191 page_no_map::iterator p = blobs->find(page_no);
1193 if (p != blobs->end()) {
1194 ut_ad(p->first == page_no);
1204 static __attribute__((nonnull, warn_unused_result))
1206 row_log_table_apply_convert_mrec(
1210 const ulint* offsets,
1220 if (log->add_cols) {
1225 dict_table_get_nth_col(log->table, i),
1226 dfield_get_type(dtuple_get_nth_field(row, i)));
1235 = dict_index_get_nth_field(index, i);
1252 if (col_no == ULINT_UNDEFINED) {
1258 = dtuple_get_nth_field(row, col_no);
1260 const byte* data= NULL;
1266 if (
const page_no_map* blobs = log->blobs) {
1267 data = rec_get_nth_field(
1268 mrec, offsets, i, &len);
1274 page_no_map::const_iterator p = blobs->find(
1276 if (p != blobs->end()
1277 && p->second.is_freed(log->head.total)) {
1298 data = rec_get_nth_field(mrec, offsets, i, &len);
1305 = dict_table_get_nth_col(log->table, col_no);
1310 ut_ad(!((new_col->
prtype ^ dfield_get_type(dfield)->prtype)
1317 if ((new_col->
prtype & DATA_NOT_NULL)
1325 dfield_get_type(dfield)->prtype = new_col->
prtype;
1327 ut_ad(dict_col_type_assert_equal(new_col,
1328 dfield_get_type(dfield)));
1332 *error = DB_SUCCESS;
1339 static __attribute__((nonnull, warn_unused_result))
1341 row_log_table_apply_insert_low(
1355 const row_log_t*log = dup->index->online_log;
1358 ut_ad(dtuple_validate(row));
1361 #ifdef ROW_LOG_APPLY_PRINT
1362 if (row_log_apply_print) {
1363 fprintf(stderr,
"table apply insert "
1364 IB_ID_FMT
" " IB_ID_FMT
"\n",
1370 static const ulint
flags
1392 if (!(index = dict_table_get_next_index(index))) {
1396 if (index->
type & DICT_FTS) {
1403 index, offsets_heap, heap, entry, trx_id, thr);
1404 }
while (error == DB_SUCCESS);
1412 static __attribute__((nonnull, warn_unused_result))
1414 row_log_table_apply_insert(
1418 const ulint* offsets,
1426 const row_log_t*log = dup->index->online_log;
1428 const dtuple_t* row = row_log_table_apply_convert_mrec(
1429 mrec, dup->index, offsets, log, heap, trx_id, &error);
1431 ut_ad(error == DB_SUCCESS || !row);
1434 ut_ad(error != DB_DUPLICATE_KEY);
1436 if (error != DB_SUCCESS)
1440 error = row_log_table_apply_insert_low(
1441 thr, row, trx_id, offsets_heap, heap, dup);
1442 if (error != DB_SUCCESS) {
1454 static __attribute__((nonnull(1, 2, 4, 5), warn_unused_result))
1456 row_log_table_apply_delete_low(
1460 const ulint* offsets,
1470 dict_index_t* index = btr_pcur_get_btr_cur(pcur)->index;
1474 #ifdef ROW_LOG_APPLY_PRINT
1475 if (row_log_apply_print) {
1476 fprintf(stderr,
"table apply delete "
1477 IB_ID_FMT
" " IB_ID_FMT
"\n",
1482 if (dict_table_get_next_index(index)) {
1485 ROW_COPY_DATA, index, btr_pcur_get_rec(pcur),
1486 offsets, NULL, NULL, NULL,
1487 save_ext ? NULL : &ext, heap);
1499 if (error != DB_SUCCESS) {
1503 while ((index = dict_table_get_next_index(index)) != NULL) {
1504 if (index->
type & DICT_FTS) {
1509 row, save_ext, index, heap);
1511 btr_pcur_open(index, entry, PAGE_CUR_LE,
1514 switch (btr_pcur_get_btr_cur(pcur)->flag) {
1541 btr_pcur_get_btr_cur(pcur),
1552 static __attribute__((nonnull(1, 3, 4, 5, 6, 7), warn_unused_result))
1554 row_log_table_apply_delete(
1561 const ulint* moffsets,
1569 dict_index_t* index = dict_table_get_first_index(new_table);
1584 for (ulint i = 0; i <= index->
n_uniq; i++) {
1587 field = rec_get_nth_field(mrec, moffsets, i, &len);
1588 ut_ad(len != UNIV_SQL_NULL);
1594 btr_pcur_open(index, old_pk, PAGE_CUR_LE,
1597 switch (btr_pcur_get_btr_cur(&pcur)->flag) {
1621 offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL,
1622 ULINT_UNDEFINED, &offsets_heap);
1623 #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
1632 const void* mrec_trx_id
1633 = rec_get_nth_field(mrec, moffsets, trx_id_col, &len);
1634 ut_ad(len == DATA_TRX_ID_LEN);
1635 const void* rec_trx_id
1636 = rec_get_nth_field(btr_pcur_get_rec(&pcur), offsets,
1638 ut_ad(len == DATA_TRX_ID_LEN);
1639 if (memcmp(mrec_trx_id, rec_trx_id, DATA_TRX_ID_LEN)) {
1644 return(row_log_table_apply_delete_low(&pcur, offsets, save_ext,
1651 static __attribute__((nonnull, warn_unused_result))
1653 row_log_table_apply_update(
1659 ulint new_trx_id_col,
1663 const ulint* offsets,
1675 const row_log_t*log = dup->index->online_log;
1686 + (dup->index->online_log->same_pk ? 0 : 2));
1688 row = row_log_table_apply_convert_mrec(
1689 mrec, dup->index, offsets, log, heap, trx_id, &error);
1691 ut_ad(error == DB_SUCCESS || !row);
1694 ut_ad(error != DB_DUPLICATE_KEY);
1701 btr_pcur_open(index, old_pk, PAGE_CUR_LE,
1704 switch (btr_pcur_get_btr_cur(&pcur)->flag) {
1721 ut_ad(mtr.state == MTR_COMMITTED);
1723 error = row_log_table_apply_insert_low(
1724 thr, row, trx_id, offsets_heap, heap, dup);
1725 if (error != DB_SUCCESS) {
1736 ulint* cur_offsets = rec_get_offsets(
1737 btr_pcur_get_rec(&pcur),
1738 index, NULL, ULINT_UNDEFINED, &offsets_heap);
1741 row, NULL, index, heap);
1743 index, entry, btr_pcur_get_rec(&pcur), cur_offsets,
1760 error = row_log_table_apply_delete_low(
1761 &pcur, cur_offsets, NULL, heap, &mtr);
1762 ut_ad(mtr.state == MTR_COMMITTED);
1764 if (error != DB_SUCCESS) {
1771 if (upd_get_nth_field(update, 0)->field_no < new_trx_id_col) {
1772 if (dup->index->online_log->same_pk) {
1789 const byte* cur_trx_roll = rec_get_nth_field(
1790 mrec, offsets, trx_id_col, &len);
1791 ut_ad(len == DATA_TRX_ID_LEN);
1792 const dfield_t* new_trx_roll = dtuple_get_nth_field(
1793 old_pk, new_trx_id_col);
1796 ut_ad(rec_get_nth_field(mrec, offsets, trx_id_col + 1, &len)
1797 == cur_trx_roll + DATA_TRX_ID_LEN);
1798 ut_ad(len == DATA_ROLL_PTR_LEN);
1799 ut_ad(new_trx_roll->
len == DATA_TRX_ID_LEN);
1800 ut_ad(dtuple_get_nth_field(old_pk, new_trx_id_col + 1)
1801 -> len == DATA_ROLL_PTR_LEN);
1802 ut_ad(static_cast<const byte*>(
1803 dtuple_get_nth_field(old_pk, new_trx_id_col + 1)
1805 == static_cast<const byte*>(new_trx_roll->
data)
1808 if (!memcmp(cur_trx_roll, new_trx_roll->
data,
1809 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)) {
1823 if (dict_table_get_next_index(index)) {
1827 ROW_COPY_DATA, index, btr_pcur_get_rec(&pcur),
1828 cur_offsets, NULL, NULL, NULL, &old_ext, heap);
1830 #ifdef ROW_LOG_APPLY_PRINT
1831 if (row_log_apply_print) {
1832 fprintf(stderr,
"table apply update "
1833 IB_ID_FMT
" " IB_ID_FMT
"\n",
1850 btr_pcur_get_btr_cur(&pcur),
1851 &cur_offsets, &offsets_heap, heap, &big_rec,
1852 update, 0, thr, 0, &mtr);
1855 if (error == DB_SUCCESS) {
1857 index, btr_pcur_get_block(&pcur),
1858 btr_pcur_get_rec(&pcur), cur_offsets,
1865 while ((index = dict_table_get_next_index(index)) != NULL) {
1866 if (error != DB_SUCCESS) {
1870 if (index->
type & DICT_FTS) {
1874 if (!row_upd_changes_ord_field_binary(
1875 index, update, thr, old_row, NULL)) {
1897 &error, FALSE, btr_pcur_get_btr_cur(&pcur),
1900 if (error != DB_SUCCESS) {
1911 entry, trx_id, thr);
1918 if (error != DB_SUCCESS) {
1929 static __attribute__((nonnull, warn_unused_result))
1931 row_log_table_apply_op(
1936 ulint new_trx_id_col,
1950 row_log_t* log = dup->index->online_log;
1962 *error = DB_SUCCESS;
1965 if (mrec + 3 >= mrec_end) {
1969 const mrec_t*
const mrec_start = mrec;
1977 extra_size = *mrec++;
1979 if (extra_size >= 0x80) {
1982 extra_size = (extra_size & 0x7f) << 8;
1983 extra_size |= *mrec++;
1988 if (mrec > mrec_end) {
1992 rec_offs_set_n_fields(offsets, dup->index->n_fields);
1997 if (next_mrec > mrec_end) {
2000 log->
head.
total += next_mrec - mrec_start;
2003 const byte* db_trx_id
2004 = rec_get_nth_field(
2005 mrec, offsets, trx_id_col, &len);
2006 ut_ad(len == DATA_TRX_ID_LEN);
2007 *error = row_log_table_apply_insert(
2008 thr, mrec, offsets, offsets_heap,
2015 if (mrec + 4 >= mrec_end) {
2019 extra_size = *mrec++;
2022 ut_ad(mrec < mrec_end);
2028 rec_offs_set_n_fields(offsets, new_index->
n_uniq + 1);
2031 if (next_mrec > mrec_end) {
2035 log->
head.
total += next_mrec - mrec_start;
2047 byte* ext_start =
reinterpret_cast<byte*
>(ext);
2049 ulint ext_len =
sizeof(*ext)
2050 + (ext->
n_ext - 1) *
sizeof ext->
len;
2052 ext->
ext = reinterpret_cast<ulint*>(ext_start + ext_len);
2053 ext_len += ext->
n_ext *
sizeof(*ext->
ext);
2055 ext->
buf =
static_cast<byte*
>(ext_start + ext_len);
2060 *error = row_log_table_apply_delete(
2061 thr, new_trx_id_col,
2062 mrec, offsets, offsets_heap, heap,
2075 if (dup->index->online_log->same_pk) {
2078 extra_size = *mrec++;
2080 if (extra_size >= 0x80) {
2083 extra_size = (extra_size & 0x7f) << 8;
2084 extra_size |= *mrec++;
2089 if (mrec > mrec_end) {
2093 rec_offs_set_n_fields(offsets, dup->index->n_fields);
2098 if (next_mrec > mrec_end) {
2104 old_pk, new_index, old_pk->
n_fields);
2107 for (ulint i = 0; i < new_index->
n_uniq; i++) {
2114 field = rec_get_nth_field(
2115 mrec, offsets, i, &len);
2116 ut_ad(len != UNIV_SQL_NULL);
2118 dfield = dtuple_get_nth_field(old_pk, i);
2126 if (mrec > mrec_end) {
2132 rec_offs_set_n_fields(offsets, new_index->
n_uniq + 2);
2136 if (next_mrec + 2 > mrec_end) {
2155 field = rec_get_nth_field(
2156 mrec, offsets, i, &len);
2157 ut_ad(len != UNIV_SQL_NULL);
2159 dfield = dtuple_get_nth_field(old_pk, i);
2167 extra_size = *mrec++;
2169 if (extra_size >= 0x80) {
2172 extra_size = (extra_size & 0x7f) << 8;
2173 extra_size |= *mrec++;
2178 if (mrec > mrec_end) {
2182 rec_offs_set_n_fields(offsets, dup->index->n_fields);
2187 if (next_mrec > mrec_end) {
2192 ut_ad(next_mrec <= mrec_end);
2193 log->
head.
total += next_mrec - mrec_start;
2198 const byte* db_trx_id
2199 = rec_get_nth_field(
2200 mrec, offsets, trx_id_col, &len);
2201 ut_ad(len == DATA_TRX_ID_LEN);
2202 *error = row_log_table_apply_update(
2203 thr, trx_id_col, new_trx_id_col,
2204 mrec, offsets, offsets_heap,
2220 static __attribute__((nonnull, warn_unused_result))
2222 row_log_table_apply_ops(
2229 const mrec_t* mrec = NULL;
2231 const mrec_t* mrec_end = NULL;
2232 const mrec_t* next_mrec_end;
2236 bool has_index_lock;
2242 const ulint i = 1 + REC_OFFS_HEADER_SIZE
2246 dict_table_get_sys_col(index->
table, DATA_TRX_ID), index);
2248 dict_table_get_sys_col(new_table, DATA_TRX_ID), new_index);
2254 #ifdef UNIV_SYNC_DEBUG
2258 ut_ad(trx_id_col > 0);
2259 ut_ad(trx_id_col != ULINT_UNDEFINED);
2260 ut_ad(new_trx_id_col > 0);
2261 ut_ad(new_trx_id_col != ULINT_UNDEFINED);
2263 UNIV_MEM_INVALID(&mrec_end,
sizeof mrec_end);
2265 offsets =
static_cast<ulint*
>(
ut_malloc(i *
sizeof *offsets));
2271 has_index_lock =
true;
2274 ut_ad(has_index_lock);
2275 #ifdef UNIV_SYNC_DEBUG
2293 if (error != DB_SUCCESS) {
2300 fprintf(stderr,
"InnoDB: unexpected end of temporary file"
2310 #ifdef HAVE_FTRUNCATE
2321 if (next_mrec_end == next_mrec) {
2324 ut_ad(has_index_lock);
2339 ut_ad(has_index_lock);
2340 has_index_lock =
false;
2347 success = os_file_read_no_error_handling(
2353 fprintf(stderr,
"InnoDB: unable to read temporary file"
2358 #ifdef POSIX_FADV_DONTNEED
2363 #if 0 //def FALLOC_FL_PUNCH_HOLE
2368 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
2381 if (error != DB_SUCCESS) {
2393 ut_ad(mrec_end > mrec);
2396 memcpy((
mrec_t*) mrec_end, next_mrec,
2398 mrec = row_log_table_apply_op(
2399 thr, trx_id_col, new_trx_id_col,
2400 dup, &error, offsets_heap, heap,
2403 if (error != DB_SUCCESS) {
2405 }
else if (UNIV_UNLIKELY(mrec == NULL)) {
2412 ut_a(mrec > mrec_end);
2418 ut_ad(next_mrec <= next_mrec_end);
2432 ut_ad(next_mrec == next_mrec_end);
2455 mrec_end = next_mrec_end;
2459 ut_ad(mrec < mrec_end);
2461 if (!has_index_lock) {
2492 if (error != DB_SUCCESS) {
2496 next_mrec = row_log_table_apply_op(
2497 thr, trx_id_col, new_trx_id_col,
2498 dup, &error, offsets_heap, heap,
2499 mrec, mrec_end, offsets);
2501 if (error != DB_SUCCESS) {
2503 }
else if (next_mrec == next_mrec_end) {
2506 if (has_index_lock) {
2515 has_index_lock =
true;
2520 }
else if (next_mrec != NULL) {
2521 ut_ad(next_mrec < next_mrec_end);
2523 }
else if (has_index_lock) {
2531 goto unexpected_eof;
2537 goto process_next_block;
2542 error = DB_INTERRUPTED;
2544 if (!has_index_lock) {
2564 struct TABLE* table)
2572 #ifdef UNIV_SYNC_DEBUG
2575 clust_index = dict_table_get_first_index(old_table);
2593 error = row_log_table_apply_ops(thr, &dup);
2595 ut_ad(error != DB_SUCCESS
2620 const ulint* col_map)
2626 DBUG_ENTER(
"row_log_allocate");
2631 ut_ad(same_pk || table);
2632 ut_ad(!table || col_map);
2633 ut_ad(!add_cols || col_map);
2634 #ifdef UNIV_SYNC_DEBUG
2650 mutex_create(index_online_log_key, &log->mutex,
2651 SYNC_INDEX_ONLINE_LOG);
2654 log->same_pk = same_pk;
2655 log->add_cols = add_cols;
2656 log->col_map = col_map;
2657 log->error = DB_SUCCESS;
2659 log->head.block =
buf;
2661 log->tail.blocks = log->tail.bytes = 0;
2662 log->tail.total = 0;
2663 log->head.blocks = log->head.bytes = 0;
2664 log->head.total = 0;
2688 mutex_free(&log->
mutex);
2704 #ifdef UNIV_SYNC_DEBUG
2714 static __attribute__((nonnull))
2716 row_log_apply_op_low(
2724 bool has_index_lock,
2732 ulint* offsets = NULL;
2735 #ifdef UNIV_SYNC_DEBUG
2753 &cursor, 0, __FILE__, __LINE__,
2765 rec_t* rec = btr_cur_get_rec(&cursor);
2779 if (btr_cur_optimistic_delete(
2781 *error = DB_SUCCESS;
2785 if (!has_index_lock) {
2791 index, 0, entry, PAGE_CUR_LE,
2793 __FILE__, __LINE__, &mtr);
2801 btr_cur_get_rec(&cursor)));
2809 error, FALSE, &cursor,
2823 goto insert_the_rec;
2844 && (!index->n_nullable
2858 &cursor, &offsets, &offsets_heap,
2859 const_cast<dtuple_t*>(entry),
2860 &rec, &big_rec, 0, NULL, &mtr);
2862 if (*error != DB_FAIL) {
2866 if (!has_index_lock) {
2872 index, 0, entry, PAGE_CUR_LE,
2874 __FILE__, __LINE__, &mtr);
2887 &cursor, &offsets, &offsets_heap,
2888 const_cast<dtuple_t*>(entry),
2897 if (*error == DB_SUCCESS && trx_id) {
2911 static __attribute__((nonnull, warn_unused_result))
2923 bool has_index_lock,
2940 #ifdef UNIV_SYNC_DEBUG
2950 *error = DB_SUCCESS;
2962 op =
static_cast<enum
row_op>(*mrec++);
2964 mrec += DATA_TRX_ID_LEN;
2967 op =
static_cast<enum
row_op>(*mrec++);
2977 extra_size = *mrec++;
2979 ut_ad(mrec < mrec_end);
2981 if (extra_size >= 0x80) {
2984 extra_size = (extra_size & 0x7f) << 8;
2985 extra_size |= *mrec++;
2990 if (mrec > mrec_end) {
3008 if (mrec > mrec_end) {
3013 mrec - data_size, index, offsets, &n_ext, heap);
3017 #ifdef ROW_LOG_APPLY_PRINT
3018 if (row_log_apply_print) {
3019 fprintf(stderr,
"apply " IB_ID_FMT
" " TRX_ID_FMT " %u %u ",
3021 unsigned (op),
unsigned (has_index_lock));
3022 for (
const byte* m = mrec - data_size; m < mrec; m++) {
3023 fprintf(stderr,
"%02x", *m);
3028 row_log_apply_op_low(index, dup, error, offsets_heap,
3029 has_index_lock, op, trx_id, entry);
3036 static __attribute__((nonnull))
3047 const mrec_t* mrec = NULL;
3049 const mrec_t* mrec_end= NULL;
3050 const mrec_t* next_mrec_end;
3054 bool has_index_lock;
3055 const ulint i = 1 + REC_OFFS_HEADER_SIZE
3060 #ifdef UNIV_SYNC_DEBUG
3063 ut_ad(index->online_log);
3064 UNIV_MEM_INVALID(&mrec_end,
sizeof mrec_end);
3066 offsets =
static_cast<ulint*
>(
ut_malloc(i *
sizeof *offsets));
3072 has_index_lock =
true;
3075 ut_ad(has_index_lock);
3076 #ifdef UNIV_SYNC_DEBUG
3079 ut_ad(index->online_log->head.bytes == 0);
3090 if (UNIV_UNLIKELY(index->online_log->head.blocks
3091 > index->online_log->tail.blocks)) {
3093 fprintf(stderr,
"InnoDB: unexpected end of temporary file"
3094 " for index %s\n", index->name + 1);
3100 if (index->online_log->head.blocks
3101 == index->online_log->tail.blocks) {
3102 if (index->online_log->head.blocks) {
3103 #ifdef HAVE_FTRUNCATE
3105 ftruncate(index->online_log->fd, 0);
3107 index->online_log->head.blocks
3108 = index->online_log->tail.blocks = 0;
3111 next_mrec = index->online_log->tail.block;
3112 next_mrec_end = next_mrec + index->online_log->tail.bytes;
3114 if (next_mrec_end == next_mrec) {
3117 ut_ad(has_index_lock);
3118 ut_ad(index->online_log->head.blocks == 0);
3119 ut_ad(index->online_log->tail.blocks == 0);
3127 ofs = (
os_offset_t) index->online_log->head.blocks
3130 ut_ad(has_index_lock);
3131 has_index_lock =
false;
3136 success = os_file_read_no_error_handling(
3138 index->online_log->head.block, ofs,
3142 fprintf(stderr,
"InnoDB: unable to read temporary file"
3143 " for index %s\n", index->name + 1);
3147 #ifdef POSIX_FADV_DONTNEED
3149 posix_fadvise(index->online_log->fd,
3152 #if 0 //def FALLOC_FL_PUNCH_HOLE
3156 fallocate(index->online_log->fd,
3157 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
3161 next_mrec = index->online_log->head.block;
3172 ut_ad(mrec == index->online_log->head.buf);
3173 ut_ad(mrec_end > mrec);
3174 ut_ad(mrec_end < (&index->online_log->head.buf)[1]);
3176 memcpy((
mrec_t*) mrec_end, next_mrec,
3177 (&index->online_log->head.buf)[1] - mrec_end);
3178 mrec = row_log_apply_op(
3179 index, dup, &error, offsets_heap, heap,
3180 has_index_lock, index->online_log->head.buf,
3181 (&index->online_log->head.buf)[1], offsets);
3182 if (error != DB_SUCCESS) {
3184 }
else if (UNIV_UNLIKELY(mrec == NULL)) {
3191 ut_a(mrec > mrec_end);
3193 index->online_log->head.bytes = mrec - mrec_end;
3194 next_mrec += index->online_log->head.bytes;
3197 ut_ad(next_mrec <= next_mrec_end);
3203 ut_ad((mrec == NULL) == (index->online_log->head.bytes == 0));
3206 if (next_mrec_end == index->online_log->head.block
3210 if (index->online_log->tail.bytes == 0) {
3211 ut_ad(next_mrec == next_mrec_end);
3212 ut_ad(index->online_log->tail.blocks == 0);
3213 ut_ad(index->online_log->head.blocks == 0);
3214 ut_ad(index->online_log->head.bytes == 0);
3216 ut_ad(next_mrec == index->online_log->head.block
3217 + index->online_log->head.bytes);
3218 ut_ad(index->online_log->tail.blocks
3219 > index->online_log->head.blocks);
3221 }
else if (next_mrec_end == index->online_log->tail.block
3222 + index->online_log->tail.bytes) {
3223 ut_ad(next_mrec == index->online_log->tail.block
3224 + index->online_log->head.bytes);
3225 ut_ad(index->online_log->tail.blocks == 0);
3226 ut_ad(index->online_log->head.blocks == 0);
3227 ut_ad(index->online_log->head.bytes
3228 <= index->online_log->tail.bytes);
3234 mrec_end = next_mrec_end;
3238 ut_ad(mrec < mrec_end);
3240 if (!has_index_lock) {
3246 ut_ad(mrec >= index->online_log->head.block);
3247 ut_ad(mrec_end == index->online_log->head.block
3249 ut_ad(index->online_log->head.bytes
3259 ut_ad(index->online_log->head.blocks == 0);
3260 ut_ad(index->online_log->tail.blocks == 0);
3261 ut_ad(mrec_end == index->online_log->tail.block
3262 + index->online_log->tail.bytes);
3263 ut_ad(mrec >= index->online_log->tail.block);
3266 next_mrec = row_log_apply_op(
3267 index, dup, &error, offsets_heap, heap,
3268 has_index_lock, mrec, mrec_end, offsets);
3270 if (error != DB_SUCCESS) {
3272 }
else if (next_mrec == next_mrec_end) {
3275 if (has_index_lock) {
3284 has_index_lock =
true;
3286 index->online_log->head.bytes = 0;
3287 index->online_log->head.blocks++;
3289 }
else if (next_mrec != NULL) {
3290 ut_ad(next_mrec < next_mrec_end);
3291 index->online_log->head.bytes += next_mrec - mrec;
3292 }
else if (has_index_lock) {
3296 ut_ad(index->online_log->tail.blocks == 0);
3297 ut_ad(mrec_end == index->online_log->tail.block
3298 + index->online_log->tail.bytes);
3300 goto unexpected_eof;
3302 memcpy(index->online_log->head.buf, mrec,
3304 mrec_end += index->online_log->head.buf - mrec;
3305 mrec = index->online_log->head.buf;
3306 goto process_next_block;
3311 error = DB_INTERRUPTED;
3313 if (!has_index_lock) {
3321 if (((
os_offset_t) index->online_log->tail.blocks + 1)
3350 struct TABLE* table)
3356 DBUG_ENTER(
"row_log_apply");
3366 error = row_log_apply_ops(trx, index, &dup);
3371 if (error != DB_SUCCESS || dup.
n_dup) {
3379 if (error == DB_SUCCESS) {
3380 error = DB_DUPLICATE_KEY;