summaryrefslogtreecommitdiff
path: root/src/dbinc/db_verify.h
blob: ea87680fe4ebe112d54e1e6e5f4190912e187722 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1999, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 * $Id$
 */

#ifndef _DB_VERIFY_H_
#define	_DB_VERIFY_H_

#if defined(__cplusplus)
extern "C" {
#endif

/*
 * Structures and macros for the storage and retrieval of all information
 * needed for inter-page verification of a database.
 */

/*
 * EPRINT is the macro for error printing.  Takes as an arg the arg set
 * for DB->err.
 */
#define	EPRINT(x) do {							\
	if (!LF_ISSET(DB_SALVAGE))					\
		__db_errx x;						\
} while (0)

/* Complain about a totally zeroed page where we don't expect one. */
#define	ZEROPG_ERR_PRINT(dbenv, pgno, str) do {				\
	EPRINT(((dbenv), DB_STR_A("0501", 				\
	    "Page %lu: %s is of inappropriate type %lu", "%lu %s %lu"),	\
	    (u_long)(pgno), str, (u_long)P_INVALID));			\
	EPRINT(((dbenv), DB_STR_A("0502",				\
	    "Page %lu: totally zeroed page",				\
	    "%lu"), (u_long)(pgno)));					\
} while (0)

/*
 * Note that 0 is, in general, a valid pgno, despite equaling PGNO_INVALID;
 * we have to test it separately where it's not appropriate.
 */
#define	IS_VALID_PGNO(x)	((x) <= vdp->last_pgno)

/*
 * VRFY_DBINFO is the fundamental structure;  it either represents the database
 * of subdatabases, or the sole database if there are no subdatabases.
 */
struct __vrfy_dbinfo {
	DB_THREAD_INFO *thread_info;
	/* Info about this database in particular. */
	DBTYPE		type;

	/* List of subdatabase meta pages, if any. */
	LIST_HEAD(__subdbs, __vrfy_childinfo) subdbs;

	/* Transaction handle for CDS group. */
	DB_TXN *txn;

	/* File-global info--stores VRFY_PAGEINFOs for each page. */
	DB *pgdbp;

	/* Child database--stores VRFY_CHILDINFOs of each page. */
	DB *cdbp;

	/* Page info structures currently in use. */
	LIST_HEAD(__activepips, __vrfy_pageinfo) activepips;

	/*
	 * DB we use to keep track of which pages are linked somehow
	 * during verification.  0 is the default, "unseen";  1 is seen.
	 */
	DB *pgset;

	/*
	 * This is a database we use during salvaging to keep track of which
	 * overflow and dup pages we need to come back to at the end and print
	 * with key "UNKNOWN".  Pages which print with a good key get set
	 * to SALVAGE_IGNORE;  others get set, as appropriate, to SALVAGE_LDUP,
	 * SALVAGE_LRECNODUP, SALVAGE_OVERFLOW for normal db overflow pages,
	 * and SALVAGE_BTREE, SALVAGE_LRECNO, and SALVAGE_HASH for subdb
	 * pages.
	 */
#define	SALVAGE_INVALID		0
#define	SALVAGE_IGNORE		1
#define	SALVAGE_LDUP		2
#define	SALVAGE_IBTREE		3
#define	SALVAGE_OVERFLOW	4
#define	SALVAGE_LBTREE		5
#define	SALVAGE_HASH		6
#define	SALVAGE_LRECNO		7
#define	SALVAGE_LRECNODUP	8
	DB *salvage_pages;

	db_pgno_t	last_pgno;
	db_pgno_t	meta_last_pgno;
	db_pgno_t	pgs_remaining;	/* For dbp->db_feedback(). */

	/*
	 * These are used during __bam_vrfy_subtree to keep track, while
	 * walking up and down the Btree structure, of the prev- and next-page
	 * chain of leaf pages and verify that it's intact.  Also, make sure
	 * that this chain contains pages of only one type.
	 */
	db_pgno_t	prev_pgno;
	db_pgno_t	next_pgno;
	u_int8_t	leaf_type;

