00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "os.h"
00024 #include "sqliteInt.h"
00025 #include "pager.h"
00026 #include <assert.h>
00027 #include <string.h>
00028
00029
00030
00031
00032 #if 0
00033 static Pager *mainPager = 0;
00034 #define SET_PAGER(X) if( mainPager==0 ) mainPager = (X)
00035 #define CLR_PAGER(X) if( mainPager==(X) ) mainPager = 0
00036 #define TRACE1(X) if( pPager==mainPager ) fprintf(stderr,X)
00037 #define TRACE2(X,Y) if( pPager==mainPager ) fprintf(stderr,X,Y)
00038 #define TRACE3(X,Y,Z) if( pPager==mainPager ) fprintf(stderr,X,Y,Z)
00039 #else
00040 #define SET_PAGER(X)
00041 #define CLR_PAGER(X)
00042 #define TRACE1(X)
00043 #define TRACE2(X,Y)
00044 #define TRACE3(X,Y,Z)
00045 #endif
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #define SQLITE_UNLOCK 0
00079 #define SQLITE_READLOCK 1
00080 #define SQLITE_WRITELOCK 2
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 typedef struct PgHdr PgHdr;
00102 struct PgHdr {
00103 Pager *pPager;
00104 Pgno pgno;
00105 PgHdr *pNextHash, *pPrevHash;
00106 int nRef;
00107 PgHdr *pNextFree, *pPrevFree;
00108 PgHdr *pNextAll, *pPrevAll;
00109 PgHdr *pNextCkpt, *pPrevCkpt;
00110 u8 inJournal;
00111 u8 inCkpt;
00112 u8 dirty;
00113 u8 needSync;
00114 u8 alwaysRollback;
00115 PgHdr *pDirty;
00116
00117
00118 };
00119
00120
00121
00122
00123
00124 #ifdef SQLITE_HAS_CODEC
00125 # define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); }
00126 #else
00127 # define CODEC(P,D,N,X)
00128 #endif
00129
00130
00131
00132
00133
00134 #define PGHDR_TO_DATA(P) ((void*)(&(P)[1]))
00135 #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1])
00136 #define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE])
00137
00138
00139
00140
00141
00142 #define N_PG_HASH 2048
00143
00144
00145
00146
00147 #define pager_hash(PN) ((PN)&(N_PG_HASH-1))
00148
00149
00150
00151
00152 struct Pager {
00153 char *zFilename;
00154 char *zJournal;
00155 char *zDirectory;
00156 OsFile fd, jfd;
00157 OsFile cpfd;
00158 int dbSize;
00159 int origDbSize;
00160 int ckptSize;
00161 off_t ckptJSize;
00162 int nRec;
00163 u32 cksumInit;
00164 int ckptNRec;
00165 int nExtra;
00166 void (*xDestructor)(void*);
00167 int nPage;
00168 int nRef;
00169 int mxPage;
00170 int nHit, nMiss, nOvfl;
00171 void (*xCodec)(void*,void*,Pgno,int);
00172 void *pCodecArg;
00173 u8 journalOpen;
00174 u8 journalStarted;
00175 u8 useJournal;
00176 u8 ckptOpen;
00177 u8 ckptInUse;
00178 u8 ckptAutoopen;
00179 u8 noSync;
00180 u8 fullSync;
00181 u8 state;
00182 u8 errMask;
00183 u8 tempFile;
00184 u8 readOnly;
00185 u8 needSync;
00186 u8 dirtyFile;
00187 u8 alwaysRollback;
00188 u8 *aInJournal;
00189 u8 *aInCkpt;
00190 PgHdr *pFirst, *pLast;
00191 PgHdr *pFirstSynced;
00192 PgHdr *pAll;
00193 PgHdr *pCkpt;
00194 PgHdr *aHash[N_PG_HASH];
00195 };
00196
00197
00198
00199
00200 #define PAGER_ERR_FULL 0x01
00201 #define PAGER_ERR_MEM 0x02
00202 #define PAGER_ERR_LOCK 0x04
00203 #define PAGER_ERR_CORRUPT 0x08
00204 #define PAGER_ERR_DISK 0x10
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 typedef struct PageRecord PageRecord;
00215 struct PageRecord {
00216 Pgno pgno;
00217 char aData[SQLITE_PAGE_SIZE];
00218 };
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 static const unsigned char aJournalMagic1[] = {
00250 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4,
00251 };
00252 static const unsigned char aJournalMagic2[] = {
00253 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd5,
00254 };
00255 static const unsigned char aJournalMagic3[] = {
00256 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd6,
00257 };
00258 #define JOURNAL_FORMAT_1 1
00259 #define JOURNAL_FORMAT_2 2
00260 #define JOURNAL_FORMAT_3 3
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 #ifdef SQLITE_TEST
00272 int journal_format = 3;
00273 #else
00274 # define journal_format 3
00275 #endif
00276
00277
00278
00279
00280
00281
00282 #define JOURNAL_HDR_SZ(X) \
00283 (sizeof(aJournalMagic1) + sizeof(Pgno) + ((X)>=3)*2*sizeof(u32))
00284 #define JOURNAL_PG_SZ(X) \
00285 (SQLITE_PAGE_SIZE + sizeof(Pgno) + ((X)>=3)*sizeof(u32))
00286
00287
00288
00289
00290 #ifdef SQLITE_TEST
00291 int pager_refinfo_enable = 0;
00292 static void pager_refinfo(PgHdr *p){
00293 static int cnt = 0;
00294 if( !pager_refinfo_enable ) return;
00295 printf(
00296 "REFCNT: %4d addr=0x%08x nRef=%d\n",
00297 p->pgno, (int)PGHDR_TO_DATA(p), p->nRef
00298 );
00299 cnt++;
00300 }
00301 # define REFINFO(X) pager_refinfo(X)
00302 #else
00303 # define REFINFO(X)
00304 #endif
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static int read32bits(int format, OsFile *fd, u32 *pRes){
00316 u32 res;
00317 int rc;
00318 rc = sqliteOsRead(fd, &res, sizeof(res));
00319 if( rc==SQLITE_OK && format>JOURNAL_FORMAT_1 ){
00320 unsigned char ac[4];
00321 memcpy(ac, &res, 4);
00322 res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
00323 }
00324 *pRes = res;
00325 return rc;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 static int write32bits(OsFile *fd, u32 val){
00338 unsigned char ac[4];
00339 if( journal_format<=1 ){
00340 return sqliteOsWrite(fd, &val, 4);
00341 }
00342 ac[0] = (val>>24) & 0xff;
00343 ac[1] = (val>>16) & 0xff;
00344 ac[2] = (val>>8) & 0xff;
00345 ac[3] = val & 0xff;
00346 return sqliteOsWrite(fd, ac, 4);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356 static void store32bits(u32 val, PgHdr *p, int offset){
00357 unsigned char *ac;
00358 ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];
00359 if( journal_format<=1 ){
00360 memcpy(ac, &val, 4);
00361 }else{
00362 ac[0] = (val>>24) & 0xff;
00363 ac[1] = (val>>16) & 0xff;
00364 ac[2] = (val>>8) & 0xff;
00365 ac[3] = val & 0xff;
00366 }
00367 }
00368
00369
00370
00371
00372
00373
00374 static int pager_errcode(Pager *pPager){
00375 int rc = SQLITE_OK;
00376 if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
00377 if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR;
00378 if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
00379 if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM;
00380 if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
00381 return rc;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static void page_add_to_ckpt_list(PgHdr *pPg){
00394 Pager *pPager = pPg->pPager;
00395 if( pPg->inCkpt ) return;
00396 assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 );
00397 pPg->pPrevCkpt = 0;
00398 if( pPager->pCkpt ){
00399 pPager->pCkpt->pPrevCkpt = pPg;
00400 }
00401 pPg->pNextCkpt = pPager->pCkpt;
00402 pPager->pCkpt = pPg;
00403 pPg->inCkpt = 1;
00404 }
00405 static void page_remove_from_ckpt_list(PgHdr *pPg){
00406 if( !pPg->inCkpt ) return;
00407 if( pPg->pPrevCkpt ){
00408 assert( pPg->pPrevCkpt->pNextCkpt==pPg );
00409 pPg->pPrevCkpt->pNextCkpt = pPg->pNextCkpt;
00410 }else{
00411 assert( pPg->pPager->pCkpt==pPg );
00412 pPg->pPager->pCkpt = pPg->pNextCkpt;
00413 }
00414 if( pPg->pNextCkpt ){
00415 assert( pPg->pNextCkpt->pPrevCkpt==pPg );
00416 pPg->pNextCkpt->pPrevCkpt = pPg->pPrevCkpt;
00417 }
00418 pPg->pNextCkpt = 0;
00419 pPg->pPrevCkpt = 0;
00420 pPg->inCkpt = 0;
00421 }
00422
00423
00424
00425
00426
00427 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
00428 PgHdr *p = pPager->aHash[pager_hash(pgno)];
00429 while( p && p->pgno!=pgno ){
00430 p = p->pNextHash;
00431 }
00432 return p;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 static void pager_reset(Pager *pPager){
00442 PgHdr *pPg, *pNext;
00443 for(pPg=pPager->pAll; pPg; pPg=pNext){
00444 pNext = pPg->pNextAll;
00445 sqliteFree(pPg);
00446 }
00447 pPager->pFirst = 0;
00448 pPager->pFirstSynced = 0;
00449 pPager->pLast = 0;
00450 pPager->pAll = 0;
00451 memset(pPager->aHash, 0, sizeof(pPager->aHash));
00452 pPager->nPage = 0;
00453 if( pPager->state>=SQLITE_WRITELOCK ){
00454 sqlitepager_rollback(pPager);
00455 }
00456 sqliteOsUnlock(&pPager->fd);
00457 pPager->state = SQLITE_UNLOCK;
00458 pPager->dbSize = -1;
00459 pPager->nRef = 0;
00460 assert( pPager->journalOpen==0 );
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 static int pager_unwritelock(Pager *pPager){
00474 int rc;
00475 PgHdr *pPg;
00476 if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK;
00477 sqlitepager_ckpt_commit(pPager);
00478 if( pPager->ckptOpen ){
00479 sqliteOsClose(&pPager->cpfd);
00480 pPager->ckptOpen = 0;
00481 }
00482 if( pPager->journalOpen ){
00483 sqliteOsClose(&pPager->jfd);
00484 pPager->journalOpen = 0;
00485 sqliteOsDelete(pPager->zJournal);
00486 sqliteFree( pPager->aInJournal );
00487 pPager->aInJournal = 0;
00488 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
00489 pPg->inJournal = 0;
00490 pPg->dirty = 0;
00491 pPg->needSync = 0;
00492 }
00493 }else{
00494 assert( pPager->dirtyFile==0 || pPager->useJournal==0 );
00495 }
00496 rc = sqliteOsReadLock(&pPager->fd);
00497 if( rc==SQLITE_OK ){
00498 pPager->state = SQLITE_READLOCK;
00499 }else{
00500
00501
00502
00503
00504 pPager->state = SQLITE_UNLOCK;
00505 }
00506 return rc;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516 static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){
00517 u32 cksum = pPager->cksumInit + pgno;
00518 return cksum;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528 static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){
00529 int rc;
00530 PgHdr *pPg;
00531 PageRecord pgRec;
00532 u32 cksum;
00533
00534 rc = read32bits(format, jfd, &pgRec.pgno);
00535 if( rc!=SQLITE_OK ) return rc;
00536 rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData));
00537 if( rc!=SQLITE_OK ) return rc;
00538
00539
00540
00541
00542
00543
00544 if( pgRec.pgno==0 ){
00545 return SQLITE_DONE;
00546 }
00547 if( pgRec.pgno>(unsigned)pPager->dbSize ){
00548 return SQLITE_OK;
00549 }
00550 if( format>=JOURNAL_FORMAT_3 ){
00551 rc = read32bits(format, jfd, &cksum);
00552 if( rc ) return rc;
00553 if( pager_cksum(pPager, pgRec.pgno, pgRec.aData)!=cksum ){
00554 return SQLITE_DONE;
00555 }
00556 }
00557
00558
00559
00560
00561 pPg = pager_lookup(pPager, pgRec.pgno);
00562 TRACE2("PLAYBACK %d\n", pgRec.pgno);
00563 sqliteOsSeek(&pPager->fd, (pgRec.pgno-1)*(off_t)SQLITE_PAGE_SIZE);
00564 rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
00565 if( pPg ){
00566
00567
00568
00569
00570 assert( pPg->nRef==0 || pPg->pgno==1 );
00571 memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
00572 memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
00573 pPg->dirty = 0;
00574 pPg->needSync = 0;
00575 CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
00576 }
00577 return rc;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 static int pager_playback(Pager *pPager, int useJournalSize){
00633 off_t szJ;
00634 int nRec;
00635 int i;
00636 Pgno mxPg = 0;
00637 int format;
00638 unsigned char aMagic[sizeof(aJournalMagic1)];
00639 int rc;
00640
00641
00642
00643
00644 assert( pPager->journalOpen );
00645 sqliteOsSeek(&pPager->jfd, 0);
00646 rc = sqliteOsFileSize(&pPager->jfd, &szJ);
00647 if( rc!=SQLITE_OK ){
00648 goto end_playback;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657 if( szJ < sizeof(aMagic)+sizeof(Pgno) ){
00658 goto end_playback;
00659 }
00660
00661
00662
00663
00664 rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic));
00665 if( rc!=SQLITE_OK ){
00666 rc = SQLITE_PROTOCOL;
00667 goto end_playback;
00668 }
00669 if( memcmp(aMagic, aJournalMagic3, sizeof(aMagic))==0 ){
00670 format = JOURNAL_FORMAT_3;
00671 }else if( memcmp(aMagic, aJournalMagic2, sizeof(aMagic))==0 ){
00672 format = JOURNAL_FORMAT_2;
00673 }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){
00674 format = JOURNAL_FORMAT_1;
00675 }else{
00676 rc = SQLITE_PROTOCOL;
00677 goto end_playback;
00678 }
00679 if( format>=JOURNAL_FORMAT_3 ){
00680 if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){
00681
00682
00683
00684
00685
00686
00687 goto end_playback;
00688 }
00689 rc = read32bits(format, &pPager->jfd, (u32*)&nRec);
00690 if( rc ) goto end_playback;
00691 rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
00692 if( rc ) goto end_playback;
00693 if( nRec==0xffffffff || useJournalSize ){
00694 nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
00695 }
00696 }else{
00697 nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2);
00698 assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ );
00699 }
00700 rc = read32bits(format, &pPager->jfd, &mxPg);
00701 if( rc!=SQLITE_OK ){
00702 goto end_playback;
00703 }
00704 assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
00705 rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg);
00706 if( rc!=SQLITE_OK ){
00707 goto end_playback;
00708 }
00709 pPager->dbSize = mxPg;
00710
00711
00712
00713 for(i=0; i<nRec; i++){
00714 rc = pager_playback_one_page(pPager, &pPager->jfd, format);
00715 if( rc!=SQLITE_OK ){
00716 if( rc==SQLITE_DONE ){
00717 rc = SQLITE_OK;
00718 }
00719 break;
00720 }
00721 }
00722
00723
00724
00725
00726
00727 if( rc==SQLITE_OK ){
00728 PgHdr *pPg;
00729 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
00730 char zBuf[SQLITE_PAGE_SIZE];
00731 if( !pPg->dirty ) continue;
00732 if( (int)pPg->pgno <= pPager->origDbSize ){
00733 sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
00734 rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
00735 TRACE2("REFETCH %d\n", pPg->pgno);
00736 CODEC(pPager, zBuf, pPg->pgno, 2);
00737 if( rc ) break;
00738 }else{
00739 memset(zBuf, 0, SQLITE_PAGE_SIZE);
00740 }
00741 if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
00742 memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
00743 memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
00744 }
00745 pPg->needSync = 0;
00746 pPg->dirty = 0;
00747 }
00748 }
00749
00750 end_playback:
00751 if( rc!=SQLITE_OK ){
00752 pager_unwritelock(pPager);
00753 pPager->errMask |= PAGER_ERR_CORRUPT;
00754 rc = SQLITE_CORRUPT;
00755 }else{
00756 rc = pager_unwritelock(pPager);
00757 }
00758 return rc;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 static int pager_ckpt_playback(Pager *pPager){
00776 off_t szJ;
00777 int nRec;
00778 int i;
00779 int rc;
00780
00781
00782
00783 rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize);
00784 pPager->dbSize = pPager->ckptSize;
00785
00786
00787
00788 assert( pPager->ckptInUse && pPager->journalOpen );
00789 sqliteOsSeek(&pPager->cpfd, 0);
00790 nRec = pPager->ckptNRec;
00791
00792
00793
00794
00795
00796
00797 for(i=nRec-1; i>=0; i--){
00798 rc = pager_playback_one_page(pPager, &pPager->cpfd, 2);
00799 assert( rc!=SQLITE_DONE );
00800 if( rc!=SQLITE_OK ) goto end_ckpt_playback;
00801 }
00802
00803
00804
00805
00806 rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize);
00807 if( rc!=SQLITE_OK ){
00808 goto end_ckpt_playback;
00809 }
00810 rc = sqliteOsFileSize(&pPager->jfd, &szJ);
00811 if( rc!=SQLITE_OK ){
00812 goto end_ckpt_playback;
00813 }
00814 nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format);
00815 for(i=nRec-1; i>=0; i--){
00816 rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format);
00817 if( rc!=SQLITE_OK ){
00818 assert( rc!=SQLITE_DONE );
00819 goto end_ckpt_playback;
00820 }
00821 }
00822
00823 end_ckpt_playback:
00824 if( rc!=SQLITE_OK ){
00825 pPager->errMask |= PAGER_ERR_CORRUPT;
00826 rc = SQLITE_CORRUPT;
00827 }
00828 return rc;
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 void sqlitepager_set_cachesize(Pager *pPager, int mxPage){
00842 if( mxPage>=0 ){
00843 pPager->noSync = pPager->tempFile;
00844 if( pPager->noSync==0 ) pPager->needSync = 0;
00845 }else{
00846 pPager->noSync = 1;
00847 mxPage = -mxPage;
00848 }
00849 if( mxPage>10 ){
00850 pPager->mxPage = mxPage;
00851 }
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 void sqlitepager_set_safety_level(Pager *pPager, int level){
00881 pPager->noSync = level==1 || pPager->tempFile;
00882 pPager->fullSync = level==3 && !pPager->tempFile;
00883 if( pPager->noSync==0 ) pPager->needSync = 0;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 static int sqlitepager_opentemp(char *zFile, OsFile *fd){
00896 int cnt = 8;
00897 int rc;
00898 do{
00899 cnt--;
00900 sqliteOsTempFileName(zFile);
00901 rc = sqliteOsOpenExclusive(zFile, fd, 1);
00902 }while( cnt>0 && rc!=SQLITE_OK );
00903 return rc;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 int sqlitepager_open(
00917 Pager **ppPager,
00918 const char *zFilename,
00919 int mxPage,
00920 int nExtra,
00921 int useJournal
00922 ){
00923 Pager *pPager;
00924 char *zFullPathname;
00925 int nameLen;
00926 OsFile fd;
00927 int rc, i;
00928 int tempFile;
00929 int readOnly = 0;
00930 char zTemp[SQLITE_TEMPNAME_SIZE];
00931
00932 *ppPager = 0;
00933 if( sqlite_malloc_failed ){
00934 return SQLITE_NOMEM;
00935 }
00936 if( zFilename && zFilename[0] ){
00937 zFullPathname = sqliteOsFullPathname(zFilename);
00938 rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly);
00939 tempFile = 0;
00940 }else{
00941 rc = sqlitepager_opentemp(zTemp, &fd);
00942 zFilename = zTemp;
00943 zFullPathname = sqliteOsFullPathname(zFilename);
00944 tempFile = 1;
00945 }
00946 if( sqlite_malloc_failed ){
00947 return SQLITE_NOMEM;
00948 }
00949 if( rc!=SQLITE_OK ){
00950 sqliteFree(zFullPathname);
00951 return SQLITE_CANTOPEN;
00952 }
00953 nameLen = strlen(zFullPathname);
00954 pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
00955 if( pPager==0 ){
00956 sqliteOsClose(&fd);
00957 sqliteFree(zFullPathname);
00958 return SQLITE_NOMEM;
00959 }
00960 SET_PAGER(pPager);
00961 pPager->zFilename = (char*)&pPager[1];
00962 pPager->zDirectory = &pPager->zFilename[nameLen+1];
00963 pPager->zJournal = &pPager->zDirectory[nameLen+1];
00964 strcpy(pPager->zFilename, zFullPathname);
00965 strcpy(pPager->zDirectory, zFullPathname);
00966 for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){}
00967 if( i>0 ) pPager->zDirectory[i-1] = 0;
00968 strcpy(pPager->zJournal, zFullPathname);
00969 sqliteFree(zFullPathname);
00970 strcpy(&pPager->zJournal[nameLen], "-journal");
00971 pPager->fd = fd;
00972 pPager->journalOpen = 0;
00973 pPager->useJournal = useJournal;
00974 pPager->ckptOpen = 0;
00975 pPager->ckptInUse = 0;
00976 pPager->nRef = 0;
00977 pPager->dbSize = -1;
00978 pPager->ckptSize = 0;
00979 pPager->ckptJSize = 0;
00980 pPager->nPage = 0;
00981 pPager->mxPage = mxPage>5 ? mxPage : 10;
00982 pPager->state = SQLITE_UNLOCK;
00983 pPager->errMask = 0;
00984 pPager->tempFile = tempFile;
00985 pPager->readOnly = readOnly;
00986 pPager->needSync = 0;
00987 pPager->noSync = pPager->tempFile || !useJournal;
00988 pPager->pFirst = 0;
00989 pPager->pFirstSynced = 0;
00990 pPager->pLast = 0;
00991 pPager->nExtra = nExtra;
00992 memset(pPager->aHash, 0, sizeof(pPager->aHash));
00993 *ppPager = pPager;
00994 return SQLITE_OK;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
01006 pPager->xDestructor = xDesc;
01007 }
01008
01009
01010
01011
01012
01013 int sqlitepager_pagecount(Pager *pPager){
01014 off_t n;
01015 assert( pPager!=0 );
01016 if( pPager->dbSize>=0 ){
01017 return pPager->dbSize;
01018 }
01019 if( sqliteOsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
01020 pPager->errMask |= PAGER_ERR_DISK;
01021 return 0;
01022 }
01023 n /= SQLITE_PAGE_SIZE;
01024 if( pPager->state!=SQLITE_UNLOCK ){
01025 pPager->dbSize = n;
01026 }
01027 return n;
01028 }
01029
01030
01031
01032
01033 static int syncJournal(Pager*);
01034
01035
01036
01037
01038 int sqlitepager_truncate(Pager *pPager, Pgno nPage){
01039 int rc;
01040 if( pPager->dbSize<0 ){
01041 sqlitepager_pagecount(pPager);
01042 }
01043 if( pPager->errMask!=0 ){
01044 rc = pager_errcode(pPager);
01045 return rc;
01046 }
01047 if( nPage>=(unsigned)pPager->dbSize ){
01048 return SQLITE_OK;
01049 }
01050 syncJournal(pPager);
01051 rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
01052 if( rc==SQLITE_OK ){
01053 pPager->dbSize = nPage;
01054 }
01055 return rc;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 int sqlitepager_close(Pager *pPager){
01068 PgHdr *pPg, *pNext;
01069 switch( pPager->state ){
01070 case SQLITE_WRITELOCK: {
01071 sqlitepager_rollback(pPager);
01072 sqliteOsUnlock(&pPager->fd);
01073 assert( pPager->journalOpen==0 );
01074 break;
01075 }
01076 case SQLITE_READLOCK: {
01077 sqliteOsUnlock(&pPager->fd);
01078 break;
01079 }
01080 default: {
01081
01082 break;
01083 }
01084 }
01085 for(pPg=pPager->pAll; pPg; pPg=pNext){
01086 pNext = pPg->pNextAll;
01087 sqliteFree(pPg);
01088 }
01089 sqliteOsClose(&pPager->fd);
01090 assert( pPager->journalOpen==0 );
01091
01092
01093
01094
01095
01096 CLR_PAGER(pPager);
01097 if( pPager->zFilename!=(char*)&pPager[1] ){
01098 assert( 0 );
01099 sqliteFree(pPager->zFilename);
01100 sqliteFree(pPager->zJournal);
01101 sqliteFree(pPager->zDirectory);
01102 }
01103 sqliteFree(pPager);
01104 return SQLITE_OK;
01105 }
01106
01107
01108
01109
01110 Pgno sqlitepager_pagenumber(void *pData){
01111 PgHdr *p = DATA_TO_PGHDR(pData);
01112 return p->pgno;
01113 }
01114
01115
01116
01117
01118
01119
01120 #define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
01121 static void _page_ref(PgHdr *pPg){
01122 if( pPg->nRef==0 ){
01123
01124 if( pPg==pPg->pPager->pFirstSynced ){
01125 PgHdr *p = pPg->pNextFree;
01126 while( p && p->needSync ){ p = p->pNextFree; }
01127 pPg->pPager->pFirstSynced = p;
01128 }
01129 if( pPg->pPrevFree ){
01130 pPg->pPrevFree->pNextFree = pPg->pNextFree;
01131 }else{
01132 pPg->pPager->pFirst = pPg->pNextFree;
01133 }
01134 if( pPg->pNextFree ){
01135 pPg->pNextFree->pPrevFree = pPg->pPrevFree;
01136 }else{
01137 pPg->pPager->pLast = pPg->pPrevFree;
01138 }
01139 pPg->pPager->nRef++;
01140 }
01141 pPg->nRef++;
01142 REFINFO(pPg);
01143 }
01144
01145
01146
01147
01148
01149 int sqlitepager_ref(void *pData){
01150 PgHdr *pPg = DATA_TO_PGHDR(pData);
01151 page_ref(pPg);
01152 return SQLITE_OK;
01153 }
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 static int syncJournal(Pager *pPager){
01176 PgHdr *pPg;
01177 int rc = SQLITE_OK;
01178
01179
01180
01181
01182 if( pPager->needSync ){
01183 if( !pPager->tempFile ){
01184 assert( pPager->journalOpen );
01185
01186
01187 #ifndef NDEBUG
01188 {
01189
01190
01191
01192 off_t hdrSz, pgSz, jSz;
01193 hdrSz = JOURNAL_HDR_SZ(journal_format);
01194 pgSz = JOURNAL_PG_SZ(journal_format);
01195 rc = sqliteOsFileSize(&pPager->jfd, &jSz);
01196 if( rc!=0 ) return rc;
01197 assert( pPager->nRec*pgSz+hdrSz==jSz );
01198 }
01199 #endif
01200 if( journal_format>=3 ){
01201
01202 off_t szJ;
01203 if( pPager->fullSync ){
01204 TRACE1("SYNC\n");
01205 rc = sqliteOsSync(&pPager->jfd);
01206 if( rc!=0 ) return rc;
01207 }
01208 sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1));
01209 rc = write32bits(&pPager->jfd, pPager->nRec);
01210 if( rc ) return rc;
01211 szJ = JOURNAL_HDR_SZ(journal_format) +
01212 pPager->nRec*JOURNAL_PG_SZ(journal_format);
01213 sqliteOsSeek(&pPager->jfd, szJ);
01214 }
01215 TRACE1("SYNC\n");
01216 rc = sqliteOsSync(&pPager->jfd);
01217 if( rc!=0 ) return rc;
01218 pPager->journalStarted = 1;
01219 }
01220 pPager->needSync = 0;
01221
01222
01223
01224 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
01225 pPg->needSync = 0;
01226 }
01227 pPager->pFirstSynced = pPager->pFirst;
01228 }
01229
01230 #ifndef NDEBUG
01231
01232
01233
01234
01235 else{
01236 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
01237 assert( pPg->needSync==0 );
01238 }
01239 assert( pPager->pFirstSynced==pPager->pFirst );
01240 }
01241 #endif
01242
01243 return rc;
01244 }
01245
01246
01247
01248
01249
01250
01251 static int pager_write_pagelist(PgHdr *pList){
01252 Pager *pPager;
01253 int rc;
01254
01255 if( pList==0 ) return SQLITE_OK;
01256 pPager = pList->pPager;
01257 while( pList ){
01258 assert( pList->dirty );
01259 sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE);
01260 CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
01261 TRACE2("STORE %d\n", pList->pgno);
01262 rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE);
01263 CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
01264 if( rc ) return rc;
01265 pList->dirty = 0;
01266 pList = pList->pDirty;
01267 }
01268 return SQLITE_OK;
01269 }
01270
01271
01272
01273
01274
01275
01276 static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
01277 PgHdr *p, *pList;
01278 pList = 0;
01279 for(p=pPager->pAll; p; p=p->pNextAll){
01280 if( p->dirty ){
01281 p->pDirty = pList;
01282 pList = p;
01283 }
01284 }
01285 return pList;
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
01312 PgHdr *pPg;
01313 int rc;
01314
01315
01316
01317 assert( pPager!=0 );
01318 assert( pgno!=0 );
01319 *ppPage = 0;
01320 if( pPager->errMask & ~(PAGER_ERR_FULL) ){
01321 return pager_errcode(pPager);
01322 }
01323
01324
01325
01326
01327 if( pPager->nRef==0 ){
01328 rc = sqliteOsReadLock(&pPager->fd);
01329 if( rc!=SQLITE_OK ){
01330 return rc;
01331 }
01332 pPager->state = SQLITE_READLOCK;
01333
01334
01335
01336 if( pPager->useJournal && sqliteOsFileExists(pPager->zJournal) ){
01337 int rc;
01338
01339
01340
01341 rc = sqliteOsWriteLock(&pPager->fd);
01342 if( rc!=SQLITE_OK ){
01343 if( sqliteOsUnlock(&pPager->fd)!=SQLITE_OK ){
01344
01345 rc = SQLITE_INTERNAL;
01346 }
01347 return rc;
01348 }
01349 pPager->state = SQLITE_WRITELOCK;
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359 rc = sqliteOsOpenReadOnly(pPager->zJournal, &pPager->jfd);
01360 if( rc!=SQLITE_OK ){
01361 rc = sqliteOsUnlock(&pPager->fd);
01362 assert( rc==SQLITE_OK );
01363 return SQLITE_BUSY;
01364 }
01365 pPager->journalOpen = 1;
01366 pPager->journalStarted = 0;
01367
01368
01369
01370
01371 rc = pager_playback(pPager, 0);
01372 if( rc!=SQLITE_OK ){
01373 return rc;
01374 }
01375 }
01376 pPg = 0;
01377 }else{
01378
01379 pPg = pager_lookup(pPager, pgno);
01380 }
01381 if( pPg==0 ){
01382
01383 int h;
01384 pPager->nMiss++;
01385 if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 ){
01386
01387 pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE
01388 + sizeof(u32) + pPager->nExtra );
01389 if( pPg==0 ){
01390 pager_unwritelock(pPager);
01391 pPager->errMask |= PAGER_ERR_MEM;
01392 return SQLITE_NOMEM;
01393 }
01394 memset(pPg, 0, sizeof(*pPg));
01395 pPg->pPager = pPager;
01396 pPg->pNextAll = pPager->pAll;
01397 if( pPager->pAll ){
01398 pPager->pAll->pPrevAll = pPg;
01399 }
01400 pPg->pPrevAll = 0;
01401 pPager->pAll = pPg;
01402 pPager->nPage++;
01403 }else{
01404
01405
01406
01407 pPg = pPager->pFirstSynced;
01408
01409
01410
01411
01412
01413
01414 if( pPg==0 ){
01415 int rc = syncJournal(pPager);
01416 if( rc!=0 ){
01417 sqlitepager_rollback(pPager);
01418 return SQLITE_IOERR;
01419 }
01420 pPg = pPager->pFirst;
01421 }
01422 assert( pPg->nRef==0 );
01423
01424
01425
01426 if( pPg->dirty ){
01427 assert( pPg->needSync==0 );
01428 pPg->pDirty = 0;
01429 rc = pager_write_pagelist( pPg );
01430 if( rc!=SQLITE_OK ){
01431 sqlitepager_rollback(pPager);
01432 return SQLITE_IOERR;
01433 }
01434 }
01435 assert( pPg->dirty==0 );
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445 if( pPg->alwaysRollback ){
01446 pPager->alwaysRollback = 1;
01447 }
01448
01449
01450
01451 if( pPg==pPager->pFirstSynced ){
01452 PgHdr *p = pPg->pNextFree;
01453 while( p && p->needSync ){ p = p->pNextFree; }
01454 pPager->pFirstSynced = p;
01455 }
01456 if( pPg->pPrevFree ){
01457 pPg->pPrevFree->pNextFree = pPg->pNextFree;
01458 }else{
01459 assert( pPager->pFirst==pPg );
01460 pPager->pFirst = pPg->pNextFree;
01461 }
01462 if( pPg->pNextFree ){
01463 pPg->pNextFree->pPrevFree = pPg->pPrevFree;
01464 }else{
01465 assert( pPager->pLast==pPg );
01466 pPager->pLast = pPg->pPrevFree;
01467 }
01468 pPg->pNextFree = pPg->pPrevFree = 0;
01469 if( pPg->pNextHash ){
01470 pPg->pNextHash->pPrevHash = pPg->pPrevHash;
01471 }
01472 if( pPg->pPrevHash ){
01473 pPg->pPrevHash->pNextHash = pPg->pNextHash;
01474 }else{
01475 h = pager_hash(pPg->pgno);
01476 assert( pPager->aHash[h]==pPg );
01477 pPager->aHash[h] = pPg->pNextHash;
01478 }
01479 pPg->pNextHash = pPg->pPrevHash = 0;
01480 pPager->nOvfl++;
01481 }
01482 pPg->pgno = pgno;
01483 if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
01484 sqliteCheckMemory(pPager->aInJournal, pgno/8);
01485 assert( pPager->journalOpen );
01486 pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0;
01487 pPg->needSync = 0;
01488 }else{
01489 pPg->inJournal = 0;
01490 pPg->needSync = 0;
01491 }
01492 if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize
01493 && (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){
01494 page_add_to_ckpt_list(pPg);
01495 }else{
01496 page_remove_from_ckpt_list(pPg);
01497 }
01498 pPg->dirty = 0;
01499 pPg->nRef = 1;
01500 REFINFO(pPg);
01501 pPager->nRef++;
01502 h = pager_hash(pgno);
01503 pPg->pNextHash = pPager->aHash[h];
01504 pPager->aHash[h] = pPg;
01505 if( pPg->pNextHash ){
01506 assert( pPg->pNextHash->pPrevHash==0 );
01507 pPg->pNextHash->pPrevHash = pPg;
01508 }
01509 if( pPager->nExtra>0 ){
01510 memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
01511 }
01512 if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
01513 if( pPager->errMask!=0 ){
01514 sqlitepager_unref(PGHDR_TO_DATA(pPg));
01515 rc = pager_errcode(pPager);
01516 return rc;
01517 }
01518 if( pPager->dbSize<(int)pgno ){
01519 memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
01520 }else{
01521 int rc;
01522 sqliteOsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE);
01523 rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
01524 TRACE2("FETCH %d\n", pPg->pgno);
01525 CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
01526 if( rc!=SQLITE_OK ){
01527 off_t fileSize;
01528 if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
01529 || fileSize>=pgno*SQLITE_PAGE_SIZE ){
01530 sqlitepager_unref(PGHDR_TO_DATA(pPg));
01531 return rc;
01532 }else{
01533 memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
01534 }
01535 }
01536 }
01537 }else{
01538
01539 pPager->nHit++;
01540 page_ref(pPg);
01541 }
01542 *ppPage = PGHDR_TO_DATA(pPg);
01543 return SQLITE_OK;
01544 }
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
01558 PgHdr *pPg;
01559
01560 assert( pPager!=0 );
01561 assert( pgno!=0 );
01562 if( pPager->errMask & ~(PAGER_ERR_FULL) ){
01563 return 0;
01564 }
01565
01566
01567
01568
01569 pPg = pager_lookup(pPager, pgno);
01570 if( pPg==0 ) return 0;
01571 page_ref(pPg);
01572 return PGHDR_TO_DATA(pPg);
01573 }
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 int sqlitepager_unref(void *pData){
01584 PgHdr *pPg;
01585
01586
01587
01588 pPg = DATA_TO_PGHDR(pData);
01589 assert( pPg->nRef>0 );
01590 pPg->nRef--;
01591 REFINFO(pPg);
01592
01593
01594
01595
01596 if( pPg->nRef==0 ){
01597 Pager *pPager;
01598 pPager = pPg->pPager;
01599 pPg->pNextFree = 0;
01600 pPg->pPrevFree = pPager->pLast;
01601 pPager->pLast = pPg;
01602 if( pPg->pPrevFree ){
01603 pPg->pPrevFree->pNextFree = pPg;
01604 }else{
01605 pPager->pFirst = pPg;
01606 }
01607 if( pPg->needSync==0 && pPager->pFirstSynced==0 ){
01608 pPager->pFirstSynced = pPg;
01609 }
01610 if( pPager->xDestructor ){
01611 pPager->xDestructor(pData);
01612 }
01613
01614
01615
01616
01617 pPager->nRef--;
01618 assert( pPager->nRef>=0 );
01619 if( pPager->nRef==0 ){
01620 pager_reset(pPager);
01621 }
01622 }
01623 return SQLITE_OK;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633 static int pager_open_journal(Pager *pPager){
01634 int rc;
01635 assert( pPager->state==SQLITE_WRITELOCK );
01636 assert( pPager->journalOpen==0 );
01637 assert( pPager->useJournal );
01638 sqlitepager_pagecount(pPager);
01639 pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
01640 if( pPager->aInJournal==0 ){
01641 sqliteOsReadLock(&pPager->fd);
01642 pPager->state = SQLITE_READLOCK;
01643 return SQLITE_NOMEM;
01644 }
01645 rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
01646 if( rc!=SQLITE_OK ){
01647 sqliteFree(pPager->aInJournal);
01648 pPager->aInJournal = 0;
01649 sqliteOsReadLock(&pPager->fd);
01650 pPager->state = SQLITE_READLOCK;
01651 return SQLITE_CANTOPEN;
01652 }
01653 sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd);
01654 pPager->journalOpen = 1;
01655 pPager->journalStarted = 0;
01656 pPager->needSync = 0;
01657 pPager->alwaysRollback = 0;
01658 pPager->nRec = 0;
01659 if( pPager->errMask!=0 ){
01660 rc = pager_errcode(pPager);
01661 return rc;
01662 }
01663 pPager->origDbSize = pPager->dbSize;
01664 if( journal_format==JOURNAL_FORMAT_3 ){
01665 rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3));
01666 if( rc==SQLITE_OK ){
01667 rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0);
01668 }
01669 if( rc==SQLITE_OK ){
01670 sqliteRandomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
01671 rc = write32bits(&pPager->jfd, pPager->cksumInit);
01672 }
01673 }else if( journal_format==JOURNAL_FORMAT_2 ){
01674 rc = sqliteOsWrite(&pPager->jfd, aJournalMagic2, sizeof(aJournalMagic2));
01675 }else{
01676 assert( journal_format==JOURNAL_FORMAT_1 );
01677 rc = sqliteOsWrite(&pPager->jfd, aJournalMagic1, sizeof(aJournalMagic1));
01678 }
01679 if( rc==SQLITE_OK ){
01680 rc = write32bits(&pPager->jfd, pPager->dbSize);
01681 }
01682 if( pPager->ckptAutoopen && rc==SQLITE_OK ){
01683 rc = sqlitepager_ckpt_begin(pPager);
01684 }
01685 if( rc!=SQLITE_OK ){
01686 rc = pager_unwritelock(pPager);
01687 if( rc==SQLITE_OK ){
01688 rc = SQLITE_FULL;
01689 }
01690 }
01691 return rc;
01692 }
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714 int sqlitepager_begin(void *pData){
01715 PgHdr *pPg = DATA_TO_PGHDR(pData);
01716 Pager *pPager = pPg->pPager;
01717 int rc = SQLITE_OK;
01718 assert( pPg->nRef>0 );
01719 assert( pPager->state!=SQLITE_UNLOCK );
01720 if( pPager->state==SQLITE_READLOCK ){
01721 assert( pPager->aInJournal==0 );
01722 rc = sqliteOsWriteLock(&pPager->fd);
01723 if( rc!=SQLITE_OK ){
01724 return rc;
01725 }
01726 pPager->state = SQLITE_WRITELOCK;
01727 pPager->dirtyFile = 0;
01728 TRACE1("TRANSACTION\n");
01729 if( pPager->useJournal && !pPager->tempFile ){
01730 rc = pager_open_journal(pPager);
01731 }
01732 }
01733 return rc;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753 int sqlitepager_write(void *pData){
01754 PgHdr *pPg = DATA_TO_PGHDR(pData);
01755 Pager *pPager = pPg->pPager;
01756 int rc = SQLITE_OK;
01757
01758
01759
01760 if( pPager->errMask ){
01761 return pager_errcode(pPager);
01762 }
01763 if( pPager->readOnly ){
01764 return SQLITE_PERM;
01765 }
01766
01767
01768
01769
01770 pPg->dirty = 1;
01771 if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){
01772 pPager->dirtyFile = 1;
01773 return SQLITE_OK;
01774 }
01775
01776
01777
01778
01779
01780
01781
01782
01783 assert( pPager->state!=SQLITE_UNLOCK );
01784 rc = sqlitepager_begin(pData);
01785 if( rc!=SQLITE_OK ){
01786 return rc;
01787 }
01788 assert( pPager->state==SQLITE_WRITELOCK );
01789 if( !pPager->journalOpen && pPager->useJournal ){
01790 rc = pager_open_journal(pPager);
01791 if( rc!=SQLITE_OK ) return rc;
01792 }
01793 assert( pPager->journalOpen || !pPager->useJournal );
01794 pPager->dirtyFile = 1;
01795
01796
01797
01798
01799
01800 if( !pPg->inJournal && pPager->useJournal ){
01801 if( (int)pPg->pgno <= pPager->origDbSize ){
01802 int szPg;
01803 u32 saved;
01804 if( journal_format>=JOURNAL_FORMAT_3 ){
01805 u32 cksum = pager_cksum(pPager, pPg->pgno, pData);
01806 saved = *(u32*)PGHDR_TO_EXTRA(pPg);
01807 store32bits(cksum, pPg, SQLITE_PAGE_SIZE);
01808 szPg = SQLITE_PAGE_SIZE+8;
01809 }else{
01810 szPg = SQLITE_PAGE_SIZE+4;
01811 }
01812 store32bits(pPg->pgno, pPg, -4);
01813 CODEC(pPager, pData, pPg->pgno, 7);
01814 rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
01815 TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync);
01816 CODEC(pPager, pData, pPg->pgno, 0);
01817 if( journal_format>=JOURNAL_FORMAT_3 ){
01818 *(u32*)PGHDR_TO_EXTRA(pPg) = saved;
01819 }
01820 if( rc!=SQLITE_OK ){
01821 sqlitepager_rollback(pPager);
01822 pPager->errMask |= PAGER_ERR_FULL;
01823 return rc;
01824 }
01825 pPager->nRec++;
01826 assert( pPager->aInJournal!=0 );
01827 pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01828 pPg->needSync = !pPager->noSync;
01829 pPg->inJournal = 1;
01830 if( pPager->ckptInUse ){
01831 pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01832 page_add_to_ckpt_list(pPg);
01833 }
01834 }else{
01835 pPg->needSync = !pPager->journalStarted && !pPager->noSync;
01836 TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync);
01837 }
01838 if( pPg->needSync ){
01839 pPager->needSync = 1;
01840 }
01841 }
01842
01843
01844
01845
01846
01847
01848 if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
01849 assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
01850 store32bits(pPg->pgno, pPg, -4);
01851 CODEC(pPager, pData, pPg->pgno, 7);
01852 rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4);
01853 TRACE2("CKPT-JOURNAL %d\n", pPg->pgno);
01854 CODEC(pPager, pData, pPg->pgno, 0);
01855 if( rc!=SQLITE_OK ){
01856 sqlitepager_rollback(pPager);
01857 pPager->errMask |= PAGER_ERR_FULL;
01858 return rc;
01859 }
01860 pPager->ckptNRec++;
01861 assert( pPager->aInCkpt!=0 );
01862 pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01863 page_add_to_ckpt_list(pPg);
01864 }
01865
01866
01867
01868 if( pPager->dbSize<(int)pPg->pgno ){
01869 pPager->dbSize = pPg->pgno;
01870 }
01871 return rc;
01872 }
01873
01874
01875
01876
01877
01878
01879 int sqlitepager_iswriteable(void *pData){
01880 PgHdr *pPg = DATA_TO_PGHDR(pData);
01881 return pPg->dirty;
01882 }
01883
01884
01885
01886
01887
01888 int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
01889 void *pPage;
01890 int rc;
01891
01892 rc = sqlitepager_get(pPager, pgno, &pPage);
01893 if( rc==SQLITE_OK ){
01894 rc = sqlitepager_write(pPage);
01895 if( rc==SQLITE_OK ){
01896 memcpy(pPage, pData, SQLITE_PAGE_SIZE);
01897 }
01898 sqlitepager_unref(pPage);
01899 }
01900 return rc;
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927 void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
01928 PgHdr *pPg;
01929
01930 pPg = pager_lookup(pPager, pgno);
01931 pPg->alwaysRollback = 1;
01932 if( pPg && pPg->dirty && !pPager->ckptInUse ){
01933 if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
01934
01935
01936
01937
01938
01939
01940
01941
01942 }else{
01943 TRACE2("DONT_WRITE %d\n", pgno);
01944 pPg->dirty = 0;
01945 }
01946 }
01947 }
01948
01949
01950
01951
01952
01953
01954
01955 void sqlitepager_dont_rollback(void *pData){
01956 PgHdr *pPg = DATA_TO_PGHDR(pData);
01957 Pager *pPager = pPg->pPager;
01958
01959 if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return;
01960 if( pPg->alwaysRollback || pPager->alwaysRollback ) return;
01961 if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
01962 assert( pPager->aInJournal!=0 );
01963 pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01964 pPg->inJournal = 1;
01965 if( pPager->ckptInUse ){
01966 pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01967 page_add_to_ckpt_list(pPg);
01968 }
01969 TRACE2("DONT_ROLLBACK %d\n", pPg->pgno);
01970 }
01971 if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
01972 assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
01973 assert( pPager->aInCkpt!=0 );
01974 pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
01975 page_add_to_ckpt_list(pPg);
01976 }
01977 }
01978
01979
01980
01981
01982
01983
01984
01985
01986 int sqlitepager_commit(Pager *pPager){
01987 int rc;
01988 PgHdr *pPg;
01989
01990 if( pPager->errMask==PAGER_ERR_FULL ){
01991 rc = sqlitepager_rollback(pPager);
01992 if( rc==SQLITE_OK ){
01993 rc = SQLITE_FULL;
01994 }
01995 return rc;
01996 }
01997 if( pPager->errMask!=0 ){
01998 rc = pager_errcode(pPager);
01999 return rc;
02000 }
02001 if( pPager->state!=SQLITE_WRITELOCK ){
02002 return SQLITE_ERROR;
02003 }
02004 TRACE1("COMMIT\n");
02005 if( pPager->dirtyFile==0 ){
02006
02007
02008 assert( pPager->needSync==0 );
02009 rc = pager_unwritelock(pPager);
02010 pPager->dbSize = -1;
02011 return rc;
02012 }
02013 assert( pPager->journalOpen );
02014 rc = syncJournal(pPager);
02015 if( rc!=SQLITE_OK ){
02016 goto commit_abort;
02017 }
02018 pPg = pager_get_all_dirty_pages(pPager);
02019 if( pPg ){
02020 rc = pager_write_pagelist(pPg);
02021 if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){
02022 goto commit_abort;
02023 }
02024 }
02025 rc = pager_unwritelock(pPager);
02026 pPager->dbSize = -1;
02027 return rc;
02028
02029
02030
02031 commit_abort:
02032 rc = sqlitepager_rollback(pPager);
02033 if( rc==SQLITE_OK ){
02034 rc = SQLITE_FULL;
02035 }
02036 return rc;
02037 }
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 int sqlitepager_rollback(Pager *pPager){
02052 int rc;
02053 TRACE1("ROLLBACK\n");
02054 if( !pPager->dirtyFile || !pPager->journalOpen ){
02055 rc = pager_unwritelock(pPager);
02056 pPager->dbSize = -1;
02057 return rc;
02058 }
02059
02060 if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
02061 if( pPager->state>=SQLITE_WRITELOCK ){
02062 pager_playback(pPager, 1);
02063 }
02064 return pager_errcode(pPager);
02065 }
02066 if( pPager->state!=SQLITE_WRITELOCK ){
02067 return SQLITE_OK;
02068 }
02069 rc = pager_playback(pPager, 1);
02070 if( rc!=SQLITE_OK ){
02071 rc = SQLITE_CORRUPT;
02072 pPager->errMask |= PAGER_ERR_CORRUPT;
02073 }
02074 pPager->dbSize = -1;
02075 return rc;
02076 }
02077
02078
02079
02080
02081
02082 int sqlitepager_isreadonly(Pager *pPager){
02083 return pPager->readOnly;
02084 }
02085
02086
02087
02088
02089 int *sqlitepager_stats(Pager *pPager){
02090 static int a[9];
02091 a[0] = pPager->nRef;
02092 a[1] = pPager->nPage;
02093 a[2] = pPager->mxPage;
02094 a[3] = pPager->dbSize;
02095 a[4] = pPager->state;
02096 a[5] = pPager->errMask;
02097 a[6] = pPager->nHit;
02098 a[7] = pPager->nMiss;
02099 a[8] = pPager->nOvfl;
02100 return a;
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110 int sqlitepager_ckpt_begin(Pager *pPager){
02111 int rc;
02112 char zTemp[SQLITE_TEMPNAME_SIZE];
02113 if( !pPager->journalOpen ){
02114 pPager->ckptAutoopen = 1;
02115 return SQLITE_OK;
02116 }
02117 assert( pPager->journalOpen );
02118 assert( !pPager->ckptInUse );
02119 pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 );
02120 if( pPager->aInCkpt==0 ){
02121 sqliteOsReadLock(&pPager->fd);
02122 return SQLITE_NOMEM;
02123 }
02124 #ifndef NDEBUG
02125 rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
02126 if( rc ) goto ckpt_begin_failed;
02127 assert( pPager->ckptJSize ==
02128 pPager->nRec*JOURNAL_PG_SZ(journal_format)+JOURNAL_HDR_SZ(journal_format) );
02129 #endif
02130 pPager->ckptJSize = pPager->nRec*JOURNAL_PG_SZ(journal_format)
02131 + JOURNAL_HDR_SZ(journal_format);
02132 pPager->ckptSize = pPager->dbSize;
02133 if( !pPager->ckptOpen ){
02134 rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
02135 if( rc ) goto ckpt_begin_failed;
02136 pPager->ckptOpen = 1;
02137 pPager->ckptNRec = 0;
02138 }
02139 pPager->ckptInUse = 1;
02140 return SQLITE_OK;
02141
02142 ckpt_begin_failed:
02143 if( pPager->aInCkpt ){
02144 sqliteFree(pPager->aInCkpt);
02145 pPager->aInCkpt = 0;
02146 }
02147 return rc;
02148 }
02149
02150
02151
02152
02153 int sqlitepager_ckpt_commit(Pager *pPager){
02154 if( pPager->ckptInUse ){
02155 PgHdr *pPg, *pNext;
02156 sqliteOsSeek(&pPager->cpfd, 0);
02157
02158 pPager->ckptNRec = 0;
02159 pPager->ckptInUse = 0;
02160 sqliteFree( pPager->aInCkpt );
02161 pPager->aInCkpt = 0;
02162 for(pPg=pPager->pCkpt; pPg; pPg=pNext){
02163 pNext = pPg->pNextCkpt;
02164 assert( pPg->inCkpt );
02165 pPg->inCkpt = 0;
02166 pPg->pPrevCkpt = pPg->pNextCkpt = 0;
02167 }
02168 pPager->pCkpt = 0;
02169 }
02170 pPager->ckptAutoopen = 0;
02171 return SQLITE_OK;
02172 }
02173
02174
02175
02176
02177 int sqlitepager_ckpt_rollback(Pager *pPager){
02178 int rc;
02179 if( pPager->ckptInUse ){
02180 rc = pager_ckpt_playback(pPager);
02181 sqlitepager_ckpt_commit(pPager);
02182 }else{
02183 rc = SQLITE_OK;
02184 }
02185 pPager->ckptAutoopen = 0;
02186 return rc;
02187 }
02188
02189
02190
02191
02192 const char *sqlitepager_filename(Pager *pPager){
02193 return pPager->zFilename;
02194 }
02195
02196
02197
02198
02199 void sqlitepager_set_codec(
02200 Pager *pPager,
02201 void (*xCodec)(void*,void*,Pgno,int),
02202 void *pCodecArg
02203 ){
02204 pPager->xCodec = xCodec;
02205 pPager->pCodecArg = pCodecArg;
02206 }
02207
02208 #ifdef SQLITE_TEST
02209
02210
02211
02212 void sqlitepager_refdump(Pager *pPager){
02213 PgHdr *pPg;
02214 for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
02215 if( pPg->nRef<=0 ) continue;
02216 printf("PAGE %3d addr=0x%08x nRef=%d\n",
02217 pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef);
02218 }
02219 }
02220 #endif