~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to plugin/innobase/btr/btr0btr.cc

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-10-29 15:43:40 UTC
  • mfrom: (1.2.12) (2.1.19 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029154340-2gp39el6cv8bwf2o
Tags: 1:7.2.3-2ubuntu1
* Merge from debian, remaining changes:
  - Link against boost_system because of boost_thread.
  - Add required libs to message/include.am
  - Add upstart job and adjust init script to be upstart compatible.
  - Disable -floop-parallelize-all due to gcc-4.8/4.9 compiler ICE
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57732

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
#include "trx0trx.h"
44
44
#include "page0zip.h"
45
45
 
 
46
#ifdef UNIV_BLOB_DEBUG
 
47
# include "srv0srv.h"
 
48
# include "ut0rbt.h"
 
49
 
 
50
/** TRUE when messages about index->blobs modification are enabled. */
 
51
static ibool btr_blob_dbg_msg;
 
52
 
 
53
/** Issue a message about an operation on index->blobs.
 
54
@param op       operation
 
55
@param b        the entry being subjected to the operation
 
56
@param ctx      the context of the operation */
 
57
#define btr_blob_dbg_msg_issue(op, b, ctx)                      \
 
58
        fprintf(stderr, op " %u:%u:%u->%u %s(%u,%u,%u)\n",      \
 
59
                (b)->ref_page_no, (b)->ref_heap_no,             \
 
60
                (b)->ref_field_no, (b)->blob_page_no, ctx,      \
 
61
                (b)->owner, (b)->always_owner, (b)->del)
 
62
 
 
63
/** Insert to index->blobs a reference to an off-page column.
 
64
@param index    the index tree
 
65
@param b        the reference
 
66
@param ctx      context (for logging) */
 
67
UNIV_INTERN
 
68
void
 
69
btr_blob_dbg_rbt_insert(
 
70
/*====================*/
 
71
        dict_index_t*           index,  /*!< in/out: index tree */
 
72
        const btr_blob_dbg_t*   b,      /*!< in: the reference */
 
73
        const char*             ctx)    /*!< in: context (for logging) */
 
74
{
 
75
        if (btr_blob_dbg_msg) {
 
76
                btr_blob_dbg_msg_issue("insert", b, ctx);
 
77
        }
 
78
        mutex_enter(&index->blobs_mutex);
 
79
        rbt_insert(index->blobs, b, b);
 
80
        mutex_exit(&index->blobs_mutex);
 
81
}
 
82
 
 
83
/** Remove from index->blobs a reference to an off-page column.
 
84
@param index    the index tree
 
85
@param b        the reference
 
86
@param ctx      context (for logging) */
 
87
UNIV_INTERN
 
88
void
 
89
btr_blob_dbg_rbt_delete(
 
90
/*====================*/
 
91
        dict_index_t*           index,  /*!< in/out: index tree */
 
92
        const btr_blob_dbg_t*   b,      /*!< in: the reference */
 
93
        const char*             ctx)    /*!< in: context (for logging) */
 
94
{
 
95
        if (btr_blob_dbg_msg) {
 
96
                btr_blob_dbg_msg_issue("delete", b, ctx);
 
97
        }
 
98
        mutex_enter(&index->blobs_mutex);
 
99
        ut_a(rbt_delete(index->blobs, b));
 
100
        mutex_exit(&index->blobs_mutex);
 
101
}
 
102
 
 
103
/**************************************************************//**
 
104
Comparator for items (btr_blob_dbg_t) in index->blobs.
 
105
The key in index->blobs is (ref_page_no, ref_heap_no, ref_field_no).
 
106
@return negative, 0 or positive if *a<*b, *a=*b, *a>*b */
 
107
static
 
108
int
 
109
btr_blob_dbg_cmp(
 
110
/*=============*/
 
111
        const void*     a,      /*!< in: first btr_blob_dbg_t to compare */
 
112
        const void*     b)      /*!< in: second btr_blob_dbg_t to compare */
 
113
{
 
114
        const btr_blob_dbg_t*   aa      = a;
 
115
        const btr_blob_dbg_t*   bb      = b;
 
116
 
 
117
        ut_ad(aa != NULL);
 
118
        ut_ad(bb != NULL);
 
119
 
 
120
        if (aa->ref_page_no != bb->ref_page_no) {
 
121
                return(aa->ref_page_no < bb->ref_page_no ? -1 : 1);
 
122
        }
 
123
        if (aa->ref_heap_no != bb->ref_heap_no) {
 
124
                return(aa->ref_heap_no < bb->ref_heap_no ? -1 : 1);
 
125
        }
 
126
        if (aa->ref_field_no != bb->ref_field_no) {
 
127
                return(aa->ref_field_no < bb->ref_field_no ? -1 : 1);
 
128
        }
 
129
        return(0);
 
130
}
 
131
 
 
132
/**************************************************************//**
 
133
Add a reference to an off-page column to the index->blobs map. */
 
134
UNIV_INTERN
 
135
void
 
136
btr_blob_dbg_add_blob(
 
137
/*==================*/
 
138
        const rec_t*    rec,            /*!< in: clustered index record */
 
139
        ulint           field_no,       /*!< in: off-page column number */
 
140
        ulint           page_no,        /*!< in: start page of the column */
 
141
        dict_index_t*   index,          /*!< in/out: index tree */
 
142
        const char*     ctx)            /*!< in: context (for logging) */
 
143
{
 
144
        btr_blob_dbg_t  b;
 
145
        const page_t*   page    = page_align(rec);
 
146
 
 
147
        ut_a(index->blobs);
 
148
 
 
149
        b.blob_page_no = page_no;
 
150
        b.ref_page_no = page_get_page_no(page);
 
151
        b.ref_heap_no = page_rec_get_heap_no(rec);
 
152
        b.ref_field_no = field_no;
 
153
        ut_a(b.ref_field_no >= index->n_uniq);
 
154
        b.always_owner = b.owner = TRUE;
 
155
        b.del = FALSE;
 
156
        ut_a(!rec_get_deleted_flag(rec, page_is_comp(page)));
 
157
        btr_blob_dbg_rbt_insert(index, &b, ctx);
 
158
}
 
159
 
 
160
/**************************************************************//**
 
161
Add to index->blobs any references to off-page columns from a record.
 
162
@return number of references added */
 
163
UNIV_INTERN
 
164
ulint
 
165
btr_blob_dbg_add_rec(
 
166
/*=================*/
 
167
        const rec_t*    rec,    /*!< in: record */
 
168
        dict_index_t*   index,  /*!< in/out: index */
 
169
        const ulint*    offsets,/*!< in: offsets */
 
170
        const char*     ctx)    /*!< in: context (for logging) */
 
171
{
 
172
        ulint           count   = 0;
 
173
        ulint           i;
 
174
        btr_blob_dbg_t  b;
 
175
        ibool           del;
 
176
 
 
177
        ut_ad(rec_offs_validate(rec, index, offsets));
 
178
 
 
179
        if (!rec_offs_any_extern(offsets)) {
 
180
                return(0);
 
181
        }
 
182
 
 
183
        b.ref_page_no = page_get_page_no(page_align(rec));
 
184
        b.ref_heap_no = page_rec_get_heap_no(rec);
 
185
        del = (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) != 0);
 
186
 
 
187
        for (i = 0; i < rec_offs_n_fields(offsets); i++) {
 
188
                if (rec_offs_nth_extern(offsets, i)) {
 
189
                        ulint           len;
 
190
                        const byte*     field_ref = rec_get_nth_field(
 
191
                                rec, offsets, i, &len);
 
192
 
 
193
                        ut_a(len != UNIV_SQL_NULL);
 
194
                        ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 
195
                        field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
 
196
 
 
197
                        if (!memcmp(field_ref, field_ref_zero,
 
198
                                    BTR_EXTERN_FIELD_REF_SIZE)) {
 
199
                                /* the column has not been stored yet */
 
200
                                continue;
 
201
                        }
 
202
 
 
203
                        b.ref_field_no = i;
 
204
                        b.blob_page_no = mach_read_from_4(
 
205
                                field_ref + BTR_EXTERN_PAGE_NO);
 
206
                        ut_a(b.ref_field_no >= index->n_uniq);
 
207
                        b.always_owner = b.owner
 
208
                                = !(field_ref[BTR_EXTERN_LEN]
 
209
                                    & BTR_EXTERN_OWNER_FLAG);
 
210
                        b.del = del;
 
211
 
 
212
                        btr_blob_dbg_rbt_insert(index, &b, ctx);
 
213
                        count++;
 
214
                }
 
215
        }
 
216
 
 
217
        return(count);
 
218
}
 