	/* Queue needs these to verify data pages in the first pass. */
	u_int32_t	re_pad;		/* Record pad character. */
	u_int32_t	re_len;		/* Record length. */
	u_int32_t	rec_page;
	u_int32_t	page_ext;
	u_int32_t       first_recno;
	u_int32_t       last_recno;
	int		nextents;
	db_pgno_t	*extents;

#define	SALVAGE_PRINTABLE	0x01	/* Output printable chars literally. */
#define	SALVAGE_PRINTHEADER	0x02	/* Print the unknown-key header. */
#define	SALVAGE_PRINTFOOTER	0x04	/* Print the unknown-key footer. */
#define	SALVAGE_STREAM_BLOB	0x08	/* Currently streaming a blob. */
#define	SALVAGE_HASSUBDBS	0x10	/* There are subdatabases to salvage. */
#define	SALVAGE_LEAFCHAIN_BROKEN 0x20	/* Lost one or more Btree leaf pgs. */
#define	SALVAGE_QMETA_SET	0x40    /* We've seen a QUEUE meta page and
					   set things up for it. */
	u_int32_t	flags;
}; /* VRFY_DBINFO */

/*
 * The amount of state information we need per-page is small enough that
 * it's not worth the trouble to define separate structures for each
 * possible type of page, and since we're doing verification with these we
 * have to be open to the possibility that page N will be of a completely
 * unexpected type anyway.  So we define one structure here with all the
 * info we need for inter-page verification.
 */
struct __vrfy_pageinfo {
	u_int8_t	type;
	u_int8_t	bt_level;
	u_int8_t	unused1;
	u_int8_t	unused2;
	db_pgno_t	pgno;
	db_pgno_t	prev_pgno;
	db_pgno_t	next_pgno;

	/* meta pages */
	db_pgno_t	root;
	db_pgno_t	free;		/* Free list head. */

	db_indx_t	entries;	/* Actual number of entries. */
	u_int16_t	unused;
	db_recno_t	rec_cnt;	/* Record count. */
	u_int32_t	re_pad;		/* Record pad character. */
	u_int32_t	re_len;		/* Record length. */
	u_int32_t	bt_minkey;
	u_int32_t	h_ffactor;
	u_int32_t	h_nelem;

	/* overflow pages */
	/*
	 * Note that refcount is the refcount for an overflow page; pi_refcount
	 * is this structure's own refcount!
	 */
	u_int32_t	refcount;
	u_int32_t	olen;

#define	VRFY_DUPS_UNSORTED	0x0001	/* Have to flag the negative! */
#define	VRFY_HAS_CHKSUM		0x0002
#define	VRFY_HAS_DUPS		0x0004
#define	VRFY_HAS_DUPSORT	0x0008	/* Has the flag set. */
#define	VRFY_HAS_PART_RANGE	0x0010	/* Has the flag set. */
#define	VRFY_HAS_PART_CALLBACK	0x0020	/* Has the flag set. */
#define	VRFY_HAS_RECNUMS	0x0040
#define	VRFY_HAS_SUBDBS		0x0080
#define	VRFY_INCOMPLETE		0x0100	/* Meta or item order checks incomp. */
#define	VRFY_IS_ALLZEROES	0x0200	/* Hash page we haven't touched? */
#define	VRFY_IS_FIXEDLEN	0x0400
#define	VRFY_IS_RECNO		0x0800
#define	VRFY_IS_RRECNO		0x1000
#define	VRFY_OVFL_LEAFSEEN	0x2000
#define	VRFY_HAS_COMPRESS	0x4000
#define	VRFY_NONEXISTENT	0x8000
	u_int32_t	flags;

	LIST_ENTRY(__vrfy_pageinfo) links;
	u_int32_t	pi_refcount;
}; /* VRFY_PAGEINFO */

struct __vrfy_childinfo {
	/* The following fields are set by the caller of __db_vrfy_childput. */
	db_pgno_t	pgno;

#define	V_DUPLICATE	1		/* off-page dup metadata */
#define	V_OVERFLOW	2		/* overflow page */
#define	V_RECNO		3		/* btree internal or leaf page */
	u_int32_t	type;
	db_recno_t	nrecs;		/* record count on a btree subtree */
	u_int32_t	tlen;		/* ovfl. item total size */

	/* The following field is maintained by __db_vrfy_childput. */
	u_int32_t	refcnt;		/* # of times parent points to child. */

	LIST_ENTRY(__vrfy_childinfo) links;
}; /* VRFY_CHILDINFO */

#if defined(__cplusplus)
}
#endif
#endif /* !_DB_VERIFY_H_ */