1*c5c4113dSnw141292 2*c5c4113dSnw141292 #pragma ident "%Z%%M% %I% %E% SMI" 3*c5c4113dSnw141292 4*c5c4113dSnw141292 /* 5*c5c4113dSnw141292 ** 2001 September 15 6*c5c4113dSnw141292 ** 7*c5c4113dSnw141292 ** The author disclaims copyright to this source code. In place of 8*c5c4113dSnw141292 ** a legal notice, here is a blessing: 9*c5c4113dSnw141292 ** 10*c5c4113dSnw141292 ** May you do good and not evil. 11*c5c4113dSnw141292 ** May you find forgiveness for yourself and forgive others. 12*c5c4113dSnw141292 ** May you share freely, never taking more than you give. 13*c5c4113dSnw141292 ** 14*c5c4113dSnw141292 ************************************************************************* 15*c5c4113dSnw141292 ** Code for testing the pager.c module in SQLite. This code 16*c5c4113dSnw141292 ** is not included in the SQLite library. It is used for automated 17*c5c4113dSnw141292 ** testing of the SQLite library. 18*c5c4113dSnw141292 ** 19*c5c4113dSnw141292 ** $Id: test2.c,v 1.16 2004/02/10 01:54:28 drh Exp $ 20*c5c4113dSnw141292 */ 21*c5c4113dSnw141292 #include "os.h" 22*c5c4113dSnw141292 #include "sqliteInt.h" 23*c5c4113dSnw141292 #include "pager.h" 24*c5c4113dSnw141292 #include "tcl.h" 25*c5c4113dSnw141292 #include <stdlib.h> 26*c5c4113dSnw141292 #include <string.h> 27*c5c4113dSnw141292 28*c5c4113dSnw141292 /* 29*c5c4113dSnw141292 ** Interpret an SQLite error number 30*c5c4113dSnw141292 */ 31*c5c4113dSnw141292 static char *errorName(int rc){ 32*c5c4113dSnw141292 char *zName; 33*c5c4113dSnw141292 switch( rc ){ 34*c5c4113dSnw141292 case SQLITE_OK: zName = "SQLITE_OK"; break; 35*c5c4113dSnw141292 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 36*c5c4113dSnw141292 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 37*c5c4113dSnw141292 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 38*c5c4113dSnw141292 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 39*c5c4113dSnw141292 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 40*c5c4113dSnw141292 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 41*c5c4113dSnw141292 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 42*c5c4113dSnw141292 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 43*c5c4113dSnw141292 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 44*c5c4113dSnw141292 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 45*c5c4113dSnw141292 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; 46*c5c4113dSnw141292 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 47*c5c4113dSnw141292 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 48*c5c4113dSnw141292 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 49*c5c4113dSnw141292 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 50*c5c4113dSnw141292 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; 51*c5c4113dSnw141292 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; 52*c5c4113dSnw141292 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; 53*c5c4113dSnw141292 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; 54*c5c4113dSnw141292 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; 55*c5c4113dSnw141292 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; 56*c5c4113dSnw141292 default: zName = "SQLITE_Unknown"; break; 57*c5c4113dSnw141292 } 58*c5c4113dSnw141292 return zName; 59*c5c4113dSnw141292 } 60*c5c4113dSnw141292 61*c5c4113dSnw141292 /* 62*c5c4113dSnw141292 ** Usage: pager_open FILENAME N-PAGE 63*c5c4113dSnw141292 ** 64*c5c4113dSnw141292 ** Open a new pager 65*c5c4113dSnw141292 */ 66*c5c4113dSnw141292 static int pager_open( 67*c5c4113dSnw141292 void *NotUsed, 68*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 69*c5c4113dSnw141292 int argc, /* Number of arguments */ 70*c5c4113dSnw141292 const char **argv /* Text of each argument */ 71*c5c4113dSnw141292 ){ 72*c5c4113dSnw141292 Pager *pPager; 73*c5c4113dSnw141292 int nPage; 74*c5c4113dSnw141292 int rc; 75*c5c4113dSnw141292 char zBuf[100]; 76*c5c4113dSnw141292 if( argc!=3 ){ 77*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 78*c5c4113dSnw141292 " FILENAME N-PAGE\"", 0); 79*c5c4113dSnw141292 return TCL_ERROR; 80*c5c4113dSnw141292 } 81*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; 82*c5c4113dSnw141292 rc = sqlitepager_open(&pPager, argv[1], nPage, 0, 1); 83*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 84*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 85*c5c4113dSnw141292 return TCL_ERROR; 86*c5c4113dSnw141292 } 87*c5c4113dSnw141292 sprintf(zBuf,"0x%x",(int)pPager); 88*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 89*c5c4113dSnw141292 return TCL_OK; 90*c5c4113dSnw141292 } 91*c5c4113dSnw141292 92*c5c4113dSnw141292 /* 93*c5c4113dSnw141292 ** Usage: pager_close ID 94*c5c4113dSnw141292 ** 95*c5c4113dSnw141292 ** Close the given pager. 96*c5c4113dSnw141292 */ 97*c5c4113dSnw141292 static int pager_close( 98*c5c4113dSnw141292 void *NotUsed, 99*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 100*c5c4113dSnw141292 int argc, /* Number of arguments */ 101*c5c4113dSnw141292 const char **argv /* Text of each argument */ 102*c5c4113dSnw141292 ){ 103*c5c4113dSnw141292 Pager *pPager; 104*c5c4113dSnw141292 int rc; 105*c5c4113dSnw141292 if( argc!=2 ){ 106*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 107*c5c4113dSnw141292 " ID\"", 0); 108*c5c4113dSnw141292 return TCL_ERROR; 109*c5c4113dSnw141292 } 110*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 111*c5c4113dSnw141292 rc = sqlitepager_close(pPager); 112*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 113*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 114*c5c4113dSnw141292 return TCL_ERROR; 115*c5c4113dSnw141292 } 116*c5c4113dSnw141292 return TCL_OK; 117*c5c4113dSnw141292 } 118*c5c4113dSnw141292 119*c5c4113dSnw141292 /* 120*c5c4113dSnw141292 ** Usage: pager_rollback ID 121*c5c4113dSnw141292 ** 122*c5c4113dSnw141292 ** Rollback changes 123*c5c4113dSnw141292 */ 124*c5c4113dSnw141292 static int pager_rollback( 125*c5c4113dSnw141292 void *NotUsed, 126*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 127*c5c4113dSnw141292 int argc, /* Number of arguments */ 128*c5c4113dSnw141292 const char **argv /* Text of each argument */ 129*c5c4113dSnw141292 ){ 130*c5c4113dSnw141292 Pager *pPager; 131*c5c4113dSnw141292 int rc; 132*c5c4113dSnw141292 if( argc!=2 ){ 133*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 134*c5c4113dSnw141292 " ID\"", 0); 135*c5c4113dSnw141292 return TCL_ERROR; 136*c5c4113dSnw141292 } 137*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 138*c5c4113dSnw141292 rc = sqlitepager_rollback(pPager); 139*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 140*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 141*c5c4113dSnw141292 return TCL_ERROR; 142*c5c4113dSnw141292 } 143*c5c4113dSnw141292 return TCL_OK; 144*c5c4113dSnw141292 } 145*c5c4113dSnw141292 146*c5c4113dSnw141292 /* 147*c5c4113dSnw141292 ** Usage: pager_commit ID 148*c5c4113dSnw141292 ** 149*c5c4113dSnw141292 ** Commit all changes 150*c5c4113dSnw141292 */ 151*c5c4113dSnw141292 static int pager_commit( 152*c5c4113dSnw141292 void *NotUsed, 153*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 154*c5c4113dSnw141292 int argc, /* Number of arguments */ 155*c5c4113dSnw141292 const char **argv /* Text of each argument */ 156*c5c4113dSnw141292 ){ 157*c5c4113dSnw141292 Pager *pPager; 158*c5c4113dSnw141292 int rc; 159*c5c4113dSnw141292 if( argc!=2 ){ 160*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 161*c5c4113dSnw141292 " ID\"", 0); 162*c5c4113dSnw141292 return TCL_ERROR; 163*c5c4113dSnw141292 } 164*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 165*c5c4113dSnw141292 rc = sqlitepager_commit(pPager); 166*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 167*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 168*c5c4113dSnw141292 return TCL_ERROR; 169*c5c4113dSnw141292 } 170*c5c4113dSnw141292 return TCL_OK; 171*c5c4113dSnw141292 } 172*c5c4113dSnw141292 173*c5c4113dSnw141292 /* 174*c5c4113dSnw141292 ** Usage: pager_ckpt_begin ID 175*c5c4113dSnw141292 ** 176*c5c4113dSnw141292 ** Start a new checkpoint. 177*c5c4113dSnw141292 */ 178*c5c4113dSnw141292 static int pager_ckpt_begin( 179*c5c4113dSnw141292 void *NotUsed, 180*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 181*c5c4113dSnw141292 int argc, /* Number of arguments */ 182*c5c4113dSnw141292 const char **argv /* Text of each argument */ 183*c5c4113dSnw141292 ){ 184*c5c4113dSnw141292 Pager *pPager; 185*c5c4113dSnw141292 int rc; 186*c5c4113dSnw141292 if( argc!=2 ){ 187*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 188*c5c4113dSnw141292 " ID\"", 0); 189*c5c4113dSnw141292 return TCL_ERROR; 190*c5c4113dSnw141292 } 191*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 192*c5c4113dSnw141292 rc = sqlitepager_ckpt_begin(pPager); 193*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 194*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 195*c5c4113dSnw141292 return TCL_ERROR; 196*c5c4113dSnw141292 } 197*c5c4113dSnw141292 return TCL_OK; 198*c5c4113dSnw141292 } 199*c5c4113dSnw141292 200*c5c4113dSnw141292 /* 201*c5c4113dSnw141292 ** Usage: pager_ckpt_rollback ID 202*c5c4113dSnw141292 ** 203*c5c4113dSnw141292 ** Rollback changes to a checkpoint 204*c5c4113dSnw141292 */ 205*c5c4113dSnw141292 static int pager_ckpt_rollback( 206*c5c4113dSnw141292 void *NotUsed, 207*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 208*c5c4113dSnw141292 int argc, /* Number of arguments */ 209*c5c4113dSnw141292 const char **argv /* Text of each argument */ 210*c5c4113dSnw141292 ){ 211*c5c4113dSnw141292 Pager *pPager; 212*c5c4113dSnw141292 int rc; 213*c5c4113dSnw141292 if( argc!=2 ){ 214*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 215*c5c4113dSnw141292 " ID\"", 0); 216*c5c4113dSnw141292 return TCL_ERROR; 217*c5c4113dSnw141292 } 218*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 219*c5c4113dSnw141292 rc = sqlitepager_ckpt_rollback(pPager); 220*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 221*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 222*c5c4113dSnw141292 return TCL_ERROR; 223*c5c4113dSnw141292 } 224*c5c4113dSnw141292 return TCL_OK; 225*c5c4113dSnw141292 } 226*c5c4113dSnw141292 227*c5c4113dSnw141292 /* 228*c5c4113dSnw141292 ** Usage: pager_ckpt_commit ID 229*c5c4113dSnw141292 ** 230*c5c4113dSnw141292 ** Commit changes to a checkpoint 231*c5c4113dSnw141292 */ 232*c5c4113dSnw141292 static int pager_ckpt_commit( 233*c5c4113dSnw141292 void *NotUsed, 234*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 235*c5c4113dSnw141292 int argc, /* Number of arguments */ 236*c5c4113dSnw141292 const char **argv /* Text of each argument */ 237*c5c4113dSnw141292 ){ 238*c5c4113dSnw141292 Pager *pPager; 239*c5c4113dSnw141292 int rc; 240*c5c4113dSnw141292 if( argc!=2 ){ 241*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 242*c5c4113dSnw141292 " ID\"", 0); 243*c5c4113dSnw141292 return TCL_ERROR; 244*c5c4113dSnw141292 } 245*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 246*c5c4113dSnw141292 rc = sqlitepager_ckpt_commit(pPager); 247*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 248*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 249*c5c4113dSnw141292 return TCL_ERROR; 250*c5c4113dSnw141292 } 251*c5c4113dSnw141292 return TCL_OK; 252*c5c4113dSnw141292 } 253*c5c4113dSnw141292 254*c5c4113dSnw141292 /* 255*c5c4113dSnw141292 ** Usage: pager_stats ID 256*c5c4113dSnw141292 ** 257*c5c4113dSnw141292 ** Return pager statistics. 258*c5c4113dSnw141292 */ 259*c5c4113dSnw141292 static int pager_stats( 260*c5c4113dSnw141292 void *NotUsed, 261*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 262*c5c4113dSnw141292 int argc, /* Number of arguments */ 263*c5c4113dSnw141292 const char **argv /* Text of each argument */ 264*c5c4113dSnw141292 ){ 265*c5c4113dSnw141292 Pager *pPager; 266*c5c4113dSnw141292 int i, *a; 267*c5c4113dSnw141292 if( argc!=2 ){ 268*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 269*c5c4113dSnw141292 " ID\"", 0); 270*c5c4113dSnw141292 return TCL_ERROR; 271*c5c4113dSnw141292 } 272*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 273*c5c4113dSnw141292 a = sqlitepager_stats(pPager); 274*c5c4113dSnw141292 for(i=0; i<9; i++){ 275*c5c4113dSnw141292 static char *zName[] = { 276*c5c4113dSnw141292 "ref", "page", "max", "size", "state", "err", 277*c5c4113dSnw141292 "hit", "miss", "ovfl", 278*c5c4113dSnw141292 }; 279*c5c4113dSnw141292 char zBuf[100]; 280*c5c4113dSnw141292 Tcl_AppendElement(interp, zName[i]); 281*c5c4113dSnw141292 sprintf(zBuf,"%d",a[i]); 282*c5c4113dSnw141292 Tcl_AppendElement(interp, zBuf); 283*c5c4113dSnw141292 } 284*c5c4113dSnw141292 return TCL_OK; 285*c5c4113dSnw141292 } 286*c5c4113dSnw141292 287*c5c4113dSnw141292 /* 288*c5c4113dSnw141292 ** Usage: pager_pagecount ID 289*c5c4113dSnw141292 ** 290*c5c4113dSnw141292 ** Return the size of the database file. 291*c5c4113dSnw141292 */ 292*c5c4113dSnw141292 static int pager_pagecount( 293*c5c4113dSnw141292 void *NotUsed, 294*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 295*c5c4113dSnw141292 int argc, /* Number of arguments */ 296*c5c4113dSnw141292 const char **argv /* Text of each argument */ 297*c5c4113dSnw141292 ){ 298*c5c4113dSnw141292 Pager *pPager; 299*c5c4113dSnw141292 char zBuf[100]; 300*c5c4113dSnw141292 if( argc!=2 ){ 301*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 302*c5c4113dSnw141292 " ID\"", 0); 303*c5c4113dSnw141292 return TCL_ERROR; 304*c5c4113dSnw141292 } 305*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 306*c5c4113dSnw141292 sprintf(zBuf,"%d",sqlitepager_pagecount(pPager)); 307*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 308*c5c4113dSnw141292 return TCL_OK; 309*c5c4113dSnw141292 } 310*c5c4113dSnw141292 311*c5c4113dSnw141292 /* 312*c5c4113dSnw141292 ** Usage: page_get ID PGNO 313*c5c4113dSnw141292 ** 314*c5c4113dSnw141292 ** Return a pointer to a page from the database. 315*c5c4113dSnw141292 */ 316*c5c4113dSnw141292 static int page_get( 317*c5c4113dSnw141292 void *NotUsed, 318*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 319*c5c4113dSnw141292 int argc, /* Number of arguments */ 320*c5c4113dSnw141292 const char **argv /* Text of each argument */ 321*c5c4113dSnw141292 ){ 322*c5c4113dSnw141292 Pager *pPager; 323*c5c4113dSnw141292 char zBuf[100]; 324*c5c4113dSnw141292 void *pPage; 325*c5c4113dSnw141292 int pgno; 326*c5c4113dSnw141292 int rc; 327*c5c4113dSnw141292 if( argc!=3 ){ 328*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 329*c5c4113dSnw141292 " ID PGNO\"", 0); 330*c5c4113dSnw141292 return TCL_ERROR; 331*c5c4113dSnw141292 } 332*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 333*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 334*c5c4113dSnw141292 rc = sqlitepager_get(pPager, pgno, &pPage); 335*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 336*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 337*c5c4113dSnw141292 return TCL_ERROR; 338*c5c4113dSnw141292 } 339*c5c4113dSnw141292 sprintf(zBuf,"0x%x",(int)pPage); 340*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 341*c5c4113dSnw141292 return TCL_OK; 342*c5c4113dSnw141292 } 343*c5c4113dSnw141292 344*c5c4113dSnw141292 /* 345*c5c4113dSnw141292 ** Usage: page_lookup ID PGNO 346*c5c4113dSnw141292 ** 347*c5c4113dSnw141292 ** Return a pointer to a page if the page is already in cache. 348*c5c4113dSnw141292 ** If not in cache, return an empty string. 349*c5c4113dSnw141292 */ 350*c5c4113dSnw141292 static int page_lookup( 351*c5c4113dSnw141292 void *NotUsed, 352*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 353*c5c4113dSnw141292 int argc, /* Number of arguments */ 354*c5c4113dSnw141292 const char **argv /* Text of each argument */ 355*c5c4113dSnw141292 ){ 356*c5c4113dSnw141292 Pager *pPager; 357*c5c4113dSnw141292 char zBuf[100]; 358*c5c4113dSnw141292 void *pPage; 359*c5c4113dSnw141292 int pgno; 360*c5c4113dSnw141292 if( argc!=3 ){ 361*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 362*c5c4113dSnw141292 " ID PGNO\"", 0); 363*c5c4113dSnw141292 return TCL_ERROR; 364*c5c4113dSnw141292 } 365*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR; 366*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 367*c5c4113dSnw141292 pPage = sqlitepager_lookup(pPager, pgno); 368*c5c4113dSnw141292 if( pPage ){ 369*c5c4113dSnw141292 sprintf(zBuf,"0x%x",(int)pPage); 370*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 371*c5c4113dSnw141292 } 372*c5c4113dSnw141292 return TCL_OK; 373*c5c4113dSnw141292 } 374*c5c4113dSnw141292 375*c5c4113dSnw141292 /* 376*c5c4113dSnw141292 ** Usage: page_unref PAGE 377*c5c4113dSnw141292 ** 378*c5c4113dSnw141292 ** Drop a pointer to a page. 379*c5c4113dSnw141292 */ 380*c5c4113dSnw141292 static int page_unref( 381*c5c4113dSnw141292 void *NotUsed, 382*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 383*c5c4113dSnw141292 int argc, /* Number of arguments */ 384*c5c4113dSnw141292 const char **argv /* Text of each argument */ 385*c5c4113dSnw141292 ){ 386*c5c4113dSnw141292 void *pPage; 387*c5c4113dSnw141292 int rc; 388*c5c4113dSnw141292 if( argc!=2 ){ 389*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 390*c5c4113dSnw141292 " PAGE\"", 0); 391*c5c4113dSnw141292 return TCL_ERROR; 392*c5c4113dSnw141292 } 393*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR; 394*c5c4113dSnw141292 rc = sqlitepager_unref(pPage); 395*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 396*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 397*c5c4113dSnw141292 return TCL_ERROR; 398*c5c4113dSnw141292 } 399*c5c4113dSnw141292 return TCL_OK; 400*c5c4113dSnw141292 } 401*c5c4113dSnw141292 402*c5c4113dSnw141292 /* 403*c5c4113dSnw141292 ** Usage: page_read PAGE 404*c5c4113dSnw141292 ** 405*c5c4113dSnw141292 ** Return the content of a page 406*c5c4113dSnw141292 */ 407*c5c4113dSnw141292 static int page_read( 408*c5c4113dSnw141292 void *NotUsed, 409*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 410*c5c4113dSnw141292 int argc, /* Number of arguments */ 411*c5c4113dSnw141292 const char **argv /* Text of each argument */ 412*c5c4113dSnw141292 ){ 413*c5c4113dSnw141292 char zBuf[100]; 414*c5c4113dSnw141292 void *pPage; 415*c5c4113dSnw141292 if( argc!=2 ){ 416*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 417*c5c4113dSnw141292 " PAGE\"", 0); 418*c5c4113dSnw141292 return TCL_ERROR; 419*c5c4113dSnw141292 } 420*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR; 421*c5c4113dSnw141292 memcpy(zBuf, pPage, sizeof(zBuf)); 422*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 423*c5c4113dSnw141292 return TCL_OK; 424*c5c4113dSnw141292 } 425*c5c4113dSnw141292 426*c5c4113dSnw141292 /* 427*c5c4113dSnw141292 ** Usage: page_number PAGE 428*c5c4113dSnw141292 ** 429*c5c4113dSnw141292 ** Return the page number for a page. 430*c5c4113dSnw141292 */ 431*c5c4113dSnw141292 static int page_number( 432*c5c4113dSnw141292 void *NotUsed, 433*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 434*c5c4113dSnw141292 int argc, /* Number of arguments */ 435*c5c4113dSnw141292 const char **argv /* Text of each argument */ 436*c5c4113dSnw141292 ){ 437*c5c4113dSnw141292 char zBuf[100]; 438*c5c4113dSnw141292 void *pPage; 439*c5c4113dSnw141292 if( argc!=2 ){ 440*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 441*c5c4113dSnw141292 " PAGE\"", 0); 442*c5c4113dSnw141292 return TCL_ERROR; 443*c5c4113dSnw141292 } 444*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR; 445*c5c4113dSnw141292 sprintf(zBuf, "%d", sqlitepager_pagenumber(pPage)); 446*c5c4113dSnw141292 Tcl_AppendResult(interp, zBuf, 0); 447*c5c4113dSnw141292 return TCL_OK; 448*c5c4113dSnw141292 } 449*c5c4113dSnw141292 450*c5c4113dSnw141292 /* 451*c5c4113dSnw141292 ** Usage: page_write PAGE DATA 452*c5c4113dSnw141292 ** 453*c5c4113dSnw141292 ** Write something into a page. 454*c5c4113dSnw141292 */ 455*c5c4113dSnw141292 static int page_write( 456*c5c4113dSnw141292 void *NotUsed, 457*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 458*c5c4113dSnw141292 int argc, /* Number of arguments */ 459*c5c4113dSnw141292 const char **argv /* Text of each argument */ 460*c5c4113dSnw141292 ){ 461*c5c4113dSnw141292 void *pPage; 462*c5c4113dSnw141292 int rc; 463*c5c4113dSnw141292 if( argc!=3 ){ 464*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 465*c5c4113dSnw141292 " PAGE DATA\"", 0); 466*c5c4113dSnw141292 return TCL_ERROR; 467*c5c4113dSnw141292 } 468*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR; 469*c5c4113dSnw141292 rc = sqlitepager_write(pPage); 470*c5c4113dSnw141292 if( rc!=SQLITE_OK ){ 471*c5c4113dSnw141292 Tcl_AppendResult(interp, errorName(rc), 0); 472*c5c4113dSnw141292 return TCL_ERROR; 473*c5c4113dSnw141292 } 474*c5c4113dSnw141292 strncpy((char*)pPage, argv[2], SQLITE_USABLE_SIZE-1); 475*c5c4113dSnw141292 ((char*)pPage)[SQLITE_USABLE_SIZE-1] = 0; 476*c5c4113dSnw141292 return TCL_OK; 477*c5c4113dSnw141292 } 478*c5c4113dSnw141292 479*c5c4113dSnw141292 /* 480*c5c4113dSnw141292 ** Usage: fake_big_file N FILENAME 481*c5c4113dSnw141292 ** 482*c5c4113dSnw141292 ** Write a few bytes at the N megabyte point of FILENAME. This will 483*c5c4113dSnw141292 ** create a large file. If the file was a valid SQLite database, then 484*c5c4113dSnw141292 ** the next time the database is opened, SQLite will begin allocating 485*c5c4113dSnw141292 ** new pages after N. If N is 2096 or bigger, this will test the 486*c5c4113dSnw141292 ** ability of SQLite to write to large files. 487*c5c4113dSnw141292 */ 488*c5c4113dSnw141292 static int fake_big_file( 489*c5c4113dSnw141292 void *NotUsed, 490*c5c4113dSnw141292 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 491*c5c4113dSnw141292 int argc, /* Number of arguments */ 492*c5c4113dSnw141292 const char **argv /* Text of each argument */ 493*c5c4113dSnw141292 ){ 494*c5c4113dSnw141292 int rc; 495*c5c4113dSnw141292 int n; 496*c5c4113dSnw141292 off_t offset; 497*c5c4113dSnw141292 OsFile fd; 498*c5c4113dSnw141292 int readOnly = 0; 499*c5c4113dSnw141292 if( argc!=3 ){ 500*c5c4113dSnw141292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 501*c5c4113dSnw141292 " N-MEGABYTES FILE\"", 0); 502*c5c4113dSnw141292 return TCL_ERROR; 503*c5c4113dSnw141292 } 504*c5c4113dSnw141292 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 505*c5c4113dSnw141292 rc = sqliteOsOpenReadWrite(argv[2], &fd, &readOnly); 506*c5c4113dSnw141292 if( rc ){ 507*c5c4113dSnw141292 Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); 508*c5c4113dSnw141292 return TCL_ERROR; 509*c5c4113dSnw141292 } 510*c5c4113dSnw141292 offset = n; 511*c5c4113dSnw141292 offset *= 1024*1024; 512*c5c4113dSnw141292 rc = sqliteOsSeek(&fd, offset); 513*c5c4113dSnw141292 if( rc ){ 514*c5c4113dSnw141292 Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0); 515*c5c4113dSnw141292 return TCL_ERROR; 516*c5c4113dSnw141292 } 517*c5c4113dSnw141292 rc = sqliteOsWrite(&fd, "Hello, World!", 14); 518*c5c4113dSnw141292 sqliteOsClose(&fd); 519*c5c4113dSnw141292 if( rc ){ 520*c5c4113dSnw141292 Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); 521*c5c4113dSnw141292 return TCL_ERROR; 522*c5c4113dSnw141292 } 523*c5c4113dSnw141292 return TCL_OK; 524*c5c4113dSnw141292 } 525*c5c4113dSnw141292 526*c5c4113dSnw141292 /* 527*c5c4113dSnw141292 ** Register commands with the TCL interpreter. 528*c5c4113dSnw141292 */ 529*c5c4113dSnw141292 int Sqlitetest2_Init(Tcl_Interp *interp){ 530*c5c4113dSnw141292 extern int sqlite_io_error_pending; 531*c5c4113dSnw141292 char zBuf[100]; 532*c5c4113dSnw141292 static struct { 533*c5c4113dSnw141292 char *zName; 534*c5c4113dSnw141292 Tcl_CmdProc *xProc; 535*c5c4113dSnw141292 } aCmd[] = { 536*c5c4113dSnw141292 { "pager_open", (Tcl_CmdProc*)pager_open }, 537*c5c4113dSnw141292 { "pager_close", (Tcl_CmdProc*)pager_close }, 538*c5c4113dSnw141292 { "pager_commit", (Tcl_CmdProc*)pager_commit }, 539*c5c4113dSnw141292 { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, 540*c5c4113dSnw141292 { "pager_ckpt_begin", (Tcl_CmdProc*)pager_ckpt_begin }, 541*c5c4113dSnw141292 { "pager_ckpt_commit", (Tcl_CmdProc*)pager_ckpt_commit }, 542*c5c4113dSnw141292 { "pager_ckpt_rollback", (Tcl_CmdProc*)pager_ckpt_rollback }, 543*c5c4113dSnw141292 { "pager_stats", (Tcl_CmdProc*)pager_stats }, 544*c5c4113dSnw141292 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, 545*c5c4113dSnw141292 { "page_get", (Tcl_CmdProc*)page_get }, 546*c5c4113dSnw141292 { "page_lookup", (Tcl_CmdProc*)page_lookup }, 547*c5c4113dSnw141292 { "page_unref", (Tcl_CmdProc*)page_unref }, 548*c5c4113dSnw141292 { "page_read", (Tcl_CmdProc*)page_read }, 549*c5c4113dSnw141292 { "page_write", (Tcl_CmdProc*)page_write }, 550*c5c4113dSnw141292 { "page_number", (Tcl_CmdProc*)page_number }, 551*c5c4113dSnw141292 { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, 552*c5c4113dSnw141292 }; 553*c5c4113dSnw141292 int i; 554*c5c4113dSnw141292 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 555*c5c4113dSnw141292 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 556*c5c4113dSnw141292 } 557*c5c4113dSnw141292 Tcl_LinkVar(interp, "sqlite_io_error_pending", 558*c5c4113dSnw141292 (char*)&sqlite_io_error_pending, TCL_LINK_INT); 559*c5c4113dSnw141292 #ifdef SQLITE_TEST 560*c5c4113dSnw141292 Tcl_LinkVar(interp, "journal_format", 561*c5c4113dSnw141292 (char*)&journal_format, TCL_LINK_INT); 562*c5c4113dSnw141292 #endif 563*c5c4113dSnw141292 sprintf(zBuf, "%d", SQLITE_PAGE_SIZE); 564*c5c4113dSnw141292 Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); 565*c5c4113dSnw141292 sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE); 566*c5c4113dSnw141292 Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY); 567*c5c4113dSnw141292 sprintf(zBuf, "%d", SQLITE_USABLE_SIZE); 568*c5c4113dSnw141292 Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY); 569*c5c4113dSnw141292 return TCL_OK; 570*c5c4113dSnw141292 } 571