219
 
 
220
/**************************************************************//**
 
221
Display the references to off-page columns.
 
222
This function is to be called from a debugger,
 
223
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
 
224
UNIV_INTERN
 
225
void
 
226
btr_blob_dbg_print(
 
227
/*===============*/
 
228
        const dict_index_t*     index)  /*!< in: index tree */
 
229
{
 
230
        const ib_rbt_node_t*    node;
 
231
 
 
232
        if (!index->blobs) {
 
233
                return;
 
234
        }
 
235
 
 
236
        /* We intentionally do not acquire index->blobs_mutex here.
 
237
        This function is to be called from a debugger, and the caller
 
238
        should make sure that the index->blobs_mutex is held. */
 
239
 
 
240
        for (node = rbt_first(index->blobs);
 
241
             node != NULL; node = rbt_next(index->blobs, node)) {
 
242
                const btr_blob_dbg_t*   b
 
243
                        = rbt_value(btr_blob_dbg_t, node);
 
244
                fprintf(stderr, "%u:%u:%u->%u%s%s%s\n",
 
245
                        b->ref_page_no, b->ref_heap_no, b->ref_field_no,
 
246
                        b->blob_page_no,
 
247
                        b->owner ? "" : "(disowned)",
 
248
                        b->always_owner ? "" : "(has disowned)",
 
249
                        b->del ? "(deleted)" : "");
 
250
        }
 
251
}
 
