Diff
Not logged in

Differences From Artifact [a3038ce20f]:

To Artifact [8d633e10bb]:


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 );
}