18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
-
+
+
+
+
+
+
+
|
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code used to help verify the integrity of the
** the repository
** the repository.
**
** This file primarily implements the verify_before_commit() interface.
** Any function can call verify_before_commit() with a record id (RID)
** as an argument. Then before the next change to the database commits,
** this routine will reach in and check that the record can be extracted
** correctly from the BLOB table.
*/
#include "config.h"
#include "verify.h"
#include <assert.h>
/*
** Load the record identify by rid. Make sure we can reproduce it
|
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
|
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
|
+
+
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
+
+
-
-
-
+
+
-
+
+
+
+
+
|
}
blob_reset(&hash);
}
blob_reset(&uuid);
}
/*
** The following bag holds the rid for every record that needs
** to be verified.
**
*/
static Bag toVerify;
static int inFinalVerify = 0;
/*
** This routine is called just prior to each commit operation.
*/
static int verify_at_commit(void *notUsed){
Stmt q;
db_prepare(&q, "SELECT rid FROM toverify");
while( db_step(&q)==SQLITE_ROW ){
static int verify_at_commit(void){
int rid;
inFinalVerify = 1;
rid = bag_first(&toVerify);
while( rid>0 ){
int rid = db_column_int(&q, 0);
verify_rid(rid);
rid = bag_next(&toVerify, rid);
}
db_finalize(&q);
db_multi_exec("DELETE FROM toverify");
bag_clear(&toVerify);
inFinalVerify = 0;
return 0;
}
/*
** Arrange to verify a particular record prior to committing.
**
** If the record rid is less than 1, then just initialize the
** verification system but do not record anything as needing
** verification.
*/
void verify_before_commit(int rid){
static int isInit = 0;
if( !isInit ){
db_multi_exec(
"CREATE TEMP TABLE toverify(rid INTEGER PRIMARY KEY);"
);
sqlite3_commit_hook(g.db, verify_at_commit, 0);
db_commit_hook(verify_at_commit, 1000);
isInit = 1;
}
assert( !inFinalVerify );
if( rid>0 ){
db_multi_exec(
"INSERT OR IGNORE INTO toverify VALUES(%d)", rid
);
bag_insert(&toVerify, rid);
}
}
/*
** COMMAND: test-verify-all
**
** Verify all records in the repository.
*/
void verify_all_cmd(void){
Stmt q;
int cnt = 0;
db_must_be_within_tree();
db_prepare(&q, "SELECT rid FROM blob");
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
verify_rid(rid);
verify_before_commit(rid);
cnt++;
assert( bag_count(&toVerify)==cnt );
}
db_finalize(&q);
verify_at_commit();
assert( bag_count(&toVerify)==0 );
}
|