252
 
 
253
/**************************************************************//**
 
254
Remove from index->blobs any references to off-page columns from a record.
 
255
@return number of references removed */
 
256
UNIV_INTERN
 
257
ulint
 
258
btr_blob_dbg_remove_rec(
 
259
/*====================*/
 
260
        const rec_t*    rec,    /*!< in: record */
 
261
        dict_index_t*   index,  /*!< in/out: index */
 
262
        const ulint*    offsets,/*!< in: offsets */
 
263
        const char*     ctx)    /*!< in: context (for logging) */
 
264
{
 
265
        ulint           i;
 
266
        ulint           count   = 0;
 
267
        btr_blob_dbg_t  b;
 
268
 
 
269
        ut_ad(rec_offs_validate(rec, index, offsets));
 
270
 
 
271
        if (!rec_offs_any_extern(offsets)) {
 
272
                return(0);
 
273
        }
 
274
 
 
275
        b.ref_page_no = page_get_page_no(page_align(rec));
 
276
        b.ref_heap_no = page_rec_get_heap_no(rec);
 
277
 
 
278
        for (i = 0; i < rec_offs_n_fields(offsets); i++) {
 
279
                if (rec_offs_nth_extern(offsets, i)) {
 
280
                        ulint           len;
 
281
                        const byte*     field_ref = rec_get_nth_field(
 
282
                                rec, offsets, i, &len);
 
283
 
 
284
                        ut_a(len != UNIV_SQL_NULL);
 
285
                        ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 
286
                        field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
 
287
 
 
288
                        b.ref_field_no = i;
 
289
                        b.blob_page_no = mach_read_from_4(
 
290
                                field_ref + BTR_EXTERN_PAGE_NO);
 
291
 
 
292
                        switch (b.blob_page_no) {
 
293
                        case 0:
 
294
                                /* The column has not been stored yet.
 
295
                                The BLOB pointer must be all zero.
 
296
                                There cannot be a BLOB starting at
 
297
                                page 0, because page 0 is reserved for
 
298
                                the tablespace header. */
 
299
                                ut_a(!memcmp(field_ref, field_ref_zero,
 
300
                                             BTR_EXTERN_FIELD_REF_SIZE));
 
301
                                /* fall through */
 
302
                        case FIL_NULL:
 
303
                                /* the column has been freed already */
 
304
                                continue;
 
305
                        }
 
306
 
 
307
                        btr_blob_dbg_rbt_delete(index, &b, ctx);
 
308
                        count++;
 
309
                }
 
310
        }
 
311
 
 
312
        return(count);
 
313
}
 
