00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "os.h"
00019 #include "sqliteInt.h"
00020 #include "pager.h"
00021 #include "tcl.h"
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025
00026
00027
00028 static char *errorName(int rc){
00029 char *zName;
00030 switch( rc ){
00031 case SQLITE_OK: zName = "SQLITE_OK"; break;
00032 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
00033 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
00034 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
00035 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
00036 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
00037 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
00038 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
00039 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
00040 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
00041 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
00042 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
00043 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
00044 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
00045 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
00046 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
00047 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
00048 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
00049 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
00050 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
00051 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
00052 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
00053 default: zName = "SQLITE_Unknown"; break;
00054 }
00055 return zName;
00056 }
00057
00058
00059
00060
00061
00062
00063 static int pager_open(
00064 void *NotUsed,
00065 Tcl_Interp *interp,
00066 int argc,
00067 const char **argv
00068 ){
00069 Pager *pPager;
00070 int nPage;
00071 int rc;
00072 char zBuf[100];
00073 if( argc!=3 ){
00074 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00075 " FILENAME N-PAGE\"", 0);
00076 return TCL_ERROR;
00077 }
00078 if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
00079 rc = sqlitepager_open(&pPager, argv[1], nPage, 0, 1);
00080 if( rc!=SQLITE_OK ){
00081 Tcl_AppendResult(interp, errorName(rc), 0);
00082 return TCL_ERROR;
00083 }
00084 sprintf(zBuf,"0x%x",(int)pPager);
00085 Tcl_AppendResult(interp, zBuf, 0);
00086 return TCL_OK;
00087 }
00088
00089
00090
00091
00092
00093
00094 static int pager_close(
00095 void *NotUsed,
00096 Tcl_Interp *interp,
00097 int argc,
00098 const char **argv
00099 ){
00100 Pager *pPager;
00101 int rc;
00102 if( argc!=2 ){
00103 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00104 " ID\"", 0);
00105 return TCL_ERROR;
00106 }
00107 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00108 rc = sqlitepager_close(pPager);
00109 if( rc!=SQLITE_OK ){
00110 Tcl_AppendResult(interp, errorName(rc), 0);
00111 return TCL_ERROR;
00112 }
00113 return TCL_OK;
00114 }
00115
00116
00117
00118
00119
00120
00121 static int pager_rollback(
00122 void *NotUsed,
00123 Tcl_Interp *interp,
00124 int argc,
00125 const char **argv
00126 ){
00127 Pager *pPager;
00128 int rc;
00129 if( argc!=2 ){
00130 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00131 " ID\"", 0);
00132 return TCL_ERROR;
00133 }
00134 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00135 rc = sqlitepager_rollback(pPager);
00136 if( rc!=SQLITE_OK ){
00137 Tcl_AppendResult(interp, errorName(rc), 0);
00138 return TCL_ERROR;
00139 }
00140 return TCL_OK;
00141 }
00142
00143
00144
00145
00146
00147
00148 static int pager_commit(
00149 void *NotUsed,
00150 Tcl_Interp *interp,
00151 int argc,
00152 const char **argv
00153 ){
00154 Pager *pPager;
00155 int rc;
00156 if( argc!=2 ){
00157 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00158 " ID\"", 0);
00159 return TCL_ERROR;
00160 }
00161 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00162 rc = sqlitepager_commit(pPager);
00163 if( rc!=SQLITE_OK ){
00164 Tcl_AppendResult(interp, errorName(rc), 0);
00165 return TCL_ERROR;
00166 }
00167 return TCL_OK;
00168 }
00169
00170
00171
00172
00173
00174
00175 static int pager_ckpt_begin(
00176 void *NotUsed,
00177 Tcl_Interp *interp,
00178 int argc,
00179 const char **argv
00180 ){
00181 Pager *pPager;
00182 int rc;
00183 if( argc!=2 ){
00184 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00185 " ID\"", 0);
00186 return TCL_ERROR;
00187 }
00188 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00189 rc = sqlitepager_ckpt_begin(pPager);
00190 if( rc!=SQLITE_OK ){
00191 Tcl_AppendResult(interp, errorName(rc), 0);
00192 return TCL_ERROR;
00193 }
00194 return TCL_OK;
00195 }
00196
00197
00198
00199
00200
00201
00202 static int pager_ckpt_rollback(
00203 void *NotUsed,
00204 Tcl_Interp *interp,
00205 int argc,
00206 const char **argv
00207 ){
00208 Pager *pPager;
00209 int rc;
00210 if( argc!=2 ){
00211 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00212 " ID\"", 0);
00213 return TCL_ERROR;
00214 }
00215 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00216 rc = sqlitepager_ckpt_rollback(pPager);
00217 if( rc!=SQLITE_OK ){
00218 Tcl_AppendResult(interp, errorName(rc), 0);
00219 return TCL_ERROR;
00220 }
00221 return TCL_OK;
00222 }
00223
00224
00225
00226
00227
00228
00229 static int pager_ckpt_commit(
00230 void *NotUsed,
00231 Tcl_Interp *interp,
00232 int argc,
00233 const char **argv
00234 ){
00235 Pager *pPager;
00236 int rc;
00237 if( argc!=2 ){
00238 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00239 " ID\"", 0);
00240 return TCL_ERROR;
00241 }
00242 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00243 rc = sqlitepager_ckpt_commit(pPager);
00244 if( rc!=SQLITE_OK ){
00245 Tcl_AppendResult(interp, errorName(rc), 0);
00246 return TCL_ERROR;
00247 }
00248 return TCL_OK;
00249 }
00250
00251
00252
00253
00254
00255
00256 static int pager_stats(
00257 void *NotUsed,
00258 Tcl_Interp *interp,
00259 int argc,
00260 const char **argv
00261 ){
00262 Pager *pPager;
00263 int i, *a;
00264 if( argc!=2 ){
00265 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00266 " ID\"", 0);
00267 return TCL_ERROR;
00268 }
00269 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00270 a = sqlitepager_stats(pPager);
00271 for(i=0; i<9; i++){
00272 static char *zName[] = {
00273 "ref", "page", "max", "size", "state", "err",
00274 "hit", "miss", "ovfl",
00275 };
00276 char zBuf[100];
00277 Tcl_AppendElement(interp, zName[i]);
00278 sprintf(zBuf,"%d",a[i]);
00279 Tcl_AppendElement(interp, zBuf);
00280 }
00281 return TCL_OK;
00282 }
00283
00284
00285
00286
00287
00288
00289 static int pager_pagecount(
00290 void *NotUsed,
00291 Tcl_Interp *interp,
00292 int argc,
00293 const char **argv
00294 ){
00295 Pager *pPager;
00296 char zBuf[100];
00297 if( argc!=2 ){
00298 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00299 " ID\"", 0);
00300 return TCL_ERROR;
00301 }
00302 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00303 sprintf(zBuf,"%d",sqlitepager_pagecount(pPager));
00304 Tcl_AppendResult(interp, zBuf, 0);
00305 return TCL_OK;
00306 }
00307
00308
00309
00310
00311
00312
00313 static int page_get(
00314 void *NotUsed,
00315 Tcl_Interp *interp,
00316 int argc,
00317 const char **argv
00318 ){
00319 Pager *pPager;
00320 char zBuf[100];
00321 void *pPage;
00322 int pgno;
00323 int rc;
00324 if( argc!=3 ){
00325 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00326 " ID PGNO\"", 0);
00327 return TCL_ERROR;
00328 }
00329 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00330 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
00331 rc = sqlitepager_get(pPager, pgno, &pPage);
00332 if( rc!=SQLITE_OK ){
00333 Tcl_AppendResult(interp, errorName(rc), 0);
00334 return TCL_ERROR;
00335 }
00336 sprintf(zBuf,"0x%x",(int)pPage);
00337 Tcl_AppendResult(interp, zBuf, 0);
00338 return TCL_OK;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 static int page_lookup(
00348 void *NotUsed,
00349 Tcl_Interp *interp,
00350 int argc,
00351 const char **argv
00352 ){
00353 Pager *pPager;
00354 char zBuf[100];
00355 void *pPage;
00356 int pgno;
00357 if( argc!=3 ){
00358 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00359 " ID PGNO\"", 0);
00360 return TCL_ERROR;
00361 }
00362 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
00363 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
00364 pPage = sqlitepager_lookup(pPager, pgno);
00365 if( pPage ){
00366 sprintf(zBuf,"0x%x",(int)pPage);
00367 Tcl_AppendResult(interp, zBuf, 0);
00368 }
00369 return TCL_OK;
00370 }
00371
00372
00373
00374
00375
00376
00377 static int page_unref(
00378 void *NotUsed,
00379 Tcl_Interp *interp,
00380 int argc,
00381 const char **argv
00382 ){
00383 void *pPage;
00384 int rc;
00385 if( argc!=2 ){
00386 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00387 " PAGE\"", 0);
00388 return TCL_ERROR;
00389 }
00390 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
00391 rc = sqlitepager_unref(pPage);
00392 if( rc!=SQLITE_OK ){
00393 Tcl_AppendResult(interp, errorName(rc), 0);
00394 return TCL_ERROR;
00395 }
00396 return TCL_OK;
00397 }
00398
00399
00400
00401
00402
00403
00404 static int page_read(
00405 void *NotUsed,
00406 Tcl_Interp *interp,
00407 int argc,
00408 const char **argv
00409 ){
00410 char zBuf[100];
00411 void *pPage;
00412 if( argc!=2 ){
00413 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00414 " PAGE\"", 0);
00415 return TCL_ERROR;
00416 }
00417 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
00418 memcpy(zBuf, pPage, sizeof(zBuf));
00419 Tcl_AppendResult(interp, zBuf, 0);
00420 return TCL_OK;
00421 }
00422
00423
00424
00425
00426
00427
00428 static int page_number(
00429 void *NotUsed,
00430 Tcl_Interp *interp,
00431 int argc,
00432 const char **argv
00433 ){
00434 char zBuf[100];
00435 void *pPage;
00436 if( argc!=2 ){
00437 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00438 " PAGE\"", 0);
00439 return TCL_ERROR;
00440 }
00441 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
00442 sprintf(zBuf, "%d", sqlitepager_pagenumber(pPage));
00443 Tcl_AppendResult(interp, zBuf, 0);
00444 return TCL_OK;
00445 }
00446
00447
00448
00449
00450
00451
00452 static int page_write(
00453 void *NotUsed,
00454 Tcl_Interp *interp,
00455 int argc,
00456 const char **argv
00457 ){
00458 void *pPage;
00459 int rc;
00460 if( argc!=3 ){
00461 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00462 " PAGE DATA\"", 0);
00463 return TCL_ERROR;
00464 }
00465 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
00466 rc = sqlitepager_write(pPage);
00467 if( rc!=SQLITE_OK ){
00468 Tcl_AppendResult(interp, errorName(rc), 0);
00469 return TCL_ERROR;
00470 }
00471 strncpy((char*)pPage, argv[2], SQLITE_USABLE_SIZE-1);
00472 ((char*)pPage)[SQLITE_USABLE_SIZE-1] = 0;
00473 return TCL_OK;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 static int fake_big_file(
00486 void *NotUsed,
00487 Tcl_Interp *interp,
00488 int argc,
00489 const char **argv
00490 ){
00491 int rc;
00492 int n;
00493 off_t offset;
00494 OsFile fd;
00495 int readOnly = 0;
00496 if( argc!=3 ){
00497 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00498 " N-MEGABYTES FILE\"", 0);
00499 return TCL_ERROR;
00500 }
00501 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
00502 rc = sqliteOsOpenReadWrite(argv[2], &fd, &readOnly);
00503 if( rc ){
00504 Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0);
00505 return TCL_ERROR;
00506 }
00507 offset = n;
00508 offset *= 1024*1024;
00509 rc = sqliteOsSeek(&fd, offset);
00510 if( rc ){
00511 Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0);
00512 return TCL_ERROR;
00513 }
00514 rc = sqliteOsWrite(&fd, "Hello, World!", 14);
00515 sqliteOsClose(&fd);
00516 if( rc ){
00517 Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
00518 return TCL_ERROR;
00519 }
00520 return TCL_OK;
00521 }
00522
00523
00524
00525
00526 int Sqlitetest2_Init(Tcl_Interp *interp){
00527 extern int sqlite_io_error_pending;
00528 char zBuf[100];
00529 static struct {
00530 char *zName;
00531 Tcl_CmdProc *xProc;
00532 } aCmd[] = {
00533 { "pager_open", (Tcl_CmdProc*)pager_open },
00534 { "pager_close", (Tcl_CmdProc*)pager_close },
00535 { "pager_commit", (Tcl_CmdProc*)pager_commit },
00536 { "pager_rollback", (Tcl_CmdProc*)pager_rollback },
00537 { "pager_ckpt_begin", (Tcl_CmdProc*)pager_ckpt_begin },
00538 { "pager_ckpt_commit", (Tcl_CmdProc*)pager_ckpt_commit },
00539 { "pager_ckpt_rollback", (Tcl_CmdProc*)pager_ckpt_rollback },
00540 { "pager_stats", (Tcl_CmdProc*)pager_stats },
00541 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount },
00542 { "page_get", (Tcl_CmdProc*)page_get },
00543 { "page_lookup", (Tcl_CmdProc*)page_lookup },
00544 { "page_unref", (Tcl_CmdProc*)page_unref },
00545 { "page_read", (Tcl_CmdProc*)page_read },
00546 { "page_write", (Tcl_CmdProc*)page_write },
00547 { "page_number", (Tcl_CmdProc*)page_number },
00548 { "fake_big_file", (Tcl_CmdProc*)fake_big_file },
00549 };
00550 int i;
00551 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
00552 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
00553 }
00554 Tcl_LinkVar(interp, "sqlite_io_error_pending",
00555 (char*)&sqlite_io_error_pending, TCL_LINK_INT);
00556 #ifdef SQLITE_TEST
00557 Tcl_LinkVar(interp, "journal_format",
00558 (char*)&journal_format, TCL_LINK_INT);
00559 #endif
00560 sprintf(zBuf, "%d", SQLITE_PAGE_SIZE);
00561 Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY);
00562 sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE);
00563 Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY);
00564 sprintf(zBuf, "%d", SQLITE_USABLE_SIZE);
00565 Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY);
00566 return TCL_OK;
00567 }