File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2007 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This file contains code used to help verify the integrity of the
d5e7891b07 2007-11-18       drh: ** the repository.
d5e7891b07 2007-11-18       drh: **
d5e7891b07 2007-11-18       drh: ** This file primarily implements the verify_before_commit() interface.
d5e7891b07 2007-11-18       drh: ** Any function can call verify_before_commit() with a record id (RID)
d5e7891b07 2007-11-18       drh: ** as an argument.  Then before the next change to the database commits,
d5e7891b07 2007-11-18       drh: ** this routine will reach in and check that the record can be extracted
d5e7891b07 2007-11-18       drh: ** correctly from the BLOB table.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "verify.h"
dbda8d6ce9 2007-07-21       drh: #include <assert.h>
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Load the record identify by rid.  Make sure we can reproduce it
dbda8d6ce9 2007-07-21       drh: ** without error.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Panic if anything goes wrong.  If this procedure returns it means
dbda8d6ce9 2007-07-21       drh: ** that everything is OK.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: static void verify_rid(int rid){
dbda8d6ce9 2007-07-21       drh:   Blob uuid, hash, content;
1245b42ba3 2007-08-01       drh:   if( db_int(0, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){
1245b42ba3 2007-08-01       drh:     return;  /* No way to verify phantoms */
1245b42ba3 2007-08-01       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_zero(&uuid);
dbda8d6ce9 2007-07-21       drh:   db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
dbda8d6ce9 2007-07-21       drh:   if( blob_size(&uuid)!=UUID_SIZE ){
dbda8d6ce9 2007-07-21       drh:     fossil_panic("not a valid rid: %d", rid);
dbda8d6ce9 2007-07-21       drh:   }
edbb332d54 2007-08-10       drh:   if( content_get(rid, &content) ){
edbb332d54 2007-08-10       drh:     sha1sum_blob(&content, &hash);
edbb332d54 2007-08-10       drh:     blob_reset(&content);
edbb332d54 2007-08-10       drh:     if( blob_compare(&uuid, &hash) ){
edbb332d54 2007-08-10       drh:       fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)",
edbb332d54 2007-08-10       drh:                     rid, &hash, &uuid);
edbb332d54 2007-08-10       drh:     }
edbb332d54 2007-08-10       drh:     blob_reset(&hash);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_reset(&uuid);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
d5e7891b07 2007-11-18       drh: ** The following bag holds the rid for every record that needs
d5e7891b07 2007-11-18       drh: ** to be verified.
d5e7891b07 2007-11-18       drh: */
d5e7891b07 2007-11-18       drh: static Bag toVerify;
d5e7891b07 2007-11-18       drh: static int inFinalVerify = 0;
d5e7891b07 2007-11-18       drh: 
d5e7891b07 2007-11-18       drh: /*
d5e7891b07 2007-11-18       drh: ** This routine is called just prior to each commit operation.
dbda8d6ce9 2007-07-21       drh: **
2d581c03e5 2008-05-10       drh: ** Invoke verify_rid() on every record that has been added or modified
2d581c03e5 2008-05-10       drh: ** in the repository, in order to make sure that the repository is sane.
dbda8d6ce9 2007-07-21       drh: */
d5e7891b07 2007-11-18       drh: static int verify_at_commit(void){
d5e7891b07 2007-11-18       drh:   int rid;
61ddd63b72 2008-03-06       drh:   content_clear_cache();
d5e7891b07 2007-11-18       drh:   inFinalVerify = 1;
d5e7891b07 2007-11-18       drh:   rid = bag_first(&toVerify);
d5e7891b07 2007-11-18       drh:   while( rid>0 ){
dbda8d6ce9 2007-07-21       drh:     verify_rid(rid);
d5e7891b07 2007-11-18       drh:     rid = bag_next(&toVerify, rid);
dbda8d6ce9 2007-07-21       drh:   }
d5e7891b07 2007-11-18       drh:   bag_clear(&toVerify);
d5e7891b07 2007-11-18       drh:   inFinalVerify = 0;
dbda8d6ce9 2007-07-21       drh:   return 0;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Arrange to verify a particular record prior to committing.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** If the record rid is less than 1, then just initialize the
dbda8d6ce9 2007-07-21       drh: ** verification system but do not record anything as needing
dbda8d6ce9 2007-07-21       drh: ** verification.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void verify_before_commit(int rid){
dbda8d6ce9 2007-07-21       drh:   static int isInit = 0;
dbda8d6ce9 2007-07-21       drh:   if( !isInit ){
d5e7891b07 2007-11-18       drh:     db_commit_hook(verify_at_commit, 1000);
dbda8d6ce9 2007-07-21       drh:     isInit = 1;
dbda8d6ce9 2007-07-21       drh:   }
d5e7891b07 2007-11-18       drh:   assert( !inFinalVerify );
dbda8d6ce9 2007-07-21       drh:   if( rid>0 ){
d5e7891b07 2007-11-18       drh:     bag_insert(&toVerify, rid);
dbda8d6ce9 2007-07-21       drh:   }
0afb5e8e39 2008-03-08       drh: }
0afb5e8e39 2008-03-08       drh: 
0afb5e8e39 2008-03-08       drh: /*
0afb5e8e39 2008-03-08       drh: ** Cancel all pending verification operations.
0afb5e8e39 2008-03-08       drh: */
0afb5e8e39 2008-03-08       drh: void verify_cancel(void){
0afb5e8e39 2008-03-08       drh:   bag_clear(&toVerify);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND: test-verify-all
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Verify all records in the repository.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void verify_all_cmd(void){
dbda8d6ce9 2007-07-21       drh:   Stmt q;
d5e7891b07 2007-11-18       drh:   int cnt = 0;
dbda8d6ce9 2007-07-21       drh:   db_must_be_within_tree();
dbda8d6ce9 2007-07-21       drh:   db_prepare(&q, "SELECT rid FROM blob");
dbda8d6ce9 2007-07-21       drh:   while( db_step(&q)==SQLITE_ROW ){
dbda8d6ce9 2007-07-21       drh:     int rid = db_column_int(&q, 0);
d5e7891b07 2007-11-18       drh:     verify_before_commit(rid);
d5e7891b07 2007-11-18       drh:     cnt++;
d5e7891b07 2007-11-18       drh:     assert( bag_count(&toVerify)==cnt );
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_finalize(&q);
d5e7891b07 2007-11-18       drh:   verify_at_commit();
d5e7891b07 2007-11-18       drh:   assert( bag_count(&toVerify)==0 );
dbda8d6ce9 2007-07-21       drh: }