314
 
 
315
/**************************************************************//**
 
316
Check that there are no references to off-page columns from or to
 
317
the given page. Invoked when freeing or clearing a page.
 
318
@return TRUE when no orphan references exist */
 
319
UNIV_INTERN
 
320
ibool
 
321
btr_blob_dbg_is_empty(
 
322
/*==================*/
 
323
        dict_index_t*   index,          /*!< in: index */
 
324
        ulint           page_no)        /*!< in: page number */
 
325
{
 
326
        const ib_rbt_node_t*    node;
 
327
        ibool                   success = TRUE;
 
328
 
 
329
        if (!index->blobs) {
 
330
                return(success);
 
331
        }
 
332
 
 
333
        mutex_enter(&index->blobs_mutex);
 
334
 
 
335
        for (node = rbt_first(index->blobs);
 
336
             node != NULL; node = rbt_next(index->blobs, node)) {
 
337
                const btr_blob_dbg_t*   b
 
338
                        = rbt_value(btr_blob_dbg_t, node);
 
339
 
 
340
                if (b->ref_page_no != page_no && b->blob_page_no != page_no) {
 
341
                        continue;
 
342
                }
 
343
 
 
344
                fprintf(stderr,
 
345
                        "InnoDB: orphan BLOB ref%s%s%s %u:%u:%u->%u\n",
 
346
                        b->owner ? "" : "(disowned)",
 
347
                        b->always_owner ? "" : "(has disowned)",
 
348
                        b->del ? "(deleted)" : "",
 
349
                        b->ref_page_no, b->ref_heap_no, b->ref_field_no,
 
350
                        b->blob_page_no);
 
351
 
 
352
                if (b->blob_page_no != page_no || b->owner || !b->del) {
 
353
                        success = FALSE;
 
354
                }
 
355
        }
 
356
 
 
357
        mutex_exit(&index->blobs_mutex);
 
358
        return(success);
 
359
}
 
360
 
 
361
/**************************************************************//**
 
362
Count and process all references to off-page columns on a page.
 
363
@return number of references processed */
 
364
UNIV_INTERN
 
365
ulint
 
366
btr_blob_dbg_op(
 
367
/*============*/
 
368
        const page_t*           page,   /*!< in: B-tree leaf page */
 
369
        const rec_t*            rec,    /*!< in: record to start from
 
370
                                        (NULL to process the whole page) */
 
371
        dict_index_t*           index,  /*!< in/out: index */
 
372
        const char*             ctx,    /*!< in: context (for logging) */
 
373
        const btr_blob_dbg_op_f op)     /*!< in: operation on records */
 
374
{
 
375
        ulint           count   = 0;
 
376
        mem_heap_t*     heap    = NULL;
 
377
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
 
378
        ulint*          offsets = offsets_;
 
379
        rec_offs_init(offsets_);
 
380
 
 
381
        ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
 
382
        ut_a(!rec || page_align(rec) == page);
 
383
 
 
384
        if (!index->blobs || !page_is_leaf(page)
 
385
            || !dict_index_is_clust(index)) {
 
386
                return(0);
 
387
        }
 
388
 
 
389
        if (rec == NULL) {
 
390
                rec = page_get_infimum_rec(page);
 
391
        }
 
392
 
 
393
        do {
 
394
                offsets = rec_get_offsets(rec, index, offsets,
 
395
                                          ULINT_UNDEFINED, &heap);
 
396
                count += op(rec, index, offsets, ctx);
 
397
                rec = page_rec_get_next_const(rec);
 
398
        } while (!page_rec_is_supremum(rec));
 
399
 
 
400
        if (UNIV_LIKELY_NULL(heap)) {
 
401
                mem_heap_free(heap);
 
402
        }
 
403
 
 
404
        return(count);
 
405
}
 
406
 
 
407
/**************************************************************//**
 
408
Count and add to index->blobs any references to off-page columns
 
409
from records on a page.
 
410
@return number of references added */
 
411
UNIV_INTERN
 
412
ulint
 
