Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
27fbb7c1
Commit
27fbb7c1
authored
Feb 08, 2011
by
Marko Mäkelä
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql-5.1-innodb to mysql-5.5-innodb.
parents
1751fd90
89621ad7
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
911 additions
and
2 deletions
+911
-2
storage/innobase/btr/btr0btr.c
storage/innobase/btr/btr0btr.c
+572
-0
storage/innobase/btr/btr0cur.c
storage/innobase/btr/btr0cur.c
+44
-0
storage/innobase/dict/dict0mem.c
storage/innobase/dict/dict0mem.c
+9
-0
storage/innobase/include/btr0btr.h
storage/innobase/include/btr0btr.h
+85
-0
storage/innobase/include/btr0types.h
storage/innobase/include/btr0types.h
+125
-0
storage/innobase/include/dict0mem.h
storage/innobase/include/dict0mem.h
+7
-0
storage/innobase/include/page0zip.h
storage/innobase/include/page0zip.h
+1
-1
storage/innobase/include/univ.i
storage/innobase/include/univ.i
+2
-0
storage/innobase/page/page0cur.c
storage/innobase/page/page0cur.c
+10
-0
storage/innobase/page/page0page.c
storage/innobase/page/page0page.c
+11
-0
storage/innobase/page/page0zip.c
storage/innobase/page/page0zip.c
+4
-1
storage/innobase/row/row0upd.c
storage/innobase/row/row0upd.c
+35
-0
storage/innobase/srv/srv0start.c
storage/innobase/srv/srv0start.c
+6
-0
No files found.
storage/innobase/btr/btr0btr.c
View file @
27fbb7c1
...
...
@@ -42,6 +42,560 @@ Created 6/2/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "trx0trx.h"
#ifdef UNIV_BLOB_DEBUG
# include "srv0srv.h"
# include "ut0rbt.h"
/** TRUE when messages about index->blobs modification are enabled. */
static
ibool
btr_blob_dbg_msg
;
/** Issue a message about an operation on index->blobs.
@param op operation
@param b the entry being subjected to the operation
@param ctx the context of the operation */
#define btr_blob_dbg_msg_issue(op, b, ctx) \
fprintf(stderr, op " %u:%u:%u->%u %s(%u,%u,%u)\n", \
(b)->ref_page_no, (b)->ref_heap_no, \
(b)->ref_field_no, (b)->blob_page_no, ctx, \
(b)->owner, (b)->always_owner, (b)->del)
/** Insert to index->blobs a reference to an off-page column.
@param index the index tree
@param b the reference
@param ctx context (for logging) */
UNIV_INTERN
void
btr_blob_dbg_rbt_insert
(
/*====================*/
dict_index_t
*
index
,
/*!< in/out: index tree */
const
btr_blob_dbg_t
*
b
,
/*!< in: the reference */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
if
(
btr_blob_dbg_msg
)
{
btr_blob_dbg_msg_issue
(
"insert"
,
b
,
ctx
);
}
mutex_enter
(
&
index
->
blobs_mutex
);
rbt_insert
(
index
->
blobs
,
b
,
b
);
mutex_exit
(
&
index
->
blobs_mutex
);
}
/** Remove from index->blobs a reference to an off-page column.
@param index the index tree
@param b the reference
@param ctx context (for logging) */
UNIV_INTERN
void
btr_blob_dbg_rbt_delete
(
/*====================*/
dict_index_t
*
index
,
/*!< in/out: index tree */
const
btr_blob_dbg_t
*
b
,
/*!< in: the reference */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
if
(
btr_blob_dbg_msg
)
{
btr_blob_dbg_msg_issue
(
"delete"
,
b
,
ctx
);
}
mutex_enter
(
&
index
->
blobs_mutex
);
ut_a
(
rbt_delete
(
index
->
blobs
,
b
));
mutex_exit
(
&
index
->
blobs_mutex
);
}
/**************************************************************//**
Comparator for items (btr_blob_dbg_t) in index->blobs.
The key in index->blobs is (ref_page_no, ref_heap_no, ref_field_no).
@return negative, 0 or positive if *a<*b, *a=*b, *a>*b */
static
int
btr_blob_dbg_cmp
(
/*=============*/
const
void
*
a
,
/*!< in: first btr_blob_dbg_t to compare */
const
void
*
b
)
/*!< in: second btr_blob_dbg_t to compare */
{
const
btr_blob_dbg_t
*
aa
=
a
;
const
btr_blob_dbg_t
*
bb
=
b
;
ut_ad
(
aa
!=
NULL
);
ut_ad
(
bb
!=
NULL
);
if
(
aa
->
ref_page_no
!=
bb
->
ref_page_no
)
{
return
(
aa
->
ref_page_no
<
bb
->
ref_page_no
?
-
1
:
1
);
}
if
(
aa
->
ref_heap_no
!=
bb
->
ref_heap_no
)
{
return
(
aa
->
ref_heap_no
<
bb
->
ref_heap_no
?
-
1
:
1
);
}
if
(
aa
->
ref_field_no
!=
bb
->
ref_field_no
)
{
return
(
aa
->
ref_field_no
<
bb
->
ref_field_no
?
-
1
:
1
);
}
return
(
0
);
}
/**************************************************************//**
Add a reference to an off-page column to the index->blobs map. */
UNIV_INTERN
void
btr_blob_dbg_add_blob
(
/*==================*/
const
rec_t
*
rec
,
/*!< in: clustered index record */
ulint
field_no
,
/*!< in: off-page column number */
ulint
page_no
,
/*!< in: start page of the column */
dict_index_t
*
index
,
/*!< in/out: index tree */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
btr_blob_dbg_t
b
;
const
page_t
*
page
=
page_align
(
rec
);
ut_a
(
index
->
blobs
);
b
.
blob_page_no
=
page_no
;
b
.
ref_page_no
=
page_get_page_no
(
page
);
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
b
.
ref_field_no
=
field_no
;
ut_a
(
b
.
ref_field_no
>=
index
->
n_uniq
);
b
.
always_owner
=
b
.
owner
=
TRUE
;
b
.
del
=
FALSE
;
ut_a
(
!
rec_get_deleted_flag
(
rec
,
page_is_comp
(
page
)));
btr_blob_dbg_rbt_insert
(
index
,
&
b
,
ctx
);
}
/**************************************************************//**
Add to index->blobs any references to off-page columns from a record.
@return number of references added */
UNIV_INTERN
ulint
btr_blob_dbg_add_rec
(
/*=================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: offsets */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
ulint
count
=
0
;
ulint
i
;
btr_blob_dbg_t
b
;
ibool
del
;
ut_ad
(
rec_offs_validate
(
rec
,
index
,
offsets
));
if
(
!
rec_offs_any_extern
(
offsets
))
{
return
(
0
);
}
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
del
=
(
rec_get_deleted_flag
(
rec
,
rec_offs_comp
(
offsets
))
!=
0
);
for
(
i
=
0
;
i
<
rec_offs_n_fields
(
offsets
);
i
++
)
{
if
(
rec_offs_nth_extern
(
offsets
,
i
))
{
ulint
len
;
const
byte
*
field_ref
=
rec_get_nth_field
(
rec
,
offsets
,
i
,
&
len
);
ut_a
(
len
!=
UNIV_SQL_NULL
);
ut_a
(
len
>=
BTR_EXTERN_FIELD_REF_SIZE
);
field_ref
+=
len
-
BTR_EXTERN_FIELD_REF_SIZE
;
if
(
!
memcmp
(
field_ref
,
field_ref_zero
,
BTR_EXTERN_FIELD_REF_SIZE
))
{
/* the column has not been stored yet */
continue
;
}
b
.
ref_field_no
=
i
;
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
ut_a
(
b
.
ref_field_no
>=
index
->
n_uniq
);
b
.
always_owner
=
b
.
owner
=
!
(
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_OWNER_FLAG
);
b
.
del
=
del
;
btr_blob_dbg_rbt_insert
(
index
,
&
b
,
ctx
);
count
++
;
}
}
return
(
count
);
}
/**************************************************************//**
Display the references to off-page columns.
This function is to be called from a debugger,
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
UNIV_INTERN
void
btr_blob_dbg_print
(
/*===============*/
const
dict_index_t
*
index
)
/*!< in: index tree */
{
const
ib_rbt_node_t
*
node
;
if
(
!
index
->
blobs
)
{
return
;
}
/* We intentionally do not acquire index->blobs_mutex here.
This function is to be called from a debugger, and the caller
should make sure that the index->blobs_mutex is held. */
for
(
node
=
rbt_first
(
index
->
blobs
);
node
!=
NULL
;
node
=
rbt_next
(
index
->
blobs
,
node
))
{
const
btr_blob_dbg_t
*
b
=
rbt_value
(
btr_blob_dbg_t
,
node
);
fprintf
(
stderr
,
"%u:%u:%u->%u%s%s%s
\n
"
,
b
->
ref_page_no
,
b
->
ref_heap_no
,
b
->
ref_field_no
,
b
->
blob_page_no
,
b
->
owner
?
""
:
"(disowned)"
,
b
->
always_owner
?
""
:
"(has disowned)"
,
b
->
del
?
"(deleted)"
:
""
);
}
}
/**************************************************************//**
Remove from index->blobs any references to off-page columns from a record.
@return number of references removed */
UNIV_INTERN
ulint
btr_blob_dbg_remove_rec
(
/*====================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: offsets */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
ulint
i
;
ulint
count
=
0
;
btr_blob_dbg_t
b
;
ut_ad
(
rec_offs_validate
(
rec
,
index
,
offsets
));
if
(
!
rec_offs_any_extern
(
offsets
))
{
return
(
0
);
}
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
for
(
i
=
0
;
i
<
rec_offs_n_fields
(
offsets
);
i
++
)
{
if
(
rec_offs_nth_extern
(
offsets
,
i
))
{
ulint
len
;
const
byte
*
field_ref
=
rec_get_nth_field
(
rec
,
offsets
,
i
,
&
len
);
ut_a
(
len
!=
UNIV_SQL_NULL
);
ut_a
(
len
>=
BTR_EXTERN_FIELD_REF_SIZE
);
field_ref
+=
len
-
BTR_EXTERN_FIELD_REF_SIZE
;
b
.
ref_field_no
=
i
;
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
switch
(
b
.
blob_page_no
)
{
case
0
:
/* The column has not been stored yet.
The BLOB pointer must be all zero.
There cannot be a BLOB starting at
page 0, because page 0 is reserved for
the tablespace header. */
ut_a
(
!
memcmp
(
field_ref
,
field_ref_zero
,
BTR_EXTERN_FIELD_REF_SIZE
));
/* fall through */
case
FIL_NULL
:
/* the column has been freed already */
continue
;
}
btr_blob_dbg_rbt_delete
(
index
,
&
b
,
ctx
);
count
++
;
}
}
return
(
count
);
}
/**************************************************************//**
Check that there are no references to off-page columns from or to
the given page. Invoked when freeing or clearing a page.
@return TRUE when no orphan references exist */
UNIV_INTERN
ibool
btr_blob_dbg_is_empty
(
/*==================*/
dict_index_t
*
index
,
/*!< in: index */
ulint
page_no
)
/*!< in: page number */
{
const
ib_rbt_node_t
*
node
;
ibool
success
=
TRUE
;
if
(
!
index
->
blobs
)
{
return
(
success
);
}
mutex_enter
(
&
index
->
blobs_mutex
);
for
(
node
=
rbt_first
(
index
->
blobs
);
node
!=
NULL
;
node
=
rbt_next
(
index
->
blobs
,
node
))
{
const
btr_blob_dbg_t
*
b
=
rbt_value
(
btr_blob_dbg_t
,
node
);
if
(
b
->
ref_page_no
!=
page_no
&&
b
->
blob_page_no
!=
page_no
)
{
continue
;
}
fprintf
(
stderr
,
"InnoDB: orphan BLOB ref%s%s%s %u:%u:%u->%u
\n
"
,
b
->
owner
?
""
:
"(disowned)"
,
b
->
always_owner
?
""
:
"(has disowned)"
,
b
->
del
?
"(deleted)"
:
""
,
b
->
ref_page_no
,
b
->
ref_heap_no
,
b
->
ref_field_no
,
b
->
blob_page_no
);
if
(
b
->
blob_page_no
!=
page_no
||
b
->
owner
||
!
b
->
del
)
{
success
=
FALSE
;
}
}
mutex_exit
(
&
index
->
blobs_mutex
);
return
(
success
);
}
/**************************************************************//**
Count and process all references to off-page columns on a page.
@return number of references processed */
UNIV_INTERN
ulint
btr_blob_dbg_op
(
/*============*/
const
page_t
*
page
,
/*!< in: B-tree leaf page */
const
rec_t
*
rec
,
/*!< in: record to start from
(NULL to process the whole page) */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
,
/*!< in: context (for logging) */
const
btr_blob_dbg_op_f
op
)
/*!< in: operation on records */
{
ulint
count
=
0
;
mem_heap_t
*
heap
=
NULL
;
ulint
offsets_
[
REC_OFFS_NORMAL_SIZE
];
ulint
*
offsets
=
offsets_
;
rec_offs_init
(
offsets_
);
ut_a
(
fil_page_get_type
(
page
)
==
FIL_PAGE_INDEX
);
ut_a
(
!
rec
||
page_align
(
rec
)
==
page
);
if
(
!
index
->
blobs
||
!
page_is_leaf
(
page
)
||
!
dict_index_is_clust
(
index
))
{
return
(
0
);
}
if
(
rec
==
NULL
)
{
rec
=
page_get_infimum_rec
(
page
);
}
do
{
offsets
=
rec_get_offsets
(
rec
,
index
,
offsets
,
ULINT_UNDEFINED
,
&
heap
);
count
+=
op
(
rec
,
index
,
offsets
,
ctx
);
rec
=
page_rec_get_next_const
(
rec
);
}
while
(
!
page_rec_is_supremum
(
rec
));
if
(
UNIV_LIKELY_NULL
(
heap
))
{
mem_heap_free
(
heap
);
}
return
(
count
);
}
/**************************************************************//**
Count and add to index->blobs any references to off-page columns
from records on a page.
@return number of references added */
UNIV_INTERN
ulint
btr_blob_dbg_add
(
/*=============*/
const
page_t
*
page
,
/*!< in: rewritten page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
btr_blob_dbg_assert_empty
(
index
,
page_get_page_no
(
page
));
return
(
btr_blob_dbg_op
(
page
,
NULL
,
index
,
ctx
,
btr_blob_dbg_add_rec
));
}
/**************************************************************//**
Count and remove from index->blobs any references to off-page columns
from records on a page.
Used when reorganizing a page, before copying the records.
@return number of references removed */
UNIV_INTERN
ulint
btr_blob_dbg_remove
(
/*================*/
const
page_t
*
page
,
/*!< in: b-tree page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
ulint
count
;
count
=
btr_blob_dbg_op
(
page
,
NULL
,
index
,
ctx
,
btr_blob_dbg_remove_rec
);
/* Check that no references exist. */
btr_blob_dbg_assert_empty
(
index
,
page_get_page_no
(
page
));
return
(
count
);
}
/**************************************************************//**
Restore in index->blobs any references to off-page columns
Used when page reorganize fails due to compressed page overflow. */
UNIV_INTERN
void
btr_blob_dbg_restore
(
/*=================*/
const
page_t
*
npage
,
/*!< in: page that failed to compress */
const
page_t
*
page
,
/*!< in: copy of original page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
{
ulint
removed
;
ulint
added
;
ut_a
(
page_get_page_no
(
npage
)
==
page_get_page_no
(
page
));
ut_a
(
page_get_space_id
(
npage
)
==
page_get_space_id
(
page
));
removed
=
btr_blob_dbg_remove
(
npage
,
index
,
ctx
);
added
=
btr_blob_dbg_add
(
page
,
index
,
ctx
);
ut_a
(
added
==
removed
);
}
/**************************************************************//**
Modify the 'deleted' flag of a record. */
UNIV_INTERN
void
btr_blob_dbg_set_deleted_flag
(
/*==========================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: rec_get_offs(rec, index) */
ibool
del
)
/*!< in: TRUE=deleted, FALSE=exists */
{
const
ib_rbt_node_t
*
node
;
btr_blob_dbg_t
b
;
btr_blob_dbg_t
*
c
;
ulint
i
;
ut_ad
(
rec_offs_validate
(
rec
,
index
,
offsets
));
ut_a
(
dict_index_is_clust
(
index
));
ut_a
(
del
==
!!
del
);
/* must be FALSE==0 or TRUE==1 */
if
(
!
rec_offs_any_extern
(
offsets
)
||
!
index
->
blobs
)
{
return
;
}
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
for
(
i
=
0
;
i
<
rec_offs_n_fields
(
offsets
);
i
++
)
{
if
(
rec_offs_nth_extern
(
offsets
,
i
))
{
ulint
len
;
const
byte
*
field_ref
=
rec_get_nth_field
(
rec
,
offsets
,
i
,
&
len
);
ut_a
(
len
!=
UNIV_SQL_NULL
);
ut_a
(
len
>=
BTR_EXTERN_FIELD_REF_SIZE
);
field_ref
+=
len
-
BTR_EXTERN_FIELD_REF_SIZE
;
b
.
ref_field_no
=
i
;
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
switch
(
b
.
blob_page_no
)
{
case
0
:
ut_a
(
memcmp
(
field_ref
,
field_ref_zero
,
BTR_EXTERN_FIELD_REF_SIZE
));
/* page number 0 is for the
page allocation bitmap */
case
FIL_NULL
:
/* the column has been freed already */
ut_error
;
}
mutex_enter
(
&
index
->
blobs_mutex
);
node
=
rbt_lookup
(
index
->
blobs
,
&
b
);
ut_a
(
node
);
c
=
rbt_value
(
btr_blob_dbg_t
,
node
);
/* The flag should be modified. */
c
->
del
=
del
;
if
(
btr_blob_dbg_msg
)
{
b
=
*
c
;
mutex_exit
(
&
index
->
blobs_mutex
);
btr_blob_dbg_msg_issue
(
"del_mk"
,
&
b
,
""
);
}
else
{
mutex_exit
(
&
index
->
blobs_mutex
);
}
}
}
}
/**************************************************************//**
Change the ownership of an off-page column. */
UNIV_INTERN
void
btr_blob_dbg_owner
(
/*===============*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: rec_get_offs(rec, index) */
ulint
i
,
/*!< in: ith field in rec */
ibool
own
)
/*!< in: TRUE=owned, FALSE=disowned */
{
const
ib_rbt_node_t
*
node
;
btr_blob_dbg_t
b
;
const
byte
*
field_ref
;
ulint
len
;
ut_ad
(
rec_offs_validate
(
rec
,
index
,
offsets
));
ut_a
(
rec_offs_nth_extern
(
offsets
,
i
));
field_ref
=
rec_get_nth_field
(
rec
,
offsets
,
i
,
&
len
);
ut_a
(
len
!=
UNIV_SQL_NULL
);
ut_a
(
len
>=
BTR_EXTERN_FIELD_REF_SIZE
);
field_ref
+=
len
-
BTR_EXTERN_FIELD_REF_SIZE
;
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
b
.
ref_field_no
=
i
;
b
.
owner
=
!
(
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_OWNER_FLAG
);
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
ut_a
(
b
.
owner
==
own
);
mutex_enter
(
&
index
->
blobs_mutex
);
node
=
rbt_lookup
(
index
->
blobs
,
&
b
);
/* row_ins_clust_index_entry_by_modify() invokes
btr_cur_unmark_extern_fields() also for the newly inserted
references, which are all zero bytes until the columns are stored.
The node lookup must fail if and only if that is the case. */
ut_a
(
!
memcmp
(
field_ref
,
field_ref_zero
,
BTR_EXTERN_FIELD_REF_SIZE
)
==
!
node
);
if
(
node
)
{
btr_blob_dbg_t
*
c
=
rbt_value
(
btr_blob_dbg_t
,
node
);
/* Some code sets ownership from TRUE to TRUE.
We do not allow changing ownership from FALSE to FALSE. */
ut_a
(
own
||
c
->
owner
);
c
->
owner
=
own
;
if
(
!
own
)
{
c
->
always_owner
=
FALSE
;
}
}
mutex_exit
(
&
index
->
blobs_mutex
);
}
#endif
/* UNIV_BLOB_DEBUG */
/*
Latching strategy of the InnoDB B-tree
--------------------------------------
...
...
@@ -296,6 +850,7 @@ btr_page_create(
page_t
*
page
=
buf_block_get_frame
(
block
);
ut_ad
(
mtr_memo_contains
(
mtr
,
block
,
MTR_MEMO_PAGE_X_FIX
));
btr_blob_dbg_assert_empty
(
index
,
buf_block_get_page_no
(
block
));
if
(
UNIV_LIKELY_NULL
(
page_zip
))
{
page_create_zip
(
block
,
index
,
level
,
mtr
);
...
...
@@ -489,6 +1044,7 @@ btr_page_free_low(
modify clock */
buf_block_modify_clock_inc
(
block
);
btr_blob_dbg_assert_empty
(
index
,
buf_block_get_page_no
(
block
));
if
(
dict_index_is_ibuf
(
index
))
{
...
...
@@ -774,6 +1330,14 @@ btr_create(
block
=
buf_page_get
(
space
,
zip_size
,
page_no
,
RW_X_LATCH
,
mtr
);
}
else
{
#ifdef UNIV_BLOB_DEBUG
if
((
type
&
DICT_CLUSTERED
)
&&
!
index
->
blobs
)
{
mutex_create
(
PFS_NOT_INSTRUMENTED
,
&
index
->
blobs_mutex
,
SYNC_ANY_LATCH
);
index
->
blobs
=
rbt_create
(
sizeof
(
btr_blob_dbg_t
),
btr_blob_dbg_cmp
);
}
#endif
/* UNIV_BLOB_DEBUG */
block
=
fseg_create
(
space
,
0
,
PAGE_HEADER
+
PAGE_BTR_SEG_TOP
,
mtr
);
}
...
...
@@ -998,6 +1562,7 @@ btr_page_reorganize_low(
block
->
check_index_page_at_flush
=
TRUE
;
#endif
/* !UNIV_HOTBACKUP */
btr_blob_dbg_remove
(
page
,
index
,
"btr_page_reorganize"
);
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
...
...
@@ -1026,6 +1591,8 @@ btr_page_reorganize_low(
(
!
page_zip_compress
(
page_zip
,
page
,
index
,
NULL
)))
{
/* Restore the old page and exit. */
btr_blob_dbg_restore
(
page
,
temp_page
,
index
,
"btr_page_reorganize_compress_fail"
);
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
/* Check that the bytes that we skip are identical. */
...
...
@@ -1159,6 +1726,7 @@ btr_page_empty(
#endif
/* UNIV_ZIP_DEBUG */
btr_search_drop_page_hash_index
(
block
);
btr_blob_dbg_remove
(
page
,
index
,
"btr_page_empty"
);
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
...
...
@@ -2499,6 +3067,7 @@ btr_lift_page_up(
index
);
}
btr_blob_dbg_remove
(
page
,
index
,
"btr_lift_page_up"
);
lock_update_copy_and_discard
(
father_block
,
block
);
/* Go upward to root page, decrementing levels by one. */
...
...
@@ -2760,6 +3329,7 @@ err_exit:
lock_update_merge_right
(
merge_block
,
orig_succ
,
block
);
}
btr_blob_dbg_remove
(
page
,
index
,
"btr_compress"
);
mem_heap_free
(
heap
);
if
(
!
dict_index_is_clust
(
index
)
&&
page_is_leaf
(
merge_page
))
{
...
...
@@ -2990,6 +3560,8 @@ btr_discard_page(
block
);
}
btr_blob_dbg_remove
(
page
,
index
,
"btr_discard_page"
);
/* Free the file page */
btr_page_free
(
index
,
block
,
mtr
);
...
...
storage/innobase/btr/btr0cur.c
View file @
27fbb7c1
...
...
@@ -2690,6 +2690,7 @@ btr_cur_del_mark_set_clust_rec(
page_zip
=
buf_block_get_page_zip
(
block
);
btr_blob_dbg_set_deleted_flag
(
rec
,
index
,
offsets
,
val
);
btr_rec_set_deleted_flag
(
rec
,
page_zip
,
val
);
trx
=
thr_get_trx
(
thr
);
...
...
@@ -3873,6 +3874,8 @@ btr_cur_set_ownership_of_extern_field(
}
else
{
mach_write_to_1
(
data
+
local_len
+
BTR_EXTERN_LEN
,
byte_val
);
}
btr_blob_dbg_owner
(
rec
,
index
,
offsets
,
i
,
val
);
}
/*******************************************************************//**
...
...
@@ -4373,6 +4376,11 @@ btr_store_big_rec_extern_fields_func(
}
if
(
prev_page_no
==
FIL_NULL
)
{
btr_blob_dbg_add_blob
(
rec
,
big_rec_vec
->
fields
[
i
]
.
field_no
,
page_no
,
index
,
"store"
);
mach_write_to_4
(
field_ref
+
BTR_EXTERN_SPACE_ID
,
space_id
);
...
...
@@ -4448,6 +4456,11 @@ next_zip_page:
MLOG_4BYTES
,
&
mtr
);
if
(
prev_page_no
==
FIL_NULL
)
{
btr_blob_dbg_add_blob
(
rec
,
big_rec_vec
->
fields
[
i
]
.
field_no
,
page_no
,
index
,
"store"
);
mlog_write_ulint
(
field_ref
+
BTR_EXTERN_SPACE_ID
,
space_id
,
...
...
@@ -4616,6 +4629,37 @@ btr_free_externally_stored_field(
rec_zip_size
=
0
;
}
#ifdef UNIV_BLOB_DEBUG
if
(
!
(
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_OWNER_FLAG
)
&&
!
((
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_INHERITED_FLAG
)
&&
(
rb_ctx
==
RB_NORMAL
||
rb_ctx
==
RB_RECOVERY
)))
{
/* This off-page column will be freed.
Check that no references remain. */
btr_blob_dbg_t
b
;
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
if
(
rec
)
{
/* Remove the reference from the record to the
BLOB. If the BLOB were not freed, the
reference would be removed when the record is
removed. Freeing the BLOB will overwrite the
BTR_EXTERN_PAGE_NO in the field_ref of the
record with FIL_NULL, which would make the
btr_blob_dbg information inconsistent with the
record. */
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
b
.
ref_field_no
=
i
;
btr_blob_dbg_rbt_delete
(
index
,
&
b
,
"free"
);
}
btr_blob_dbg_assert_empty
(
index
,
b
.
blob_page_no
);
}
#endif
/* UNIV_BLOB_DEBUG */
for
(;;)
{
#ifdef UNIV_SYNC_DEBUG
buf_block_t
*
rec_block
;
...
...
storage/innobase/dict/dict0mem.c
View file @
27fbb7c1
...
...
@@ -38,6 +38,9 @@ Created 1/8/1996 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
# include "lock0lock.h"
#endif
/* !UNIV_HOTBACKUP */
#ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h"
#endif
/* UNIV_BLOB_DEBUG */
#define DICT_HEAP_SIZE 100
/*!< initial memory heap size when
creating a table or index object */
...
...
@@ -380,6 +383,12 @@ dict_mem_index_free(
{
ut_ad
(
index
);
ut_ad
(
index
->
magic_n
==
DICT_INDEX_MAGIC_N
);
#ifdef UNIV_BLOB_DEBUG
if
(
index
->
blobs
)
{
mutex_free
(
&
index
->
blobs_mutex
);
rbt_free
(
index
->
blobs
);
}
#endif
/* UNIV_BLOB_DEBUG */
mem_heap_free
(
index
->
heap
);
}
storage/innobase/include/btr0btr.h
View file @
27fbb7c1
...
...
@@ -92,6 +92,91 @@ insert/delete buffer when the record is not in the buffer pool. */
buffer when the record is not in the buffer pool. */
#define BTR_DELETE 8192
#ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h"
/** An index->blobs entry for keeping track of off-page column references */
struct
btr_blob_dbg_struct
{
unsigned
blob_page_no
:
32
;
/*!< first BLOB page number */
unsigned
ref_page_no
:
32
;
/*!< referring page number */
unsigned
ref_heap_no
:
16
;
/*!< referring heap number */
unsigned
ref_field_no
:
10
;
/*!< referring field number */
unsigned
owner
:
1
;
/*!< TRUE if BLOB owner */
unsigned
always_owner
:
1
;
/*!< TRUE if always
has been the BLOB owner;
reset to TRUE on B-tree
page splits and merges */
unsigned
del
:
1
;
/*!< TRUE if currently
delete-marked */
};
/**************************************************************//**
Add a reference to an off-page column to the index->blobs map. */
UNIV_INTERN
void
btr_blob_dbg_add_blob
(
/*==================*/
const
rec_t
*
rec
,
/*!< in: clustered index record */
ulint
field_no
,
/*!< in: number of off-page column */
ulint
page_no
,
/*!< in: start page of the column */
dict_index_t
*
index
,
/*!< in/out: index tree */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Display the references to off-page columns.
This function is to be called from a debugger,
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
UNIV_INTERN
void
btr_blob_dbg_print
(
/*===============*/
const
dict_index_t
*
index
)
/*!< in: index tree */
__attribute__
((
nonnull
));
/**************************************************************//**
Check that there are no references to off-page columns from or to
the given page. Invoked when freeing or clearing a page.
@return TRUE when no orphan references exist */
UNIV_INTERN
ibool
btr_blob_dbg_is_empty
(
/*==================*/
dict_index_t
*
index
,
/*!< in: index */
ulint
page_no
)
/*!< in: page number */
__attribute__
((
nonnull
,
warn_unused_result
));
/**************************************************************//**
Modify the 'deleted' flag of a record. */
UNIV_INTERN
void
btr_blob_dbg_set_deleted_flag
(
/*==========================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: rec_get_offs(rec, index) */
ibool
del
)
/*!< in: TRUE=deleted, FALSE=exists */
__attribute__
((
nonnull
));
/**************************************************************//**
Change the ownership of an off-page column. */
UNIV_INTERN
void
btr_blob_dbg_owner
(
/*===============*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: rec_get_offs(rec, index) */
ulint
i
,
/*!< in: ith field in rec */
ibool
own
)
/*!< in: TRUE=owned, FALSE=disowned */
__attribute__
((
nonnull
));
/** Assert that there are no BLOB references to or from the given page. */
# define btr_blob_dbg_assert_empty(index, page_no) \
ut_a(btr_blob_dbg_is_empty(index, page_no))
#else
/* UNIV_BLOB_DEBUG */
# define btr_blob_dbg_add_blob(rec, field_no, page, index, ctx) ((void) 0)
# define btr_blob_dbg_set_deleted_flag(rec, index, offsets, del)((void) 0)
# define btr_blob_dbg_owner(rec, index, offsets, i, val) ((void) 0)
# define btr_blob_dbg_assert_empty(index, page_no) ((void) 0)
#endif
/* UNIV_BLOB_DEBUG */
/**************************************************************//**
Gets the root node of a tree and x-latches it.
@return root page, x-latched */
...
...
storage/innobase/include/btr0types.h
View file @
27fbb7c1
...
...
@@ -38,6 +38,131 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef
struct
btr_search_struct
btr_search_t
;
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */
typedef
struct
btr_blob_dbg_struct
btr_blob_dbg_t
;
/** Insert to index->blobs a reference to an off-page column.
@param index the index tree
@param b the reference
@param ctx context (for logging) */
UNIV_INTERN
void
btr_blob_dbg_rbt_insert
(
/*====================*/
dict_index_t
*
index
,
/*!< in/out: index tree */
const
btr_blob_dbg_t
*
b
,
/*!< in: the reference */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/** Remove from index->blobs a reference to an off-page column.
@param index the index tree
@param b the reference
@param ctx context (for logging) */
UNIV_INTERN
void
btr_blob_dbg_rbt_delete
(
/*====================*/
dict_index_t
*
index
,
/*!< in/out: index tree */
const
btr_blob_dbg_t
*
b
,
/*!< in: the reference */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Add to index->blobs any references to off-page columns from a record.
@return number of references added */
UNIV_INTERN
ulint
btr_blob_dbg_add_rec
(
/*=================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: offsets */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Remove from index->blobs any references to off-page columns from a record.
@return number of references removed */
UNIV_INTERN
ulint
btr_blob_dbg_remove_rec
(
/*====================*/
const
rec_t
*
rec
,
/*!< in: record */
dict_index_t
*
index
,
/*!< in/out: index */
const
ulint
*
offsets
,
/*!< in: offsets */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Count and add to index->blobs any references to off-page columns
from records on a page.
@return number of references added */
UNIV_INTERN
ulint
btr_blob_dbg_add
(
/*=============*/
const
page_t
*
page
,
/*!< in: rewritten page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Count and remove from index->blobs any references to off-page columns
from records on a page.
Used when reorganizing a page, before copying the records.
@return number of references removed */
UNIV_INTERN
ulint
btr_blob_dbg_remove
(
/*================*/
const
page_t
*
page
,
/*!< in: b-tree page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/**************************************************************//**
Restore in index->blobs any references to off-page columns
Used when page reorganize fails due to compressed page overflow. */
UNIV_INTERN
void
btr_blob_dbg_restore
(
/*=================*/
const
page_t
*
npage
,
/*!< in: page that failed to compress */
const
page_t
*
page
,
/*!< in: copy of original page */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
)
/*!< in: context (for logging) */
__attribute__
((
nonnull
));
/** Operation that processes the BLOB references of an index record
@param[in] rec record on index page
@param[in/out] index the index tree of the record
@param[in] offsets rec_get_offsets(rec,index)
@param[in] ctx context (for logging)
@return number of BLOB references processed */
typedef
ulint
(
*
btr_blob_dbg_op_f
)
(
const
rec_t
*
rec
,
dict_index_t
*
index
,
const
ulint
*
offsets
,
const
char
*
ctx
);
/**************************************************************//**
Count and process all references to off-page columns on a page.
@return number of references processed */
UNIV_INTERN
ulint
btr_blob_dbg_op
(
/*============*/
const
page_t
*
page
,
/*!< in: B-tree leaf page */
const
rec_t
*
rec
,
/*!< in: record to start from
(NULL to process the whole page) */
dict_index_t
*
index
,
/*!< in/out: index */
const
char
*
ctx
,
/*!< in: context (for logging) */
const
btr_blob_dbg_op_f
op
)
/*!< in: operation on records */
__attribute__
((
nonnull
(
1
,
3
,
4
,
5
)));
#else
/* UNIV_BLOB_DEBUG */
# define btr_blob_dbg_add_rec(rec, index, offsets, ctx) ((void) 0)
# define btr_blob_dbg_add(page, index, ctx) ((void) 0)
# define btr_blob_dbg_remove_rec(rec, index, offsets, ctx) ((void) 0)
# define btr_blob_dbg_remove(page, index, ctx) ((void) 0)
# define btr_blob_dbg_restore(npage, page, index, ctx) ((void) 0)
# define btr_blob_dbg_op(page, rec, index, ctx, op) ((void) 0)
#endif
/* UNIV_BLOB_DEBUG */
/** The size of a reference to data stored on a different page.
The reference is stored at the end of the prefix of the field
in the index record. */
...
...
storage/innobase/include/dict0mem.h
View file @
27fbb7c1
...
...
@@ -395,6 +395,13 @@ struct dict_index_struct{
index, or 0 if the index existed
when InnoDB was started up */
#endif
/* !UNIV_HOTBACKUP */
#ifdef UNIV_BLOB_DEBUG
mutex_t
blobs_mutex
;
/*!< mutex protecting blobs */
void
*
blobs
;
/*!< map of (page_no,heap_no,field_no)
to first_blob_page_no; protected by
blobs_mutex; @see btr_blob_dbg_t */
#endif
/* UNIV_BLOB_DEBUG */
#ifdef UNIV_DEBUG
ulint
magic_n
;
/*!< magic number */
/** Value of dict_index_struct::magic_n */
...
...
storage/innobase/include/page0zip.h
View file @
27fbb7c1
...
...
@@ -420,7 +420,7 @@ page_zip_copy_recs(
const
page_t
*
src
,
/*!< in: page */
dict_index_t
*
index
,
/*!< in: index of the B-tree */
mtr_t
*
mtr
)
/*!< in: mini-transaction */
__attribute__
((
nonnull
(
1
,
2
,
3
,
4
)
));
__attribute__
((
nonnull
));
#endif
/* !UNIV_HOTBACKUP */
/**********************************************************************//**
...
...
storage/innobase/include/univ.i
View file @
27fbb7c1
...
...
@@ -201,6 +201,8 @@ this will break redo log file compatibility, but it may be useful when
debugging redo log application problems. */
#
define
UNIV_MEM_DEBUG
/* detect memory leaks etc */
#
define
UNIV_IBUF_DEBUG
/* debug the insert buffer */
#
define
UNIV_BLOB_DEBUG
/* track BLOB ownership;
assumes that no BLOBs survive server restart */
#
define
UNIV_IBUF_COUNT_DEBUG
/* debug the insert buffer;
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
and the insert buffer must be empty when the database is started */
...
...
storage/innobase/page/page0cur.c
View file @
27fbb7c1
...
...
@@ -1149,6 +1149,8 @@ use_heap:
current_rec
,
index
,
mtr
);
}
btr_blob_dbg_add_rec
(
insert_rec
,
index
,
offsets
,
"insert"
);
return
(
insert_rec
);
}
...
...
@@ -1195,10 +1197,12 @@ page_cur_insert_rec_zip_reorg(
}
/* Out of space: restore the page */
btr_blob_dbg_remove
(
page
,
index
,
"insert_zip_fail"
);
if
(
!
page_zip_decompress
(
page_zip
,
page
,
FALSE
))
{
ut_error
;
/* Memory corrupted? */
}
ut_ad
(
page_validate
(
page
,
index
));
btr_blob_dbg_add
(
page
,
index
,
"insert_zip_fail"
);
return
(
NULL
);
}
...
...
@@ -1490,6 +1494,8 @@ use_heap:
page_zip_write_rec
(
page_zip
,
insert_rec
,
index
,
offsets
,
1
);
btr_blob_dbg_add_rec
(
insert_rec
,
index
,
offsets
,
"insert_zip_ok"
);
/* 9. Write log record of the insert */
if
(
UNIV_LIKELY
(
mtr
!=
NULL
))
{
page_cur_insert_rec_write_log
(
insert_rec
,
rec_size
,
...
...
@@ -1697,6 +1703,9 @@ page_copy_rec_list_end_to_created_page(
heap_top
+=
rec_size
;
rec_offs_make_valid
(
insert_rec
,
index
,
offsets
);
btr_blob_dbg_add_rec
(
insert_rec
,
index
,
offsets
,
"copy_end"
);
page_cur_insert_rec_write_log
(
insert_rec
,
rec_size
,
prev_rec
,
index
,
mtr
);
prev_rec
=
insert_rec
;
...
...
@@ -1944,6 +1953,7 @@ page_cur_delete_rec(
page_dir_slot_set_n_owned
(
cur_dir_slot
,
page_zip
,
cur_n_owned
-
1
);
/* 6. Free the memory occupied by the record */
btr_blob_dbg_remove_rec
(
current_rec
,
index
,
offsets
,
"delete"
);
page_mem_free
(
page
,
page_zip
,
current_rec
,
index
,
offsets
);
/* 7. Now we have decremented the number of owned records of the slot.
...
...
storage/innobase/page/page0page.c
View file @
27fbb7c1
...
...
@@ -685,12 +685,16 @@ page_copy_rec_list_end(
if
(
UNIV_UNLIKELY
(
!
page_zip_reorganize
(
new_block
,
index
,
mtr
)))
{
btr_blob_dbg_remove
(
new_page
,
index
,
"copy_end_reorg_fail"
);
if
(
UNIV_UNLIKELY
(
!
page_zip_decompress
(
new_page_zip
,
new_page
,
FALSE
)))
{
ut_error
;
}
ut_ad
(
page_validate
(
new_page
,
index
));
btr_blob_dbg_add
(
new_page
,
index
,
"copy_end_reorg_fail"
);
return
(
NULL
);
}
else
{
/* The page was reorganized:
...
...
@@ -803,12 +807,16 @@ page_copy_rec_list_start(
if
(
UNIV_UNLIKELY
(
!
page_zip_reorganize
(
new_block
,
index
,
mtr
)))
{
btr_blob_dbg_remove
(
new_page
,
index
,
"copy_start_reorg_fail"
);
if
(
UNIV_UNLIKELY
(
!
page_zip_decompress
(
new_page_zip
,
new_page
,
FALSE
)))
{
ut_error
;
}
ut_ad
(
page_validate
(
new_page
,
index
));
btr_blob_dbg_add
(
new_page
,
index
,
"copy_start_reorg_fail"
);
return
(
NULL
);
}
else
{
/* The page was reorganized:
...
...
@@ -1080,6 +1088,9 @@ page_delete_rec_list_end(
/* Remove the record chain segment from the record chain */
page_rec_set_next
(
prev_rec
,
page_get_supremum_rec
(
page
));
btr_blob_dbg_op
(
page
,
rec
,
index
,
"delete_end"
,
btr_blob_dbg_remove_rec
);
/* Catenate the deleted chain segment to the page free list */
page_rec_set_next
(
last_rec
,
page_header_get_ptr
(
page
,
PAGE_FREE
));
...
...
storage/innobase/page/page0zip.c
View file @
27fbb7c1
...
...
@@ -4452,6 +4452,8 @@ page_zip_reorganize(
/* Copy the old page to temporary space */
buf_frame_copy
(
temp_page
,
page
);
btr_blob_dbg_remove
(
page
,
index
,
"zip_reorg"
);
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
...
...
@@ -4510,7 +4512,7 @@ page_zip_copy_recs(
mtr_t
*
mtr
)
/*!< in: mini-transaction */
{
ut_ad
(
mtr_memo_contains_page
(
mtr
,
page
,
MTR_MEMO_PAGE_X_FIX
));
ut_ad
(
mtr_memo_contains_page
(
mtr
,
(
page_t
*
)
src
,
MTR_MEMO_PAGE_X_FIX
));
ut_ad
(
mtr_memo_contains_page
(
mtr
,
src
,
MTR_MEMO_PAGE_X_FIX
));
ut_ad
(
!
dict_index_is_ibuf
(
index
));
#ifdef UNIV_ZIP_DEBUG
/* The B-tree operations that call this function may set
...
...
@@ -4580,6 +4582,7 @@ page_zip_copy_recs(
#ifdef UNIV_ZIP_DEBUG
ut_a
(
page_zip_validate
(
page_zip
,
page
));
#endif
/* UNIV_ZIP_DEBUG */
btr_blob_dbg_add
(
page
,
index
,
"page_zip_copy_recs"
);
page_zip_compress_write_log
(
page_zip
,
page
,
index
,
mtr
);
}
...
...
storage/innobase/row/row0upd.c
View file @
27fbb7c1
...
...
@@ -498,14 +498,49 @@ row_upd_rec_in_place(
n_fields
=
upd_get_n_fields
(
update
);
for
(
i
=
0
;
i
<
n_fields
;
i
++
)
{
#ifdef UNIV_BLOB_DEBUG
btr_blob_dbg_t
b
;
const
byte
*
field_ref
=
NULL
;
#endif
/* UNIV_BLOB_DEBUG */
upd_field
=
upd_get_nth_field
(
update
,
i
);
new_val
=
&
(
upd_field
->
new_val
);
ut_ad
(
!
dfield_is_ext
(
new_val
)
==
!
rec_offs_nth_extern
(
offsets
,
upd_field
->
field_no
));
#ifdef UNIV_BLOB_DEBUG
if
(
dfield_is_ext
(
new_val
))
{
ulint
len
;
field_ref
=
rec_get_nth_field
(
rec
,
offsets
,
i
,
&
len
);
ut_a
(
len
!=
UNIV_SQL_NULL
);
ut_a
(
len
>=
BTR_EXTERN_FIELD_REF_SIZE
);
field_ref
+=
len
-
BTR_EXTERN_FIELD_REF_SIZE
;
b
.
ref_page_no
=
page_get_page_no
(
page_align
(
rec
));
b
.
ref_heap_no
=
page_rec_get_heap_no
(
rec
);
b
.
ref_field_no
=
i
;
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
ut_a
(
b
.
ref_field_no
>=
index
->
n_uniq
);
btr_blob_dbg_rbt_delete
(
index
,
&
b
,
"upd_in_place"
);
}
#endif
/* UNIV_BLOB_DEBUG */
rec_set_nth_field
(
rec
,
offsets
,
upd_field
->
field_no
,
dfield_get_data
(
new_val
),
dfield_get_len
(
new_val
));
#ifdef UNIV_BLOB_DEBUG
if
(
dfield_is_ext
(
new_val
))
{
b
.
blob_page_no
=
mach_read_from_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
);
b
.
always_owner
=
b
.
owner
=
!
(
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_OWNER_FLAG
);
b
.
del
=
rec_get_deleted_flag
(
rec
,
rec_offs_comp
(
offsets
));
btr_blob_dbg_rbt_insert
(
index
,
&
b
,
"upd_in_place"
);
}
#endif
/* UNIV_BLOB_DEBUG */
}
if
(
UNIV_LIKELY_NULL
(
page_zip
))
{
...
...
storage/innobase/srv/srv0start.c
View file @
27fbb7c1
...
...
@@ -1083,6 +1083,12 @@ innobase_start_or_create_for_mysql(void)
# endif
#endif
#ifdef UNIV_BLOB_DEBUG
fprintf
(
stderr
,
"InnoDB: !!!!!!!! UNIV_BLOB_DEBUG switched on !!!!!!!!!
\n
"
"InnoDB: Server restart may fail with UNIV_BLOB_DEBUG
\n
"
);
#endif
/* UNIV_BLOB_DEBUG */
#ifdef UNIV_SYNC_DEBUG
ut_print_timestamp
(
stderr
);
fprintf
(
stderr
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment