summaryrefslogtreecommitdiff
path: root/src/heap/heap_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/heap/heap_verify.c')
-rw-r--r--src/heap/heap_verify.c169
1 files changed, 157 insertions, 12 deletions
diff --git a/src/heap/heap_verify.c b/src/heap/heap_verify.c
index ea15c28b..7c90caf0 100644
--- a/src/heap/heap_verify.c
+++ b/src/heap/heap_verify.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -9,13 +9,14 @@
#include "db_config.h"
#include "db_int.h"
+#include "dbinc/blob.h"
#include "dbinc/db_page.h"
#include "dbinc/db_verify.h"
#include "dbinc/heap.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
-static int __heap_safe_gsplit __P((DB *, VRFY_DBINFO *, PAGE *, db_indx_t,
+static int __heap_safe_gsplit __P((DB *, VRFY_DBINFO *, PAGE *, unsigned,
DBT *));
static int __heap_verify_offset_cmp __P((const void *, const void *));
@@ -37,7 +38,8 @@ __heap_vrfy_meta(dbp, vdp, meta, pgno, flags)
HEAP *h;
VRFY_PAGEINFO *pip;
db_pgno_t last_pgno, max_pgno, npgs;
- int isbad, ret;
+ int isbad, ret, t_ret;
+ db_seq_t blob_id;
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
return (ret);
@@ -97,8 +99,40 @@ __heap_vrfy_meta(dbp, vdp, meta, pgno, flags)
"%lu"), (u_long)pgno));
isbad = 1;
}
+ h->gbytes = meta->gbytes;
+ h->bytes = meta->bytes;
}
+/*
+ * Where 64-bit integer support is not available,
+ * return an error if the file has any blobs.
+ */
+ t_ret = 0;
+#ifdef HAVE_64BIT_TYPES
+ GET_BLOB_FILE_ID(dbp->env, meta, blob_id, t_ret);
+ if (t_ret != 0) {
+ isbad = 1;
+ EPRINT((dbp->env, DB_STR_A("1173",
+ "Page %lu: blob file id overflow.", "%lu"), (u_long)pgno));
+ if (ret == 0)
+ ret = t_ret;
+ }
+#else /* HAVE_64BIT_TYPES */
+ /*
+ * db_seq_t is an int on systems that do not have 64 integers types, so
+ * this will compile and run.
+ */
+ GET_BLOB_FILE_ID(env, meta, blob_id, t_ret);
+ if (t_ret != 0 || blob_id != 0) {
+ isbad = 1;
+ EPRINT((env, DB_STR_A("1206",
+ "Page %lu: blobs require 64 integer compiler support.",
+ "%lu"), (u_long)pgno));
+ if (ret == 0)
+ ret = t_ret;
+ }
+#endif
+
err: if (LF_ISSET(DB_SALVAGE))
ret = __db_salvage_markdone(vdp, pgno);
@@ -120,12 +154,16 @@ __heap_vrfy(dbp, vdp, h, pgno, flags)
db_pgno_t pgno;
u_int32_t flags;
{
+ HEAPBLOBHDR bhdr;
HEAPHDR *hdr;
- int cnt, i, j, ret;
+ int i, j, ret;
+ off_t blob_size;
+ db_seq_t blob_id, file_id;
db_indx_t *offsets, *offtbl, end;
+ u_int32_t cnt;
if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0)
- goto err;
+ return (ret);
if (TYPE(h) == P_IHEAP)
/* Nothing to verify on a region page. */
@@ -140,7 +178,7 @@ __heap_vrfy(dbp, vdp, h, pgno, flags)
/*
* Build a sorted list of all the offsets in the table. Entries in the
* offset table are not always sorted. While we're here, check that
- * flags are sane.
+ * flags are sane, and that the blob entries are sane.
*/
cnt = 0;
for (i = 0; i <= HEAP_HIGHINDX(h); i++) {
@@ -164,6 +202,36 @@ __heap_vrfy(dbp, vdp, h, pgno, flags)
ret = DB_VERIFY_BAD;
goto err;
}
+ if (F_ISSET(hdr, HEAP_RECBLOB)) {
+ /*
+ * Check that the blob file exists and is the same
+ * file size as is stored in the database record.
+ */
+ memcpy(&bhdr, hdr, sizeof(HEAPBLOBHDR));
+ blob_id = (db_seq_t)bhdr.id;
+ GET_BLOB_SIZE(dbp->env, bhdr, blob_size, ret);
+ if (ret != 0 || blob_size < 0) {
+ EPRINT((dbp->env, DB_STR_A("1175",
+ "Page %lu: blob file size value has overflowed",
+ "%lu"), (u_long)pgno));
+ ret = DB_VERIFY_BAD;
+ goto err;
+ }
+ file_id = (db_seq_t)bhdr.file_id;
+ if (file_id == 0) {
+ EPRINT((dbp->env, DB_STR_A("1177",
+ "Page %lu: invalid blob dir id %llu at item %lu",
+ "%lu %llu, %lu"), (u_long)pgno,
+ (unsigned long long)file_id, (u_long)i));
+ ret = DB_VERIFY_BAD;
+ goto err;
+ }
+ if ((ret = __blob_vrfy(dbp->env, blob_id,
+ blob_size, file_id, 0, pgno, flags)) != 0) {
+ ret = DB_VERIFY_BAD;
+ goto err;
+ }
+ }
offsets[cnt] = offtbl[i];
cnt++;
@@ -180,7 +248,7 @@ __heap_vrfy(dbp, vdp, h, pgno, flags)
* record. We can't use the P_ENTRY macro because we've kept track of
* the offsets, not the indexes.
*/
- for (i = 0; i < cnt - 1; i++) {
+ for (i = 0; i < (int)cnt - 1; i++) {
hdr = (HEAPHDR *)((u_int8_t *)h + offsets[i]);
end = offsets[i] + HEAP_HDRSIZE(hdr) + hdr->size;
if (end > offsets[i+1]) {
@@ -328,12 +396,22 @@ __heap_salvage(dbp, vdp, pgno, h, handle, callback, flags)
u_int32_t flags;
{
DBT dbt;
+ ENV *env;
HEAPHDR *hdr;
+ HEAPBLOBHDR bhdr;
db_indx_t i, *offtbl;
+ char *prefix;
int err_ret, ret, t_ret;
+ off_t blob_size, blob_offset, remaining;
+ u_int32_t blob_buf_size;
+ u_int8_t *blob_buf;
+ db_seq_t blob_id, file_id;
COMPQUIET(flags, 0);
memset(&dbt, 0, sizeof(DBT));
+ blob_buf = NULL;
+ blob_buf_size = 0;
+ env = dbp->env;
offtbl = (db_indx_t *)HEAP_OFFSETTBL(dbp, h);
err_ret = ret = t_ret = 0;
@@ -357,9 +435,74 @@ __heap_salvage(dbp, vdp, pgno, h, handle, callback, flags)
if (dbt.size > dbp->pgsize * 4)
dbt.size = dbp->pgsize * 4;
if ((ret =
- __os_malloc(dbp->env, dbt.size, &dbt.data)) != 0)
+ __os_malloc(env, dbt.size, &dbt.data)) != 0)
goto err;
- __heap_safe_gsplit(dbp, vdp, h, i, &dbt);
+ if ((ret = __heap_safe_gsplit
+ (dbp, vdp, h, i, &dbt)) != 0) {
+ err_ret = ret;
+ __os_free(env, dbt.data);
+ continue;
+ }
+ } else if (F_ISSET(hdr, HEAP_RECBLOB)) {
+ memcpy(&bhdr, hdr, HEAPBLOBREC_SIZE);
+ blob_id = (db_seq_t)bhdr.id;
+ GET_BLOB_SIZE(env, bhdr, blob_size, ret);
+ if (ret != 0 || blob_size < 0)
+ goto err;
+ file_id = (db_seq_t)bhdr.file_id;
+ /* Read the blob, in pieces if it is too large.*/
+ blob_offset = 0;
+ if (blob_size > MEGABYTE) {
+ if (blob_buf_size < MEGABYTE) {
+ if ((ret = __os_realloc(
+ env, MEGABYTE, &blob_buf)) != 0)
+ goto err;
+ blob_buf_size = MEGABYTE;
+ }
+ } else if (blob_buf_size < blob_size) {
+ blob_buf_size = (u_int32_t)blob_size;
+ if ((ret = __os_realloc(
+ env, blob_buf_size, &blob_buf)) != 0)
+ goto err;
+ }
+ dbt.data = blob_buf;
+ dbt.ulen = blob_buf_size;
+ remaining = blob_size;
+ prefix = " ";
+ do {
+ if ((ret = __blob_salvage(env, blob_id,
+ blob_offset,
+ ((remaining < blob_buf_size) ?
+ (size_t)remaining : blob_buf_size),
+ file_id, 0, &dbt)) != 0) {
+ if (LF_ISSET(DB_AGGRESSIVE)) {
+ ret = DB_VERIFY_BAD;
+ break;
+ }
+ F_CLR(vdp, SALVAGE_STREAM_BLOB);
+ goto err;
+ }
+ if (remaining > blob_buf_size)
+ F_SET(vdp, SALVAGE_STREAM_BLOB);
+ else
+ F_CLR(vdp, SALVAGE_STREAM_BLOB);
+ if ((t_ret = __db_vrfy_prdbt(
+ &dbt, 0, prefix, handle,
+ callback, 0, 0, vdp)) != 0) {
+ if (ret == 0)
+ ret = t_ret;
+ F_CLR(vdp, SALVAGE_STREAM_BLOB);
+ goto err;
+ }
+ prefix = NULL;
+ blob_offset += dbt.size;
+ if (remaining < blob_buf_size)
+ remaining = 0;
+ else
+ remaining -= blob_buf_size;
+ } while (remaining > 0);
+ F_CLR(vdp, SALVAGE_STREAM_BLOB);
+ continue;
} else {
dbt.data = (u_int8_t *)hdr + HEAP_HDRSIZE(hdr);
dbt.size = hdr->size;
@@ -369,11 +512,13 @@ __heap_salvage(dbp, vdp, pgno, h, handle, callback, flags)
0, " ", handle, callback, 0, 0, vdp)) != 0)
err_ret = ret;
if (F_ISSET(hdr, HEAP_RECSPLIT))
- __os_free(dbp->env, dbt.data);
+ __os_free(env, dbt.data);
}
err: if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
return (t_ret);
+ if (blob_buf != NULL)
+ __os_free(env, blob_buf);
return ((ret == 0 && err_ret != 0) ? err_ret : ret);
}
@@ -386,7 +531,7 @@ __heap_safe_gsplit(dbp, vdp, h, i, dbt)
DB *dbp;
VRFY_DBINFO *vdp;
PAGE *h;
- db_indx_t i;
+ unsigned i;
DBT *dbt;
{
DB_MPOOLFILE *mpf;
@@ -433,7 +578,7 @@ __heap_safe_gsplit(dbp, vdp, h, i, dbt)
err: if (gotpg && (t_ret = __memp_fput(
mpf, vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0 && ret == 0)
- t_ret = ret;
+ ret = t_ret;
return (ret);
}