413
btr_blob_dbg_add(
 
414
/*=============*/
 
415
        const page_t*   page,   /*!< in: rewritten page */
 
416
        dict_index_t*   index,  /*!< in/out: index */
 
417
        const char*     ctx)    /*!< in: context (for logging) */
 
418
{
 
419
        btr_blob_dbg_assert_empty(index, page_get_page_no(page));
 
420
 
 
421
        return(btr_blob_dbg_op(page, NULL, index, ctx, btr_blob_dbg_add_rec));
 
422
}
 
423
 
 
424
/**************************************************************//**
 
425
Count and remove from index->blobs any references to off-page columns
 
426
from records on a page.
 
427
Used when reorganizing a page, before copying the records.
 
428
@return number of references removed */
 
429
UNIV_INTERN
 
430
ulint
 
431
btr_blob_dbg_remove(
 
432
/*================*/
 
433
        const page_t*   page,   /*!< in: b-tree page */
 
434
        dict_index_t*   index,  /*!< in/out: index */
 
435
        const char*     ctx)    /*!< in: context (for logging) */
 
436
{
 
437
        ulint   count;
 
438
 
 
439
        count = btr_blob_dbg_op(page, NULL, index, ctx,
 
440
                                btr_blob_dbg_remove_rec);
 
441
 
 
442
        /* Check that no references exist. */
 
443
        btr_blob_dbg_assert_empty(index, page_get_page_no(page));
 
444
 
 
445
        return(count);
 
446
}
 
447
 
 
448
/**************************************************************//**
 
449
Restore in index->blobs any references to off-page columns
 
450
Used when page reorganize fails due to compressed page overflow. */
 
451
UNIV_INTERN
 
452
void
 
453
btr_blob_dbg_restore(
 
454
/*=================*/
 
455
        const page_t*   npage,  /*!< in: page that failed to compress  */
 
456
        const page_t*   page,   /*!< in: copy of original page */
 
457
        dict_index_t*   index,  /*!< in/out: index */
 
458
        const char*     ctx)    /*!< in: context (for logging) */
 
459
{
 
460
        ulint   removed;
 
461
        ulint   added;
 
462
 
 
463
        ut_a(page_get_page_no(npage) == page_get_page_no(page));
 
464
        ut_a(page_get_space_id(npage) == page_get_space_id(page));
 
465
 
 
466
        removed = btr_blob_dbg_remove(npage, index, ctx);
 
467
        added = btr_blob_dbg_add(page, index, ctx);
 
468
        ut_a(added == removed);
 
469
}
 
470
 
 
471
/**************************************************************//**
 
472
Modify the 'deleted' flag of a record. */
 
473
UNIV_INTERN
 
474
void
 
475
btr_blob_dbg_set_deleted_flag(
 
476
/*==========================*/
 
477
        const rec_t*            rec,    /*!< in: record */
 
478
        dict_index_t*           index,  /*!< in/out: index */
 
479
        const ulint*            offsets,/*!< in: rec_get_offs(rec, index) */
 
480
        ibool                   del)    /*!< in: TRUE=deleted, FALSE=exists */
 
481
{
 
482
        const ib_rbt_node_t*    node;
 
483
        btr_blob_dbg_t          b;
 
484
        btr_blob_dbg_t*         c;
 
485
        ulint                   i;
 
486
 
 
487
        ut_ad(rec_offs_validate(rec, index, offsets));
 
488
        ut_a(dict_index_is_clust(index));
 
489
        ut_a(del == !!del);/* must be FALSE==0 or TRUE==1 */
 
490
 
 
491
        if (!rec_offs_any_extern(offsets) || !index->blobs) {
 
492
 
 
493
                return;
 
494
        }
 
495
 
 
496
        b.ref_page_no = page_get_page_no(page_align(rec));
 
497
        b.ref_heap_no = page_rec_get_heap_no(rec);
 
498
 
 
499
        for (i = 0; i < rec_offs_n_fields(offsets); i++) {
 
500
                if (rec_offs_nth_extern(offsets, i)) {
 
501
                        ulint           len;
 
502
                        const byte*     field_ref = rec_get_nth_field(
 
503
                                rec, offsets, i, &len);
 
504
 
 
505
                        ut_a(len != UNIV_SQL_NULL);
 
506
                        ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 
507
                        field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
 
508
 
 
509
                        b.ref_field_no = i;
 
510
                        b.blob_page_no = mach_read_from_4(
 
511
                                field_ref + BTR_EXTERN_PAGE_NO);
 
512
 
 
513
                        switch (b.blob_page_no) {
 
514
                        case 0:
 
515
                                ut_a(memcmp(field_ref, field_ref_zero,
 
516
                                            BTR_EXTERN_FIELD_REF_SIZE));
 
517
                                /* page number 0 is for the
 
518
                                page allocation bitmap */
 
519
                        case FIL_NULL:
 
520
                                /* the column has been freed already */
 
521
                                ut_error;
 
522
                        }
 
523
 
 
524
                        mutex_enter(&index->blobs_mutex);
 
525
                        node = rbt_lookup(index->blobs, &b);
 
526
                        ut_a(node);
 
527
 
 
528
                        c = rbt_value(btr_blob_dbg_t, node);
 
529
                        /* The flag should be modified. */
 
530
                        c->del = del;
 
531
                        if (btr_blob_dbg_msg) {
 
532
                                b = *c;
 
533
                                mutex_exit(&index->blobs_mutex);
 
534
                                btr_blob_dbg_msg_issue("del_mk", &b, "");
 
535
                        } else {
 
536
                                mutex_exit(&index->blobs_mutex);
 
537
                        }
 
538
                }
 
539
        }
 
540
}
 
541
 
 
542
/**************************************************************//**
 
543
Change the ownership of an off-page column. */
 
544
UNIV_INTERN
 
545
void
 
546
btr_blob_dbg_owner(
 
547
/*===============*/
 
548
        const rec_t*            rec,    /*!< in: record */
 
549
        dict_index_t*           index,  /*!< in/out: index */
 
550
        const ulint*            offsets,/*!< in: rec_get_offs(rec, index) */
 
551
        ulint                   i,      /*!< in: ith field in rec */
 
552
        ibool                   own)    /*!< in: TRUE=owned, FALSE=disowned */
 
553
{
 
554
        const ib_rbt_node_t*    node;
 
555
        btr_blob_dbg_t          b;
 
556
        const byte*             field_ref;
 
557
        ulint                   len;
 
558
 
 
559
        ut_ad(rec_offs_validate(rec, index, offsets));
 
560
        ut_a(rec_offs_nth_extern(offsets, i));
 
561
 
 
562
        field_ref = rec_get_nth_field(rec, offsets, i, &len);
 
563
        ut_a(len != UNIV_SQL_NULL);
 
564
        ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 
565
        field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
 
566
 
 
567
        b.ref_page_no = page_get_page_no(page_align(rec));
 
568
        b.ref_heap_no = page_rec_get_heap_no(rec);
 
569
        b.ref_field_no = i;
 
570
        b.owner = !(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG);
 
571
        b.blob_page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
 
572
 
 
573
        ut_a(b.owner == own);
 
574
 
 
575
        mutex_enter(&index->blobs_mutex);
 
576
        node = rbt_lookup(index->blobs, &b);
 
577
        /* row_ins_clust_index_entry_by_modify() invokes
 
578
        btr_cur_unmark_extern_fields() also for the newly inserted
 
579
        references, which are all zero bytes until the columns are stored.
 
580
        The node lookup must fail if and only if that is the case. */
 
581
        ut_a(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)
 
582
             == !node);
 
583
 
 
584
        if (node) {
 
585
                btr_blob_dbg_t* c = rbt_value(btr_blob_dbg_t, node);
 
586
                /* Some code sets ownership from TRUE to TRUE.
 
587
                We do not allow changing ownership from FALSE to FALSE. */
 
588
                ut_a(own || c->owner);
 
589
 
 
590
                c->owner = own;
 
591
                if (!own) {
 
592
                        c->always_owner = FALSE;
 
593
                }
 
594
        }
 
595
 
 
596
        mutex_exit(&index->blobs_mutex);
 
597
}
 
598
#endif /* UNIV_BLOB_DEBUG */
 
599
 
46
600
/*
47
601
Latching strategy of the InnoDB B-tree
48
602
--------------------------------------
296
850
        page_t*         page = buf_block_get_frame(block);
297
851
 
298
852
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
853
        btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
299
854
 
300
855
        if (UNIV_LIKELY_NULL(page_zip)) {
301
856
                page_create_zip(block, index, level, mtr);
489
1044
        modify clock */
490
1045
 
491
1046
        buf_block_modify_clock_inc(block);
 
1047
        btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
492
1048
 
493
1049
        if (dict_index_is_ibuf(index)) {
494
1050
 
663
1219
                      " to fix the\n"
664
1220
                      "InnoDB: corruption. If the crash happens at "
665
1221
                      "the database startup, see\n"
666
 
                      "InnoDB: " REFMAN "forcing-recovery.html about\n"
 
1222
                      "InnoDB: " REFMAN "forcing-innodb-recovery.html about\n"
667
1223
                      "InnoDB: forcing recovery. "
668
1224
                      "Then dump + drop + reimport.\n", stderr);
669
1225
 
773
1329
                block = buf_page_get(space, zip_size, page_no,
774
1330
                                     RW_X_LATCH, mtr);
775
1331
        } else {
 
1332
#ifdef UNIV_BLOB_DEBUG
 
1333
                if ((type & DICT_CLUSTERED) && !index->blobs) {
 
1334
                        mutex_create(PFS_NOT_INSTRUMENTED,
 
1335
                                     &index->blobs_mutex, SYNC_ANY_LATCH);
 
1336
                        index->blobs = rbt_create(sizeof(btr_blob_dbg_t),
 
1337
                                                  btr_blob_dbg_cmp);
 
1338
                }
 
1339
#endif /* UNIV_BLOB_DEBUG */
776
1340
                block = fseg_create(space, 0,
777
1341
                                    PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
778
1342
        }
980
1544
        log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
981
1545
 
982
1546
#ifndef UNIV_HOTBACKUP
983
 
        temp_block = buf_block_alloc(buf_pool, 0);
 
1547
        temp_block = buf_block_alloc(buf_pool);
984
1548
#else /* !UNIV_HOTBACKUP */
985
1549
        ut_ad(block == back_block1);
986
1550
        temp_block = back_block2;
997
1561
 
998
1562
        block->check_index_page_at_flush = TRUE;
999
1563
#endif /* !UNIV_HOTBACKUP */
 
1564
        btr_blob_dbg_remove(page, index, "btr_page_reorganize");
1000
1565
 
1001
1566
        /* Recreate the page: note that global data on page (possible
1002
1567
        segment headers, next page-field, etc.) is preserved intact */
1025
1590
            (!page_zip_compress(page_zip, page, index, NULL))) {
1026
1591
 
1027
1592
                /* Restore the old page and exit. */
 
1593
                btr_blob_dbg_restore(page, temp_page, index,
 
1594
                                     "btr_page_reorganize_compress_fail");
1028
1595
 
1029
1596
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
1030
1597
                /* Check that the bytes that we skip are identical. */
1158
1725
#endif /* UNIV_ZIP_DEBUG */
1159
1726
 
1160
1727
        btr_search_drop_page_hash_index(block);
 
1728
        btr_blob_dbg_remove(page, index, "btr_page_empty");
1161
1729
 
1162
1730
        /* Recreate the page: note that global data on page (possible
1163
1731
        segment headers, next page-field, etc.) is preserved intact */
2496
3064
                                                       index);
2497
3065
        }
2498
3066
 
 
3067
        btr_blob_dbg_remove(page, index, "btr_lift_page_up");
2499
3068
        lock_update_copy_and_discard(father_block, block);
2500
3069
 
2501
3070
        /* Go upward to root page, decrementing levels by one. */
2757
3326
                lock_update_merge_right(merge_block, orig_succ, block);
2758
3327
        }
2759
3328
 
 
3329
        btr_blob_dbg_remove(page, index, "btr_compress");
2760
3330
        mem_heap_free(heap);
2761
3331
 
2762
3332
        if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
2987
3557
                                    block);
2988
3558
        }
2989
3559
 
 
3560
        btr_blob_dbg_remove(page, index, "btr_discard_page");
 
3561
 
2990
3562
        /* Free the file page */
2991
3563
        btr_page_free(index, block, mtr);
2992
3564