pager.c 270.8 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of the page cache subsystem or "pager".
H
more  
Hongze Cheng 已提交
13
**
H
Hongze Cheng 已提交
14 15 16 17 18 19 20 21
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
*/
#include "sqliteInt.h"
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// #include "wal.h"

// /*
// ** Macros for troubleshooting.  Normally turned off
// */
// #if 0
// int sqlite3PagerTrace=1;  /* True to enable tracing */
// #define sqlite3DebugPrintf printf
// #define PAGERTRACE(X)     if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
// #else
// #define PAGERTRACE(X)
// #endif

// /*
// ** The following two macros are used within the PAGERTRACE() macros above
H
more  
Hongze Cheng 已提交
37
// ** to print out file-descriptors.
38 39 40 41 42 43 44 45
// **
// ** PAGERID() takes a pointer to a Pager struct as its argument. The
// ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
// ** struct as its argument.
// */
// #define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd))
// #define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd))

H
more  
Hongze Cheng 已提交
46 47 48 49 50 51 52 53
#define PAGER_OPEN            0
#define PAGER_READER          1
#define PAGER_WRITER_LOCKED   2
#define PAGER_WRITER_CACHEMOD 3
#define PAGER_WRITER_DBMOD    4
#define PAGER_WRITER_FINISHED 5
#define PAGER_ERROR           6

54 55 56
// #define UNKNOWN_LOCK                (EXCLUSIVE_LOCK+1)

// /*
H
more  
Hongze Cheng 已提交
57
// ** The maximum allowed sector size. 64KiB. If the xSectorsize() method
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
// ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
// ** This could conceivably cause corruption following a power failure on
// ** such a system. This is currently an undocumented limit.
// */
// #define MAX_SECTOR_SIZE 0x10000

// typedef struct PagerSavepoint PagerSavepoint;
// struct PagerSavepoint {
//   i64 iOffset;                 /* Starting offset in main journal */
//   i64 iHdrOffset;              /* See above */
//   Bitvec *pInSavepoint;        /* Set of pages in this savepoint */
//   Pgno nOrig;                  /* Original number of pages in file */
//   Pgno iSubRec;                /* Index of first record in sub-journal */
//   int bTruncateOnRelease;      /* If stmt journal may be truncated on RELEASE */
// #ifndef SQLITE_OMIT_WAL
//   u32 aWalData[WAL_SAVEPOINT_NDATA];        /* WAL savepoint context */
// #endif
// };

// /*
// ** Bits of the Pager.doNotSpill flag.  See further description below.
// */
// #define SPILLFLAG_OFF         0x01 /* Never spill cache.  Set via pragma */
// #define SPILLFLAG_ROLLBACK    0x02 /* Current rolling back, so do not spill */
// #define SPILLFLAG_NOSYNC      0x04 /* Spill is ok, but do not sync */

H
more  
Hongze Cheng 已提交
84
struct Pager {
H
Hongze Cheng 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
  u8           exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
  u8           journalMode;   /* One of the PAGER_JOURNALMODE_* values */
  u8           useJournal;    /* Use a rollback journal on this file */
  u8           noSync;        /* Do not sync the journal if true */
  u8           fullSync;      /* Do extra syncs of the journal for robustness */
  u8           extraSync;     /* sync directory after journal delete */
  u8           syncFlags;     /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8           walSyncFlags;  /* See description above */
  u8           tempFile;      /* zFilename is a temporary or immutable file */
  u8           noLock;        /* Do not lock (except in WAL mode) */
  u8           readOnly;      /* True for a read-only database */
  u8           memDb;         /* True to inhibit all file I/O */
  u8           memVfs;        /* VFS-implemented memory database */

H
more  
Hongze Cheng 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
  /**************************************************************************
  ** The following block contains those class members that change during
  ** routine operation.  Class members not in this block are either fixed
  ** when the pager is first created or else only change when there is a
  ** significant mode change (such as changing the page_size, locking_mode,
  ** or the journal_mode).  From another view, these class members describe
  ** the "state" of the pager, while other class members describe the
  ** "configuration" of the pager.
  */
  u8   eState;            /* Pager state (OPEN, READER, WRITER_LOCKED..) */
  u8   eLock;             /* Current lock held on database file */
  u8   changeCountDone;   /* Set after incrementing the change-counter */
  u8   setSuper;          /* Super-jrnl name is written into jrnl */
  u8   doNotSpill;        /* Do not spill the cache when non-zero */
  u8   subjInMemory;      /* True to use in-memory sub-journals */
  u8   bUseFetch;         /* True to use xFetch() */
  u8   hasHeldSharedLock; /* True if a shared lock has ever been held */
  Pgno dbSize;            /* Number of pages in the database */
  Pgno dbOrigSize;        /* dbSize before the current transaction */
  Pgno dbFileSize;        /* Number of pages in the database file */
  Pgno dbHintSize;        /* Value passed to FCNTL_SIZE_HINT call */
  int  errCode;           /* One of several kinds of errors */
  int  nRec;              /* Pages journalled since last j-header written */
  u32  cksumInit;         /* Quasi-random value added to every checksum */
  u32  nSubRec;           /* Number of records written to sub-journal */
                          //   Bitvec *pInJournal;         /* One bit for each page in the database file */
  int fd;                 /* File descriptor for database */
  int jfd;                /* File descriptor for main journal */
  int sjfd;               /* File descriptor for sub-journal */
                          //   i64 journalOff;             /* Current write offset in the journal file */
                          //   i64 journalHdr;             /* Byte offset to previous journal header */
                          //   sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
                          //   PagerSavepoint *aSavepoint; /* Array of active savepoints */
                          //   int nSavepoint;             /* Number of elements in aSavepoint[] */
                          //   u32 iDataVersion;           /* Changes whenever database content changes */
                          //   char dbFileVers[16];        /* Changes whenever database file changes */
H
more  
Hongze Cheng 已提交
136 137 138 139 140 141 142 143 144 145

  //   int nMmapOut;               /* Number of mmap pages currently outstanding */
  //   sqlite3_int64 szMmap;       /* Desired maximum mmap size */
  //   PgHdr *pMmapFreelist;       /* List of free mmap page headers (pDirty) */
  //   /*
  //   ** End of the routinely-changing class members
  //   ***************************************************************************/

  //   u16 nExtra;                 /* Add this many bytes to each in-memory page */
  //   i16 nReserve;               /* Number of unused bytes at end of each page */
H
more  
Hongze Cheng 已提交
146
  u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
H
more  
Hongze Cheng 已提交
147 148 149 150
  //   u32 sectorSize;             /* Assumed sector size during rollback */
  //   Pgno mxPgno;                /* Maximum allowed size of the database */
  //   i64 pageSize;               /* Number of bytes in a page */
  //   i64 journalSizeLimit;       /* Size limit for persistent journal files */
H
more  
Hongze Cheng 已提交
151 152
  char *zFilename; /* Name of the database file */
  char *zJournal;  /* Name of the journal file */
H
more  
Hongze Cheng 已提交
153 154 155 156 157 158
  //   int (*xBusyHandler)(void*); /* Function to call when busy */
  //   void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
  //   int aStat[4];               /* Total cache hits, misses, writes, spills */
  // #ifdef SQLITE_TEST
  //   int nRead;                  /* Database pages read */
  // #endif
H
more  
Hongze Cheng 已提交
159
  void (*xReiniter)(DbPage *); /* Call this routine when reloading pages */
H
more  
Hongze Cheng 已提交
160 161
  //   int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
  //   char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
H
more  
Hongze Cheng 已提交
162 163 164
  PCache *pPCache; /* Pointer to page cache object */
                   //   Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
  char *zWal;      /* File name for write-ahead log */
H
more  
Hongze Cheng 已提交
165
};
166 167 168

// /*
// ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
H
more  
Hongze Cheng 已提交
169
// ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
// ** or CACHE_WRITE to sqlite3_db_status().
// */
// #define PAGER_STAT_HIT   0
// #define PAGER_STAT_MISS  1
// #define PAGER_STAT_WRITE 2
// #define PAGER_STAT_SPILL 3

// /*
// ** The following global variables hold counters used for
// ** testing purposes only.  These variables do not exist in
// ** a non-testing build.  These variables are not thread-safe.
// */
// #ifdef SQLITE_TEST
// int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
// int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
// int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
// # define PAGER_INCR(v)  v++
// #else
// # define PAGER_INCR(v)
// #endif

H
more  
Hongze Cheng 已提交
191 192 193
static const unsigned char aJournalMagic[] = {
    0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
};
194 195 196 197 198 199 200 201

// /*
// ** The size of the of each page record in the journal is given by
// ** the following macro.
// */
// #define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)

// /*
H
more  
Hongze Cheng 已提交
202
// ** The journal header size for this pager. This is usually the same
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
// ** size as a single disk sector. See also setSectorSize().
// */
// #define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)

// /*
// ** The macro MEMDB is true if we are dealing with an in-memory database.
// ** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
// ** the value of MEMDB will be a constant and the compiler will optimize
// ** out code that would never execute.
// */
// #ifdef SQLITE_OMIT_MEMORYDB
// # define MEMDB 0
// #else
// # define MEMDB pPager->memDb
// #endif

// /*
// ** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
// ** interfaces to access the database using memory-mapped I/O.
// */
// #if SQLITE_MAX_MMAP_SIZE>0
// # define USEFETCH(x) ((x)->bUseFetch)
// #else
// # define USEFETCH(x) 0
// #endif

// /*
// ** The argument to this macro is a file descriptor (type sqlite3_file*).
// ** Return 0 if it is not open, or non-zero (but not 1) if it is.
// **
// ** This is so that expressions can be written as:
// **
// **   if( isOpen(pPager->jfd) ){ ...
// **
// ** instead of
// **
// **   if( pPager->jfd->pMethods ){ ...
// */
// #define isOpen(pFd) ((pFd)->pMethods!=0)

// #ifdef SQLITE_DIRECT_OVERFLOW_READ
// /*
// ** Return true if page pgno can be read directly from the database file
// ** by the b-tree layer. This is the case if:
// **
// **   * the database file is open,
// **   * there are no dirty pages in the cache, and
// **   * the desired page is not currently in the wal file.
// */
// int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
//   if( pPager->fd->pMethods==0 ) return 0;
//   if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
// #ifndef SQLITE_OMIT_WAL
//   if( pPager->pWal ){
//     u32 iRead = 0;
//     int rc;
//     rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
//     return (rc==SQLITE_OK && iRead==0);
//   }
// #endif
//   return 1;
// }
// #endif

// #ifndef SQLITE_OMIT_WAL
// # define pagerUseWal(x) ((x)->pWal!=0)
// #else
// # define pagerUseWal(x) 0
// # define pagerRollbackWal(x) 0
// # define pagerWalFrames(v,w,x,y) 0
// # define pagerOpenWalIfPresent(z) SQLITE_OK
// # define pagerBeginReadTransaction(z) SQLITE_OK
// #endif

H
more  
Hongze Cheng 已提交
277
// #ifndef NDEBUG
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
// /*
// ** Usage:
// **
// **   assert( assert_pager_state(pPager) );
// **
// ** This function runs many asserts to try to find inconsistencies in
// ** the internal state of the Pager object.
// */
// static int assert_pager_state(Pager *p){
//   Pager *pPager = p;

//   /* State must be valid. */
//   assert( p->eState==PAGER_OPEN
//        || p->eState==PAGER_READER
//        || p->eState==PAGER_WRITER_LOCKED
//        || p->eState==PAGER_WRITER_CACHEMOD
//        || p->eState==PAGER_WRITER_DBMOD
//        || p->eState==PAGER_WRITER_FINISHED
//        || p->eState==PAGER_ERROR
//   );

//   /* Regardless of the current state, a temp-file connection always behaves
//   ** as if it has an exclusive lock on the database file. It never updates
//   ** the change-counter field, so the changeCountDone flag is always set.
//   */
//   assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
//   assert( p->tempFile==0 || pPager->changeCountDone );

H
more  
Hongze Cheng 已提交
306
//   /* If the useJournal flag is clear, the journal-mode must be "OFF".
307 308 309 310 311
//   ** And if the journal-mode is "OFF", the journal file must not be open.
//   */
//   assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
//   assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );

H
more  
Hongze Cheng 已提交
312 313 314 315 316 317
//   /* Check that MEMDB implies noSync. And an in-memory journal. Since
//   ** this means an in-memory pager performs no IO at all, it cannot encounter
//   ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
//   ** a journal file. (although the in-memory journal implementation may
//   ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
//   ** is therefore not possible for an in-memory pager to enter the ERROR
318 319 320 321 322
//   ** state.
//   */
//   if( MEMDB ){
//     assert( !isOpen(p->fd) );
//     assert( p->noSync );
H
more  
Hongze Cheng 已提交
323 324
//     assert( p->journalMode==PAGER_JOURNALMODE_OFF
//          || p->journalMode==PAGER_JOURNALMODE_MEMORY
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
//     );
//     assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
//     assert( pagerUseWal(p)==0 );
//   }

//   /* If changeCountDone is set, a RESERVED lock or greater must be held
//   ** on the file.
//   */
//   assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
//   assert( p->eLock!=PENDING_LOCK );

//   switch( p->eState ){
//     case PAGER_OPEN:
//       assert( !MEMDB );
//       assert( pPager->errCode==SQLITE_OK );
//       assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
//       break;

//     case PAGER_READER:
//       assert( pPager->errCode==SQLITE_OK );
//       assert( p->eLock!=UNKNOWN_LOCK );
//       assert( p->eLock>=SHARED_LOCK );
//       break;

//     case PAGER_WRITER_LOCKED:
//       assert( p->eLock!=UNKNOWN_LOCK );
//       assert( pPager->errCode==SQLITE_OK );
//       if( !pagerUseWal(pPager) ){
//         assert( p->eLock>=RESERVED_LOCK );
//       }
//       assert( pPager->dbSize==pPager->dbOrigSize );
//       assert( pPager->dbOrigSize==pPager->dbFileSize );
//       assert( pPager->dbOrigSize==pPager->dbHintSize );
//       assert( pPager->setSuper==0 );
//       break;

//     case PAGER_WRITER_CACHEMOD:
//       assert( p->eLock!=UNKNOWN_LOCK );
//       assert( pPager->errCode==SQLITE_OK );
//       if( !pagerUseWal(pPager) ){
//         /* It is possible that if journal_mode=wal here that neither the
//         ** journal file nor the WAL file are open. This happens during
//         ** a rollback transaction that switches from journal_mode=off
//         ** to journal_mode=wal.
//         */
//         assert( p->eLock>=RESERVED_LOCK );
H
more  
Hongze Cheng 已提交
371 372 373
//         assert( isOpen(p->jfd)
//              || p->journalMode==PAGER_JOURNALMODE_OFF
//              || p->journalMode==PAGER_JOURNALMODE_WAL
374 375 376 377 378 379 380 381 382 383 384
//         );
//       }
//       assert( pPager->dbOrigSize==pPager->dbFileSize );
//       assert( pPager->dbOrigSize==pPager->dbHintSize );
//       break;

//     case PAGER_WRITER_DBMOD:
//       assert( p->eLock==EXCLUSIVE_LOCK );
//       assert( pPager->errCode==SQLITE_OK );
//       assert( !pagerUseWal(pPager) );
//       assert( p->eLock>=EXCLUSIVE_LOCK );
H
more  
Hongze Cheng 已提交
385 386 387
//       assert( isOpen(p->jfd)
//            || p->journalMode==PAGER_JOURNALMODE_OFF
//            || p->journalMode==PAGER_JOURNALMODE_WAL
388 389 390 391 392 393 394 395 396
//            || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
//       );
//       assert( pPager->dbOrigSize<=pPager->dbHintSize );
//       break;

//     case PAGER_WRITER_FINISHED:
//       assert( p->eLock==EXCLUSIVE_LOCK );
//       assert( pPager->errCode==SQLITE_OK );
//       assert( !pagerUseWal(pPager) );
H
more  
Hongze Cheng 已提交
397 398 399
//       assert( isOpen(p->jfd)
//            || p->journalMode==PAGER_JOURNALMODE_OFF
//            || p->journalMode==PAGER_JOURNALMODE_WAL
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
//            || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
//       );
//       break;

//     case PAGER_ERROR:
//       /* There must be at least one outstanding reference to the pager if
//       ** in ERROR state. Otherwise the pager should have already dropped
//       ** back to OPEN state.
//       */
//       assert( pPager->errCode!=SQLITE_OK );
//       assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
//       break;
//   }

//   return 1;
// }
// #endif /* ifndef NDEBUG */

H
more  
Hongze Cheng 已提交
418
// #ifdef SQLITE_DEBUG
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
// /*
// ** Return a pointer to a human readable string in a static buffer
// ** containing the state of the Pager object passed as an argument. This
// ** is intended to be used within debuggers. For example, as an alternative
// ** to "print *pPager" in gdb:
// **
// ** (gdb) printf "%s", print_pager_state(pPager)
// **
// ** This routine has external linkage in order to suppress compiler warnings
// ** about an unused function.  It is enclosed within SQLITE_DEBUG and so does
// ** not appear in normal builds.
// */
// char *print_pager_state(Pager *p){
//   static char zRet[1024];

//   sqlite3_snprintf(1024, zRet,
//       "Filename:      %s\n"
//       "State:         %s errCode=%d\n"
//       "Lock:          %s\n"
//       "Locking mode:  locking_mode=%s\n"
//       "Journal mode:  journal_mode=%s\n"
//       "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
//       "Journal:       journalOff=%lld journalHdr=%lld\n"
//       "Size:          dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
//       , p->zFilename
//       , p->eState==PAGER_OPEN            ? "OPEN" :
//         p->eState==PAGER_READER          ? "READER" :
//         p->eState==PAGER_WRITER_LOCKED   ? "WRITER_LOCKED" :
//         p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
//         p->eState==PAGER_WRITER_DBMOD    ? "WRITER_DBMOD" :
//         p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
//         p->eState==PAGER_ERROR           ? "ERROR" : "?error?"
//       , (int)p->errCode
//       , p->eLock==NO_LOCK         ? "NO_LOCK" :
//         p->eLock==RESERVED_LOCK   ? "RESERVED" :
//         p->eLock==EXCLUSIVE_LOCK  ? "EXCLUSIVE" :
//         p->eLock==SHARED_LOCK     ? "SHARED" :
//         p->eLock==UNKNOWN_LOCK    ? "UNKNOWN" : "?error?"
//       , p->exclusiveMode ? "exclusive" : "normal"
//       , p->journalMode==PAGER_JOURNALMODE_MEMORY   ? "memory" :
//         p->journalMode==PAGER_JOURNALMODE_OFF      ? "off" :
//         p->journalMode==PAGER_JOURNALMODE_DELETE   ? "delete" :
//         p->journalMode==PAGER_JOURNALMODE_PERSIST  ? "persist" :
//         p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
//         p->journalMode==PAGER_JOURNALMODE_WAL      ? "wal" : "?error?"
//       , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
//       , p->journalOff, p->journalHdr
//       , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
//   );

//   return zRet;
// }
// #endif

// /* Forward references to the various page getters */
// static int getPageNormal(Pager*,Pgno,DbPage**,int);
// static int getPageError(Pager*,Pgno,DbPage**,int);
// #if SQLITE_MAX_MMAP_SIZE>0
// static int getPageMMap(Pager*,Pgno,DbPage**,int);
// #endif

// /*
// ** Set the Pager.xGet method for the appropriate routine used to fetch
// ** content from the pager.
// */
// static void setGetterMethod(Pager *pPager){
//   if( pPager->errCode ){
//     pPager->xGet = getPageError;
// #if SQLITE_MAX_MMAP_SIZE>0
//   }else if( USEFETCH(pPager) ){
//     pPager->xGet = getPageMMap;
// #endif /* SQLITE_MAX_MMAP_SIZE>0 */
//   }else{
//     pPager->xGet = getPageNormal;
//   }
// }

// /*
// ** Return true if it is necessary to write page *pPg into the sub-journal.
// ** A page needs to be written into the sub-journal if there exists one
// ** or more open savepoints for which:
// **
// **   * The page-number is less than or equal to PagerSavepoint.nOrig, and
// **   * The bit corresponding to the page-number is not set in
// **     PagerSavepoint.pInSavepoint.
// */
// static int subjRequiresPage(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   PagerSavepoint *p;
//   Pgno pgno = pPg->pgno;
//   int i;
//   for(i=0; i<pPager->nSavepoint; i++){
//     p = &pPager->aSavepoint[i];
//     if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
//       for(i=i+1; i<pPager->nSavepoint; i++){
//         pPager->aSavepoint[i].bTruncateOnRelease = 0;
//       }
//       return 1;
//     }
//   }
//   return 0;
// }

// #ifdef SQLITE_DEBUG
// /*
// ** Return true if the page is already in the journal file.
// */
// static int pageInJournal(Pager *pPager, PgHdr *pPg){
//   return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
// }
// #endif

// /*
// ** Read a 32-bit integer from the given file descriptor.  Store the integer
// ** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
// ** error code is something goes wrong.
// **
// ** All values are stored on disk as big-endian.
// */
// static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
//   unsigned char ac[4];
//   int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
//   if( rc==SQLITE_OK ){
//     *pRes = sqlite3Get4byte(ac);
//   }
//   return rc;
// }

// /*
// ** Write a 32-bit integer into a string buffer in big-endian byte order.
// */
// #define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)

// /*
// ** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK
// ** on success or an error code is something goes wrong.
// */
// static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
//   char ac[4];
//   put32bits(ac, val);
//   return sqlite3OsWrite(fd, ac, 4, offset);
// }

// /*
// ** Unlock the database file to level eLock, which must be either NO_LOCK
// ** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
// ** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
// **
// ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
H
more  
Hongze Cheng 已提交
568
// ** called, do not modify it. See the comment above the #define of
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
// ** UNKNOWN_LOCK for an explanation of this.
// */
// static int pagerUnlockDb(Pager *pPager, int eLock){
//   int rc = SQLITE_OK;

//   assert( !pPager->exclusiveMode || pPager->eLock==eLock );
//   assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
//   assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
//   if( isOpen(pPager->fd) ){
//     assert( pPager->eLock>=eLock );
//     rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
//     if( pPager->eLock!=UNKNOWN_LOCK ){
//       pPager->eLock = (u8)eLock;
//     }
//     IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
//   }
//   pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
//   return rc;
// }

// /*
// ** Lock the database file to level eLock, which must be either SHARED_LOCK,
// ** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
H
more  
Hongze Cheng 已提交
592
// ** Pager.eLock variable to the new locking state.
593
// **
H
more  
Hongze Cheng 已提交
594 595 596
// ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
// ** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
// ** See the comment above the #define of UNKNOWN_LOCK for an explanation
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
// ** of this.
// */
// static int pagerLockDb(Pager *pPager, int eLock){
//   int rc = SQLITE_OK;

//   assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
//   if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
//     rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
//     if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
//       pPager->eLock = (u8)eLock;
//       IOTRACE(("LOCK %p %d\n", pPager, eLock))
//     }
//   }
//   return rc;
// }

// /*
// ** This function determines whether or not the atomic-write or
// ** atomic-batch-write optimizations can be used with this pager. The
// ** atomic-write optimization can be used if:
// **
// **  (a) the value returned by OsDeviceCharacteristics() indicates that
// **      a database page may be written atomically, and
// **  (b) the value returned by OsSectorSize() is less than or equal
// **      to the page size.
// **
H
more  
Hongze Cheng 已提交
623
// ** If it can be used, then the value returned is the size of the journal
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
// ** file when it contains rollback data for exactly one page.
// **
// ** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
// ** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
// ** returned in this case.
// **
// ** If neither optimization can be used, 0 is returned.
// */
// static int jrnlBufferSize(Pager *pPager){
//   assert( !MEMDB );

// #if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
//  || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
//   int dc;                           /* Device characteristics */

//   assert( isOpen(pPager->fd) );
//   dc = sqlite3OsDeviceCharacteristics(pPager->fd);
// #else
//   UNUSED_PARAMETER(pPager);
// #endif

// #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
//   if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){
//     return -1;
//   }
// #endif

// #ifdef SQLITE_ENABLE_ATOMIC_WRITE
//   {
//     int nSector = pPager->sectorSize;
//     int szPage = pPager->pageSize;

//     assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
//     assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
//     if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
//       return 0;
//     }
//   }

//   return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
// #endif

//   return 0;
// }

// /*
// ** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
// ** on the cache using a hash function.  This is used for testing
// ** and debugging only.
// */
// #ifdef SQLITE_CHECK_PAGES
// /*
// ** Return a 32-bit hash of the page data for pPage.
// */
// static u32 pager_datahash(int nByte, unsigned char *pData){
//   u32 hash = 0;
//   int i;
//   for(i=0; i<nByte; i++){
//     hash = (hash*1039) + pData[i];
//   }
//   return hash;
// }
// static u32 pager_pagehash(PgHdr *pPage){
//   return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
// }
// static void pager_set_pagehash(PgHdr *pPage){
//   pPage->pageHash = pager_pagehash(pPage);
// }

// /*
// ** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
// ** is defined, and NDEBUG is not defined, an assert() statement checks
// ** that the page is either dirty or still matches the calculated page-hash.
// */
// #define CHECK_PAGE(x) checkPage(x)
// static void checkPage(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   assert( pPager->eState!=PAGER_ERROR );
//   assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
// }

// #else
// #define pager_datahash(X,Y)  0
// #define pager_pagehash(X)  0
// #define pager_set_pagehash(X)
// #define CHECK_PAGE(x)
// #endif  /* SQLITE_CHECK_PAGES */

// /*
// ** When this is called the journal file for pager pPager must be open.
H
more  
Hongze Cheng 已提交
714 715
// ** This function attempts to read a super-journal file name from the
// ** end of the file and, if successful, copies it into memory supplied
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
// ** by the caller. See comments above writeSuperJournal() for the format
// ** used to store a super-journal file name at the end of a journal file.
// **
// ** zSuper must point to a buffer of at least nSuper bytes allocated by
// ** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
// ** enough space to write the super-journal name). If the super-journal
// ** name in the journal is longer than nSuper bytes (including a
// ** nul-terminator), then this is handled as if no super-journal name
// ** were present in the journal.
// **
// ** If a super-journal file name is present at the end of the journal
// ** file, then it is copied into the buffer pointed to by zSuper. A
// ** nul-terminator byte is appended to the buffer following the
// ** super-journal file name.
// **
H
more  
Hongze Cheng 已提交
731
// ** If it is determined that no super-journal file name is present
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
// ** zSuper[0] is set to 0 and SQLITE_OK returned.
// **
// ** If an error occurs while reading from the journal file, an SQLite
// ** error code is returned.
// */
// static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
//   int rc;                    /* Return code */
//   u32 len;                   /* Length in bytes of super-journal name */
//   i64 szJ;                   /* Total size in bytes of journal file pJrnl */
//   u32 cksum;                 /* MJ checksum value read from journal */
//   u32 u;                     /* Unsigned loop counter */
//   unsigned char aMagic[8];   /* A buffer to hold the magic header */
//   zSuper[0] = '\0';

//   if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
//    || szJ<16
//    || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
H
more  
Hongze Cheng 已提交
749
//    || len>=nSuper
750
//    || len>szJ-16
H
more  
Hongze Cheng 已提交
751
//    || len==0
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
//    || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
//    || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
//    || memcmp(aMagic, aJournalMagic, 8)
//    || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
//   ){
//     return rc;
//   }

//   /* See if the checksum matches the super-journal name */
//   for(u=0; u<len; u++){
//     cksum -= zSuper[u];
//   }
//   if( cksum ){
//     /* If the checksum doesn't add up, then one or more of the disk sectors
//     ** containing the super-journal filename is corrupted. This means
//     ** definitely roll back, so just return SQLITE_OK and report a (nul)
//     ** super-journal filename.
//     */
//     len = 0;
//   }
//   zSuper[len] = '\0';
//   zSuper[len+1] = '\0';
H
more  
Hongze Cheng 已提交
774

775 776 777 778
//   return SQLITE_OK;
// }

// /*
H
more  
Hongze Cheng 已提交
779 780
// ** Return the offset of the sector boundary at or immediately
// ** following the value in pPager->journalOff, assuming a sector
781 782 783 784 785 786 787 788 789 790
// ** size of pPager->sectorSize bytes.
// **
// ** i.e for a sector size of 512:
// **
// **   Pager.journalOff          Return value
// **   ---------------------------------------
// **   0                         0
// **   512                       512
// **   100                       512
// **   2000                      2048
H
more  
Hongze Cheng 已提交
791
// **
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
// */
// static i64 journalHdrOffset(Pager *pPager){
//   i64 offset = 0;
//   i64 c = pPager->journalOff;
//   if( c ){
//     offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
//   }
//   assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
//   assert( offset>=c );
//   assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
//   return offset;
// }

// /*
// ** The journal file must be open when this function is called.
// **
// ** This function is a no-op if the journal file has not been written to
// ** within the current transaction (i.e. if Pager.journalOff==0).
// **
// ** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
// ** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
H
more  
Hongze Cheng 已提交
813 814
// ** zero the 28-byte header at the start of the journal file. In either case,
// ** if the pager is not in no-sync mode, sync the journal file immediately
815 816 817
// ** after writing or truncating it.
// **
// ** If Pager.journalSizeLimit is set to a positive, non-zero value, and
H
more  
Hongze Cheng 已提交
818
// ** following the truncation or zeroing described above the size of the
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
// ** journal file in bytes is larger than this value, then truncate the
// ** journal file to Pager.journalSizeLimit bytes. The journal file does
// ** not need to be synced following this operation.
// **
// ** If an IO error occurs, abandon processing and return the IO error code.
// ** Otherwise, return SQLITE_OK.
// */
// static int zeroJournalHdr(Pager *pPager, int doTruncate){
//   int rc = SQLITE_OK;                               /* Return code */
//   assert( isOpen(pPager->jfd) );
//   assert( !sqlite3JournalIsInMemory(pPager->jfd) );
//   if( pPager->journalOff ){
//     const i64 iLimit = pPager->journalSizeLimit;    /* Local cache of jsl */

//     IOTRACE(("JZEROHDR %p\n", pPager))
//     if( doTruncate || iLimit==0 ){
//       rc = sqlite3OsTruncate(pPager->jfd, 0);
//     }else{
//       static const char zeroHdr[28] = {0};
//       rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
//     }
//     if( rc==SQLITE_OK && !pPager->noSync ){
//       rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
//     }

H
more  
Hongze Cheng 已提交
844 845
//     /* At this point the transaction is committed but the write lock
//     ** is still held on the file. If there is a size limit configured for
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
//     ** the persistent journal and the journal file currently consumes more
//     ** space than that limit allows for, truncate it now. There is no need
//     ** to sync the file following this operation.
//     */
//     if( rc==SQLITE_OK && iLimit>0 ){
//       i64 sz;
//       rc = sqlite3OsFileSize(pPager->jfd, &sz);
//       if( rc==SQLITE_OK && sz>iLimit ){
//         rc = sqlite3OsTruncate(pPager->jfd, iLimit);
//       }
//     }
//   }
//   return rc;
// }

// /*
// ** The journal file must be open when this routine is called. A journal
// ** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
// ** current location.
// **
// ** The format for the journal header is as follows:
// ** - 8 bytes: Magic identifying journal format.
// ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
// ** - 4 bytes: Random number used for page hash.
// ** - 4 bytes: Initial database page count.
// ** - 4 bytes: Sector size used by the process that wrote this journal.
// ** - 4 bytes: Database page size.
H
more  
Hongze Cheng 已提交
873
// **
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
// ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
// */
// static int writeJournalHdr(Pager *pPager){
//   int rc = SQLITE_OK;                 /* Return code */
//   char *zHeader = pPager->pTmpSpace;  /* Temporary space used to build header */
//   u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
//   u32 nWrite;                         /* Bytes of header sector written */
//   int ii;                             /* Loop counter */

//   assert( isOpen(pPager->jfd) );      /* Journal file must be open. */

//   if( nHeader>JOURNAL_HDR_SZ(pPager) ){
//     nHeader = JOURNAL_HDR_SZ(pPager);
//   }

H
more  
Hongze Cheng 已提交
889 890
//   /* If there are active savepoints and any of them were created
//   ** since the most recent journal header was written, update the
891 892 893 894 895 896 897 898 899 900
//   ** PagerSavepoint.iHdrOffset fields now.
//   */
//   for(ii=0; ii<pPager->nSavepoint; ii++){
//     if( pPager->aSavepoint[ii].iHdrOffset==0 ){
//       pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
//     }
//   }

//   pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);

H
more  
Hongze Cheng 已提交
901
//   /*
902 903
//   ** Write the nRec Field - the number of page records that follow this
//   ** journal header. Normally, zero is written to this value at this time.
H
more  
Hongze Cheng 已提交
904
//   ** After the records are added to the journal (and the journal synced,
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
//   ** if in full-sync mode), the zero is overwritten with the true number
//   ** of records (see syncJournal()).
//   **
//   ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
//   ** reading the journal this value tells SQLite to assume that the
//   ** rest of the journal file contains valid page records. This assumption
//   ** is dangerous, as if a failure occurred whilst writing to the journal
//   ** file it may contain some garbage data. There are two scenarios
//   ** where this risk can be ignored:
//   **
//   **   * When the pager is in no-sync mode. Corruption can follow a
//   **     power failure in this case anyway.
//   **
//   **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
//   **     that garbage data is never appended to the journal file.
//   */
//   assert( isOpen(pPager->fd) || pPager->noSync );
//   if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
H
more  
Hongze Cheng 已提交
923
//    || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
924 925 926 927 928 929 930
//   ){
//     memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
//     put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
//   }else{
//     memset(zHeader, 0, sizeof(aJournalMagic)+4);
//   }

H
more  
Hongze Cheng 已提交
931
//   /* The random check-hash initializer */
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
//   sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
//   put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
//   /* The initial database size */
//   put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
//   /* The assumed sector size for this process */
//   put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);

//   /* The page size */
//   put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);

//   /* Initializing the tail of the buffer is not necessary.  Everything
//   ** works find if the following memset() is omitted.  But initializing
//   ** the memory prevents valgrind from complaining, so we are willing to
//   ** take the performance hit.
//   */
//   memset(&zHeader[sizeof(aJournalMagic)+20], 0,
//          nHeader-(sizeof(aJournalMagic)+20));

H
more  
Hongze Cheng 已提交
950 951 952
//   /* In theory, it is only necessary to write the 28 bytes that the
//   ** journal header consumes to the journal file here. Then increment the
//   ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
953 954 955
//   ** record is written to the following sector (leaving a gap in the file
//   ** that will be implicitly filled in by the OS).
//   **
H
more  
Hongze Cheng 已提交
956
//   ** However it has been discovered that on some systems this pattern can
957
//   ** be significantly slower than contiguously writing data to the file,
H
more  
Hongze Cheng 已提交
958
//   ** even if that means explicitly writing data to the block of
959
//   ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
H
more  
Hongze Cheng 已提交
960
//   ** is done.
961
//   **
H
more  
Hongze Cheng 已提交
962
//   ** The loop is required here in case the sector-size is larger than the
963 964 965
//   ** database page size. Since the zHeader buffer is only Pager.pageSize
//   ** bytes in size, more than one call to sqlite3OsWrite() may be required
//   ** to populate the entire journal header sector.
H
more  
Hongze Cheng 已提交
966
//   */
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
//   for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
//     IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
//     rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
//     assert( pPager->journalHdr <= pPager->journalOff );
//     pPager->journalOff += nHeader;
//   }

//   return rc;
// }

// /*
// ** The journal file must be open when this is called. A journal header file
// ** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
// ** file. The current location in the journal file is given by
// ** pPager->journalOff. See comments above function writeJournalHdr() for
// ** a description of the journal header format.
// **
// ** If the header is read successfully, *pNRec is set to the number of
// ** page records following this header and *pDbSize is set to the size of the
// ** database before the transaction began, in pages. Also, pPager->cksumInit
// ** is set to the value read from the journal header. SQLITE_OK is returned
// ** in this case.
// **
// ** If the journal header file appears to be corrupted, SQLITE_DONE is
// ** returned and *pNRec and *PDbSize are undefined.  If JOURNAL_HDR_SZ bytes
// ** cannot be read from the journal file an error code is returned.
// */
// static int readJournalHdr(
//   Pager *pPager,               /* Pager object */
//   int isHot,
//   i64 journalSize,             /* Size of the open journal file in bytes */
//   u32 *pNRec,                  /* OUT: Value read from the nRec field */
//   u32 *pDbSize                 /* OUT: Value of original database size field */
// ){
//   int rc;                      /* Return code */
//   unsigned char aMagic[8];     /* A buffer to hold the magic header */
//   i64 iHdrOff;                 /* Offset of journal header being read */

//   assert( isOpen(pPager->jfd) );      /* Journal file must be open. */

//   /* Advance Pager.journalOff to the start of the next sector. If the
//   ** journal file is too small for there to be a header stored at this
//   ** point, return SQLITE_DONE.
//   */
//   pPager->journalOff = journalHdrOffset(pPager);
//   if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
//     return SQLITE_DONE;
//   }
//   iHdrOff = pPager->journalOff;

//   /* Read in the first 8 bytes of the journal header. If they do not match
//   ** the  magic string found at the start of each journal header, return
//   ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
//   ** proceed.
//   */
//   if( isHot || iHdrOff!=pPager->journalHdr ){
//     rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
//     if( rc ){
//       return rc;
//     }
//     if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
//       return SQLITE_DONE;
//     }
//   }

//   /* Read the first three 32-bit fields of the journal header: The nRec
//   ** field, the checksum-initializer and the database size at the start
//   ** of the transaction. Return an error code if anything goes wrong.
//   */
//   if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
//    || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
//    || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
//   ){
//     return rc;
//   }

//   if( pPager->journalOff==0 ){
//     u32 iPageSize;               /* Page-size field of journal header */
//     u32 iSectorSize;             /* Sector-size field of journal header */

//     /* Read the page-size and sector-size journal header fields. */
//     if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
//      || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
//     ){
//       return rc;
//     }

//     /* Versions of SQLite prior to 3.5.8 set the page-size field of the
//     ** journal header to zero. In this case, assume that the Pager.pageSize
//     ** variable is already set to the correct page size.
//     */
//     if( iPageSize==0 ){
//       iPageSize = pPager->pageSize;
//     }

//     /* Check that the values read from the page-size and sector-size fields
//     ** are within range. To be 'in range', both values need to be a power
H
more  
Hongze Cheng 已提交
1064
//     ** of two greater than or equal to 512 or 32, and not greater than their
1065 1066 1067 1068
//     ** respective compile time maximum limits.
//     */
//     if( iPageSize<512                  || iSectorSize<32
//      || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
H
more  
Hongze Cheng 已提交
1069
//      || ((iPageSize-1)&iPageSize)!=0   || ((iSectorSize-1)&iSectorSize)!=0
1070
//     ){
H
more  
Hongze Cheng 已提交
1071 1072 1073
//       /* If the either the page-size or sector-size in the journal-header is
//       ** invalid, then the process that wrote the journal-header must have
//       ** crashed before the header was synced. In this case stop reading
1074 1075 1076 1077 1078
//       ** the journal file here.
//       */
//       return SQLITE_DONE;
//     }

H
more  
Hongze Cheng 已提交
1079 1080
//     /* Update the page-size to match the value read from the journal.
//     ** Use a testcase() macro to make sure that malloc failure within
1081 1082 1083 1084 1085
//     ** PagerSetPagesize() is tested.
//     */
//     rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
//     testcase( rc!=SQLITE_OK );

H
more  
Hongze Cheng 已提交
1086
//     /* Update the assumed sector-size to match the value used by
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
//     ** the process that created this journal. If this journal was
//     ** created by a process other than this one, then this routine
//     ** is being called from within pager_playback(). The local value
//     ** of Pager.sectorSize is restored at the end of that routine.
//     */
//     pPager->sectorSize = iSectorSize;
//   }

//   pPager->journalOff += JOURNAL_HDR_SZ(pPager);
//   return rc;
// }

// /*
// ** Write the supplied super-journal name into the journal file for pager
// ** pPager at the current location. The super-journal name must be the last
// ** thing written to a journal file. If the pager is in full-sync mode, the
// ** journal file descriptor is advanced to the next sector boundary before
// ** anything is written. The format is:
// **
// **   + 4 bytes: PAGER_MJ_PGNO.
// **   + N bytes: super-journal filename in utf-8.
// **   + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
// **   + 4 bytes: super-journal name checksum.
// **   + 8 bytes: aJournalMagic[].
// **
// ** The super-journal page checksum is the sum of the bytes in thesuper-journal
// ** name, where each byte is interpreted as a signed 8-bit integer.
// **
H
more  
Hongze Cheng 已提交
1115
// ** If zSuper is a NULL pointer (occurs for a single database transaction),
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
// ** this call is a no-op.
// */
// static int writeSuperJournal(Pager *pPager, const char *zSuper){
//   int rc;                          /* Return code */
//   int nSuper;                      /* Length of string zSuper */
//   i64 iHdrOff;                     /* Offset of header in journal file */
//   i64 jrnlSize;                    /* Size of journal file on disk */
//   u32 cksum = 0;                   /* Checksum of string zSuper */

//   assert( pPager->setSuper==0 );
//   assert( !pagerUseWal(pPager) );

H
more  
Hongze Cheng 已提交
1128 1129
//   if( !zSuper
//    || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
//    || !isOpen(pPager->jfd)
//   ){
//     return SQLITE_OK;
//   }
//   pPager->setSuper = 1;
//   assert( pPager->journalHdr <= pPager->journalOff );

//   /* Calculate the length in bytes and the checksum of zSuper */
//   for(nSuper=0; zSuper[nSuper]; nSuper++){
//     cksum += zSuper[nSuper];
//   }

//   /* If in full-sync mode, advance to the next disk sector before writing
//   ** the super-journal name. This is in case the previous page written to
//   ** the journal has already been synced.
//   */
//   if( pPager->fullSync ){
//     pPager->journalOff = journalHdrOffset(pPager);
//   }
//   iHdrOff = pPager->journalOff;

//   /* Write the super-journal data to the end of the journal file. If
//   ** an error occurs, return the error code to the caller.
//   */
//   if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
//    || (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
//    || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
//    || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
//    || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
//                                  iHdrOff+4+nSuper+8)))
//   ){
//     return rc;
//   }
//   pPager->journalOff += (nSuper+20);

H
more  
Hongze Cheng 已提交
1165
//   /* If the pager is in peristent-journal mode, then the physical
1166
//   ** journal-file may extend past the end of the super-journal name
H
more  
Hongze Cheng 已提交
1167
//   ** and 8 bytes of magic data just written to the file. This is
1168
//   ** dangerous because the code to rollback a hot-journal file
H
more  
Hongze Cheng 已提交
1169 1170
//   ** will not be able to find the super-journal name to determine
//   ** whether or not the journal is hot.
1171
//   **
H
more  
Hongze Cheng 已提交
1172
//   ** Easiest thing to do in this scenario is to truncate the journal
1173
//   ** file to the required size.
H
more  
Hongze Cheng 已提交
1174
//   */
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
//   if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
//    && jrnlSize>pPager->journalOff
//   ){
//     rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
//   }
//   return rc;
// }

// /*
// ** Discard the entire contents of the in-memory page-cache.
// */
// static void pager_reset(Pager *pPager){
//   pPager->iDataVersion++;
//   sqlite3BackupRestart(pPager->pBackup);
//   sqlite3PcacheClear(pPager->pPCache);
// }

// /*
// ** Return the pPager->iDataVersion value
// */
// u32 sqlite3PagerDataVersion(Pager *pPager){
//   return pPager->iDataVersion;
// }

// /*
// ** Free all structures in the Pager.aSavepoint[] array and set both
// ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
// ** if it is open and the pager is not in exclusive mode.
// */
// static void releaseAllSavepoints(Pager *pPager){
//   int ii;               /* Iterator for looping through Pager.aSavepoint */
//   for(ii=0; ii<pPager->nSavepoint; ii++){
//     sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
//   }
//   if( !pPager->exclusiveMode || sqlite3JournalIsInMemory(pPager->sjfd) ){
//     sqlite3OsClose(pPager->sjfd);
//   }
//   sqlite3_free(pPager->aSavepoint);
//   pPager->aSavepoint = 0;
//   pPager->nSavepoint = 0;
//   pPager->nSubRec = 0;
// }

// /*
H
more  
Hongze Cheng 已提交
1219
// ** Set the bit number pgno in the PagerSavepoint.pInSavepoint
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
// ** bitvecs of all open savepoints. Return SQLITE_OK if successful
// ** or SQLITE_NOMEM if a malloc failure occurs.
// */
// static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
//   int ii;                   /* Loop counter */
//   int rc = SQLITE_OK;       /* Result code */

//   for(ii=0; ii<pPager->nSavepoint; ii++){
//     PagerSavepoint *p = &pPager->aSavepoint[ii];
//     if( pgno<=p->nOrig ){
//       rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
//       testcase( rc==SQLITE_NOMEM );
//       assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
//     }
//   }
//   return rc;
// }

// /*
// ** This function is a no-op if the pager is in exclusive mode and not
// ** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
// ** state.
// **
// ** If the pager is not in exclusive-access mode, the database file is
// ** completely unlocked. If the file is unlocked and the file-system does
// ** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
// ** closed (if it is open).
// **
H
more  
Hongze Cheng 已提交
1248 1249
// ** If the pager is in ERROR state when this function is called, the
// ** contents of the pager cache are discarded before switching back to
1250 1251 1252 1253 1254 1255 1256
// ** the OPEN state. Regardless of whether the pager is in exclusive-mode
// ** or not, any journal file left in the file-system will be treated
// ** as a hot-journal and rolled back the next time a read-transaction
// ** is opened (by this or by any other connection).
// */
// static void pager_unlock(Pager *pPager){

H
more  
Hongze Cheng 已提交
1257 1258 1259
//   assert( pPager->eState==PAGER_READER
//        || pPager->eState==PAGER_OPEN
//        || pPager->eState==PAGER_ERROR
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
//   );

//   sqlite3BitvecDestroy(pPager->pInJournal);
//   pPager->pInJournal = 0;
//   releaseAllSavepoints(pPager);

//   if( pagerUseWal(pPager) ){
//     assert( !isOpen(pPager->jfd) );
//     sqlite3WalEndReadTransaction(pPager->pWal);
//     pPager->eState = PAGER_OPEN;
//   }else if( !pPager->exclusiveMode ){
//     int rc;                       /* Error code returned by pagerUnlockDb() */
//     int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;

//     /* If the operating system support deletion of open files, then
//     ** close the journal file when dropping the database lock.  Otherwise
//     ** another connection with journal_mode=delete might delete the file
//     ** out from under us.
//     */
//     assert( (PAGER_JOURNALMODE_MEMORY   & 5)!=1 );
//     assert( (PAGER_JOURNALMODE_OFF      & 5)!=1 );
//     assert( (PAGER_JOURNALMODE_WAL      & 5)!=1 );
//     assert( (PAGER_JOURNALMODE_DELETE   & 5)!=1 );
//     assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
//     assert( (PAGER_JOURNALMODE_PERSIST  & 5)==1 );
//     if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
//      || 1!=(pPager->journalMode & 5)
//     ){
//       sqlite3OsClose(pPager->jfd);
//     }

//     /* If the pager is in the ERROR state and the call to unlock the database
//     ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
//     ** above the #define for UNKNOWN_LOCK for an explanation of why this
//     ** is necessary.
//     */
//     rc = pagerUnlockDb(pPager, NO_LOCK);
//     if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
//       pPager->eLock = UNKNOWN_LOCK;
//     }

//     /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
//     ** without clearing the error code. This is intentional - the error
//     ** code is cleared and the cache reset in the block below.
//     */
//     assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
//     pPager->eState = PAGER_OPEN;
//   }

//   /* If Pager.errCode is set, the contents of the pager cache cannot be
//   ** trusted. Now that there are no outstanding references to the pager,
//   ** it can safely move back to PAGER_OPEN state. This happens in both
//   ** normal and exclusive-locking mode.
//   */
//   assert( pPager->errCode==SQLITE_OK || !MEMDB );
//   if( pPager->errCode ){
//     if( pPager->tempFile==0 ){
//       pager_reset(pPager);
//       pPager->changeCountDone = 0;
//       pPager->eState = PAGER_OPEN;
//     }else{
//       pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
//     }
//     if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
//     pPager->errCode = SQLITE_OK;
//     setGetterMethod(pPager);
//   }

//   pPager->journalOff = 0;
//   pPager->journalHdr = 0;
//   pPager->setSuper = 0;
// }

// /*
// ** This function is called whenever an IOERR or FULL error that requires
// ** the pager to transition into the ERROR state may ahve occurred.
H
more  
Hongze Cheng 已提交
1336 1337 1338
// ** The first argument is a pointer to the pager structure, the second
// ** the error-code about to be returned by a pager API function. The
// ** value returned is a copy of the second argument to this function.
1339 1340 1341 1342 1343 1344
// **
// ** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
// ** IOERR sub-codes, the pager enters the ERROR state and the error code
// ** is stored in Pager.errCode. While the pager remains in the ERROR state,
// ** all major API calls on the Pager will immediately return Pager.errCode.
// **
H
more  
Hongze Cheng 已提交
1345 1346
// ** The ERROR state indicates that the contents of the pager-cache
// ** cannot be trusted. This state can be cleared by completely discarding
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
// ** the contents of the pager-cache. If a transaction was active when
// ** the persistent error occurred, then the rollback journal may need
// ** to be replayed to restore the contents of the database file (as if
// ** it were a hot-journal).
// */
// static int pager_error(Pager *pPager, int rc){
//   int rc2 = rc & 0xff;
//   assert( rc==SQLITE_OK || !MEMDB );
//   assert(
//        pPager->errCode==SQLITE_FULL ||
//        pPager->errCode==SQLITE_OK ||
//        (pPager->errCode & 0xff)==SQLITE_IOERR
//   );
//   if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
//     pPager->errCode = rc;
//     pPager->eState = PAGER_ERROR;
//     setGetterMethod(pPager);
//   }
//   return rc;
// }

// static int pager_truncate(Pager *pPager, Pgno nPage);

// /*
// ** The write transaction open on pPager is being committed (bCommit==1)
// ** or rolled back (bCommit==0).
// **
// ** Return TRUE if and only if all dirty pages should be flushed to disk.
// **
// ** Rules:
// **
// **   *  For non-TEMP databases, always sync to disk.  This is necessary
// **      for transactions to be durable.
// **
// **   *  Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing
// **      file has been created already (via a spill on pagerStress()) and
// **      when the number of dirty pages in memory exceeds 25% of the total
// **      cache size.
// */
// static int pagerFlushOnCommit(Pager *pPager, int bCommit){
//   if( pPager->tempFile==0 ) return 1;
//   if( !bCommit ) return 0;
//   if( !isOpen(pPager->fd) ) return 0;
//   return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
// }

// /*
H
more  
Hongze Cheng 已提交
1394 1395
// ** This routine ends a transaction. A transaction is usually ended by
// ** either a COMMIT or a ROLLBACK operation. This routine may be called
1396 1397 1398
// ** after rollback of a hot-journal, or if an error occurs while opening
// ** the journal file or writing the very first journal-header of a
// ** database transaction.
H
more  
Hongze Cheng 已提交
1399
// **
1400 1401 1402 1403 1404 1405
// ** This routine is never called in PAGER_ERROR state. If it is called
// ** in PAGER_NONE or PAGER_SHARED state and the lock held is less
// ** exclusive than a RESERVED lock, it is a no-op.
// **
// ** Otherwise, any active savepoints are released.
// **
H
more  
Hongze Cheng 已提交
1406 1407
// ** If the journal file is open, then it is "finalized". Once a journal
// ** file has been finalized it is not possible to use it to roll back a
1408 1409 1410 1411 1412 1413
// ** transaction. Nor will it be considered to be a hot-journal by this
// ** or any other database connection. Exactly how a journal is finalized
// ** depends on whether or not the pager is running in exclusive mode and
// ** the current journal-mode (Pager.journalMode value), as follows:
// **
// **   journalMode==MEMORY
H
more  
Hongze Cheng 已提交
1414
// **     Journal file descriptor is simply closed. This destroys an
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433
// **     in-memory journal.
// **
// **   journalMode==TRUNCATE
// **     Journal file is truncated to zero bytes in size.
// **
// **   journalMode==PERSIST
// **     The first 28 bytes of the journal file are zeroed. This invalidates
// **     the first journal header in the file, and hence the entire journal
// **     file. An invalid journal file cannot be rolled back.
// **
// **   journalMode==DELETE
// **     The journal file is closed and deleted using sqlite3OsDelete().
// **
// **     If the pager is running in exclusive mode, this method of finalizing
// **     the journal file is never used. Instead, if the journalMode is
// **     DELETE and the pager is in exclusive mode, the method described under
// **     journalMode==PERSIST is used instead.
// **
// ** After the journal is finalized, the pager moves to PAGER_READER state.
H
more  
Hongze Cheng 已提交
1434
// ** If running in non-exclusive rollback mode, the lock on the file is
1435 1436 1437 1438
// ** downgraded to a SHARED_LOCK.
// **
// ** SQLITE_OK is returned if no error occurs. If an error occurs during
// ** any of the IO operations to finalize the journal file or unlock the
H
more  
Hongze Cheng 已提交
1439
// ** database then the IO error code is returned to the user. If the
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
// ** operation to finalize the journal file fails, then the code still
// ** tries to unlock the database file if not in exclusive mode. If the
// ** unlock operation fails as well, then the first error code related
// ** to the first error encountered (the journal finalization one) is
// ** returned.
// */
// static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
//   int rc = SQLITE_OK;      /* Error code from journal finalization operation */
//   int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */

//   /* Do nothing if the pager does not have an open write transaction
//   ** or at least a RESERVED lock. This function may be called when there
//   ** is no write-transaction active but a RESERVED or greater lock is
//   ** held under two circumstances:
//   **
//   **   1. After a successful hot-journal rollback, it is called with
//   **      eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
//   **
H
more  
Hongze Cheng 已提交
1458
//   **   2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
1459
//   **      lock switches back to locking_mode=normal and then executes a
H
more  
Hongze Cheng 已提交
1460
//   **      read-transaction, this function is called with eState==PAGER_READER
1461 1462 1463 1464 1465 1466 1467 1468 1469
//   **      and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
//   */
//   assert( assert_pager_state(pPager) );
//   assert( pPager->eState!=PAGER_ERROR );
//   if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
//     return SQLITE_OK;
//   }

//   releaseAllSavepoints(pPager);
H
more  
Hongze Cheng 已提交
1470
//   assert( isOpen(pPager->jfd) || pPager->pInJournal==0
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
//       || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
//   );
//   if( isOpen(pPager->jfd) ){
//     assert( !pagerUseWal(pPager) );

//     /* Finalize the journal file. */
//     if( sqlite3JournalIsInMemory(pPager->jfd) ){
//       /* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */
//       sqlite3OsClose(pPager->jfd);
//     }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
//       if( pPager->journalOff==0 ){
//         rc = SQLITE_OK;
//       }else{
//         rc = sqlite3OsTruncate(pPager->jfd, 0);
//         if( rc==SQLITE_OK && pPager->fullSync ){
//           /* Make sure the new file size is written into the inode right away.
//           ** Otherwise the journal might resurrect following a power loss and
//           ** cause the last transaction to roll back.  See
//           ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773
//           */
//           rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
//         }
//       }
//       pPager->journalOff = 0;
//     }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
//       || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
//     ){
//       rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
//       pPager->journalOff = 0;
//     }else{
//       /* This branch may be executed with Pager.journalMode==MEMORY if
//       ** a hot-journal was just rolled back. In this case the journal
//       ** file should be closed and deleted. If this connection writes to
//       ** the database file, it will do so using an in-memory journal.
//       */
//       int bDelete = !pPager->tempFile;
//       assert( sqlite3JournalIsInMemory(pPager->jfd)==0 );
H
more  
Hongze Cheng 已提交
1508 1509 1510
//       assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
//            || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
//            || pPager->journalMode==PAGER_JOURNALMODE_WAL
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
//       );
//       sqlite3OsClose(pPager->jfd);
//       if( bDelete ){
//         rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync);
//       }
//     }
//   }

// #ifdef SQLITE_CHECK_PAGES
//   sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
//   if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
//     PgHdr *p = sqlite3PagerLookup(pPager, 1);
//     if( p ){
//       p->pageHash = 0;
//       sqlite3PagerUnrefNotNull(p);
//     }
//   }
// #endif

//   sqlite3BitvecDestroy(pPager->pInJournal);
//   pPager->pInJournal = 0;
//   pPager->nRec = 0;
//   if( rc==SQLITE_OK ){
//     if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
//       sqlite3PcacheCleanAll(pPager->pPCache);
//     }else{
//       sqlite3PcacheClearWritable(pPager->pPCache);
//     }
//     sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
//   }

//   if( pagerUseWal(pPager) ){
H
more  
Hongze Cheng 已提交
1543 1544
//     /* Drop the WAL write-lock, if any. Also, if the connection was in
//     ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
1545 1546 1547 1548 1549 1550 1551
//     ** lock held on the database file.
//     */
//     rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
//     assert( rc2==SQLITE_OK );
//   }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
//     /* This branch is taken when committing a transaction in rollback-journal
//     ** mode if the database file on disk is larger than the database image.
H
more  
Hongze Cheng 已提交
1552
//     ** At this point the journal has been finalized and the transaction
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
//     ** successfully committed, but the EXCLUSIVE lock is still held on the
//     ** file. So it is safe to truncate the database file to its minimum
//     ** required size.  */
//     assert( pPager->eLock==EXCLUSIVE_LOCK );
//     rc = pager_truncate(pPager, pPager->dbSize);
//   }

//   if( rc==SQLITE_OK && bCommit ){
//     rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
//     if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
//   }

H
more  
Hongze Cheng 已提交
1565
//   if( !pPager->exclusiveMode
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
//    && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
//   ){
//     rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
//   }
//   pPager->eState = PAGER_READER;
//   pPager->setSuper = 0;

//   return (rc==SQLITE_OK?rc2:rc);
// }

// /*
H
more  
Hongze Cheng 已提交
1577 1578
// ** Execute a rollback if a transaction is active and unlock the
// ** database file.
1579
// **
H
more  
Hongze Cheng 已提交
1580
// ** If the pager has already entered the ERROR state, do not attempt
1581 1582
// ** the rollback at this time. Instead, pager_unlock() is called. The
// ** call to pager_unlock() will discard all in-memory pages, unlock
H
more  
Hongze Cheng 已提交
1583 1584 1585
// ** the database file and move the pager back to OPEN state. If this
// ** means that there is a hot-journal left in the file-system, the next
// ** connection to obtain a shared lock on the pager (which may be this one)
1586 1587 1588
// ** will roll it back.
// **
// ** If the pager has not already entered the ERROR state, but an IO or
H
more  
Hongze Cheng 已提交
1589
// ** malloc error occurs during a rollback, then this will itself cause
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
// ** the pager to enter the ERROR state. Which will be cleared by the
// ** call to pager_unlock(), as described above.
// */
// static void pagerUnlockAndRollback(Pager *pPager){
//   if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
//     assert( assert_pager_state(pPager) );
//     if( pPager->eState>=PAGER_WRITER_LOCKED ){
//       sqlite3BeginBenignMalloc();
//       sqlite3PagerRollback(pPager);
//       sqlite3EndBenignMalloc();
//     }else if( !pPager->exclusiveMode ){
//       assert( pPager->eState==PAGER_READER );
//       pager_end_transaction(pPager, 0, 0);
//     }
//   }
//   pager_unlock(pPager);
// }

// /*
// ** Parameter aData must point to a buffer of pPager->pageSize bytes
H
more  
Hongze Cheng 已提交
1610
// ** of data. Compute and return a checksum based ont the contents of the
1611 1612
// ** page of data and the current value of pPager->cksumInit.
// **
H
more  
Hongze Cheng 已提交
1613
// ** This is not a real checksum. It is really just the sum of the
1614 1615 1616 1617 1618 1619 1620
// ** random initial value (pPager->cksumInit) and every 200th byte
// ** of the page data, starting with byte offset (pPager->pageSize%200).
// ** Each byte is interpreted as an 8-bit unsigned integer.
// **
// ** Changing the formula used to compute this checksum results in an
// ** incompatible journal file format.
// **
H
more  
Hongze Cheng 已提交
1621 1622
// ** If journal corruption occurs due to a power failure, the most likely
// ** scenario is that one end or the other of the record will be changed.
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
// ** It is much less likely that the two ends of the journal record will be
// ** correct and the middle be corrupt.  Thus, this "checksum" scheme,
// ** though fast and simple, catches the mostly likely kind of corruption.
// */
// static u32 pager_cksum(Pager *pPager, const u8 *aData){
//   u32 cksum = pPager->cksumInit;         /* Checksum value to return */
//   int i = pPager->pageSize-200;          /* Loop counter */
//   while( i>0 ){
//     cksum += aData[i];
//     i -= 200;
//   }
//   return cksum;
// }

// /*
// ** Read a single page from either the journal file (if isMainJrnl==1) or
// ** from the sub-journal (if isMainJrnl==0) and playback that page.
// ** The page begins at offset *pOffset into the file. The *pOffset
// ** value is increased to the start of the next page in the journal.
// **
H
more  
Hongze Cheng 已提交
1643
// ** The main rollback journal uses checksums - the statement journal does
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662
// ** not.
// **
// ** If the page number of the page record read from the (sub-)journal file
// ** is greater than the current value of Pager.dbSize, then playback is
// ** skipped and SQLITE_OK is returned.
// **
// ** If pDone is not NULL, then it is a record of pages that have already
// ** been played back.  If the page at *pOffset has already been played back
// ** (if the corresponding pDone bit is set) then skip the playback.
// ** Make sure the pDone bit corresponding to the *pOffset page is set
// ** prior to returning.
// **
// ** If the page record is successfully read from the (sub-)journal file
// ** and played back, then SQLITE_OK is returned. If an IO error occurs
// ** while reading the record from the (sub-)journal file or while writing
// ** to the database file, then the IO error code is returned. If data
// ** is successfully read from the (sub-)journal file but appears to be
// ** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
// ** two circumstances:
H
more  
Hongze Cheng 已提交
1663
// **
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
// **   * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
// **   * If the record is being rolled back from the main journal file
// **     and the checksum field does not match the record content.
// **
// ** Neither of these two scenarios are possible during a savepoint rollback.
// **
// ** If this is a savepoint rollback, then memory may have to be dynamically
// ** allocated by this function. If this is the case and an allocation fails,
// ** SQLITE_NOMEM is returned.
// */
// static int pager_playback_one_page(
//   Pager *pPager,                /* The pager being played back */
//   i64 *pOffset,                 /* Offset of record to playback */
//   Bitvec *pDone,                /* Bitvec of pages already played back */
//   int isMainJrnl,               /* 1 -> main journal. 0 -> sub-journal. */
//   int isSavepnt                 /* True for a savepoint rollback */
// ){
//   int rc;
//   PgHdr *pPg;                   /* An existing page in the cache */
//   Pgno pgno;                    /* The page number of a page in journal */
//   u32 cksum;                    /* Checksum used for sanity checking */
//   char *aData;                  /* Temporary storage for the page */
//   sqlite3_file *jfd;            /* The file descriptor for the journal file */
//   int isSynced;                 /* True if journal page is synced */

//   assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
//   assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
//   assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
//   assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */

//   aData = pPager->pTmpSpace;
//   assert( aData );         /* Temp storage must have already been allocated */
//   assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );

H
more  
Hongze Cheng 已提交
1698
//   /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
//   ** or savepoint rollback done at the request of the caller) or this is
//   ** a hot-journal rollback. If it is a hot-journal rollback, the pager
//   ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
//   ** only reads from the main journal, not the sub-journal.
//   */
//   assert( pPager->eState>=PAGER_WRITER_CACHEMOD
//        || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
//   );
//   assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );

//   /* Read the page number and page data from the journal or sub-journal
//   ** file. Return an error code to the caller if an IO error occurs.
//   */
//   jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
//   rc = read32bits(jfd, *pOffset, &pgno);
//   if( rc!=SQLITE_OK ) return rc;
//   rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
//   if( rc!=SQLITE_OK ) return rc;
//   *pOffset += pPager->pageSize + 4 + isMainJrnl*4;

//   /* Sanity checking on the page.  This is more important that I originally
//   ** thought.  If a power failure occurs while the journal is being written,
//   ** it could cause invalid data to be written into the journal.  We need to
//   ** detect this invalid data (with high probability) and ignore it.
//   */
//   if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
//     assert( !isSavepnt );
//     return SQLITE_DONE;
//   }
//   if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
//     return SQLITE_OK;
//   }
//   if( isMainJrnl ){
//     rc = read32bits(jfd, (*pOffset)-4, &cksum);
//     if( rc ) return rc;
//     if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
//       return SQLITE_DONE;
//     }
//   }

//   /* If this page has already been played back before during the current
//   ** rollback, then don't bother to play it back again.
//   */
//   if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
//     return rc;
//   }

//   /* When playing back page 1, restore the nReserve setting
//   */
//   if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
//     pPager->nReserve = ((u8*)aData)[20];
//   }

//   /* If the pager is in CACHEMOD state, then there must be a copy of this
//   ** page in the pager cache. In this case just update the pager cache,
//   ** not the database file. The page is left marked dirty in this case.
//   **
//   ** An exception to the above rule: If the database is in no-sync mode
//   ** and a page is moved during an incremental vacuum then the page may
//   ** not be in the pager cache. Later: if a malloc() or IO error occurs
//   ** during a Movepage() call, then the page may not be in the cache
//   ** either. So the condition described in the above paragraph is not
//   ** assert()able.
//   **
//   ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
H
more  
Hongze Cheng 已提交
1764
//   ** pager cache if it exists and the main file. The page is then marked
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
//   ** not dirty. Since this code is only executed in PAGER_OPEN state for
//   ** a hot-journal rollback, it is guaranteed that the page-cache is empty
//   ** if the pager is in OPEN state.
//   **
//   ** Ticket #1171:  The statement journal might contain page content that is
//   ** different from the page content at the start of the transaction.
//   ** This occurs when a page is changed prior to the start of a statement
//   ** then changed again within the statement.  When rolling back such a
//   ** statement we must not write to the original database unless we know
//   ** for certain that original page contents are synced into the main rollback
//   ** journal.  Otherwise, a power loss might leave modified data in the
//   ** database file without an entry in the rollback journal that can
//   ** restore the database to its original form.  Two conditions must be
//   ** met before writing to the database files. (1) the database must be
//   ** locked.  (2) we know that the original page content is fully synced
//   ** in the main journal either because the page is not in cache or else
//   ** the page is marked as needSync==0.
//   **
//   ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
//   ** is possible to fail a statement on a database that does not yet exist.
//   ** Do not attempt to write if database file has never been opened.
//   */
//   if( pagerUseWal(pPager) ){
//     pPg = 0;
//   }else{
//     pPg = sqlite3PagerLookup(pPager, pgno);
//   }
//   assert( pPg || !MEMDB );
//   assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
//   PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
//            PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
//            (isMainJrnl?"main-journal":"sub-journal")
//   ));
//   if( isMainJrnl ){
//     isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
//   }else{
//     isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
//   }
//   if( isOpen(pPager->fd)
//    && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
//    && isSynced
//   ){
//     i64 ofst = (pgno-1)*(i64)pPager->pageSize;
//     testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
//     assert( !pagerUseWal(pPager) );

//     /* Write the data read from the journal back into the database file.
//     ** This is usually safe even for an encrypted database - as the data
//     ** was encrypted before it was written to the journal file. The exception
//     ** is if the data was just read from an in-memory sub-journal. In that
//     ** case it must be encrypted here before it is copied into the database
//     ** file.  */
//     rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);

//     if( pgno>pPager->dbFileSize ){
//       pPager->dbFileSize = pgno;
//     }
//     if( pPager->pBackup ){
//       sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
//     }
//   }else if( !isMainJrnl && pPg==0 ){
//     /* If this is a rollback of a savepoint and data was not written to
//     ** the database and the page is not in-memory, there is a potential
H
more  
Hongze Cheng 已提交
1828 1829 1830
//     ** problem. When the page is next fetched by the b-tree layer, it
//     ** will be read from the database file, which may or may not be
//     ** current.
1831 1832
//     **
//     ** There are a couple of different ways this can happen. All are quite
H
more  
Hongze Cheng 已提交
1833
//     ** obscure. When running in synchronous mode, this can only happen
1834 1835 1836 1837
//     ** if the page is on the free-list at the start of the transaction, then
//     ** populated, then moved using sqlite3PagerMovepage().
//     **
//     ** The solution is to add an in-memory page to the cache containing
H
more  
Hongze Cheng 已提交
1838 1839
//     ** the data just read from the sub-journal. Mark the page as dirty
//     ** and if the pager requires a journal-sync, then mark the page as
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
//     ** requiring a journal-sync before it is written.
//     */
//     assert( isSavepnt );
//     assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
//     pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
//     rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
//     assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
//     pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
//     if( rc!=SQLITE_OK ) return rc;
//     sqlite3PcacheMakeDirty(pPg);
//   }
//   if( pPg ){
//     /* No page should ever be explicitly rolled back that is in use, except
//     ** for page 1 which is held in use in order to keep the lock on the
//     ** database active. However such a page may be rolled back as a result
//     ** of an internal error resulting in an automatic call to
//     ** sqlite3PagerRollback().
//     */
//     void *pData;
//     pData = pPg->pData;
//     memcpy(pData, (u8*)aData, pPager->pageSize);
//     pPager->xReiniter(pPg);
//     /* It used to be that sqlite3PcacheMakeClean(pPg) was called here.  But
//     ** that call was dangerous and had no detectable benefit since the cache
//     ** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so
//     ** has been removed. */
//     pager_set_pagehash(pPg);

//     /* If this was page 1, then restore the value of Pager.dbFileVers.
//     ** Do this before any decoding. */
//     if( pgno==1 ){
//       memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
//     }
//     sqlite3PcacheRelease(pPg);
//   }
//   return rc;
// }

// /*
// ** Parameter zSuper is the name of a super-journal file. A single journal
// ** file that referred to the super-journal file has just been rolled back.
// ** This routine checks if it is possible to delete the super-journal file,
// ** and does so if it is.
// **
H
more  
Hongze Cheng 已提交
1884
// ** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
1885 1886
// ** available for use within this function.
// **
H
more  
Hongze Cheng 已提交
1887 1888 1889
// ** When a super-journal file is created, it is populated with the names
// ** of all of its child journals, one after another, formatted as utf-8
// ** encoded text. The end of each child journal file is marked with a
1890 1891 1892 1893 1894
// ** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
// ** file for a transaction involving two databases might be:
// **
// **   "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
// **
H
more  
Hongze Cheng 已提交
1895
// ** A super-journal file may only be deleted once all of its child
1896 1897
// ** journals have been rolled back.
// **
H
more  
Hongze Cheng 已提交
1898
// ** This function reads the contents of the super-journal file into
1899 1900 1901 1902
// ** memory and loops through each of the child journal names. For
// ** each child journal, it checks if:
// **
// **   * if the child journal exists, and if so
H
more  
Hongze Cheng 已提交
1903
// **   * if the child journal contains a reference to super-journal
1904 1905 1906 1907 1908 1909 1910 1911 1912
// **     file zSuper
// **
// ** If a child journal can be found that matches both of the criteria
// ** above, this function returns without doing anything. Otherwise, if
// ** no such child journal can be found, file zSuper is deleted from
// ** the file-system using sqlite3OsDelete().
// **
// ** If an IO error within this function, an error code is returned. This
// ** function allocates memory by calling sqlite3Malloc(). If an allocation
H
more  
Hongze Cheng 已提交
1913
// ** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
1914 1915 1916 1917
// ** occur, SQLITE_OK is returned.
// **
// ** TODO: This function allocates a single block of memory to load
// ** the entire contents of the super-journal file. This could be
H
more  
Hongze Cheng 已提交
1918
// ** a couple of kilobytes or so - potentially larger than the page
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
// ** size.
// */
// static int pager_delsuper(Pager *pPager, const char *zSuper){
//   sqlite3_vfs *pVfs = pPager->pVfs;
//   int rc;                   /* Return code */
//   sqlite3_file *pSuper;     /* Malloc'd super-journal file descriptor */
//   sqlite3_file *pJournal;   /* Malloc'd child-journal file descriptor */
//   char *zSuperJournal = 0;  /* Contents of super-journal file */
//   i64 nSuperJournal;        /* Size of super-journal file */
//   char *zJournal;           /* Pointer to one journal within MJ file */
//   char *zSuperPtr;          /* Space to hold super-journal filename */
//   char *zFree = 0;          /* Free this buffer */
//   int nSuperPtr;            /* Amount of space allocated to zSuperPtr[] */

//   /* Allocate space for both the pJournal and pSuper file descriptors.
//   ** If successful, open the super-journal file for reading.
//   */
//   pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
//   if( !pSuper ){
//     rc = SQLITE_NOMEM;
//     pJournal = 0;
//   }else{
//     const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
//     rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
//     pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
//   }
//   if( rc!=SQLITE_OK ) goto delsuper_out;

//   /* Load the entire super-journal file into space obtained from
//   ** sqlite3_malloc() and pointed to by zSuperJournal.   Also obtain
//   ** sufficient space (in zSuperPtr) to hold the names of super-journal
//   ** files extracted from regular rollback-journals.
//   */
//   rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
//   if( rc!=SQLITE_OK ) goto delsuper_out;
//   nSuperPtr = pVfs->mxPathname+1;
//   zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
//   if( !zFree ){
//     rc = SQLITE_NOMEM;
//     goto delsuper_out;
//   }
//   zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
//   zSuperJournal = &zFree[4];
//   zSuperPtr = &zSuperJournal[nSuperJournal+2];
//   rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
//   if( rc!=SQLITE_OK ) goto delsuper_out;
//   zSuperJournal[nSuperJournal] = 0;
//   zSuperJournal[nSuperJournal+1] = 0;

//   zJournal = zSuperJournal;
//   while( (zJournal-zSuperJournal)<nSuperJournal ){
//     int exists;
//     rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
//     if( rc!=SQLITE_OK ){
//       goto delsuper_out;
//     }
//     if( exists ){
//       /* One of the journals pointed to by the super-journal exists.
//       ** Open it and check if it points at the super-journal. If
//       ** so, return without deleting the super-journal file.
H
more  
Hongze Cheng 已提交
1979
//       ** NB:  zJournal is really a MAIN_JOURNAL.  But call it a
1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
//       ** SUPER_JOURNAL here so that the VFS will not send the zJournal
//       ** name into sqlite3_database_file_object().
//       */
//       int c;
//       int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
//       rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
//       if( rc!=SQLITE_OK ){
//         goto delsuper_out;
//       }

//       rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
//       sqlite3OsClose(pJournal);
//       if( rc!=SQLITE_OK ){
//         goto delsuper_out;
//       }

//       c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
//       if( c ){
//         /* We have a match. Do not delete the super-journal file. */
//         goto delsuper_out;
//       }
//     }
//     zJournal += (sqlite3Strlen30(zJournal)+1);
//   }
H
more  
Hongze Cheng 已提交
2004

2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
//   sqlite3OsClose(pSuper);
//   rc = sqlite3OsDelete(pVfs, zSuper, 0);

// delsuper_out:
//   sqlite3_free(zFree);
//   if( pSuper ){
//     sqlite3OsClose(pSuper);
//     assert( !isOpen(pJournal) );
//     sqlite3_free(pSuper);
//   }
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
2019
// ** This function is used to change the actual size of the database
2020 2021 2022 2023
// ** file in the file-system. This only happens when committing a transaction,
// ** or rolling back a transaction (including rolling back a hot-journal).
// **
// ** If the main database file is not open, or the pager is not in either
H
more  
Hongze Cheng 已提交
2024 2025
// ** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
// ** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
2026 2027 2028
// ** If the file on disk is currently larger than nPage pages, then use the VFS
// ** xTruncate() method to truncate it.
// **
H
more  
Hongze Cheng 已提交
2029 2030 2031 2032
// ** Or, it might be the case that the file on disk is smaller than
// ** nPage pages. Some operating system implementations can get confused if
// ** you try to truncate a file to some size that is larger than it
// ** currently is, so detect this case and write a single zero byte to
2033 2034 2035 2036 2037 2038 2039 2040 2041
// ** the end of the new file instead.
// **
// ** If successful, return SQLITE_OK. If an IO error occurs while modifying
// ** the database file, return the error code to the caller.
// */
// static int pager_truncate(Pager *pPager, Pgno nPage){
//   int rc = SQLITE_OK;
//   assert( pPager->eState!=PAGER_ERROR );
//   assert( pPager->eState!=PAGER_READER );
H
more  
Hongze Cheng 已提交
2042 2043 2044

//   if( isOpen(pPager->fd)
//    && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
//   ){
//     i64 currentSize, newSize;
//     int szPage = pPager->pageSize;
//     assert( pPager->eLock==EXCLUSIVE_LOCK );
//     /* TODO: Is it safe to use Pager.dbFileSize here? */
//     rc = sqlite3OsFileSize(pPager->fd, &currentSize);
//     newSize = szPage*(i64)nPage;
//     if( rc==SQLITE_OK && currentSize!=newSize ){
//       if( currentSize>newSize ){
//         rc = sqlite3OsTruncate(pPager->fd, newSize);
//       }else if( (currentSize+szPage)<=newSize ){
//         char *pTmp = pPager->pTmpSpace;
//         memset(pTmp, 0, szPage);
//         testcase( (newSize-szPage) == currentSize );
//         testcase( (newSize-szPage) >  currentSize );
//         rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
//       }
//       if( rc==SQLITE_OK ){
//         pPager->dbFileSize = nPage;
//       }
//     }
//   }
//   return rc;
// }

// /*
// ** Return a sanitized version of the sector-size of OS file pFile. The
// ** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
// */
// int sqlite3SectorSize(sqlite3_file *pFile){
//   int iRet = sqlite3OsSectorSize(pFile);
//   if( iRet<32 ){
//     iRet = 512;
//   }else if( iRet>MAX_SECTOR_SIZE ){
//     assert( MAX_SECTOR_SIZE>=512 );
//     iRet = MAX_SECTOR_SIZE;
//   }
//   return iRet;
// }

// /*
// ** Set the value of the Pager.sectorSize variable for the given
// ** pager based on the value returned by the xSectorSize method
H
more  
Hongze Cheng 已提交
2088 2089
// ** of the open database file. The sector size will be used
// ** to determine the size and alignment of journal header and
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111
// ** super-journal pointers within created journal files.
// **
// ** For temporary files the effective sector size is always 512 bytes.
// **
// ** Otherwise, for non-temporary files, the effective sector size is
// ** the value returned by the xSectorSize() method rounded up to 32 if
// ** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
// ** is greater than MAX_SECTOR_SIZE.
// **
// ** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
// ** the effective sector size to its minimum value (512).  The purpose of
// ** pPager->sectorSize is to define the "blast radius" of bytes that
// ** might change if a crash occurs while writing to a single byte in
// ** that range.  But with POWERSAFE_OVERWRITE, the blast radius is zero
// ** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
// ** size.  For backwards compatibility of the rollback journal file format,
// ** we cannot reduce the effective sector size below 512.
// */
// static void setSectorSize(Pager *pPager){
//   assert( isOpen(pPager->fd) || pPager->tempFile );

//   if( pPager->tempFile
H
more  
Hongze Cheng 已提交
2112
//    || (sqlite3OsDeviceCharacteristics(pPager->fd) &
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125
//               SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
//   ){
//     /* Sector size doesn't matter for temporary files. Also, the file
//     ** may not have been opened yet, in which case the OsSectorSize()
//     ** call will segfault. */
//     pPager->sectorSize = 512;
//   }else{
//     pPager->sectorSize = sqlite3SectorSize(pPager->fd);
//   }
// }

// /*
// ** Playback the journal and thus restore the database file to
H
more  
Hongze Cheng 已提交
2126
// ** the state it was in before we started making changes.
2127
// **
H
more  
Hongze Cheng 已提交
2128
// ** The journal file format is as follows:
2129 2130 2131 2132 2133
// **
// **  (1)  8 byte prefix.  A copy of aJournalMagic[].
// **  (2)  4 byte big-endian integer which is the number of valid page records
// **       in the journal.  If this value is 0xffffffff, then compute the
// **       number of page records from the journal size.
H
more  
Hongze Cheng 已提交
2134
// **  (3)  4 byte big-endian integer which is the initial value for the
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
// **       sanity checksum.
// **  (4)  4 byte integer which is the number of pages to truncate the
// **       database to during a rollback.
// **  (5)  4 byte big-endian integer which is the sector size.  The header
// **       is this many bytes in size.
// **  (6)  4 byte big-endian integer which is the page size.
// **  (7)  zero padding out to the next sector size.
// **  (8)  Zero or more pages instances, each as follows:
// **        +  4 byte page number.
// **        +  pPager->pageSize bytes of data.
// **        +  4 byte checksum
// **
// ** When we speak of the journal header, we mean the first 7 items above.
// ** Each entry in the journal is an instance of the 8th item.
// **
// ** Call the value from the second bullet "nRec".  nRec is the number of
// ** valid page entries in the journal.  In most cases, you can compute the
// ** value of nRec from the size of the journal file.  But if a power
// ** failure occurred while the journal was being written, it could be the
// ** case that the size of the journal file had already been increased but
// ** the extra entries had not yet made it safely to disk.  In such a case,
// ** the value of nRec computed from the file size would be too large.  For
// ** that reason, we always use the nRec value in the header.
// **
// ** If the nRec value is 0xffffffff it means that nRec should be computed
// ** from the file size.  This value is used when the user selects the
// ** no-sync option for the journal.  A power failure could lead to corruption
// ** in this case.  But for things like temporary table (which will be
H
more  
Hongze Cheng 已提交
2163
// ** deleted when the power is restored) we don't care.
2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
// **
// ** If the file opened as the journal file is not a well-formed
// ** journal file then all pages up to the first corrupted page are rolled
// ** back (or no pages if the journal header is corrupted). The journal file
// ** is then deleted and SQLITE_OK returned, just as if no corruption had
// ** been encountered.
// **
// ** If an I/O or malloc() error occurs, the journal-file is not deleted
// ** and an error code is returned.
// **
// ** The isHot parameter indicates that we are trying to rollback a journal
H
more  
Hongze Cheng 已提交
2175
// ** that might be a hot journal.  Or, it could be that the journal is
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225
// ** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
// ** If the journal really is hot, reset the pager cache prior rolling
// ** back any content.  If the journal is merely persistent, no reset is
// ** needed.
// */
// static int pager_playback(Pager *pPager, int isHot){
//   sqlite3_vfs *pVfs = pPager->pVfs;
//   i64 szJ;                 /* Size of the journal file in bytes */
//   u32 nRec;                /* Number of Records in the journal */
//   u32 u;                   /* Unsigned loop counter */
//   Pgno mxPg = 0;           /* Size of the original file in pages */
//   int rc;                  /* Result code of a subroutine */
//   int res = 1;             /* Value returned by sqlite3OsAccess() */
//   char *zSuper = 0;        /* Name of super-journal file if any */
//   int needPagerReset;      /* True to reset page prior to first page rollback */
//   int nPlayback = 0;       /* Total number of pages restored from journal */
//   u32 savedPageSize = pPager->pageSize;

//   /* Figure out how many records are in the journal.  Abort early if
//   ** the journal is empty.
//   */
//   assert( isOpen(pPager->jfd) );
//   rc = sqlite3OsFileSize(pPager->jfd, &szJ);
//   if( rc!=SQLITE_OK ){
//     goto end_playback;
//   }

//   /* Read the super-journal name from the journal, if it is present.
//   ** If a super-journal file name is specified, but the file is not
//   ** present on disk, then the journal is not hot and does not need to be
//   ** played back.
//   **
//   ** TODO: Technically the following is an error because it assumes that
//   ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
//   ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
//   ** mxPathname is 512, which is the same as the minimum allowable value
//   ** for pageSize.
//   */
//   zSuper = pPager->pTmpSpace;
//   rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
//   if( rc==SQLITE_OK && zSuper[0] ){
//     rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
//   }
//   zSuper = 0;
//   if( rc!=SQLITE_OK || !res ){
//     goto end_playback;
//   }
//   pPager->journalOff = 0;
//   needPagerReset = isHot;

H
more  
Hongze Cheng 已提交
2226 2227 2228
//   /* This loop terminates either when a readJournalHdr() or
//   ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
//   ** occurs.
2229 2230 2231 2232 2233 2234 2235 2236
//   */
//   while( 1 ){
//     /* Read the next journal header from the journal file.  If there are
//     ** not enough bytes left in the journal file for a complete header, or
//     ** it is corrupted, then a process must have failed while writing it.
//     ** This indicates nothing more needs to be rolled back.
//     */
//     rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
H
more  
Hongze Cheng 已提交
2237
//     if( rc!=SQLITE_OK ){
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
//       if( rc==SQLITE_DONE ){
//         rc = SQLITE_OK;
//       }
//       goto end_playback;
//     }

//     /* If nRec is 0xffffffff, then this journal was created by a process
//     ** working in no-sync mode. This means that the rest of the journal
//     ** file consists of pages, there are no more journal headers. Compute
//     ** the value of nRec based on this assumption.
//     */
//     if( nRec==0xffffffff ){
//       assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
//       nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
//     }

//     /* If nRec is 0 and this rollback is of a transaction created by this
//     ** process and if this is the final header in the journal, then it means
//     ** that this part of the journal was being filled but has not yet been
//     ** synced to disk.  Compute the number of pages based on the remaining
//     ** size of the file.
//     **
//     ** The third term of the test was added to fix ticket #2565.
//     ** When rolling back a hot journal, nRec==0 always means that the next
//     ** chunk of the journal contains zero pages to be rolled back.  But
//     ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
//     ** the journal, it means that the journal might contain additional
H
more  
Hongze Cheng 已提交
2265
//     ** pages that need to be rolled back and that the number of pages
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
//     ** should be computed based on the journal file size.
//     */
//     if( nRec==0 && !isHot &&
//         pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
//       nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
//     }

//     /* If this is the first header read from the journal, truncate the
//     ** database file back to its original size.
//     */
//     if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
//       rc = pager_truncate(pPager, mxPg);
//       if( rc!=SQLITE_OK ){
//         goto end_playback;
//       }
//       pPager->dbSize = mxPg;
//     }

H
more  
Hongze Cheng 已提交
2284
//     /* Copy original pages out of the journal and back into the
2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
//     ** database file and/or page cache.
//     */
//     for(u=0; u<nRec; u++){
//       if( needPagerReset ){
//         pager_reset(pPager);
//         needPagerReset = 0;
//       }
//       rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
//       if( rc==SQLITE_OK ){
//         nPlayback++;
//       }else{
//         if( rc==SQLITE_DONE ){
//           pPager->journalOff = szJ;
//           break;
//         }else if( rc==SQLITE_IOERR_SHORT_READ ){
//           /* If the journal has been truncated, simply stop reading and
//           ** processing the journal. This might happen if the journal was
//           ** not completely written and synced prior to a crash.  In that
//           ** case, the database should have never been written in the
//           ** first place so it is OK to simply abandon the rollback. */
//           rc = SQLITE_OK;
//           goto end_playback;
//         }else{
//           /* If we are unable to rollback, quit and return the error
//           ** code.  This will cause the pager to enter the error state
//           ** so that no further harm will be done.  Perhaps the next
//           ** process to come along will be able to rollback the database.
//           */
//           goto end_playback;
//         }
//       }
//     }
//   }
//   /*NOTREACHED*/
//   assert( 0 );

// end_playback:
//   if( rc==SQLITE_OK ){
//     rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1);
//   }
//   /* Following a rollback, the database file should be back in its original
//   ** state prior to the start of the transaction, so invoke the
//   ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
//   ** assertion that the transaction counter was modified.
//   */
// #ifdef SQLITE_DEBUG
//   sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
// #endif

H
more  
Hongze Cheng 已提交
2334 2335 2336 2337
//   /* If this playback is happening automatically as a result of an IO or
//   ** malloc error that occurred after the change-counter was updated but
//   ** before the transaction was committed, then the change-counter
//   ** modification may just have been reverted. If this happens in exclusive
2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
//   ** mode, then subsequent transactions performed by the connection will not
//   ** update the change-counter at all. This may lead to cache inconsistency
//   ** problems for other processes at some point in the future. So, just
//   ** in case this has happened, clear the changeCountDone flag now.
//   */
//   pPager->changeCountDone = pPager->tempFile;

//   if( rc==SQLITE_OK ){
//     /* Leave 4 bytes of space before the super-journal filename in memory.
//     ** This is because it may end up being passed to sqlite3OsOpen(), in
//     ** which case it requires 4 0x00 bytes in memory immediately before
//     ** the filename. */
//     zSuper = &pPager->pTmpSpace[4];
//     rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
//     testcase( rc!=SQLITE_OK );
//   }
//   if( rc==SQLITE_OK
//    && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
//   ){
//     rc = sqlite3PagerSync(pPager, 0);
//   }
//   if( rc==SQLITE_OK ){
//     rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
//     testcase( rc!=SQLITE_OK );
//   }
//   if( rc==SQLITE_OK && zSuper[0] && res ){
//     /* If there was a super-journal and this routine will return success,
//     ** see if it is possible to delete the super-journal.
//     */
//     assert( zSuper==&pPager->pTmpSpace[4] );
//     memset(&zSuper[-4], 0, 4);
//     rc = pager_delsuper(pPager, zSuper);
//     testcase( rc!=SQLITE_OK );
//   }
//   if( isHot && nPlayback ){
//     sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
//                 nPlayback, pPager->zJournal);
//   }

//   /* The Pager.sectorSize variable may have been updated while rolling
//   ** back a journal created by a process with a different sector size
//   ** value. Reset it to the correct value for this process.
//   */
//   setSectorSize(pPager);
//   return rc;
// }

// /*
// ** Read the content for page pPg out of the database file (or out of
H
more  
Hongze Cheng 已提交
2387
// ** the WAL if that is where the most recent copy if found) into
2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476
// ** pPg->pData. A shared lock or greater must be held on the database
// ** file before this function is called.
// **
// ** If page 1 is read, then the value of Pager.dbFileVers[] is set to
// ** the value read from the database file.
// **
// ** If an IO error occurs, then the IO error is returned to the caller.
// ** Otherwise, SQLITE_OK is returned.
// */
// static int readDbPage(PgHdr *pPg){
//   Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
//   int rc = SQLITE_OK;          /* Return code */

// #ifndef SQLITE_OMIT_WAL
//   u32 iFrame = 0;              /* Frame of WAL containing pgno */

//   assert( pPager->eState>=PAGER_READER && !MEMDB );
//   assert( isOpen(pPager->fd) );

//   if( pagerUseWal(pPager) ){
//     rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
//     if( rc ) return rc;
//   }
//   if( iFrame ){
//     rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData);
//   }else
// #endif
//   {
//     i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize;
//     rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
//     if( rc==SQLITE_IOERR_SHORT_READ ){
//       rc = SQLITE_OK;
//     }
//   }

//   if( pPg->pgno==1 ){
//     if( rc ){
//       /* If the read is unsuccessful, set the dbFileVers[] to something
//       ** that will never be a valid file version.  dbFileVers[] is a copy
//       ** of bytes 24..39 of the database.  Bytes 28..31 should always be
//       ** zero or the size of the database in page. Bytes 32..35 and 35..39
//       ** should be page numbers which are never 0xffffffff.  So filling
//       ** pPager->dbFileVers[] with all 0xff bytes should suffice.
//       **
//       ** For an encrypted database, the situation is more complex:  bytes
//       ** 24..39 of the database are white noise.  But the probability of
//       ** white noise equaling 16 bytes of 0xff is vanishingly small so
//       ** we should still be ok.
//       */
//       memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
//     }else{
//       u8 *dbFileVers = &((u8*)pPg->pData)[24];
//       memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
//     }
//   }
//   PAGER_INCR(sqlite3_pager_readdb_count);
//   PAGER_INCR(pPager->nRead);
//   IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
//   PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
//                PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));

//   return rc;
// }

// /*
// ** Update the value of the change-counter at offsets 24 and 92 in
// ** the header and the sqlite version number at offset 96.
// **
// ** This is an unconditional update.  See also the pager_incr_changecounter()
// ** routine which only updates the change-counter if the update is actually
// ** needed, as determined by the pPager->changeCountDone state variable.
// */
// static void pager_write_changecounter(PgHdr *pPg){
//   u32 change_counter;
//   if( NEVER(pPg==0) ) return;

//   /* Increment the value just read and write it back to byte 24. */
//   change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
//   put32bits(((char*)pPg->pData)+24, change_counter);

//   /* Also store the SQLite version number in bytes 96..99 and in
//   ** bytes 92..95 store the change counter for which the version number
//   ** is valid. */
//   put32bits(((char*)pPg->pData)+92, change_counter);
//   put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
// }

// #ifndef SQLITE_OMIT_WAL
// /*
H
more  
Hongze Cheng 已提交
2477
// ** This function is invoked once for each page that has already been
2478
// ** written into the log file when a WAL transaction is rolled back.
H
more  
Hongze Cheng 已提交
2479
// ** Parameter iPg is the page number of said page. The pCtx argument
2480 2481 2482 2483 2484
// ** is actually a pointer to the Pager structure.
// **
// ** If page iPg is present in the cache, and has no outstanding references,
// ** it is discarded. Otherwise, if there are one or more outstanding
// ** references, the page content is reloaded from the database. If the
H
more  
Hongze Cheng 已提交
2485
// ** attempt to reload content from the database is required and fails,
2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
// ** return an SQLite error code. Otherwise, SQLITE_OK.
// */
// static int pagerUndoCallback(void *pCtx, Pgno iPg){
//   int rc = SQLITE_OK;
//   Pager *pPager = (Pager *)pCtx;
//   PgHdr *pPg;

//   assert( pagerUseWal(pPager) );
//   pPg = sqlite3PagerLookup(pPager, iPg);
//   if( pPg ){
//     if( sqlite3PcachePageRefcount(pPg)==1 ){
//       sqlite3PcacheDrop(pPg);
//     }else{
//       rc = readDbPage(pPg);
//       if( rc==SQLITE_OK ){
//         pPager->xReiniter(pPg);
//       }
//       sqlite3PagerUnrefNotNull(pPg);
//     }
//   }

//   /* Normally, if a transaction is rolled back, any backup processes are
//   ** updated as data is copied out of the rollback journal and into the
//   ** database. This is not generally possible with a WAL database, as
//   ** rollback involves simply truncating the log file. Therefore, if one
H
more  
Hongze Cheng 已提交
2511
//   ** or more frames have already been written to the log (and therefore
2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527
//   ** also copied into the backup databases) as part of this transaction,
//   ** the backups must be restarted.
//   */
//   sqlite3BackupRestart(pPager->pBackup);

//   return rc;
// }

// /*
// ** This function is called to rollback a transaction on a WAL database.
// */
// static int pagerRollbackWal(Pager *pPager){
//   int rc;                         /* Return Code */
//   PgHdr *pList;                   /* List of dirty pages to revert */

//   /* For all pages in the cache that are currently dirty or have already
H
more  
Hongze Cheng 已提交
2528
//   ** been written (but not committed) to the log file, do one of the
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549
//   ** following:
//   **
//   **   + Discard the cached page (if refcount==0), or
//   **   + Reload page content from the database (if refcount>0).
//   */
//   pPager->dbSize = pPager->dbOrigSize;
//   rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
//   pList = sqlite3PcacheDirtyList(pPager->pPCache);
//   while( pList && rc==SQLITE_OK ){
//     PgHdr *pNext = pList->pDirty;
//     rc = pagerUndoCallback((void *)pPager, pList->pgno);
//     pList = pNext;
//   }

//   return rc;
// }

// /*
// ** This function is a wrapper around sqlite3WalFrames(). As well as logging
// ** the contents of the list of pages headed by pList (connected by pDirty),
// ** this function notifies any active backup processes that the pages have
H
more  
Hongze Cheng 已提交
2550
// ** changed.
2551 2552 2553
// **
// ** The list of pages passed into this routine is always sorted by page number.
// ** Hence, if page 1 appears anywhere on the list, it will be the first page.
H
more  
Hongze Cheng 已提交
2554
// */
2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594
// static int pagerWalFrames(
//   Pager *pPager,                  /* Pager object */
//   PgHdr *pList,                   /* List of frames to log */
//   Pgno nTruncate,                 /* Database size after this commit */
//   int isCommit                    /* True if this is a commit */
// ){
//   int rc;                         /* Return code */
//   int nList;                      /* Number of pages in pList */
//   PgHdr *p;                       /* For looping over pages */

//   assert( pPager->pWal );
//   assert( pList );
// #ifdef SQLITE_DEBUG
//   /* Verify that the page list is in accending order */
//   for(p=pList; p && p->pDirty; p=p->pDirty){
//     assert( p->pgno < p->pDirty->pgno );
//   }
// #endif

//   assert( pList->pDirty==0 || isCommit );
//   if( isCommit ){
//     /* If a WAL transaction is being committed, there is no point in writing
//     ** any pages with page numbers greater than nTruncate into the WAL file.
//     ** They will never be read by any client. So remove them from the pDirty
//     ** list here. */
//     PgHdr **ppNext = &pList;
//     nList = 0;
//     for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
//       if( p->pgno<=nTruncate ){
//         ppNext = &p->pDirty;
//         nList++;
//       }
//     }
//     assert( pList );
//   }else{
//     nList = 1;
//   }
//   pPager->aStat[PAGER_STAT_WRITE] += nList;

//   if( pList->pgno==1 ) pager_write_changecounter(pList);
H
more  
Hongze Cheng 已提交
2595
//   rc = sqlite3WalFrames(pPager->pWal,
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709
//       pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
//   );
//   if( rc==SQLITE_OK && pPager->pBackup ){
//     for(p=pList; p; p=p->pDirty){
//       sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
//     }
//   }

// #ifdef SQLITE_CHECK_PAGES
//   pList = sqlite3PcacheDirtyList(pPager->pPCache);
//   for(p=pList; p; p=p->pDirty){
//     pager_set_pagehash(p);
//   }
// #endif

//   return rc;
// }

// /*
// ** Begin a read transaction on the WAL.
// **
// ** This routine used to be called "pagerOpenSnapshot()" because it essentially
// ** makes a snapshot of the database at the current point in time and preserves
// ** that snapshot for use by the reader in spite of concurrently changes by
// ** other writers or checkpointers.
// */
// static int pagerBeginReadTransaction(Pager *pPager){
//   int rc;                         /* Return code */
//   int changed = 0;                /* True if cache must be reset */

//   assert( pagerUseWal(pPager) );
//   assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );

//   /* sqlite3WalEndReadTransaction() was not called for the previous
//   ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
//   ** are in locking_mode=NORMAL and EndRead() was previously called,
//   ** the duplicate call is harmless.
//   */
//   sqlite3WalEndReadTransaction(pPager->pWal);

//   rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
//   if( rc!=SQLITE_OK || changed ){
//     pager_reset(pPager);
//     if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
//   }

//   return rc;
// }
// #endif

// /*
// ** This function is called as part of the transition from PAGER_OPEN
// ** to PAGER_READER state to determine the size of the database file
// ** in pages (assuming the page size currently stored in Pager.pageSize).
// **
// ** If no error occurs, SQLITE_OK is returned and the size of the database
// ** in pages is stored in *pnPage. Otherwise, an error code (perhaps
// ** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
// */
// static int pagerPagecount(Pager *pPager, Pgno *pnPage){
//   Pgno nPage;                     /* Value to return via *pnPage */

//   /* Query the WAL sub-system for the database size. The WalDbsize()
//   ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
//   ** if the database size is not available. The database size is not
//   ** available from the WAL sub-system if the log file is empty or
//   ** contains no valid committed transactions.
//   */
//   assert( pPager->eState==PAGER_OPEN );
//   assert( pPager->eLock>=SHARED_LOCK );
//   assert( isOpen(pPager->fd) );
//   assert( pPager->tempFile==0 );
//   nPage = sqlite3WalDbsize(pPager->pWal);

//   /* If the number of pages in the database is not available from the
//   ** WAL sub-system, determine the page count based on the size of
//   ** the database file.  If the size of the database file is not an
//   ** integer multiple of the page-size, round up the result.
//   */
//   if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
//     i64 n = 0;                    /* Size of db file in bytes */
//     int rc = sqlite3OsFileSize(pPager->fd, &n);
//     if( rc!=SQLITE_OK ){
//       return rc;
//     }
//     nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
//   }

//   /* If the current number of pages in the file is greater than the
//   ** configured maximum pager number, increase the allowed limit so
//   ** that the file can be read.
//   */
//   if( nPage>pPager->mxPgno ){
//     pPager->mxPgno = (Pgno)nPage;
//   }

//   *pnPage = nPage;
//   return SQLITE_OK;
// }

// #ifndef SQLITE_OMIT_WAL
// /*
// ** Check if the *-wal file that corresponds to the database opened by pPager
// ** exists if the database is not empy, or verify that the *-wal file does
// ** not exist (by deleting it) if the database file is empty.
// **
// ** If the database is not empty and the *-wal file exists, open the pager
// ** in WAL mode.  If the database is empty or if no *-wal file exists and
// ** if no error occurs, make sure Pager.journalMode is not set to
// ** PAGER_JOURNALMODE_WAL.
// **
// ** Return SQLITE_OK or an error code.
// **
// ** The caller must hold a SHARED lock on the database file to call this
H
more  
Hongze Cheng 已提交
2710 2711 2712
// ** function. Because an EXCLUSIVE lock on the db file is required to delete
// ** a WAL on a none-empty database, this ensures there is no race condition
// ** between the xAccess() below and an xDelete() being executed by some
2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
// ** other connection.
// */
// static int pagerOpenWalIfPresent(Pager *pPager){
//   int rc = SQLITE_OK;
//   assert( pPager->eState==PAGER_OPEN );
//   assert( pPager->eLock>=SHARED_LOCK );

//   if( !pPager->tempFile ){
//     int isWal;                    /* True if WAL file exists */
//     rc = sqlite3OsAccess(
//         pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
//     );
//     if( rc==SQLITE_OK ){
//       if( isWal ){
//         Pgno nPage;                   /* Size of the database file */

//         rc = pagerPagecount(pPager, &nPage);
//         if( rc ) return rc;
//         if( nPage==0 ){
//           rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
//         }else{
//           testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
//           rc = sqlite3PagerOpenWal(pPager, 0);
//         }
//       }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
//         pPager->journalMode = PAGER_JOURNALMODE_DELETE;
//       }
//     }
//   }
//   return rc;
// }
// #endif

// /*
// ** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
H
more  
Hongze Cheng 已提交
2748 2749
// ** the entire super-journal file. The case pSavepoint==NULL occurs when
// ** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
2750 2751
// ** savepoint.
// **
H
more  
Hongze Cheng 已提交
2752
// ** When pSavepoint is not NULL (meaning a non-transaction savepoint is
2753 2754 2755 2756
// ** being rolled back), then the rollback consists of up to three stages,
// ** performed in the order specified:
// **
// **   * Pages are played back from the main journal starting at byte
H
more  
Hongze Cheng 已提交
2757
// **     offset PagerSavepoint.iOffset and continuing to
2758 2759 2760 2761
// **     PagerSavepoint.iHdrOffset, or to the end of the main journal
// **     file if PagerSavepoint.iHdrOffset is zero.
// **
// **   * If PagerSavepoint.iHdrOffset is not zero, then pages are played
H
more  
Hongze Cheng 已提交
2762
// **     back starting from the journal header immediately following
2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777
// **     PagerSavepoint.iHdrOffset to the end of the main journal file.
// **
// **   * Pages are then played back from the sub-journal file, starting
// **     with the PagerSavepoint.iSubRec and continuing to the end of
// **     the journal file.
// **
// ** Throughout the rollback process, each time a page is rolled back, the
// ** corresponding bit is set in a bitvec structure (variable pDone in the
// ** implementation below). This is used to ensure that a page is only
// ** rolled back the first time it is encountered in either journal.
// **
// ** If pSavepoint is NULL, then pages are only played back from the main
// ** journal file. There is no need for a bitvec in this case.
// **
// ** In either case, before playback commences the Pager.dbSize variable
H
more  
Hongze Cheng 已提交
2778
// ** is reset to the value that it held at the start of the savepoint
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
// ** (or transaction). No page with a page-number greater than this value
// ** is played back. If one is encountered it is simply skipped.
// */
// static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
//   i64 szJ;                 /* Effective size of the main journal */
//   i64 iHdrOff;             /* End of first segment of main-journal records */
//   int rc = SQLITE_OK;      /* Return code */
//   Bitvec *pDone = 0;       /* Bitvec to ensure pages played back only once */

//   assert( pPager->eState!=PAGER_ERROR );
//   assert( pPager->eState>=PAGER_WRITER_LOCKED );

//   /* Allocate a bitvec to use to store the set of pages rolled back */
//   if( pSavepoint ){
//     pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
//     if( !pDone ){
//       return SQLITE_NOMEM;
//     }
//   }

H
more  
Hongze Cheng 已提交
2799
//   /* Set the database size back to the value it was before the savepoint
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851
//   ** being reverted was opened.
//   */
//   pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
//   pPager->changeCountDone = pPager->tempFile;

//   if( !pSavepoint && pagerUseWal(pPager) ){
//     return pagerRollbackWal(pPager);
//   }

//   /* Use pPager->journalOff as the effective size of the main rollback
//   ** journal.  The actual file might be larger than this in
//   ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST.  But anything
//   ** past pPager->journalOff is off-limits to us.
//   */
//   szJ = pPager->journalOff;
//   assert( pagerUseWal(pPager)==0 || szJ==0 );

//   /* Begin by rolling back records from the main journal starting at
//   ** PagerSavepoint.iOffset and continuing to the next journal header.
//   ** There might be records in the main journal that have a page number
//   ** greater than the current database size (pPager->dbSize) but those
//   ** will be skipped automatically.  Pages are added to pDone as they
//   ** are played back.
//   */
//   if( pSavepoint && !pagerUseWal(pPager) ){
//     iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
//     pPager->journalOff = pSavepoint->iOffset;
//     while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
//       rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
//     }
//     assert( rc!=SQLITE_DONE );
//   }else{
//     pPager->journalOff = 0;
//   }

//   /* Continue rolling back records out of the main journal starting at
//   ** the first journal header seen and continuing until the effective end
//   ** of the main journal file.  Continue to skip out-of-range pages and
//   ** continue adding pages rolled back to pDone.
//   */
//   while( rc==SQLITE_OK && pPager->journalOff<szJ ){
//     u32 ii;            /* Loop counter */
//     u32 nJRec = 0;     /* Number of Journal Records */
//     u32 dummy;
//     rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
//     assert( rc!=SQLITE_DONE );

//     /*
//     ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
//     ** test is related to ticket #2565.  See the discussion in the
//     ** pager_playback() function for additional information.
//     */
H
more  
Hongze Cheng 已提交
2852
//     if( nJRec==0
2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027
//      && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
//     ){
//       nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
//     }
//     for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
//       rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
//     }
//     assert( rc!=SQLITE_DONE );
//   }
//   assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );

//   /* Finally,  rollback pages from the sub-journal.  Page that were
//   ** previously rolled back out of the main journal (and are hence in pDone)
//   ** will be skipped.  Out-of-range pages are also skipped.
//   */
//   if( pSavepoint ){
//     u32 ii;            /* Loop counter */
//     i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);

//     if( pagerUseWal(pPager) ){
//       rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
//     }
//     for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
//       assert( offset==(i64)ii*(4+pPager->pageSize) );
//       rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
//     }
//     assert( rc!=SQLITE_DONE );
//   }

//   sqlite3BitvecDestroy(pDone);
//   if( rc==SQLITE_OK ){
//     pPager->journalOff = szJ;
//   }

//   return rc;
// }

// /*
// ** Change the maximum number of in-memory pages that are allowed
// ** before attempting to recycle clean and unused pages.
// */
// void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
//   sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
// }

// /*
// ** Change the maximum number of in-memory pages that are allowed
// ** before attempting to spill pages to journal.
// */
// int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){
//   return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage);
// }

// /*
// ** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
// */
// static void pagerFixMaplimit(Pager *pPager){
// #if SQLITE_MAX_MMAP_SIZE>0
//   sqlite3_file *fd = pPager->fd;
//   if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
//     sqlite3_int64 sz;
//     sz = pPager->szMmap;
//     pPager->bUseFetch = (sz>0);
//     setGetterMethod(pPager);
//     sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
//   }
// #endif
// }

// /*
// ** Change the maximum size of any memory mapping made of the database file.
// */
// void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
//   pPager->szMmap = szMmap;
//   pagerFixMaplimit(pPager);
// }

// /*
// ** Free as much memory as possible from the pager.
// */
// void sqlite3PagerShrink(Pager *pPager){
//   sqlite3PcacheShrink(pPager->pPCache);
// }

// /*
// ** Adjust settings of the pager to those specified in the pgFlags parameter.
// **
// ** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
// ** of the database to damage due to OS crashes or power failures by
// ** changing the number of syncs()s when writing the journals.
// ** There are four levels:
// **
// **    OFF       sqlite3OsSync() is never called.  This is the default
// **              for temporary and transient files.
// **
// **    NORMAL    The journal is synced once before writes begin on the
// **              database.  This is normally adequate protection, but
// **              it is theoretically possible, though very unlikely,
// **              that an inopertune power failure could leave the journal
// **              in a state which would cause damage to the database
// **              when it is rolled back.
// **
// **    FULL      The journal is synced twice before writes begin on the
// **              database (with some additional information - the nRec field
// **              of the journal header - being written in between the two
// **              syncs).  If we assume that writing a
// **              single disk sector is atomic, then this mode provides
// **              assurance that the journal will not be corrupted to the
// **              point of causing damage to the database during rollback.
// **
// **    EXTRA     This is like FULL except that is also syncs the directory
// **              that contains the rollback journal after the rollback
// **              journal is unlinked.
// **
// ** The above is for a rollback-journal mode.  For WAL mode, OFF continues
// ** to mean that no syncs ever occur.  NORMAL means that the WAL is synced
// ** prior to the start of checkpoint and that the database file is synced
// ** at the conclusion of the checkpoint if the entire content of the WAL
// ** was written back into the database.  But no sync operations occur for
// ** an ordinary commit in NORMAL mode with WAL.  FULL means that the WAL
// ** file is synced following each commit operation, in addition to the
// ** syncs associated with NORMAL.  There is no difference between FULL
// ** and EXTRA for WAL mode.
// **
// ** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL.  The
// ** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
// ** using fcntl(F_FULLFSYNC).  SQLITE_SYNC_NORMAL means to do an
// ** ordinary fsync() call.  There is no difference between SQLITE_SYNC_FULL
// ** and SQLITE_SYNC_NORMAL on platforms other than MacOSX.  But the
// ** synchronous=FULL versus synchronous=NORMAL setting determines when
// ** the xSync primitive is called and is relevant to all platforms.
// **
// ** Numeric values associated with these states are OFF==1, NORMAL=2,
// ** and FULL=3.
// */
// #ifndef SQLITE_OMIT_PAGER_PRAGMAS
// void sqlite3PagerSetFlags(
//   Pager *pPager,        /* The pager to set safety level for */
//   unsigned pgFlags      /* Various flags */
// ){
//   unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
//   if( pPager->tempFile ){
//     pPager->noSync = 1;
//     pPager->fullSync = 0;
//     pPager->extraSync = 0;
//   }else{
//     pPager->noSync =  level==PAGER_SYNCHRONOUS_OFF ?1:0;
//     pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;
//     pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;
//   }
//   if( pPager->noSync ){
//     pPager->syncFlags = 0;
//   }else if( pgFlags & PAGER_FULLFSYNC ){
//     pPager->syncFlags = SQLITE_SYNC_FULL;
//   }else{
//     pPager->syncFlags = SQLITE_SYNC_NORMAL;
//   }
//   pPager->walSyncFlags = (pPager->syncFlags<<2);
//   if( pPager->fullSync ){
//     pPager->walSyncFlags |= pPager->syncFlags;
//   }
//   if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
//     pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
//   }
//   if( pgFlags & PAGER_CACHESPILL ){
//     pPager->doNotSpill &= ~SPILLFLAG_OFF;
//   }else{
//     pPager->doNotSpill |= SPILLFLAG_OFF;
//   }
// }
// #endif

// /*
// ** The following global variable is incremented whenever the library
// ** attempts to open a temporary file.  This information is used for
H
more  
Hongze Cheng 已提交
3028
// ** testing and analysis only.
3029 3030 3031 3032 3033 3034 3035 3036
// */
// #ifdef SQLITE_TEST
// int sqlite3_opentemp_count = 0;
// #endif

// /*
// ** Open a temporary file.
// **
H
more  
Hongze Cheng 已提交
3037 3038
// ** Write the file descriptor into *pFile. Return SQLITE_OK on success
// ** or some other error code if we fail. The OS will automatically
3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
// ** delete the temporary file when it is closed.
// **
// ** The flags passed to the VFS layer xOpen() call are those specified
// ** by parameter vfsFlags ORed with the following:
// **
// **     SQLITE_OPEN_READWRITE
// **     SQLITE_OPEN_CREATE
// **     SQLITE_OPEN_EXCLUSIVE
// **     SQLITE_OPEN_DELETEONCLOSE
// */
// static int pagerOpentemp(
//   Pager *pPager,        /* The pager object */
//   sqlite3_file *pFile,  /* Write the file descriptor here */
//   int vfsFlags          /* Flags passed through to the VFS */
// ){
//   int rc;               /* Return code */

// #ifdef SQLITE_TEST
//   sqlite3_opentemp_count++;  /* Used for testing and analysis only */
// #endif

//   vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
//             SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
//   rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
//   assert( rc!=SQLITE_OK || isOpen(pFile) );
//   return rc;
// }

// /*
// ** Set the busy handler function.
// **
H
more  
Hongze Cheng 已提交
3070
// ** The pager invokes the busy-handler if sqlite3OsLock() returns
3071
// ** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
H
more  
Hongze Cheng 已提交
3072
// ** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083
// ** lock. It does *not* invoke the busy handler when upgrading from
// ** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
// ** (which occurs during hot-journal rollback). Summary:
// **
// **   Transition                        | Invokes xBusyHandler
// **   --------------------------------------------------------
// **   NO_LOCK       -> SHARED_LOCK      | Yes
// **   SHARED_LOCK   -> RESERVED_LOCK    | No
// **   SHARED_LOCK   -> EXCLUSIVE_LOCK   | No
// **   RESERVED_LOCK -> EXCLUSIVE_LOCK   | Yes
// **
H
more  
Hongze Cheng 已提交
3084
// ** If the busy-handler callback returns non-zero, the lock is
3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101
// ** retried. If it returns zero, then the SQLITE_BUSY error is
// ** returned to the caller of the pager API function.
// */
// void sqlite3PagerSetBusyHandler(
//   Pager *pPager,                       /* Pager object */
//   int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
//   void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
// ){
//   void **ap;
//   pPager->xBusyHandler = xBusyHandler;
//   pPager->pBusyHandlerArg = pBusyHandlerArg;
//   ap = (void **)&pPager->xBusyHandler;
//   assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
//   assert( ap[1]==pBusyHandlerArg );
//   sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
// }

H
more  
Hongze Cheng 已提交
3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136
int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve) {
  // int rc = SQLITE_OK;

  // /* It is not possible to do a full assert_pager_state() here, as this
  // ** function may be called from within PagerOpen(), before the state
  // ** of the Pager object is internally consistent.
  // **
  // ** At one point this function returned an error if the pager was in
  // ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
  // ** there is at least one outstanding page reference, this function
  // ** is a no-op for that case anyhow.
  // */

  // u32 pageSize = *pPageSize;
  // assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
  // if( (pPager->memDb==0 || pPager->dbSize==0)
  //  && sqlite3PcacheRefCount(pPager->pPCache)==0
  //  && pageSize && pageSize!=(u32)pPager->pageSize
  // ){
  //   char *pNew = NULL;             /* New temp space */
  //   i64 nByte = 0;

  //   if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
  //     rc = sqlite3OsFileSize(pPager->fd, &nByte);
  //   }
  //   if( rc==SQLITE_OK ){
  //     /* 8 bytes of zeroed overrun space is sufficient so that the b-tree
  //     * cell header parser will never run off the end of the allocation */
  //     pNew = (char *)sqlite3PageMalloc(pageSize+8);
  //     if( !pNew ){
  //       rc = SQLITE_NOMEM;
  //     }else{
  //       memset(pNew+pageSize, 0, 8);
  //     }
  //   }
3137

H
more  
Hongze Cheng 已提交
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160
  //   if( rc==SQLITE_OK ){
  //     pager_reset(pPager);
  //     rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
  //   }
  //   if( rc==SQLITE_OK ){
  //     sqlite3PageFree(pPager->pTmpSpace);
  //     pPager->pTmpSpace = pNew;
  //     pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
  //     pPager->pageSize = pageSize;
  //   }else{
  //     sqlite3PageFree(pNew);
  //   }
  // }

  // *pPageSize = pPager->pageSize;
  // if( rc==SQLITE_OK ){
  //   if( nReserve<0 ) nReserve = pPager->nReserve;
  //   assert( nReserve>=0 && nReserve<1000 );
  //   pPager->nReserve = (i16)nReserve;
  //   pagerFixMaplimit(pPager);
  // }
  // return rc;
}
3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174

// /*
// ** Return a pointer to the "temporary page" buffer held internally
// ** by the pager.  This is a buffer that is big enough to hold the
// ** entire content of a database page.  This buffer is used internally
// ** during rollback and will be overwritten whenever a rollback
// ** occurs.  But other modules are free to use it too, as long as
// ** no rollbacks are happening.
// */
// void *sqlite3PagerTempSpace(Pager *pPager){
//   return pPager->pTmpSpace;
// }

// /*
H
more  
Hongze Cheng 已提交
3175
// ** Attempt to set the maximum database page count if mxPage is positive.
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218
// ** Make no changes if mxPage is zero or negative.  And never reduce the
// ** maximum page count below the current size of the database.
// **
// ** Regardless of mxPage, return the current maximum page count.
// */
// Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){
//   if( mxPage>0 ){
//     pPager->mxPgno = mxPage;
//   }
//   assert( pPager->eState!=PAGER_OPEN );      /* Called only by OP_MaxPgcnt */
//   /* assert( pPager->mxPgno>=pPager->dbSize ); */
//   /* OP_MaxPgcnt ensures that the parameter passed to this function is not
//   ** less than the total number of valid pages in the database. But this
//   ** may be less than Pager.dbSize, and so the assert() above is not valid */
//   return pPager->mxPgno;
// }

// /*
// ** The following set of routines are used to disable the simulated
// ** I/O error mechanism.  These routines are used to avoid simulated
// ** errors in places where we do not care about errors.
// **
// ** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
// ** and generate no code.
// */
// #ifdef SQLITE_TEST
// extern int sqlite3_io_error_pending;
// extern int sqlite3_io_error_hit;
// static int saved_cnt;
// void disable_simulated_io_errors(void){
//   saved_cnt = sqlite3_io_error_pending;
//   sqlite3_io_error_pending = -1;
// }
// void enable_simulated_io_errors(void){
//   sqlite3_io_error_pending = saved_cnt;
// }
// #else
// # define disable_simulated_io_errors()
// # define enable_simulated_io_errors()
// #endif

// /*
// ** Read the first N bytes from the beginning of the file into memory
H
more  
Hongze Cheng 已提交
3219
// ** that pDest points to.
3220 3221 3222
// **
// ** If the pager was opened on a transient file (zFilename==""), or
// ** opened on a file less than N bytes in size, the output buffer is
H
more  
Hongze Cheng 已提交
3223
// ** zeroed and SQLITE_OK returned. The rationale for this is that this
3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255
// ** function is used to read database headers, and a new transient or
// ** zero sized database has a header than consists entirely of zeroes.
// **
// ** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
// ** the error code is returned to the caller and the contents of the
// ** output buffer undefined.
// */
// int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
//   int rc = SQLITE_OK;
//   memset(pDest, 0, N);
//   assert( isOpen(pPager->fd) || pPager->tempFile );

//   /* This routine is only called by btree immediately after creating
//   ** the Pager object.  There has not been an opportunity to transition
//   ** to WAL mode yet.
//   */
//   assert( !pagerUseWal(pPager) );

//   if( isOpen(pPager->fd) ){
//     IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
//     rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
//     if( rc==SQLITE_IOERR_SHORT_READ ){
//       rc = SQLITE_OK;
//     }
//   }
//   return rc;
// }

// /*
// ** This function may only be called when a read-transaction is open on
// ** the pager. It returns the total number of pages in the database.
// **
H
more  
Hongze Cheng 已提交
3256
// ** However, if the file is between 1 and <page-size> bytes in size, then
3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269
// ** this is considered a 1 page file.
// */
// void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
//   assert( pPager->eState>=PAGER_READER );
//   assert( pPager->eState!=PAGER_WRITER_FINISHED );
//   *pnPage = (int)pPager->dbSize;
// }

// /*
// ** Try to obtain a lock of type locktype on the database file. If
// ** a similar or greater lock is already held, this function is a no-op
// ** (returning SQLITE_OK immediately).
// **
H
more  
Hongze Cheng 已提交
3270 3271 3272
// ** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
// ** the busy callback if the lock is currently not available. Repeat
// ** until the busy callback returns false or until the attempt to
3273 3274 3275
// ** obtain the lock succeeds.
// **
// ** Return SQLITE_OK on success and an error code if we cannot obtain
H
more  
Hongze Cheng 已提交
3276
// ** the lock. If the lock is obtained successfully, set the Pager.state
3277 3278 3279 3280 3281
// ** variable to locktype before returning.
// */
// static int pager_wait_on_lock(Pager *pPager, int locktype){
//   int rc;                              /* Return code */

H
more  
Hongze Cheng 已提交
3282
//   /* Check that this is either a no-op (because the requested lock is
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298
//   ** already held), or one of the transitions that the busy-handler
//   ** may be invoked during, according to the comment above
//   ** sqlite3PagerSetBusyhandler().
//   */
//   assert( (pPager->eLock>=locktype)
//        || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
//        || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
//   );

//   do {
//     rc = pagerLockDb(pPager, locktype);
//   }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
3299
// ** Function assertTruncateConstraint(pPager) checks that one of the
3300 3301
// ** following is true for all dirty pages currently in the page-cache:
// **
H
more  
Hongze Cheng 已提交
3302
// **   a) The page number is less than or equal to the size of the
3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314
// **      current database image, in pages, OR
// **
// **   b) if the page content were written at this time, it would not
// **      be necessary to write the current content out to the sub-journal
// **      (as determined by function subjRequiresPage()).
// **
// ** If the condition asserted by this function were not true, and the
// ** dirty page were to be discarded from the cache via the pagerStress()
// ** routine, pagerStress() would not write the current page content to
// ** the database file. If a savepoint transaction were rolled back after
// ** this happened, the correct behavior would be to restore the current
// ** content of the page. However, since this content is not present in either
H
more  
Hongze Cheng 已提交
3315
// ** the database file or the portion of the rollback journal and
3316
// ** sub-journal rolled back the content could not be restored and the
H
more  
Hongze Cheng 已提交
3317
// ** database image would become corrupt. It is therefore fortunate that
3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332
// ** this circumstance cannot arise.
// */
// #if defined(SQLITE_DEBUG)
// static void assertTruncateConstraintCb(PgHdr *pPg){
//   assert( pPg->flags&PGHDR_DIRTY );
//   assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
// }
// static void assertTruncateConstraint(Pager *pPager){
//   sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
// }
// #else
// # define assertTruncateConstraint(pPager)
// #endif

// /*
H
more  
Hongze Cheng 已提交
3333 3334 3335
// ** Truncate the in-memory database file image to nPage pages. This
// ** function does not actually modify the database file on disk. It
// ** just sets the internal state of the pager object so that the
3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350
// ** truncation will be done when the current transaction is committed.
// **
// ** This function is only called right before committing a transaction.
// ** Once this function has been called, the transaction must either be
// ** rolled back or committed. It is not safe to call this function and
// ** then continue writing to the database.
// */
// void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
//   assert( pPager->dbSize>=nPage || CORRUPT_DB );
//   testcase( pPager->dbSize<nPage );
//   assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
//   pPager->dbSize = nPage;

//   /* At one point the code here called assertTruncateConstraint() to
//   ** ensure that all pages being truncated away by this operation are,
H
more  
Hongze Cheng 已提交
3351
//   ** if one or more savepoints are open, present in the savepoint
3352 3353
//   ** journal so that they can be restored if the savepoint is rolled
//   ** back. This is no longer necessary as this function is now only
H
more  
Hongze Cheng 已提交
3354 3355
//   ** called right before committing a transaction. So although the
//   ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
3356 3357 3358 3359 3360 3361 3362 3363 3364 3365
//   ** they cannot be rolled back. So the assertTruncateConstraint() call
//   ** is no longer correct. */
// }

// /*
// ** This function is called before attempting a hot-journal rollback. It
// ** syncs the journal file to disk, then sets pPager->journalHdr to the
// ** size of the journal file so that the pager_playback() routine knows
// ** that the entire journal file has been synced.
// **
H
more  
Hongze Cheng 已提交
3366
// ** Syncing a hot-journal to disk before attempting to roll it back ensures
3367 3368 3369 3370
// ** that if a power-failure occurs during the rollback, the process that
// ** attempts rollback following system recovery sees the same journal
// ** content as this process.
// **
H
more  
Hongze Cheng 已提交
3371
// ** If everything goes as planned, SQLITE_OK is returned. Otherwise,
3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386
// ** an SQLite error code.
// */
// static int pagerSyncHotJournal(Pager *pPager){
//   int rc = SQLITE_OK;
//   if( !pPager->noSync ){
//     rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
//   }
//   if( rc==SQLITE_OK ){
//     rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
//   }
//   return rc;
// }

// #if SQLITE_MAX_MMAP_SIZE>0
// /*
H
more  
Hongze Cheng 已提交
3387
// ** Obtain a reference to a memory mapped page object for page number pgno.
3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402
// ** The new object will use the pointer pData, obtained from xFetch().
// ** If successful, set *ppPage to point to the new page reference
// ** and return SQLITE_OK. Otherwise, return an SQLite error code and set
// ** *ppPage to zero.
// **
// ** Page references obtained by calling this function should be released
// ** by calling pagerReleaseMapPage().
// */
// static int pagerAcquireMapPage(
//   Pager *pPager,                  /* Pager object */
//   Pgno pgno,                      /* Page number */
//   void *pData,                    /* xFetch()'d data for this page */
//   PgHdr **ppPage                  /* OUT: Acquired page object */
// ){
//   PgHdr *p;                       /* Memory mapped page to return */
H
more  
Hongze Cheng 已提交
3403

3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436
//   if( pPager->pMmapFreelist ){
//     *ppPage = p = pPager->pMmapFreelist;
//     pPager->pMmapFreelist = p->pDirty;
//     p->pDirty = 0;
//     assert( pPager->nExtra>=8 );
//     memset(p->pExtra, 0, 8);
//   }else{
//     *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
//     if( p==0 ){
//       sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
//       return SQLITE_NOMEM;
//     }
//     p->pExtra = (void *)&p[1];
//     p->flags = PGHDR_MMAP;
//     p->nRef = 1;
//     p->pPager = pPager;
//   }

//   assert( p->pExtra==(void *)&p[1] );
//   assert( p->pPage==0 );
//   assert( p->flags==PGHDR_MMAP );
//   assert( p->pPager==pPager );
//   assert( p->nRef==1 );

//   p->pgno = pgno;
//   p->pData = pData;
//   pPager->nMmapOut++;

//   return SQLITE_OK;
// }
// #endif

// /*
H
more  
Hongze Cheng 已提交
3437
// ** Release a reference to page pPg. pPg must have been returned by an
3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485
// ** earlier call to pagerAcquireMapPage().
// */
// static void pagerReleaseMapPage(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   pPager->nMmapOut--;
//   pPg->pDirty = pPager->pMmapFreelist;
//   pPager->pMmapFreelist = pPg;

//   assert( pPager->fd->pMethods->iVersion>=3 );
//   sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
// }

// /*
// ** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
// */
// static void pagerFreeMapHdrs(Pager *pPager){
//   PgHdr *p;
//   PgHdr *pNext;
//   for(p=pPager->pMmapFreelist; p; p=pNext){
//     pNext = p->pDirty;
//     sqlite3_free(p);
//   }
// }

// /* Verify that the database file has not be deleted or renamed out from
// ** under the pager.  Return SQLITE_OK if the database is still where it ought
// ** to be on disk.  Return non-zero (SQLITE_READONLY_DBMOVED or some other error
// ** code from sqlite3OsAccess()) if the database has gone missing.
// */
// static int databaseIsUnmoved(Pager *pPager){
//   int bHasMoved = 0;
//   int rc;

//   if( pPager->tempFile ) return SQLITE_OK;
//   if( pPager->dbSize==0 ) return SQLITE_OK;
//   assert( pPager->zFilename && pPager->zFilename[0] );
//   rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
//   if( rc==SQLITE_NOTFOUND ){
//     /* If the HAS_MOVED file-control is unimplemented, assume that the file
//     ** has not been moved.  That is the historical behavior of SQLite: prior to
//     ** version 3.8.3, it never checked */
//     rc = SQLITE_OK;
//   }else if( rc==SQLITE_OK && bHasMoved ){
//     rc = SQLITE_READONLY_DBMOVED;
//   }
//   return rc;
// }

H
more  
Hongze Cheng 已提交
3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
/*
** Shutdown the page cache.  Free all memory and close all files.
**
** If a transaction was in progress when this routine is called, that
** transaction is rolled back.  All outstanding pages are invalidated
** and their memory is freed.  Any attempt to use a page associated
** with this page cache after this function returns will likely
** result in a coredump.
**
** This function always succeeds. If a transaction is active an attempt
** is made to roll it back. If an error occurs during the rollback
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
int sqlite3PagerClose(Pager *pPager, sqlite3 *db) {
  //   u8 *pTmp = (u8*)pPager->pTmpSpace;
  //   assert( db || pagerUseWal(pPager)==0 );
  //   assert( assert_pager_state(pPager) );
  //   disable_simulated_io_errors();
  //   sqlite3BeginBenignMalloc();
  //   pagerFreeMapHdrs(pPager);
  //   /* pPager->errCode = 0; */
  //   pPager->exclusiveMode = 0;
  // #ifndef SQLITE_OMIT_WAL
  //   {
  //     u8 *a = 0;
  //     assert( db || pPager->pWal==0 );
  //     if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
  //      && SQLITE_OK==databaseIsUnmoved(pPager)
  //     ){
  //       a = pTmp;
  //     }
  //     sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
  //     pPager->pWal = 0;
  //   }
  // #endif
  //   pager_reset(pPager);
  //   if( MEMDB ){
  //     pager_unlock(pPager);
  //   }else{
  //     /* If it is open, sync the journal file before calling UnlockAndRollback.
  //     ** If this is not done, then an unsynced portion of the open journal
  //     ** file may be played back into the database. If a power failure occurs
  //     ** while this is happening, the database could become corrupt.
  //     **
  //     ** If an error occurs while trying to sync the journal, shift the pager
  //     ** into the ERROR state. This causes UnlockAndRollback to unlock the
  //     ** database and close the journal file without attempting to roll it
  //     ** back or finalize it. The next database user will have to do hot-journal
  //     ** rollback before accessing the database file.
  //     */
  //     if( isOpen(pPager->jfd) ){
  //       pager_error(pPager, pagerSyncHotJournal(pPager));
  //     }
  //     pagerUnlockAndRollback(pPager);
  //   }
  //   sqlite3EndBenignMalloc();
  //   enable_simulated_io_errors();
  //   PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
  //   IOTRACE(("CLOSE %p\n", pPager))
  //   sqlite3OsClose(pPager->jfd);
  //   sqlite3OsClose(pPager->fd);
  //   sqlite3PageFree(pTmp);
  //   sqlite3PcacheClose(pPager->pPCache);
  //   assert( !pPager->aSavepoint && !pPager->pInJournal );
  //   assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );

  //   sqlite3_free(pPager);
  return SQLITE_OK;
}
3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578

// #if !defined(NDEBUG) || defined(SQLITE_TEST)
// /*
// ** Return the page number for page pPg.
// */
// Pgno sqlite3PagerPagenumber(DbPage *pPg){
//   return pPg->pgno;
// }
// #endif

// /*
// ** Increment the reference count for page pPg.
// */
// void sqlite3PagerRef(DbPage *pPg){
//   sqlite3PcacheRef(pPg);
// }

// /*
// ** Sync the journal. In other words, make sure all the pages that have
// ** been written to the journal have actually reached the surface of the
// ** disk and can be restored in the event of a hot-journal rollback.
// **
// ** If the Pager.noSync flag is set, then this function is a no-op.
H
more  
Hongze Cheng 已提交
3579
// ** Otherwise, the actions required depend on the journal-mode and the
3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590
// ** device characteristics of the file-system, as follows:
// **
// **   * If the journal file is an in-memory journal file, no action need
// **     be taken.
// **
// **   * Otherwise, if the device does not support the SAFE_APPEND property,
// **     then the nRec field of the most recently written journal header
// **     is updated to contain the number of journal records that have
// **     been written following it. If the pager is operating in full-sync
// **     mode, then the journal file is synced before this field is updated.
// **
H
more  
Hongze Cheng 已提交
3591
// **   * If the device does not support the SEQUENTIAL property, then
3592 3593 3594 3595 3596 3597 3598 3599
// **     journal file is synced.
// **
// ** Or, in pseudo-code:
// **
// **   if( NOT <in-memory journal> ){
// **     if( NOT SAFE_APPEND ){
// **       if( <full-sync mode> ) xSync(<journal file>);
// **       <update nRec field>
H
more  
Hongze Cheng 已提交
3600
// **     }
3601 3602 3603
// **     if( NOT SEQUENTIAL ) xSync(<journal file>);
// **   }
// **
H
more  
Hongze Cheng 已提交
3604
// ** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631
// ** page currently held in memory before returning SQLITE_OK. If an IO
// ** error is encountered, then the IO error code is returned to the caller.
// */
// static int syncJournal(Pager *pPager, int newHdr){
//   int rc;                         /* Return code */

//   assert( pPager->eState==PAGER_WRITER_CACHEMOD
//        || pPager->eState==PAGER_WRITER_DBMOD
//   );
//   assert( assert_pager_state(pPager) );
//   assert( !pagerUseWal(pPager) );

//   rc = sqlite3PagerExclusiveLock(pPager);
//   if( rc!=SQLITE_OK ) return rc;

//   if( !pPager->noSync ){
//     assert( !pPager->tempFile );
//     if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
//       const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
//       assert( isOpen(pPager->jfd) );

//       if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
//         /* This block deals with an obscure problem. If the last connection
//         ** that wrote to this database was operating in persistent-journal
//         ** mode, then the journal file may at this point actually be larger
//         ** than Pager.journalOff bytes. If the next thing in the journal
//         ** file happens to be a journal-header (written as part of the
H
more  
Hongze Cheng 已提交
3632 3633 3634 3635
//         ** previous connection's transaction), and a crash or power-failure
//         ** occurs after nRec is updated but before this connection writes
//         ** anything else to the journal file (or commits/rolls back its
//         ** transaction), then SQLite may become confused when doing the
3636 3637 3638 3639 3640 3641 3642 3643 3644
//         ** hot-journal rollback following recovery. It may roll back all
//         ** of this connections data, then proceed to rolling back the old,
//         ** out-of-date data that follows it. Database corruption.
//         **
//         ** To work around this, if the journal file does appear to contain
//         ** a valid header following Pager.journalOff, then write a 0x00
//         ** byte to the start of it to prevent it from being recognized.
//         **
//         ** Variable iNextHdrOffset is set to the offset at which this
H
more  
Hongze Cheng 已提交
3645
//         ** problematic header will occur, if it exists. aMagic is used
3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671
//         ** as a temporary buffer to inspect the first couple of bytes of
//         ** the potential journal header.
//         */
//         i64 iNextHdrOffset;
//         u8 aMagic[8];
//         u8 zHeader[sizeof(aJournalMagic)+4];

//         memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
//         put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);

//         iNextHdrOffset = journalHdrOffset(pPager);
//         rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
//         if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
//           static const u8 zerobyte = 0;
//           rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
//         }
//         if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
//           return rc;
//         }

//         /* Write the nRec value into the journal file header. If in
//         ** full-synchronous mode, sync the journal first. This ensures that
//         ** all data has really hit the disk before nRec is updated to mark
//         ** it as a candidate for rollback.
//         **
//         ** This is not required if the persistent media supports the
H
more  
Hongze Cheng 已提交
3672
//         ** SAFE_APPEND property. Because in this case it is not possible
3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691
//         ** for garbage data to be appended to the file, the nRec field
//         ** is populated with 0xFFFFFFFF when the journal header is written
//         ** and never needs to be updated.
//         */
//         if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
//           PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
//           IOTRACE(("JSYNC %p\n", pPager))
//           rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
//           if( rc!=SQLITE_OK ) return rc;
//         }
//         IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
//         rc = sqlite3OsWrite(
//             pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
//         );
//         if( rc!=SQLITE_OK ) return rc;
//       }
//       if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
//         PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
//         IOTRACE(("JSYNC %p\n", pPager))
H
more  
Hongze Cheng 已提交
3692
//         rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
//           (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
//         );
//         if( rc!=SQLITE_OK ) return rc;
//       }

//       pPager->journalHdr = pPager->journalOff;
//       if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
//         pPager->nRec = 0;
//         rc = writeJournalHdr(pPager);
//         if( rc!=SQLITE_OK ) return rc;
//       }
//     }else{
//       pPager->journalHdr = pPager->journalOff;
//     }
//   }

H
more  
Hongze Cheng 已提交
3709 3710
//   /* Unless the pager is in noSync mode, the journal file was just
//   ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729
//   ** all pages.
//   */
//   sqlite3PcacheClearSyncFlags(pPager->pPCache);
//   pPager->eState = PAGER_WRITER_DBMOD;
//   assert( assert_pager_state(pPager) );
//   return SQLITE_OK;
// }

// /*
// ** The argument is the first in a linked list of dirty pages connected
// ** by the PgHdr.pDirty pointer. This function writes each one of the
// ** in-memory pages in the list to the database file. The argument may
// ** be NULL, representing an empty list. In this case this function is
// ** a no-op.
// **
// ** The pager must hold at least a RESERVED lock when this function
// ** is called. Before writing anything to the database file, this lock
// ** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
// ** SQLITE_BUSY is returned and no data is written to the database file.
H
more  
Hongze Cheng 已提交
3730
// **
3731
// ** If the pager is a temp-file pager and the actual file-system file
H
more  
Hongze Cheng 已提交
3732
// ** is not yet open, it is created and opened before any data is
3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
// ** written out.
// **
// ** Once the lock has been upgraded and, if necessary, the file opened,
// ** the pages are written out to the database file in list order. Writing
// ** a page is skipped if it meets either of the following criteria:
// **
// **   * The page number is greater than Pager.dbSize, or
// **   * The PGHDR_DONT_WRITE flag is set on the page.
// **
// ** If writing out a page causes the database file to grow, Pager.dbFileSize
// ** is updated accordingly. If page 1 is written out, then the value cached
// ** in Pager.dbFileVers[] is updated to match the new value stored in
// ** the database file.
// **
H
more  
Hongze Cheng 已提交
3747
// ** If everything is successful, SQLITE_OK is returned. If an IO error
3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
// ** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
// ** be obtained, SQLITE_BUSY is returned.
// */
// static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
//   int rc = SQLITE_OK;                  /* Return code */

//   /* This function is only called for rollback pagers in WRITER_DBMOD state. */
//   assert( !pagerUseWal(pPager) );
//   assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
//   assert( pPager->eLock==EXCLUSIVE_LOCK );
//   assert( isOpen(pPager->fd) || pList->pDirty==0 );

//   /* If the file is a temp-file has not yet been opened, open it now. It
//   ** is not possible for rc to be other than SQLITE_OK if this branch
//   ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
//   */
//   if( !isOpen(pPager->fd) ){
//     assert( pPager->tempFile && rc==SQLITE_OK );
//     rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
//   }

//   /* Before the first write, give the VFS a hint of what the final
//   ** file size will be.
//   */
//   assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
H
more  
Hongze Cheng 已提交
3773
//   if( rc==SQLITE_OK
3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794
//    && pPager->dbHintSize<pPager->dbSize
//    && (pList->pDirty || pList->pgno>pPager->dbHintSize)
//   ){
//     sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
//     sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
//     pPager->dbHintSize = pPager->dbSize;
//   }

//   while( rc==SQLITE_OK && pList ){
//     Pgno pgno = pList->pgno;

//     /* If there are dirty pages in the page cache with page numbers greater
//     ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
//     ** make the file smaller (presumably by auto-vacuum code). Do not write
//     ** any such pages to the file.
//     **
//     ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
//     ** set (set by sqlite3PagerDontWrite()).
//     */
//     if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
//       i64 offset = (pgno-1)*(i64)pPager->pageSize;   /* Offset to write */
H
more  
Hongze Cheng 已提交
3795
//       char *pData;                                   /* Data to write */
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805

//       assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
//       if( pList->pgno==1 ) pager_write_changecounter(pList);

//       pData = pList->pData;

//       /* Write out the page data. */
//       rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);

//       /* If page 1 was just written, update Pager.dbFileVers to match
H
more  
Hongze Cheng 已提交
3806 3807
//       ** the value now stored in the database file. If writing this
//       ** page caused the database file to grow, update dbFileSize.
3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834
//       */
//       if( pgno==1 ){
//         memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
//       }
//       if( pgno>pPager->dbFileSize ){
//         pPager->dbFileSize = pgno;
//       }
//       pPager->aStat[PAGER_STAT_WRITE]++;

//       /* Update any backup objects copying the contents of this pager. */
//       sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);

//       PAGERTRACE(("STORE %d page %d hash(%08x)\n",
//                    PAGERID(pPager), pgno, pager_pagehash(pList)));
//       IOTRACE(("PGOUT %p %d\n", pPager, pgno));
//       PAGER_INCR(sqlite3_pager_writedb_count);
//     }else{
//       PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
//     }
//     pager_set_pagehash(pList);
//     pList = pList->pDirty;
//   }

//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
3835
// ** Ensure that the sub-journal file is open. If it is already open, this
3836 3837
// ** function is a no-op.
// **
H
more  
Hongze Cheng 已提交
3838 3839
// ** SQLITE_OK is returned if everything goes according to plan. An
// ** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
3840 3841 3842 3843 3844
// ** fails.
// */
// static int openSubJournal(Pager *pPager){
//   int rc = SQLITE_OK;
//   if( !isOpen(pPager->sjfd) ){
H
more  
Hongze Cheng 已提交
3845 3846
//     const int flags =  SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE
//       | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE
3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857
//       | SQLITE_OPEN_DELETEONCLOSE;
//     int nStmtSpill = sqlite3Config.nStmtSpill;
//     if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
//       nStmtSpill = -1;
//     }
//     rc = sqlite3JournalOpen(pPager->pVfs, 0, pPager->sjfd, flags, nStmtSpill);
//   }
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
3858
// ** Append a record of the current state of page pPg to the sub-journal.
3859 3860 3861 3862 3863
// **
// ** If successful, set the bit corresponding to pPg->pgno in the bitvecs
// ** for all open savepoints before returning.
// **
// ** This function returns SQLITE_OK if everything is successful, an IO
H
more  
Hongze Cheng 已提交
3864
// ** error code if the attempt to write to the sub-journal fails, or
3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876
// ** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
// ** bitvec.
// */
// static int subjournalPage(PgHdr *pPg){
//   int rc = SQLITE_OK;
//   Pager *pPager = pPg->pPager;
//   if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){

//     /* Open the sub-journal, if it has not already been opened */
//     assert( pPager->useJournal );
//     assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
//     assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
H
more  
Hongze Cheng 已提交
3877 3878 3879
//     assert( pagerUseWal(pPager)
//          || pageInJournal(pPager, pPg)
//          || pPg->pgno>pPager->dbOrigSize
3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915
//     );
//     rc = openSubJournal(pPager);

//     /* If the sub-journal was opened successfully (or was already open),
//     ** write the journal record into the file.  */
//     if( rc==SQLITE_OK ){
//       void *pData = pPg->pData;
//       i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
//       char *pData2;
//       pData2 = pData;
//       PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
//       rc = write32bits(pPager->sjfd, offset, pPg->pgno);
//       if( rc==SQLITE_OK ){
//         rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
//       }
//     }
//   }
//   if( rc==SQLITE_OK ){
//     pPager->nSubRec++;
//     assert( pPager->nSavepoint>0 );
//     rc = addToSavepointBitvecs(pPager, pPg->pgno);
//   }
//   return rc;
// }
// static int subjournalPageIfRequired(PgHdr *pPg){
//   if( subjRequiresPage(pPg) ){
//     return subjournalPage(pPg);
//   }else{
//     return SQLITE_OK;
//   }
// }

// /*
// ** This function is called by the pcache layer when it has reached some
// ** soft memory limit. The first argument is a pointer to a Pager object
// ** (cast as a void*). The pager is always 'purgeable' (not an in-memory
H
more  
Hongze Cheng 已提交
3916
// ** database). The second argument is a reference to a page that is
3917
// ** currently dirty but has no outstanding references. The page
H
more  
Hongze Cheng 已提交
3918
// ** is always associated with the Pager object passed as the first
3919 3920 3921 3922
// ** argument.
// **
// ** The job of this function is to make pPg clean by writing its contents
// ** out to the database file, if possible. This may involve syncing the
H
more  
Hongze Cheng 已提交
3923
// ** journal file.
3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947
// **
// ** If successful, sqlite3PcacheMakeClean() is called on the page and
// ** SQLITE_OK returned. If an IO error occurs while trying to make the
// ** page clean, the IO error code is returned. If the page cannot be
// ** made clean for some other reason, but no error occurs, then SQLITE_OK
// ** is returned by sqlite3PcacheMakeClean() is not called.
// */
// static int pagerStress(void *p, PgHdr *pPg){
//   Pager *pPager = (Pager *)p;
//   int rc = SQLITE_OK;

//   assert( pPg->pPager==pPager );
//   assert( pPg->flags&PGHDR_DIRTY );

//   /* The doNotSpill NOSYNC bit is set during times when doing a sync of
//   ** journal (and adding a new header) is not allowed.  This occurs
//   ** during calls to sqlite3PagerWrite() while trying to journal multiple
//   ** pages belonging to the same sector.
//   **
//   ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
//   ** regardless of whether or not a sync is required.  This is set during
//   ** a rollback or by user request, respectively.
//   **
//   ** Spilling is also prohibited when in an error state since that could
H
more  
Hongze Cheng 已提交
3948
//   ** lead to database corruption.   In the current implementation it
3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968
//   ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3
//   ** while in the error state, hence it is impossible for this routine to
//   ** be called in the error state.  Nevertheless, we include a NEVER()
//   ** test for the error state as a safeguard against future changes.
//   */
//   if( NEVER(pPager->errCode) ) return SQLITE_OK;
//   testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
//   testcase( pPager->doNotSpill & SPILLFLAG_OFF );
//   testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
//   if( pPager->doNotSpill
//    && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
//       || (pPg->flags & PGHDR_NEED_SYNC)!=0)
//   ){
//     return SQLITE_OK;
//   }

//   pPager->aStat[PAGER_STAT_SPILL]++;
//   pPg->pDirty = 0;
//   if( pagerUseWal(pPager) ){
//     /* Write a single frame for this page to the log. */
H
more  
Hongze Cheng 已提交
3969
//     rc = subjournalPageIfRequired(pPg);
3970 3971 3972 3973
//     if( rc==SQLITE_OK ){
//       rc = pagerWalFrames(pPager, pPg, 0, 0);
//     }
//   }else{
H
more  
Hongze Cheng 已提交
3974

3975 3976 3977 3978 3979 3980
// #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
//     if( pPager->tempFile==0 ){
//       rc = sqlite3JournalCreate(pPager->jfd);
//       if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
//     }
// #endif
H
more  
Hongze Cheng 已提交
3981

3982
//     /* Sync the journal file if required. */
H
more  
Hongze Cheng 已提交
3983
//     if( pPg->flags&PGHDR_NEED_SYNC
3984 3985 3986 3987
//      || pPager->eState==PAGER_WRITER_CACHEMOD
//     ){
//       rc = syncJournal(pPager, 1);
//     }
H
more  
Hongze Cheng 已提交
3988

3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001
//     /* Write the contents of the page out to the database file. */
//     if( rc==SQLITE_OK ){
//       assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
//       rc = pager_write_pagelist(pPager, pPg);
//     }
//   }

//   /* Mark the page as clean. */
//   if( rc==SQLITE_OK ){
//     PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
//     sqlite3PcacheMakeClean(pPg);
//   }

H
more  
Hongze Cheng 已提交
4002
//   return pager_error(pPager, rc);
4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024
// }

// /*
// ** Flush all unreferenced dirty pages to disk.
// */
// int sqlite3PagerFlush(Pager *pPager){
//   int rc = pPager->errCode;
//   if( !MEMDB ){
//     PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
//     assert( assert_pager_state(pPager) );
//     while( rc==SQLITE_OK && pList ){
//       PgHdr *pNext = pList->pDirty;
//       if( pList->nRef==0 ){
//         rc = pagerStress((void*)pPager, pList);
//       }
//       pList = pNext;
//     }
//   }

//   return rc;
// }

H
more  
Hongze Cheng 已提交
4025 4026 4027 4028 4029 4030 4031 4032
int sqlite3PagerOpen(Pager **ppPager, const char *zFilename, int nExtra, int flags, int vfsFlags,
                     void (*xReinit)(DbPage *)) {
  u8 *        pPtr;
  Pager *     pPager = 0;                                     /* Pager object to allocate and return */
  int         rc = SQLITE_OK;                                 /* Return code */
  int         tempFile = 0;                                   /* True for temp files (incl. in-memory files) */
  int         memDb = 0;                                      /* True if this is an in-memory file */
  int         memJM = 0;                                      /* Memory journal mode */
H
Hongze Cheng 已提交
4033 4034
  int         readOnly = 0;                                   /* True if this is a read-only file */
  int         journalFileSize;                                /* Bytes to allocate for each journal fd */
H
more  
Hongze Cheng 已提交
4035
  int         nPathname = 120;                                /* Number of bytes in zPathname */
H
Hongze Cheng 已提交
4036 4037 4038 4039 4040 4041
  int         useJournal = (flags & PAGER_OMIT_JOURNAL) == 0; /* False to omit journal */
  int         pcacheSize = sqlite3PcacheSize();               /* Bytes to allocate for PCache */
  u32         szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;          /* Default page size */
  const char *zUri = 0;                                       /* URI args to copy */
  int         nUriByte = 1;                                   /* Number of bytes of URI args at *zUri */
  int         nUri = 0;                                       /* Number of URI parameters */
H
more  
Hongze Cheng 已提交
4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183
  int         tsize;

  journalFileSize = 120;

  /* Set the output variable to NULL in case an error occurs. */
  *ppPager = 0;

  tsize = ROUND8(sizeof(*pPager)) /* Pager */
          + ROUND8(pcacheSize)    /* PCache */
          + sizeof(pPager)        /* Self contained pager pointer */
          + 4                     /* Database prefix (4 Bytes) */
          + nPathname + 1         /* Database file name */
          + nPathname + 8 + 1     /* Journal file name */
          + nPathname + 4 + 1     /* WAL file name */
          + 3;                    /* 3 bytes of terminalter */

  pPtr = (u8 *)calloc(1, tsize);
  if (!pPtr) {
    return SQLITE_NOMEM;
  }
  pPager = (Pager *)pPtr;
  pPtr += ROUND8(sizeof(*pPager));
  pPager->pPCache = (PCache *)pPtr;
  pPtr += ROUND8(pcacheSize);
  memcpy(pPtr, &pPager, sizeof(pPager));
  pPtr += sizeof(pPager);
  pPtr += 4;
  pPager->zFilename = (char *)pPtr;
  memcpy(pPtr, zFilename, strlen(zFilename));
  pPtr += (nPathname + 1);
  pPager->zJournal = (char *)pPtr;
  memcpy(pPtr, zFilename, strlen(zFilename));
  pPtr += nPathname;
  memcpy(pPtr, "-journal", 8);
  pPtr += 8 + 1;
  pPager->zWal = (char *)pPtr;
  memcpy(pPtr, zFilename, nPathname);
  pPtr += nPathname;
  memcpy(pPtr, "-wal", 4);
  pPtr += 4 + 1;

  pPager->vfsFlags = vfsFlags;

  /* Open the pager file.
   */
  int fout = 0; /* VFS flags returned by xOpen() */
  pPager->fd = open(zFilename, O_RDWR | O_CREAT, 0755);
  if (pPager->fd < 0) {
    return -1;
  }
  readOnly = 0;

  /* If the file was successfully opened for read/write access,
  ** choose a default page size in case we have to create the
  ** database file. The default page size is the maximum of:
  **
  **    + SQLITE_DEFAULT_PAGE_SIZE,
  **    + The value returned by sqlite3OsSectorSize()
  **    + The largest page size that can be written atomically.
  */
  if (rc == SQLITE_OK) {
    int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
    if (!readOnly) {
      setSectorSize(pPager);
      assert(SQLITE_DEFAULT_PAGE_SIZE <= SQLITE_MAX_DEFAULT_PAGE_SIZE);
      if (szPageDflt < pPager->sectorSize) {
        if (pPager->sectorSize > SQLITE_MAX_DEFAULT_PAGE_SIZE) {
          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
        } else {
          szPageDflt = (u32)pPager->sectorSize;
        }
      }
    }
    pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
    if ((iDc & SQLITE_IOCAP_IMMUTABLE) != 0 || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0)) {
      vfsFlags |= SQLITE_OPEN_READONLY;
      goto act_like_temp_file;
    }
  }
  /* The following call to PagerSetPagesize() serves to set the value of
  ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
  */
  if (rc == SQLITE_OK) {
    assert(pPager->memDb == 0);
    rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
    testcase(rc != SQLITE_OK);
  }

  /* Initialize the PCache object. */
  if (rc == SQLITE_OK) {
    nExtra = ROUND8(nExtra);
    assert(nExtra >= 8 && nExtra < 1000);
    rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb ? pagerStress : 0, (void *)pPager, pPager->pPCache);
  }

  /* If an error occurred above, free the  Pager structure and close the file.
   */
  if (rc != SQLITE_OK) {
    sqlite3OsClose(pPager->fd);
    sqlite3PageFree(pPager->pTmpSpace);
    sqlite3_free(pPager);
    return rc;
  }

  PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  pPager->useJournal = (u8)useJournal;
  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
  pPager->tempFile = (u8)tempFile;
  assert(tempFile == PAGER_LOCKINGMODE_NORMAL || tempFile == PAGER_LOCKINGMODE_EXCLUSIVE);
  assert(PAGER_LOCKINGMODE_EXCLUSIVE == 1);
  pPager->exclusiveMode = (u8)tempFile;
  pPager->changeCountDone = pPager->tempFile;
  pPager->memDb = (u8)memDb;
  pPager->readOnly = (u8)readOnly;
  assert(useJournal || pPager->tempFile);
  pPager->noSync = pPager->tempFile;
  if (pPager->noSync) {
    assert(pPager->fullSync == 0);
    assert(pPager->extraSync == 0);
    assert(pPager->syncFlags == 0);
    assert(pPager->walSyncFlags == 0);
  } else {
    pPager->fullSync = 1;
    pPager->extraSync = 0;
    pPager->syncFlags = SQLITE_SYNC_NORMAL;
    pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL << 2);
  }
  pPager->nExtra = (u16)nExtra;
  pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
  assert(isOpen(pPager->fd) || tempFile);
  setSectorSize(pPager);
  if (!useJournal) {
    pPager->journalMode = PAGER_JOURNALMODE_OFF;
  } else if (memDb || memJM) {
    pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  }
  pPager->xReiniter = xReinit;
  setGetterMethod(pPager);

  *ppPager = pPager;
H
more  
Hongze Cheng 已提交
4184 4185
  return SQLITE_OK;
}
4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203

// /*
// ** Return the sqlite3_file for the main database given the name
// ** of the corresonding WAL or Journal name as passed into
// ** xOpen.
// */
// sqlite3_file *sqlite3_database_file_object(const char *zName){
//   Pager *pPager;
//   while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
//     zName--;
//   }
//   pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
//   return pPager->fd;
// }

// /*
// ** This function is called after transitioning from PAGER_UNLOCK to
// ** PAGER_SHARED state. It tests if there is a hot journal present in
H
more  
Hongze Cheng 已提交
4204
// ** the file-system for the given pager. A hot journal is one that
4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222
// ** needs to be played back. According to this function, a hot-journal
// ** file exists if the following criteria are met:
// **
// **   * The journal file exists in the file system, and
// **   * No process holds a RESERVED or greater lock on the database file, and
// **   * The database file itself is greater than 0 bytes in size, and
// **   * The first byte of the journal file exists and is not 0x00.
// **
// ** If the current size of the database file is 0 but a journal file
// ** exists, that is probably an old journal left over from a prior
// ** database with the same name. In this case the journal file is
// ** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
// ** is returned.
// **
// ** This routine does not check if there is a super-journal filename
// ** at the end of the file. If there is, and that super-journal file
// ** does not exist, then the journal file is not really hot. In this
// ** case this routine will return a false-positive. The pager_playback()
H
more  
Hongze Cheng 已提交
4223 4224
// ** routine will discover that the journal file is not really hot and
// ** will not roll it back.
4225
// **
H
more  
Hongze Cheng 已提交
4226
// ** If a hot-journal file is found to exist, *pExists is set to 1 and
4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253
// ** SQLITE_OK returned. If no hot-journal file is present, *pExists is
// ** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
// ** to determine whether or not a hot-journal file exists, the IO error
// ** code is returned and the value of *pExists is undefined.
// */
// static int hasHotJournal(Pager *pPager, int *pExists){
//   sqlite3_vfs * const pVfs = pPager->pVfs;
//   int rc = SQLITE_OK;           /* Return code */
//   int exists = 1;               /* True if a journal file is present */
//   int jrnlOpen = !!isOpen(pPager->jfd);

//   assert( pPager->useJournal );
//   assert( isOpen(pPager->fd) );
//   assert( pPager->eState==PAGER_OPEN );

//   assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
//     SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
//   ));

//   *pExists = 0;
//   if( !jrnlOpen ){
//     rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
//   }
//   if( rc==SQLITE_OK && exists ){
//     int locked = 0;             /* True if some process holds a RESERVED lock */

//     /* Race condition here:  Another process might have been holding the
H
more  
Hongze Cheng 已提交
4254
//     ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286
//     ** call above, but then delete the journal and drop the lock before
//     ** we get to the following sqlite3OsCheckReservedLock() call.  If that
//     ** is the case, this routine might think there is a hot journal when
//     ** in fact there is none.  This results in a false-positive which will
//     ** be dealt with by the playback routine.  Ticket #3883.
//     */
//     rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
//     if( rc==SQLITE_OK && !locked ){
//       Pgno nPage;                 /* Number of pages in database file */

//       assert( pPager->tempFile==0 );
//       rc = pagerPagecount(pPager, &nPage);
//       if( rc==SQLITE_OK ){
//         /* If the database is zero pages in size, that means that either (1) the
//         ** journal is a remnant from a prior database with the same name where
//         ** the database file but not the journal was deleted, or (2) the initial
//         ** transaction that populates a new database is being rolled back.
//         ** In either case, the journal file can be deleted.  However, take care
//         ** not to delete the journal file if it is already open due to
//         ** journal_mode=PERSIST.
//         */
//         if( nPage==0 && !jrnlOpen ){
//           sqlite3BeginBenignMalloc();
//           if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
//             sqlite3OsDelete(pVfs, pPager->zJournal, 0);
//             if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
//           }
//           sqlite3EndBenignMalloc();
//         }else{
//           /* The journal file exists and no other connection has a reserved
//           ** or greater lock on the database file. Now check that there is
//           ** at least one non-zero bytes at the start of the journal file.
H
more  
Hongze Cheng 已提交
4287
//           ** If there is, then we consider this journal to be hot. If not,
4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336
//           ** it can be ignored.
//           */
//           if( !jrnlOpen ){
//             int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
//             rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
//           }
//           if( rc==SQLITE_OK ){
//             u8 first = 0;
//             rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
//             if( rc==SQLITE_IOERR_SHORT_READ ){
//               rc = SQLITE_OK;
//             }
//             if( !jrnlOpen ){
//               sqlite3OsClose(pPager->jfd);
//             }
//             *pExists = (first!=0);
//           }else if( rc==SQLITE_CANTOPEN ){
//             /* If we cannot open the rollback journal file in order to see if
//             ** it has a zero header, that might be due to an I/O error, or
//             ** it might be due to the race condition described above and in
//             ** ticket #3883.  Either way, assume that the journal is hot.
//             ** This might be a false positive.  But if it is, then the
//             ** automatic journal playback and recovery mechanism will deal
//             ** with it under an EXCLUSIVE lock where we do not need to
//             ** worry so much with race conditions.
//             */
//             *pExists = 1;
//             rc = SQLITE_OK;
//           }
//         }
//       }
//     }
//   }

//   return rc;
// }

// /*
// ** This function is called to obtain a shared lock on the database file.
// ** It is illegal to call sqlite3PagerGet() until after this function
// ** has been successfully called. If a shared-lock is already held when
// ** this function is called, it is a no-op.
// **
// ** The following operations are also performed by this function.
// **
// **   1) If the pager is currently in PAGER_OPEN state (no lock held
// **      on the database file), then an attempt is made to obtain a
// **      SHARED lock on the database file. Immediately after obtaining
// **      the SHARED lock, the file-system is checked for a hot-journal,
H
more  
Hongze Cheng 已提交
4337
// **      which is played back if present. Following any hot-journal
4338 4339 4340 4341 4342 4343 4344 4345 4346 4347
// **      rollback, the contents of the cache are validated by checking
// **      the 'change-counter' field of the database file header and
// **      discarded if they are found to be invalid.
// **
// **   2) If the pager is running in exclusive-mode, and there are currently
// **      no outstanding references to any pages, and is in the error state,
// **      then an attempt is made to clear the error state by discarding
// **      the contents of the page cache and rolling back any open journal
// **      file.
// **
H
more  
Hongze Cheng 已提交
4348 4349
// ** If everything is successful, SQLITE_OK is returned. If an IO error
// ** occurs while locking the database, checking for a hot-journal file or
4350 4351 4352 4353 4354 4355 4356
// ** rolling back a journal file, the IO error code is returned.
// */
// int sqlite3PagerSharedLock(Pager *pPager){
//   int rc = SQLITE_OK;                /* Return code */

//   /* This routine is only called from b-tree and only when there are no
//   ** outstanding pages. This implies that the pager state should either
H
more  
Hongze Cheng 已提交
4357
//   ** be OPEN or READER. READER is only possible if the pager is or was in
4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
//   ** exclusive access mode.  */
//   assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
//   assert( assert_pager_state(pPager) );
//   assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
//   assert( pPager->errCode==SQLITE_OK );

//   if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
//     int bHotJournal = 1;          /* True if there exists a hot journal-file */

//     assert( !MEMDB );
//     assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );

//     rc = pager_wait_on_lock(pPager, SHARED_LOCK);
//     if( rc!=SQLITE_OK ){
//       assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
//       goto failed;
//     }

//     /* If a journal file exists, and there is no RESERVED lock on the
//     ** database file, then it either needs to be played back or deleted.
//     */
//     if( pPager->eLock<=SHARED_LOCK ){
//       rc = hasHotJournal(pPager, &bHotJournal);
//     }
//     if( rc!=SQLITE_OK ){
//       goto failed;
//     }
//     if( bHotJournal ){
//       if( pPager->readOnly ){
//         rc = SQLITE_READONLY_ROLLBACK;
//         goto failed;
//       }

//       /* Get an EXCLUSIVE lock on the database file. At this point it is
//       ** important that a RESERVED lock is not obtained on the way to the
//       ** EXCLUSIVE lock. If it were, another process might open the
//       ** database file, detect the RESERVED lock, and conclude that the
H
more  
Hongze Cheng 已提交
4395
//       ** database is safe to read while this process is still rolling the
4396
//       ** hot-journal back.
H
more  
Hongze Cheng 已提交
4397
//       **
4398
//       ** Because the intermediate RESERVED lock is not requested, any
H
more  
Hongze Cheng 已提交
4399 4400
//       ** other process attempting to access the database file will get to
//       ** this point in the code and fail to obtain its own EXCLUSIVE lock
4401 4402 4403 4404 4405 4406 4407 4408 4409
//       ** on the database file.
//       **
//       ** Unless the pager is in locking_mode=exclusive mode, the lock is
//       ** downgraded to SHARED_LOCK before this function returns.
//       */
//       rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
//       if( rc!=SQLITE_OK ){
//         goto failed;
//       }
H
more  
Hongze Cheng 已提交
4410 4411 4412 4413 4414 4415

//       /* If it is not already open and the file exists on disk, open the
//       ** journal for read/write access. Write access is required because
//       ** in exclusive-access mode the file descriptor will be kept open
//       ** and possibly used for a transaction later on. Also, write-access
//       ** is usually required to finalize the journal in journal_mode=persist
4416 4417
//       ** mode (and also for journal_mode=truncate on some systems).
//       **
H
more  
Hongze Cheng 已提交
4418 4419 4420
//       ** If the journal does not exist, it usually means that some
//       ** other connection managed to get in and roll it back before
//       ** this connection obtained the exclusive lock above. Or, it
4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440
//       ** may mean that the pager was in the error-state when this
//       ** function was called and the journal file does not exist.
//       */
//       if( !isOpen(pPager->jfd) ){
//         sqlite3_vfs * const pVfs = pPager->pVfs;
//         int bExists;              /* True if journal file exists */
//         rc = sqlite3OsAccess(
//             pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
//         if( rc==SQLITE_OK && bExists ){
//           int fout = 0;
//           int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
//           assert( !pPager->tempFile );
//           rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
//           assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
//           if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
//             rc = SQLITE_CANTOPEN_BKPT;
//             sqlite3OsClose(pPager->jfd);
//           }
//         }
//       }
H
more  
Hongze Cheng 已提交
4441

4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465
//       /* Playback and delete the journal.  Drop the database write
//       ** lock and reacquire the read lock. Purge the cache before
//       ** playing back the hot-journal so that we don't end up with
//       ** an inconsistent cache.  Sync the hot journal before playing
//       ** it back since the process that crashed and left the hot journal
//       ** probably did not sync it and we are required to always sync
//       ** the journal before playing it back.
//       */
//       if( isOpen(pPager->jfd) ){
//         assert( rc==SQLITE_OK );
//         rc = pagerSyncHotJournal(pPager);
//         if( rc==SQLITE_OK ){
//           rc = pager_playback(pPager, !pPager->tempFile);
//           pPager->eState = PAGER_OPEN;
//         }
//       }else if( !pPager->exclusiveMode ){
//         pagerUnlockDb(pPager, SHARED_LOCK);
//       }

//       if( rc!=SQLITE_OK ){
//         /* This branch is taken if an error occurs while trying to open
//         ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
//         ** pager_unlock() routine will be called before returning to unlock
//         ** the file. If the unlock attempt fails, then Pager.eLock must be
H
more  
Hongze Cheng 已提交
4466 4467
//         ** set to UNKNOWN_LOCK (see the comment above the #define for
//         ** UNKNOWN_LOCK above for an explanation).
4468 4469 4470 4471 4472 4473 4474
//         **
//         ** In order to get pager_unlock() to do this, set Pager.eState to
//         ** PAGER_ERROR now. This is not actually counted as a transition
//         ** to ERROR state in the state diagram at the top of this file,
//         ** since we know that the same call to pager_unlock() will very
//         ** shortly transition the pager object to the OPEN state. Calling
//         ** assert_pager_state() would fail now, as it should not be possible
H
more  
Hongze Cheng 已提交
4475
//         ** to be in ERROR state when there are zero outstanding page
4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499
//         ** references.
//         */
//         pager_error(pPager, rc);
//         goto failed;
//       }

//       assert( pPager->eState==PAGER_OPEN );
//       assert( (pPager->eLock==SHARED_LOCK)
//            || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
//       );
//     }

//     if( !pPager->tempFile && pPager->hasHeldSharedLock ){
//       /* The shared-lock has just been acquired then check to
//       ** see if the database has been modified.  If the database has changed,
//       ** flush the cache.  The hasHeldSharedLock flag prevents this from
//       ** occurring on the very first access to a file, in order to save a
//       ** single unnecessary sqlite3OsRead() call at the start-up.
//       **
//       ** Database changes are detected by looking at 15 bytes beginning
//       ** at offset 24 into the file.  The first 4 of these 16 bytes are
//       ** a 32-bit counter that is incremented with each change.  The
//       ** other bytes change randomly with each file change when
//       ** a codec is in use.
H
more  
Hongze Cheng 已提交
4500 4501
//       **
//       ** There is a vanishingly small chance that a change will not be
4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567
//       ** detected.  The chance of an undetected change is so small that
//       ** it can be neglected.
//       */
//       char dbFileVers[sizeof(pPager->dbFileVers)];

//       IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
//       rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
//       if( rc!=SQLITE_OK ){
//         if( rc!=SQLITE_IOERR_SHORT_READ ){
//           goto failed;
//         }
//         memset(dbFileVers, 0, sizeof(dbFileVers));
//       }

//       if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
//         pager_reset(pPager);

//         /* Unmap the database file. It is possible that external processes
//         ** may have truncated the database file and then extended it back
//         ** to its original size while this process was not holding a lock.
//         ** In this case there may exist a Pager.pMap mapping that appears
//         ** to be the right size but is not actually valid. Avoid this
//         ** possibility by unmapping the db here. */
//         if( USEFETCH(pPager) ){
//           sqlite3OsUnfetch(pPager->fd, 0, 0);
//         }
//       }
//     }

//     /* If there is a WAL file in the file-system, open this database in WAL
//     ** mode. Otherwise, the following function call is a no-op.
//     */
//     rc = pagerOpenWalIfPresent(pPager);
// #ifndef SQLITE_OMIT_WAL
//     assert( pPager->pWal==0 || rc==SQLITE_OK );
// #endif
//   }

//   if( pagerUseWal(pPager) ){
//     assert( rc==SQLITE_OK );
//     rc = pagerBeginReadTransaction(pPager);
//   }

//   if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
//     rc = pagerPagecount(pPager, &pPager->dbSize);
//   }

//  failed:
//   if( rc!=SQLITE_OK ){
//     assert( !MEMDB );
//     pager_unlock(pPager);
//     assert( pPager->eState==PAGER_OPEN );
//   }else{
//     pPager->eState = PAGER_READER;
//     pPager->hasHeldSharedLock = 1;
//   }
//   return rc;
// }

// /*
// ** If the reference count has reached zero, rollback any active
// ** transaction and unlock the pager.
// **
// ** Except, in locking_mode=EXCLUSIVE when there is nothing to in
// ** the rollback journal, the unlock is not performed and there is
// ** nothing to rollback, so this routine is a no-op.
H
more  
Hongze Cheng 已提交
4568
// */
4569 4570 4571 4572 4573 4574 4575 4576 4577
// static void pagerUnlockIfUnused(Pager *pPager){
//   if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
//     assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
//     pagerUnlockAndRollback(pPager);
//   }
// }

// /*
// ** The page getter methods each try to acquire a reference to a
H
more  
Hongze Cheng 已提交
4578
// ** page with page number pgno. If the requested reference is
4579 4580 4581 4582 4583 4584 4585 4586 4587
// ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
// **
// ** There are different implementations of the getter method depending
// ** on the current state of the pager.
// **
// **     getPageNormal()         --  The normal getter
// **     getPageError()          --  Used if the pager is in an error state
// **     getPageMmap()           --  Used if memory-mapped I/O is enabled
// **
H
more  
Hongze Cheng 已提交
4588
// ** If the requested page is already in the cache, it is returned.
4589 4590 4591 4592 4593
// ** Otherwise, a new page object is allocated and populated with data
// ** read from the database file. In some cases, the pcache module may
// ** choose not to allocate a new page object and may reuse an existing
// ** object with no outstanding references.
// **
H
more  
Hongze Cheng 已提交
4594 4595
// ** The extra data appended to a page is always initialized to zeros the
// ** first time a page is loaded into memory. If the page requested is
4596 4597 4598
// ** already in the cache when this function is called, then the extra
// ** data is left as it was when the page object was last used.
// **
H
more  
Hongze Cheng 已提交
4599 4600 4601 4602 4603
// ** If the database image is smaller than the requested page or if
// ** the flags parameter contains the PAGER_GET_NOCONTENT bit and the
// ** requested page is not already stored in the cache, then no
// ** actual disk read occurs. In this case the memory image of the
// ** page is initialized to all zeros.
4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673
// **
// ** If PAGER_GET_NOCONTENT is true, it means that we do not care about
// ** the contents of the page. This occurs in two scenarios:
// **
// **   a) When reading a free-list leaf page from the database, and
// **
// **   b) When a savepoint is being rolled back and we need to load
// **      a new page into the cache to be filled with the data read
// **      from the savepoint journal.
// **
// ** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead
// ** of being read from the database. Additionally, the bits corresponding
// ** to pgno in Pager.pInJournal (bitvec of pages already written to the
// ** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
// ** savepoints are set. This means if the page is made writable at any
// ** point in the future, using a call to sqlite3PagerWrite(), its contents
// ** will not be journaled. This saves IO.
// **
// ** The acquisition might fail for several reasons.  In all cases,
// ** an appropriate error code is returned and *ppPage is set to NULL.
// **
// ** See also sqlite3PagerLookup().  Both this routine and Lookup() attempt
// ** to find a page in the in-memory cache first.  If the page is not already
// ** in memory, this routine goes to disk to read it in whereas Lookup()
// ** just returns 0.  This routine acquires a read-lock the first time it
// ** has to go to disk, and could also playback an old journal if necessary.
// ** Since Lookup() never goes to disk, it never has to deal with locks
// ** or journal files.
// */
// static int getPageNormal(
//   Pager *pPager,      /* The pager open on the database file */
//   Pgno pgno,          /* Page number to fetch */
//   DbPage **ppPage,    /* Write a pointer to the page here */
//   int flags           /* PAGER_GET_XXX flags */
// ){
//   int rc = SQLITE_OK;
//   PgHdr *pPg;
//   u8 noContent;                   /* True if PAGER_GET_NOCONTENT is set */
//   sqlite3_pcache_page *pBase;

//   assert( pPager->errCode==SQLITE_OK );
//   assert( pPager->eState>=PAGER_READER );
//   assert( assert_pager_state(pPager) );
//   assert( pPager->hasHeldSharedLock==1 );

//   if( pgno==0 ) return SQLITE_CORRUPT_BKPT;
//   pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
//   if( pBase==0 ){
//     pPg = 0;
//     rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
//     if( rc!=SQLITE_OK ) goto pager_acquire_err;
//     if( pBase==0 ){
//       rc = SQLITE_NOMEM;
//       goto pager_acquire_err;
//     }
//   }
//   pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
//   assert( pPg==(*ppPage) );
//   assert( pPg->pgno==pgno );
//   assert( pPg->pPager==pPager || pPg->pPager==0 );

//   noContent = (flags & PAGER_GET_NOCONTENT)!=0;
//   if( pPg->pPager && !noContent ){
//     /* In this case the pcache already contains an initialized copy of
//     ** the page. Return without further ado.  */
//     assert( pgno!=PAGER_MJ_PGNO(pPager) );
//     pPager->aStat[PAGER_STAT_HIT]++;
//     return SQLITE_OK;

//   }else{
H
more  
Hongze Cheng 已提交
4674
//     /* The pager cache has created a new page. Its content needs to
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694
//     ** be initialized. But first some error checks:
//     **
//     ** (*) obsolete.  Was: maximum page number is 2^31
//     ** (2) Never try to fetch the locking page
//     */
//     if( pgno==PAGER_MJ_PGNO(pPager) ){
//       rc = SQLITE_CORRUPT_BKPT;
//       goto pager_acquire_err;
//     }

//     pPg->pPager = pPager;

//     assert( !isOpen(pPager->fd) || !MEMDB );
//     if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
//       if( pgno>pPager->mxPgno ){
//         rc = SQLITE_FULL;
//         goto pager_acquire_err;
//       }
//       if( noContent ){
//         /* Failure to set the bits in the InJournal bit-vectors is benign.
H
more  
Hongze Cheng 已提交
4695 4696 4697
//         ** It merely means that we might do some extra work to journal a
//         ** page that does not need to be journaled.  Nevertheless, be sure
//         ** to test the case where a malloc error occurs while trying to set
4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746
//         ** a bit in a bit vector.
//         */
//         sqlite3BeginBenignMalloc();
//         if( pgno<=pPager->dbOrigSize ){
//           TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
//           testcase( rc==SQLITE_NOMEM );
//         }
//         TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
//         testcase( rc==SQLITE_NOMEM );
//         sqlite3EndBenignMalloc();
//       }
//       memset(pPg->pData, 0, pPager->pageSize);
//       IOTRACE(("ZERO %p %d\n", pPager, pgno));
//     }else{
//       assert( pPg->pPager==pPager );
//       pPager->aStat[PAGER_STAT_MISS]++;
//       rc = readDbPage(pPg);
//       if( rc!=SQLITE_OK ){
//         goto pager_acquire_err;
//       }
//     }
//     pager_set_pagehash(pPg);
//   }
//   return SQLITE_OK;

// pager_acquire_err:
//   assert( rc!=SQLITE_OK );
//   if( pPg ){
//     sqlite3PcacheDrop(pPg);
//   }
//   pagerUnlockIfUnused(pPager);
//   *ppPage = 0;
//   return rc;
// }

// #if SQLITE_MAX_MMAP_SIZE>0
// /* The page getter for when memory-mapped I/O is enabled */
// static int getPageMMap(
//   Pager *pPager,      /* The pager open on the database file */
//   Pgno pgno,          /* Page number to fetch */
//   DbPage **ppPage,    /* Write a pointer to the page here */
//   int flags           /* PAGER_GET_XXX flags */
// ){
//   int rc = SQLITE_OK;
//   PgHdr *pPg = 0;
//   u32 iFrame = 0;                 /* Frame to read from WAL file */

//   /* It is acceptable to use a read-only (mmap) page for any page except
//   ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
H
more  
Hongze Cheng 已提交
4747
//   ** flag was specified by the caller. And so long as the db is not a
4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775
//   ** temporary or in-memory database.  */
//   const int bMmapOk = (pgno>1
//    && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
//   );

//   assert( USEFETCH(pPager) );

//   /* Optimization note:  Adding the "pgno<=1" term before "pgno==0" here
//   ** allows the compiler optimizer to reuse the results of the "pgno>1"
//   ** test in the previous statement, and avoid testing pgno==0 in the
//   ** common case where pgno is large. */
//   if( pgno<=1 && pgno==0 ){
//     return SQLITE_CORRUPT_BKPT;
//   }
//   assert( pPager->eState>=PAGER_READER );
//   assert( assert_pager_state(pPager) );
//   assert( pPager->hasHeldSharedLock==1 );
//   assert( pPager->errCode==SQLITE_OK );

//   if( bMmapOk && pagerUseWal(pPager) ){
//     rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
//     if( rc!=SQLITE_OK ){
//       *ppPage = 0;
//       return rc;
//     }
//   }
//   if( bMmapOk && iFrame==0 ){
//     void *pData = 0;
H
more  
Hongze Cheng 已提交
4776
//     rc = sqlite3OsFetch(pPager->fd,
4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830
//         (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
//     );
//     if( rc==SQLITE_OK && pData ){
//       if( pPager->eState>PAGER_READER || pPager->tempFile ){
//         pPg = sqlite3PagerLookup(pPager, pgno);
//       }
//       if( pPg==0 ){
//         rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
//       }else{
//         sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
//       }
//       if( pPg ){
//         assert( rc==SQLITE_OK );
//         *ppPage = pPg;
//         return SQLITE_OK;
//       }
//     }
//     if( rc!=SQLITE_OK ){
//       *ppPage = 0;
//       return rc;
//     }
//   }
//   return getPageNormal(pPager, pgno, ppPage, flags);
// }
// #endif /* SQLITE_MAX_MMAP_SIZE>0 */

// /* The page getter method for when the pager is an error state */
// static int getPageError(
//   Pager *pPager,      /* The pager open on the database file */
//   Pgno pgno,          /* Page number to fetch */
//   DbPage **ppPage,    /* Write a pointer to the page here */
//   int flags           /* PAGER_GET_XXX flags */
// ){
//   UNUSED_PARAMETER(pgno);
//   UNUSED_PARAMETER(flags);
//   assert( pPager->errCode!=SQLITE_OK );
//   *ppPage = 0;
//   return pPager->errCode;
// }

// /* Dispatch all page fetch requests to the appropriate getter method.
// */
// int sqlite3PagerGet(
//   Pager *pPager,      /* The pager open on the database file */
//   Pgno pgno,          /* Page number to fetch */
//   DbPage **ppPage,    /* Write a pointer to the page here */
//   int flags           /* PAGER_GET_XXX flags */
// ){
//   return pPager->xGet(pPager, pgno, ppPage, flags);
// }

// /*
// ** Acquire a page if it is already in the in-memory cache.  Do
// ** not read the page from disk.  Return a pointer to the page,
H
more  
Hongze Cheng 已提交
4831
// ** or 0 if the page is not in cache.
4832 4833 4834 4835
// **
// ** See also sqlite3PagerGet().  The difference between this routine
// ** and sqlite3PagerGet() is that _get() will go to the disk and read
// ** in the page if the page is not already in cache.  This routine
H
more  
Hongze Cheng 已提交
4836
// ** returns NULL if the page is not in cache or if a disk I/O error
4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888
// ** has ever happened.
// */
// DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
//   sqlite3_pcache_page *pPage;
//   assert( pPager!=0 );
//   assert( pgno!=0 );
//   assert( pPager->pPCache!=0 );
//   pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
//   assert( pPage==0 || pPager->hasHeldSharedLock );
//   if( pPage==0 ) return 0;
//   return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
// }

// /*
// ** Release a page reference.
// **
// ** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be
// ** used if we know that the page being released is not the last page.
// ** The btree layer always holds page1 open until the end, so these first
// ** to routines can be used to release any page other than BtShared.pPage1.
// **
// ** Use sqlite3PagerUnrefPageOne() to release page1.  This latter routine
// ** checks the total number of outstanding pages and if the number of
// ** pages reaches zero it drops the database lock.
// */
// void sqlite3PagerUnrefNotNull(DbPage *pPg){
//   TESTONLY( Pager *pPager = pPg->pPager; )
//   assert( pPg!=0 );
//   if( pPg->flags & PGHDR_MMAP ){
//     assert( pPg->pgno!=1 );  /* Page1 is never memory mapped */
//     pagerReleaseMapPage(pPg);
//   }else{
//     sqlite3PcacheRelease(pPg);
//   }
//   /* Do not use this routine to release the last reference to page1 */
//   assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
// }
// void sqlite3PagerUnref(DbPage *pPg){
//   if( pPg ) sqlite3PagerUnrefNotNull(pPg);
// }
// void sqlite3PagerUnrefPageOne(DbPage *pPg){
//   Pager *pPager;
//   assert( pPg!=0 );
//   assert( pPg->pgno==1 );
//   assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
//   pPager = pPg->pPager;
//   sqlite3PcacheRelease(pPg);
//   pagerUnlockIfUnused(pPager);
// }

// /*
// ** This function is called at the start of every write transaction.
H
more  
Hongze Cheng 已提交
4889
// ** There must already be a RESERVED or EXCLUSIVE lock on the database
4890 4891 4892 4893
// ** file when this routine is called.
// **
// ** Open the journal file for pager pPager and write a journal header
// ** to the start of it. If there are active savepoints, open the sub-journal
H
more  
Hongze Cheng 已提交
4894 4895
// ** as well. This function is only used when the journal file is being
// ** opened to write a rollback log for a transaction. It is not used
4896 4897 4898 4899
// ** when opening a hot journal file to roll it back.
// **
// ** If the journal file is already open (as it may be in exclusive mode),
// ** then this function just writes a journal header to the start of the
H
more  
Hongze Cheng 已提交
4900
// ** already open file.
4901 4902 4903 4904
// **
// ** Whether or not the journal file is opened by this function, the
// ** Pager.pInJournal bitvec structure is allocated.
// **
H
more  
Hongze Cheng 已提交
4905 4906
// ** Return SQLITE_OK if everything is successful. Otherwise, return
// ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
4907 4908 4909 4910 4911 4912 4913 4914 4915
// ** an IO error code if opening or writing the journal file fails.
// */
// static int pager_open_journal(Pager *pPager){
//   int rc = SQLITE_OK;                        /* Return code */
//   sqlite3_vfs * const pVfs = pPager->pVfs;   /* Local cache of vfs pointer */

//   assert( pPager->eState==PAGER_WRITER_LOCKED );
//   assert( assert_pager_state(pPager) );
//   assert( pPager->pInJournal==0 );
H
more  
Hongze Cheng 已提交
4916

4917 4918 4919 4920 4921 4922 4923 4924 4925 4926
//   /* If already in the error state, this function is a no-op.  But on
//   ** the other hand, this routine is never called if we are already in
//   ** an error state. */
//   if( NEVER(pPager->errCode) ) return pPager->errCode;

//   if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
//     pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
//     if( pPager->pInJournal==0 ){
//       return SQLITE_NOMEM;
//     }
H
more  
Hongze Cheng 已提交
4927

4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942
//     /* Open the journal file if it is not already open. */
//     if( !isOpen(pPager->jfd) ){
//       if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
//         sqlite3MemJournalOpen(pPager->jfd);
//       }else{
//         int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
//         int nSpill;

//         if( pPager->tempFile ){
//           flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
//           nSpill = sqlite3Config.nStmtSpill;
//         }else{
//           flags |= SQLITE_OPEN_MAIN_JOURNAL;
//           nSpill = jrnlBufferSize(pPager);
//         }
H
more  
Hongze Cheng 已提交
4943

4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954
//         /* Verify that the database still has the same name as it did when
//         ** it was originally opened. */
//         rc = databaseIsUnmoved(pPager);
//         if( rc==SQLITE_OK ){
//           rc = sqlite3JournalOpen (
//               pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
//           );
//         }
//       }
//       assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
//     }
H
more  
Hongze Cheng 已提交
4955 4956

//     /* Write the first journal header to the journal file and open
4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980
//     ** the sub-journal if necessary.
//     */
//     if( rc==SQLITE_OK ){
//       /* TODO: Check if all of these are really required. */
//       pPager->nRec = 0;
//       pPager->journalOff = 0;
//       pPager->setSuper = 0;
//       pPager->journalHdr = 0;
//       rc = writeJournalHdr(pPager);
//     }
//   }

//   if( rc!=SQLITE_OK ){
//     sqlite3BitvecDestroy(pPager->pInJournal);
//     pPager->pInJournal = 0;
//   }else{
//     assert( pPager->eState==PAGER_WRITER_LOCKED );
//     pPager->eState = PAGER_WRITER_CACHEMOD;
//   }

//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
4981
// ** Begin a write-transaction on the specified pager object. If a
4982 4983 4984 4985
// ** write-transaction has already been opened, this function is a no-op.
// **
// ** If the exFlag argument is false, then acquire at least a RESERVED
// ** lock on the database file. If exFlag is true, then acquire at least
H
more  
Hongze Cheng 已提交
4986
// ** an EXCLUSIVE lock. If such a lock is already held, no locking
4987 4988 4989 4990 4991 4992 4993
// ** functions need be called.
// **
// ** If the subjInMemory argument is non-zero, then any sub-journal opened
// ** within this transaction will be opened as an in-memory file. This
// ** has no effect if the sub-journal is already opened (as it may be when
// ** running in exclusive mode) or if the transaction does not require a
// ** sub-journal. If the subjInMemory argument is zero, then any required
H
more  
Hongze Cheng 已提交
4994
// ** sub-journal is implemented in-memory if pPager is an in-memory database,
4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041
// ** or using a temporary file otherwise.
// */
// int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
//   int rc = SQLITE_OK;

//   if( pPager->errCode ) return pPager->errCode;
//   assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
//   pPager->subjInMemory = (u8)subjInMemory;

//   if( pPager->eState==PAGER_READER ){
//     assert( pPager->pInJournal==0 );

//     if( pagerUseWal(pPager) ){
//       /* If the pager is configured to use locking_mode=exclusive, and an
//       ** exclusive lock on the database is not already held, obtain it now.
//       */
//       if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
//         rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
//         if( rc!=SQLITE_OK ){
//           return rc;
//         }
//         (void)sqlite3WalExclusiveMode(pPager->pWal, 1);
//       }

//       /* Grab the write lock on the log file. If successful, upgrade to
//       ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
//       ** The busy-handler is not invoked if another connection already
//       ** holds the write-lock. If possible, the upper layer will call it.
//       */
//       rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
//     }else{
//       /* Obtain a RESERVED lock on the database file. If the exFlag parameter
//       ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
//       ** busy-handler callback can be used when upgrading to the EXCLUSIVE
//       ** lock, but not when obtaining the RESERVED lock.
//       */
//       rc = pagerLockDb(pPager, RESERVED_LOCK);
//       if( rc==SQLITE_OK && exFlag ){
//         rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
//       }
//     }

//     if( rc==SQLITE_OK ){
//       /* Change to WRITER_LOCKED state.
//       **
//       ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
//       ** when it has an open transaction, but never to DBMOD or FINISHED.
H
more  
Hongze Cheng 已提交
5042 5043 5044
//       ** This is because in those states the code to roll back savepoint
//       ** transactions may copy data from the sub-journal into the database
//       ** file as well as into the page cache. Which would be incorrect in
5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097
//       ** WAL mode.
//       */
//       pPager->eState = PAGER_WRITER_LOCKED;
//       pPager->dbHintSize = pPager->dbSize;
//       pPager->dbFileSize = pPager->dbSize;
//       pPager->dbOrigSize = pPager->dbSize;
//       pPager->journalOff = 0;
//     }

//     assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
//     assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
//     assert( assert_pager_state(pPager) );
//   }

//   PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
//   return rc;
// }

// /*
// ** Write page pPg onto the end of the rollback journal.
// */
// static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   int rc;
//   u32 cksum;
//   char *pData2;
//   i64 iOff = pPager->journalOff;

//   /* We should never write to the journal file the page that
//   ** contains the database locks.  The following assert verifies
//   ** that we do not. */
//   assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );

//   assert( pPager->journalHdr<=pPager->journalOff );
//   pData2 = pPg->pData;
//   cksum = pager_cksum(pPager, (u8*)pData2);

//   /* Even if an IO or diskfull error occurs while journalling the
//   ** page in the block above, set the need-sync flag for the page.
//   ** Otherwise, when the transaction is rolled back, the logic in
//   ** playback_one_page() will think that the page needs to be restored
//   ** in the database file. And if an IO error occurs while doing so,
//   ** then corruption may follow.
//   */
//   pPg->flags |= PGHDR_NEED_SYNC;

//   rc = write32bits(pPager->jfd, iOff, pPg->pgno);
//   if( rc!=SQLITE_OK ) return rc;
//   rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
//   if( rc!=SQLITE_OK ) return rc;
//   rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
//   if( rc!=SQLITE_OK ) return rc;

H
more  
Hongze Cheng 已提交
5098
//   IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
5099 5100 5101
//            pPager->journalOff, pPager->pageSize));
//   PAGER_INCR(sqlite3_pager_writej_count);
//   PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
H
more  
Hongze Cheng 已提交
5102
//        PAGERID(pPager), pPg->pgno,
5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116
//        ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));

//   pPager->journalOff += 8 + pPager->pageSize;
//   pPager->nRec++;
//   assert( pPager->pInJournal!=0 );
//   rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
//   testcase( rc==SQLITE_NOMEM );
//   assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
//   rc |= addToSavepointBitvecs(pPager, pPg->pgno);
//   assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
5117
// ** Mark a single data page as writeable. The page is written into the
5118
// ** main journal or sub-journal as required. If the page is written into
H
more  
Hongze Cheng 已提交
5119
// ** one of the journals, the corresponding bit is set in the
5120 5121 5122 5123 5124 5125 5126
// ** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
// ** of any open savepoints as appropriate.
// */
// static int pager_write(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   int rc = SQLITE_OK;

H
more  
Hongze Cheng 已提交
5127
//   /* This routine is not called unless a write-transaction has already
5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143
//   ** been started. The journal file may or may not be open at this point.
//   ** It is never called in the ERROR state.
//   */
//   assert( pPager->eState==PAGER_WRITER_LOCKED
//        || pPager->eState==PAGER_WRITER_CACHEMOD
//        || pPager->eState==PAGER_WRITER_DBMOD
//   );
//   assert( assert_pager_state(pPager) );
//   assert( pPager->errCode==0 );
//   assert( pPager->readOnly==0 );
//   CHECK_PAGE(pPg);

//   /* The journal file needs to be opened. Higher level routines have already
//   ** obtained the necessary locks to begin the write-transaction, but the
//   ** rollback journal might not yet be open. Open it now if this is the case.
//   **
H
more  
Hongze Cheng 已提交
5144
//   ** This is done before calling sqlite3PcacheMakeDirty() on the page.
5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188
//   ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
//   ** an error might occur and the pager would end up in WRITER_LOCKED state
//   ** with pages marked as dirty in the cache.
//   */
//   if( pPager->eState==PAGER_WRITER_LOCKED ){
//     rc = pager_open_journal(pPager);
//     if( rc!=SQLITE_OK ) return rc;
//   }
//   assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
//   assert( assert_pager_state(pPager) );

//   /* Mark the page that is about to be modified as dirty. */
//   sqlite3PcacheMakeDirty(pPg);

//   /* If a rollback journal is in use, them make sure the page that is about
//   ** to change is in the rollback journal, or if the page is a new page off
//   ** then end of the file, make sure it is marked as PGHDR_NEED_SYNC.
//   */
//   assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) );
//   if( pPager->pInJournal!=0
//    && sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0
//   ){
//     assert( pagerUseWal(pPager)==0 );
//     if( pPg->pgno<=pPager->dbOrigSize ){
//       rc = pagerAddPageToRollbackJournal(pPg);
//       if( rc!=SQLITE_OK ){
//         return rc;
//       }
//     }else{
//       if( pPager->eState!=PAGER_WRITER_DBMOD ){
//         pPg->flags |= PGHDR_NEED_SYNC;
//       }
//       PAGERTRACE(("APPEND %d page %d needSync=%d\n",
//               PAGERID(pPager), pPg->pgno,
//              ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
//     }
//   }

//   /* The PGHDR_DIRTY bit is set above when the page was added to the dirty-list
//   ** and before writing the page into the rollback journal.  Wait until now,
//   ** after the page has been successfully journalled, before setting the
//   ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified.
//   */
//   pPg->flags |= PGHDR_WRITEABLE;
H
more  
Hongze Cheng 已提交
5189

5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272
//   /* If the statement journal is open and the page is not in it,
//   ** then write the page into the statement journal.
//   */
//   if( pPager->nSavepoint>0 ){
//     rc = subjournalPageIfRequired(pPg);
//   }

//   /* Update the database size and return. */
//   if( pPager->dbSize<pPg->pgno ){
//     pPager->dbSize = pPg->pgno;
//   }
//   return rc;
// }

// /*
// ** This is a variant of sqlite3PagerWrite() that runs when the sector size
// ** is larger than the page size.  SQLite makes the (reasonable) assumption that
// ** all bytes of a sector are written together by hardware.  Hence, all bytes of
// ** a sector need to be journalled in case of a power loss in the middle of
// ** a write.
// **
// ** Usually, the sector size is less than or equal to the page size, in which
// ** case pages can be individually written.  This routine only runs in the
// ** exceptional case where the page size is smaller than the sector size.
// */
// static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
//   int rc = SQLITE_OK;          /* Return code */
//   Pgno nPageCount;             /* Total number of pages in database file */
//   Pgno pg1;                    /* First page of the sector pPg is located on. */
//   int nPage = 0;               /* Number of pages starting at pg1 to journal */
//   int ii;                      /* Loop counter */
//   int needSync = 0;            /* True if any page has PGHDR_NEED_SYNC */
//   Pager *pPager = pPg->pPager; /* The pager that owns pPg */
//   Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);

//   /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
//   ** a journal header to be written between the pages journaled by
//   ** this function.
//   */
//   assert( !MEMDB );
//   assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
//   pPager->doNotSpill |= SPILLFLAG_NOSYNC;

//   /* This trick assumes that both the page-size and sector-size are
//   ** an integer power of 2. It sets variable pg1 to the identifier
//   ** of the first page of the sector pPg is located on.
//   */
//   pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;

//   nPageCount = pPager->dbSize;
//   if( pPg->pgno>nPageCount ){
//     nPage = (pPg->pgno - pg1)+1;
//   }else if( (pg1+nPagePerSector-1)>nPageCount ){
//     nPage = nPageCount+1-pg1;
//   }else{
//     nPage = nPagePerSector;
//   }
//   assert(nPage>0);
//   assert(pg1<=pPg->pgno);
//   assert((pg1+nPage)>pPg->pgno);

//   for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
//     Pgno pg = pg1+ii;
//     PgHdr *pPage;
//     if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
//       if( pg!=PAGER_MJ_PGNO(pPager) ){
//         rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
//         if( rc==SQLITE_OK ){
//           rc = pager_write(pPage);
//           if( pPage->flags&PGHDR_NEED_SYNC ){
//             needSync = 1;
//           }
//           sqlite3PagerUnrefNotNull(pPage);
//         }
//       }
//     }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){
//       if( pPage->flags&PGHDR_NEED_SYNC ){
//         needSync = 1;
//       }
//       sqlite3PagerUnrefNotNull(pPage);
//     }
//   }

H
more  
Hongze Cheng 已提交
5273
//   /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
//   ** starting at pg1, then it needs to be set for all of them. Because
//   ** writing to any of these nPage pages may damage the others, the
//   ** journal file must contain sync()ed copies of all of them
//   ** before any of them can be written out to the database file.
//   */
//   if( rc==SQLITE_OK && needSync ){
//     assert( !MEMDB );
//     for(ii=0; ii<nPage; ii++){
//       PgHdr *pPage = sqlite3PagerLookup(pPager, pg1+ii);
//       if( pPage ){
//         pPage->flags |= PGHDR_NEED_SYNC;
//         sqlite3PagerUnrefNotNull(pPage);
//       }
//     }
//   }

//   assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
//   pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
5296 5297 5298
// ** Mark a data page as writeable. This routine must be called before
// ** making changes to a page. The caller must check the return value
// ** of this function and be careful not to change any page data unless
5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348
// ** this routine returns SQLITE_OK.
// **
// ** The difference between this function and pager_write() is that this
// ** function also deals with the special case where 2 or more pages
// ** fit on a single disk sector. In this case all co-resident pages
// ** must have been written to the journal file before returning.
// **
// ** If an error occurs, SQLITE_NOMEM or an IO error code is returned
// ** as appropriate. Otherwise, SQLITE_OK.
// */
// int sqlite3PagerWrite(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   assert( (pPg->flags & PGHDR_MMAP)==0 );
//   assert( pPager->eState>=PAGER_WRITER_LOCKED );
//   assert( assert_pager_state(pPager) );
//   if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
//     if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
//     return SQLITE_OK;
//   }else if( pPager->errCode ){
//     return pPager->errCode;
//   }else if( pPager->sectorSize > (u32)pPager->pageSize ){
//     assert( pPager->tempFile==0 );
//     return pagerWriteLargeSector(pPg);
//   }else{
//     return pager_write(pPg);
//   }
// }

// /*
// ** Return TRUE if the page given in the argument was previously passed
// ** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
// ** to change the content of the page.
// */
// #ifndef NDEBUG
// int sqlite3PagerIswriteable(DbPage *pPg){
//   return pPg->flags & PGHDR_WRITEABLE;
// }
// #endif

// /*
// ** A call to this routine tells the pager that it is not necessary to
// ** write the information on page pPg back to the disk, even though
// ** that page might be marked as dirty.  This happens, for example, when
// ** the page has been added as a leaf of the freelist and so its
// ** content no longer matters.
// **
// ** The overlying software layer calls this routine when all of the data
// ** on the given page is unused. The pager marks the page as clean so
// ** that it does not get written to disk.
// **
H
more  
Hongze Cheng 已提交
5349
// ** Tests show that this optimization can quadruple the speed of large
5350 5351 5352 5353
// ** DELETE operations.
// **
// ** This optimization cannot be used with a temp-file, as the page may
// ** have been dirty at the start of the transaction. In that case, if
H
more  
Hongze Cheng 已提交
5354 5355
// ** memory pressure forces page pPg out of the cache, the data does need
// ** to be written out to disk so that it may be read back in if the
5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370
// ** current transaction is rolled back.
// */
// void sqlite3PagerDontWrite(PgHdr *pPg){
//   Pager *pPager = pPg->pPager;
//   if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
//     PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
//     IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
//     pPg->flags |= PGHDR_DONT_WRITE;
//     pPg->flags &= ~PGHDR_WRITEABLE;
//     testcase( pPg->flags & PGHDR_NEED_SYNC );
//     pager_set_pagehash(pPg);
//   }
// }

// /*
H
more  
Hongze Cheng 已提交
5371 5372
// ** This routine is called to increment the value of the database file
// ** change-counter, stored as a 4-byte big-endian integer starting at
5373 5374 5375 5376 5377
// ** byte offset 24 of the pager file.  The secondary change counter at
// ** 92 is also updated, as is the SQLite version number at offset 96.
// **
// ** But this only happens if the pPager->changeCountDone flag is false.
// ** To avoid excess churning of page 1, the update only happens once.
H
more  
Hongze Cheng 已提交
5378
// ** See also the pager_write_changecounter() routine that does an
5379 5380
// ** unconditional update of the change counters.
// **
H
more  
Hongze Cheng 已提交
5381
// ** If the isDirectMode flag is zero, then this is done by calling
5382 5383 5384 5385 5386 5387 5388
// ** sqlite3PagerWrite() on page 1, then modifying the contents of the
// ** page data. In this case the file will be updated when the current
// ** transaction is committed.
// **
// ** The isDirectMode flag may only be non-zero if the library was compiled
// ** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
// ** if isDirect is non-zero, then the database file is updated directly
H
more  
Hongze Cheng 已提交
5389
// ** by writing an updated version of page 1 using a call to the
5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427
// ** sqlite3OsWrite() function.
// */
// static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
//   int rc = SQLITE_OK;

//   assert( pPager->eState==PAGER_WRITER_CACHEMOD
//        || pPager->eState==PAGER_WRITER_DBMOD
//   );
//   assert( assert_pager_state(pPager) );

//   /* Declare and initialize constant integer 'isDirect'. If the
//   ** atomic-write optimization is enabled in this build, then isDirect
//   ** is initialized to the value passed as the isDirectMode parameter
//   ** to this function. Otherwise, it is always set to zero.
//   **
//   ** The idea is that if the atomic-write optimization is not
//   ** enabled at compile time, the compiler can omit the tests of
//   ** 'isDirect' below, as well as the block enclosed in the
//   ** "if( isDirect )" condition.
//   */
// #ifndef SQLITE_ENABLE_ATOMIC_WRITE
// # define DIRECT_MODE 0
//   assert( isDirectMode==0 );
//   UNUSED_PARAMETER(isDirectMode);
// #else
// # define DIRECT_MODE isDirectMode
// #endif

//   if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
//     PgHdr *pPgHdr;                /* Reference to page 1 */

//     assert( !pPager->tempFile && isOpen(pPager->fd) );

//     /* Open page 1 of the file for writing. */
//     rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0);
//     assert( pPgHdr==0 || rc==SQLITE_OK );

//     /* If page one was fetched successfully, and this function is not
H
more  
Hongze Cheng 已提交
5428
//     ** operating in direct-mode, make page 1 writable.  When not in
5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488
//     ** direct mode, page 1 is always held in cache and hence the PagerGet()
//     ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
//     */
//     if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
//       rc = sqlite3PagerWrite(pPgHdr);
//     }

//     if( rc==SQLITE_OK ){
//       /* Actually do the update of the change counter */
//       pager_write_changecounter(pPgHdr);

//       /* If running in direct mode, write the contents of page 1 to the file. */
//       if( DIRECT_MODE ){
//         const void *zBuf;
//         assert( pPager->dbFileSize>0 );
//         zBuf = pPgHdr->pData;
//         if( rc==SQLITE_OK ){
//           rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
//           pPager->aStat[PAGER_STAT_WRITE]++;
//         }
//         if( rc==SQLITE_OK ){
//           /* Update the pager's copy of the change-counter. Otherwise, the
//           ** next time a read transaction is opened the cache will be
//           ** flushed (as the change-counter values will not match).  */
//           const void *pCopy = (const void *)&((const char *)zBuf)[24];
//           memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
//           pPager->changeCountDone = 1;
//         }
//       }else{
//         pPager->changeCountDone = 1;
//       }
//     }

//     /* Release the page reference. */
//     sqlite3PagerUnref(pPgHdr);
//   }
//   return rc;
// }

// /*
// ** Sync the database file to disk. This is a no-op for in-memory databases
// ** or pages with the Pager.noSync flag set.
// **
// ** If successful, or if called on a pager for which it is a no-op, this
// ** function returns SQLITE_OK. Otherwise, an IO error code is returned.
// */
// int sqlite3PagerSync(Pager *pPager, const char *zSuper){
//   int rc = SQLITE_OK;
//   void *pArg = (void*)zSuper;
//   rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
//   if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
//   if( rc==SQLITE_OK && !pPager->noSync ){
//     assert( !MEMDB );
//     rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
//   }
//   return rc;
// }

// /*
// ** This function may only be called while a write-transaction is active in
H
more  
Hongze Cheng 已提交
5489 5490
// ** rollback. If the connection is in WAL mode, this call is a no-op.
// ** Otherwise, if the connection does not already have an EXCLUSIVE lock on
5491 5492 5493 5494
// ** the database file, an attempt is made to obtain one.
// **
// ** If the EXCLUSIVE lock is already held or the attempt to obtain it is
// ** successful, or the connection is in WAL mode, SQLITE_OK is returned.
H
more  
Hongze Cheng 已提交
5495
// ** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
5496 5497 5498 5499 5500 5501
// ** returned.
// */
// int sqlite3PagerExclusiveLock(Pager *pPager){
//   int rc = pPager->errCode;
//   assert( assert_pager_state(pPager) );
//   if( rc==SQLITE_OK ){
H
more  
Hongze Cheng 已提交
5502 5503 5504
//     assert( pPager->eState==PAGER_WRITER_CACHEMOD
//          || pPager->eState==PAGER_WRITER_DBMOD
//          || pPager->eState==PAGER_WRITER_LOCKED
5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516
//     );
//     assert( assert_pager_state(pPager) );
//     if( 0==pagerUseWal(pPager) ){
//       rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
//     }
//   }
//   return rc;
// }

// /*
// ** Sync the database file for the pager pPager. zSuper points to the name
// ** of a super-journal file that should be written into the individual
H
more  
Hongze Cheng 已提交
5517
// ** journal file. zSuper may be NULL, which is interpreted as no
5518 5519 5520 5521 5522 5523
// ** super-journal (a single database transaction).
// **
// ** This routine ensures that:
// **
// **   * The database file change-counter is updated,
// **   * the journal is synced (unless the atomic-write optimization is used),
H
more  
Hongze Cheng 已提交
5524
// **   * all dirty pages are written to the database file,
5525
// **   * the database file is truncated (if required), and
H
more  
Hongze Cheng 已提交
5526
// **   * the database file synced.
5527
// **
H
more  
Hongze Cheng 已提交
5528 5529
// ** The only thing that remains to commit the transaction is to finalize
// ** (delete, truncate or zero the first part of) the journal file (or
5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559
// ** delete the super-journal file if specified).
// **
// ** Note that if zSuper==NULL, this does not overwrite a previous value
// ** passed to an sqlite3PagerCommitPhaseOne() call.
// **
// ** If the final parameter - noSync - is true, then the database file itself
// ** is not synced. The caller must call sqlite3PagerSync() directly to
// ** sync the database file before calling CommitPhaseTwo() to delete the
// ** journal file in this case.
// */
// int sqlite3PagerCommitPhaseOne(
//   Pager *pPager,                  /* Pager object */
//   const char *zSuper,            /* If not NULL, the super-journal name */
//   int noSync                      /* True to omit the xSync on the db file */
// ){
//   int rc = SQLITE_OK;             /* Return code */

//   assert( pPager->eState==PAGER_WRITER_LOCKED
//        || pPager->eState==PAGER_WRITER_CACHEMOD
//        || pPager->eState==PAGER_WRITER_DBMOD
//        || pPager->eState==PAGER_ERROR
//   );
//   assert( assert_pager_state(pPager) );

//   /* If a prior error occurred, report that error again. */
//   if( NEVER(pPager->errCode) ) return pPager->errCode;

//   /* Provide the ability to easily simulate an I/O error during testing */
//   if( sqlite3FaultSim(400) ) return SQLITE_IOERR;

H
more  
Hongze Cheng 已提交
5560
//   PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n",
5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610
//       pPager->zFilename, zSuper, pPager->dbSize));

//   /* If no database changes have been made, return early. */
//   if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;

//   assert( MEMDB==0 || pPager->tempFile );
//   assert( isOpen(pPager->fd) || pPager->tempFile );
//   if( 0==pagerFlushOnCommit(pPager, 1) ){
//     /* If this is an in-memory db, or no pages have been written to, or this
//     ** function has already been called, it is mostly a no-op.  However, any
//     ** backup in progress needs to be restarted.  */
//     sqlite3BackupRestart(pPager->pBackup);
//   }else{
//     PgHdr *pList;
//     if( pagerUseWal(pPager) ){
//       PgHdr *pPageOne = 0;
//       pList = sqlite3PcacheDirtyList(pPager->pPCache);
//       if( pList==0 ){
//         /* Must have at least one page for the WAL commit flag.
//         ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
//         rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0);
//         pList = pPageOne;
//         pList->pDirty = 0;
//       }
//       assert( rc==SQLITE_OK );
//       if( ALWAYS(pList) ){
//         rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
//       }
//       sqlite3PagerUnref(pPageOne);
//       if( rc==SQLITE_OK ){
//         sqlite3PcacheCleanAll(pPager->pPCache);
//       }
//     }else{
//       /* The bBatch boolean is true if the batch-atomic-write commit method
//       ** should be used.  No rollback journal is created if batch-atomic-write
//       ** is enabled.
//       */
// #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
//       sqlite3_file *fd = pPager->fd;
//       int bBatch = zSuper==0    /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
//         && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
//         && !pPager->noSync
//         && sqlite3JournalIsInMemory(pPager->jfd);
// #else
// #     define bBatch 0
// #endif

// #ifdef SQLITE_ENABLE_ATOMIC_WRITE
//       /* The following block updates the change-counter. Exactly how it
//       ** does this depends on whether or not the atomic-update optimization
H
more  
Hongze Cheng 已提交
5611 5612
//       ** was enabled at compile time, and if this transaction meets the
//       ** runtime criteria to use the operation:
5613 5614
//       **
//       **    * The file-system supports the atomic-write property for
H
more  
Hongze Cheng 已提交
5615
//       **      blocks of size page-size, and
5616 5617 5618 5619 5620 5621 5622 5623 5624
//       **    * This commit is not part of a multi-file transaction, and
//       **    * Exactly one page has been modified and store in the journal file.
//       **
//       ** If the optimization was not enabled at compile time, then the
//       ** pager_incr_changecounter() function is called to update the change
//       ** counter in 'indirect-mode'. If the optimization is compiled in but
//       ** is not applicable to this transaction, call sqlite3JournalCreate()
//       ** to make sure the journal file has actually been created, then call
//       ** pager_incr_changecounter() to update the change-counter in indirect
H
more  
Hongze Cheng 已提交
5625
//       ** mode.
5626 5627 5628 5629 5630 5631 5632 5633
//       **
//       ** Otherwise, if the optimization is both enabled and applicable,
//       ** then call pager_incr_changecounter() to update the change-counter
//       ** in 'direct' mode. In this case the journal file will never be
//       ** created for this transaction.
//       */
//       if( bBatch==0 ){
//         PgHdr *pPg;
H
more  
Hongze Cheng 已提交
5634 5635 5636
//         assert( isOpen(pPager->jfd)
//             || pPager->journalMode==PAGER_JOURNALMODE_OFF
//             || pPager->journalMode==PAGER_JOURNALMODE_WAL
5637
//             );
H
more  
Hongze Cheng 已提交
5638 5639
//         if( !zSuper && isOpen(pPager->jfd)
//          && pPager->journalOff==jrnlBufferSize(pPager)
5640 5641 5642
//          && pPager->dbSize>=pPager->dbOrigSize
//          && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
//         ){
H
more  
Hongze Cheng 已提交
5643 5644 5645 5646
//           /* Update the db file change counter via the direct-write method. The
//           ** following call will modify the in-memory representation of page 1
//           ** to include the updated change counter and then write page 1
//           ** directly to the database file. Because of the atomic-write
5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667
//           ** property of the host file-system, this is safe.
//           */
//           rc = pager_incr_changecounter(pPager, 1);
//         }else{
//           rc = sqlite3JournalCreate(pPager->jfd);
//           if( rc==SQLITE_OK ){
//             rc = pager_incr_changecounter(pPager, 0);
//           }
//         }
//       }
// #else  /* SQLITE_ENABLE_ATOMIC_WRITE */
// #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
//       if( zSuper ){
//         rc = sqlite3JournalCreate(pPager->jfd);
//         if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
//         assert( bBatch==0 );
//       }
// #endif
//       rc = pager_incr_changecounter(pPager, 0);
// #endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
//       if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
H
more  
Hongze Cheng 已提交
5668

5669
//       /* Write the super-journal name into the journal file. If a
H
more  
Hongze Cheng 已提交
5670
//       ** super-journal file name has already been written to the journal file,
5671 5672 5673 5674
//       ** or if zSuper is NULL (no super-journal), then this call is a no-op.
//       */
//       rc = writeSuperJournal(pPager, zSuper);
//       if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
H
more  
Hongze Cheng 已提交
5675

5676
//       /* Sync the journal file and write all dirty pages to the database.
H
more  
Hongze Cheng 已提交
5677
//       ** If the atomic-update optimization is being used, this sync will not
5678 5679 5680 5681 5682
//       ** create the journal file or perform any real IO.
//       **
//       ** Because the change-counter page was just modified, unless the
//       ** atomic-update optimization is used it is almost certain that the
//       ** journal requires a sync here. However, in locking_mode=exclusive
H
more  
Hongze Cheng 已提交
5683
//       ** on a system under memory pressure it is just possible that this is
5684
//       ** not the case. In this case it is likely enough that the redundant
H
more  
Hongze Cheng 已提交
5685
//       ** xSync() call will be changed to a no-op by the OS anyhow.
5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725
//       */
//       rc = syncJournal(pPager, 0);
//       if( rc!=SQLITE_OK ) goto commit_phase_one_exit;

//       pList = sqlite3PcacheDirtyList(pPager->pPCache);
// #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
//       if( bBatch ){
//         rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
//         if( rc==SQLITE_OK ){
//           rc = pager_write_pagelist(pPager, pList);
//           if( rc==SQLITE_OK ){
//             rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
//           }
//           if( rc!=SQLITE_OK ){
//             sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
//           }
//         }

//         if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){
//           rc = sqlite3JournalCreate(pPager->jfd);
//           if( rc!=SQLITE_OK ){
//             sqlite3OsClose(pPager->jfd);
//             goto commit_phase_one_exit;
//           }
//           bBatch = 0;
//         }else{
//           sqlite3OsClose(pPager->jfd);
//         }
//       }
// #endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */

//       if( bBatch==0 ){
//         rc = pager_write_pagelist(pPager, pList);
//       }
//       if( rc!=SQLITE_OK ){
//         assert( rc!=SQLITE_IOERR_BLOCKED );
//         goto commit_phase_one_exit;
//       }
//       sqlite3PcacheCleanAll(pPager->pPCache);

H
more  
Hongze Cheng 已提交
5726
//       /* If the file on disk is smaller than the database image, use
5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737
//       ** pager_truncate to grow the file here. This can happen if the database
//       ** image was extended as part of the current transaction and then the
//       ** last page in the db image moved to the free-list. In this case the
//       ** last page is never written out to disk, leaving the database file
//       ** undersized. Fix this now if it is the case.  */
//       if( pPager->dbSize>pPager->dbFileSize ){
//         Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
//         assert( pPager->eState==PAGER_WRITER_DBMOD );
//         rc = pager_truncate(pPager, nNew);
//         if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
//       }
H
more  
Hongze Cheng 已提交
5738

5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756
//       /* Finally, sync the database file. */
//       if( !noSync ){
//         rc = sqlite3PagerSync(pPager, zSuper);
//       }
//       IOTRACE(("DBSYNC %p\n", pPager))
//     }
//   }

// commit_phase_one_exit:
//   if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
//     pPager->eState = PAGER_WRITER_FINISHED;
//   }
//   return rc;
// }

// /*
// ** When this function is called, the database file has been completely
// ** updated to reflect the changes made by the current transaction and
H
more  
Hongze Cheng 已提交
5757
// ** synced to disk. The journal file still exists in the file-system
5758 5759 5760
// ** though, and if a failure occurs at this point it will eventually
// ** be used as a hot-journal and the current transaction rolled back.
// **
H
more  
Hongze Cheng 已提交
5761 5762
// ** This function finalizes the journal file, either by deleting,
// ** truncating or partially zeroing it, so that it cannot be used
5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787
// ** for hot-journal rollback. Once this is done the transaction is
// ** irrevocably committed.
// **
// ** If an error occurs, an IO error code is returned and the pager
// ** moves into the error state. Otherwise, SQLITE_OK is returned.
// */
// int sqlite3PagerCommitPhaseTwo(Pager *pPager){
//   int rc = SQLITE_OK;                  /* Return code */

//   /* This routine should not be called if a prior error has occurred.
//   ** But if (due to a coding error elsewhere in the system) it does get
//   ** called, just return the same error code without doing anything. */
//   if( NEVER(pPager->errCode) ) return pPager->errCode;
//   pPager->iDataVersion++;

//   assert( pPager->eState==PAGER_WRITER_LOCKED
//        || pPager->eState==PAGER_WRITER_FINISHED
//        || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
//   );
//   assert( assert_pager_state(pPager) );

//   /* An optimization. If the database was not actually modified during
//   ** this transaction, the pager is running in exclusive-mode and is
//   ** using persistent journals, then this function is a no-op.
//   **
H
more  
Hongze Cheng 已提交
5788
//   ** The start of the journal file currently contains a single journal
5789 5790
//   ** header with the nRec field set to 0. If such a journal is used as
//   ** a hot-journal during hot-journal rollback, 0 changes will be made
H
more  
Hongze Cheng 已提交
5791
//   ** to the database file. So there is no need to zero the journal
5792 5793 5794
//   ** header. Since the pager is in exclusive mode, there is no need
//   ** to drop any locks either.
//   */
H
more  
Hongze Cheng 已提交
5795 5796
//   if( pPager->eState==PAGER_WRITER_LOCKED
//    && pPager->exclusiveMode
5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809
//    && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
//   ){
//     assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
//     pPager->eState = PAGER_READER;
//     return SQLITE_OK;
//   }

//   PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
//   rc = pager_end_transaction(pPager, pPager->setSuper, 1);
//   return pager_error(pPager, rc);
// }

// /*
H
more  
Hongze Cheng 已提交
5810
// ** If a write transaction is open, then all changes made within the
5811 5812 5813 5814 5815 5816 5817 5818 5819
// ** transaction are reverted and the current write-transaction is closed.
// ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
// ** state if an error occurs.
// **
// ** If the pager is already in PAGER_ERROR state when this function is called,
// ** it returns Pager.errCode immediately. No work is performed in this case.
// **
// ** Otherwise, in rollback mode, this function performs two functions:
// **
H
more  
Hongze Cheng 已提交
5820
// **   1) It rolls back the journal file, restoring all database file and
5821 5822 5823 5824 5825 5826
// **      in-memory cache pages to the state they were in when the transaction
// **      was opened, and
// **
// **   2) It finalizes the journal file, so that it is not used for hot
// **      rollback at any point in the future.
// **
H
more  
Hongze Cheng 已提交
5827
// ** Finalization of the journal file (task 2) is only performed if the
5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839
// ** rollback is successful.
// **
// ** In WAL mode, all cache-entries containing data modified within the
// ** current transaction are either expelled from the cache or reverted to
// ** their pre-transaction state by re-reading data from the database or
// ** WAL files. The WAL transaction is then closed.
// */
// int sqlite3PagerRollback(Pager *pPager){
//   int rc = SQLITE_OK;                  /* Return code */
//   PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));

//   /* PagerRollback() is a no-op if called in READER or OPEN state. If
H
more  
Hongze Cheng 已提交
5840
//   ** the pager is already in the ERROR state, the rollback is not
5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855
//   ** attempted here. Instead, the error code is returned to the caller.
//   */
//   assert( assert_pager_state(pPager) );
//   if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
//   if( pPager->eState<=PAGER_READER ) return SQLITE_OK;

//   if( pagerUseWal(pPager) ){
//     int rc2;
//     rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
//     rc2 = pager_end_transaction(pPager, pPager->setSuper, 0);
//     if( rc==SQLITE_OK ) rc = rc2;
//   }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
//     int eState = pPager->eState;
//     rc = pager_end_transaction(pPager, 0, 0);
//     if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
H
more  
Hongze Cheng 已提交
5856
//       /* This can happen using journal_mode=off. Move the pager to the error
5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870
//       ** state to indicate that the contents of the cache may not be trusted.
//       ** Any active readers will get SQLITE_ABORT.
//       */
//       pPager->errCode = SQLITE_ABORT;
//       pPager->eState = PAGER_ERROR;
//       setGetterMethod(pPager);
//       return rc;
//     }
//   }else{
//     rc = pager_playback(pPager, 0);
//   }

//   assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
//   assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
H
more  
Hongze Cheng 已提交
5871
//           || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944
//           || rc==SQLITE_CANTOPEN
//   );

//   /* If an error occurs during a ROLLBACK, we can no longer trust the pager
//   ** cache. So call pager_error() on the way out to make any error persistent.
//   */
//   return pager_error(pPager, rc);
// }

// /*
// ** Return TRUE if the database file is opened read-only.  Return FALSE
// ** if the database is (in theory) writable.
// */
// u8 sqlite3PagerIsreadonly(Pager *pPager){
//   return pPager->readOnly;
// }

// #ifdef SQLITE_DEBUG
// /*
// ** Return the sum of the reference counts for all pages held by pPager.
// */
// int sqlite3PagerRefcount(Pager *pPager){
//   return sqlite3PcacheRefCount(pPager->pPCache);
// }
// #endif

// /*
// ** Return the approximate number of bytes of memory currently
// ** used by the pager and its associated cache.
// */
// int sqlite3PagerMemUsed(Pager *pPager){
//   int perPageSize = pPager->pageSize + pPager->nExtra
//     + (int)(sizeof(PgHdr) + 5*sizeof(void*));
//   return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
//            + sqlite3MallocSize(pPager)
//            + pPager->pageSize;
// }

// /*
// ** Return the number of references to the specified page.
// */
// int sqlite3PagerPageRefcount(DbPage *pPage){
//   return sqlite3PcachePageRefcount(pPage);
// }

// #ifdef SQLITE_TEST
// /*
// ** This routine is used for testing and analysis only.
// */
// int *sqlite3PagerStats(Pager *pPager){
//   static int a[11];
//   a[0] = sqlite3PcacheRefCount(pPager->pPCache);
//   a[1] = sqlite3PcachePagecount(pPager->pPCache);
//   a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
//   a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
//   a[4] = pPager->eState;
//   a[5] = pPager->errCode;
//   a[6] = pPager->aStat[PAGER_STAT_HIT];
//   a[7] = pPager->aStat[PAGER_STAT_MISS];
//   a[8] = 0;  /* Used to be pPager->nOvfl */
//   a[9] = pPager->nRead;
//   a[10] = pPager->aStat[PAGER_STAT_WRITE];
//   return a;
// }
// #endif

// /*
// ** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE,
// ** or _WRITE+1.  The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation
// ** of SQLITE_DBSTATUS_CACHE_SPILL.  The _SPILL case is not contiguous because
// ** it was added later.
// **
// ** Before returning, *pnVal is incremented by the
H
more  
Hongze Cheng 已提交
5945 5946
// ** current cache hit or miss count, according to the value of eStat. If the
// ** reset parameter is non-zero, the cache hit or miss count is zeroed before
5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981
// ** returning.
// */
// void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){

//   assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
//        || eStat==SQLITE_DBSTATUS_CACHE_MISS
//        || eStat==SQLITE_DBSTATUS_CACHE_WRITE
//        || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1
//   );

//   assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
//   assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
//   assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1
//            && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 );

//   eStat -= SQLITE_DBSTATUS_CACHE_HIT;
//   *pnVal += pPager->aStat[eStat];
//   if( reset ){
//     pPager->aStat[eStat] = 0;
//   }
// }

// /*
// ** Return true if this is an in-memory or temp-file backed pager.
// */
// int sqlite3PagerIsMemdb(Pager *pPager){
//   return pPager->tempFile || pPager->memVfs;
// }

// /*
// ** Check that there are at least nSavepoint savepoints open. If there are
// ** currently less than nSavepoints open, then open one or more savepoints
// ** to make up the difference. If the number of savepoints is already
// ** equal to nSavepoint, then this function is a no-op.
// **
H
more  
Hongze Cheng 已提交
5982
// ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996
// ** occurs while opening the sub-journal file, then an IO error code is
// ** returned. Otherwise, SQLITE_OK.
// */
// static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
//   int rc = SQLITE_OK;                       /* Return code */
//   int nCurrent = pPager->nSavepoint;        /* Current number of savepoints */
//   int ii;                                   /* Iterator variable */
//   PagerSavepoint *aNew;                     /* New Pager.aSavepoint array */

//   assert( pPager->eState>=PAGER_WRITER_LOCKED );
//   assert( assert_pager_state(pPager) );
//   assert( nSavepoint>nCurrent && pPager->useJournal );

//   /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
H
more  
Hongze Cheng 已提交
5997
//   ** if the allocation fails. Otherwise, zero the new portion in case a
5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044
//   ** malloc failure occurs while populating it in the for(...) loop below.
//   */
//   aNew = (PagerSavepoint *)sqlite3Realloc(
//       pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
//   );
//   if( !aNew ){
//     return SQLITE_NOMEM;
//   }
//   memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
//   pPager->aSavepoint = aNew;

//   /* Populate the PagerSavepoint structures just allocated. */
//   for(ii=nCurrent; ii<nSavepoint; ii++){
//     aNew[ii].nOrig = pPager->dbSize;
//     if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
//       aNew[ii].iOffset = pPager->journalOff;
//     }else{
//       aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
//     }
//     aNew[ii].iSubRec = pPager->nSubRec;
//     aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
//     aNew[ii].bTruncateOnRelease = 1;
//     if( !aNew[ii].pInSavepoint ){
//       return SQLITE_NOMEM;
//     }
//     if( pagerUseWal(pPager) ){
//       sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
//     }
//     pPager->nSavepoint = ii+1;
//   }
//   assert( pPager->nSavepoint==nSavepoint );
//   assertTruncateConstraint(pPager);
//   return rc;
// }
// int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
//   assert( pPager->eState>=PAGER_WRITER_LOCKED );
//   assert( assert_pager_state(pPager) );

//   if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){
//     return pagerOpenSavepoint(pPager, nSavepoint);
//   }else{
//     return SQLITE_OK;
//   }
// }

// /*
// ** This function is called to rollback or release (commit) a savepoint.
H
more  
Hongze Cheng 已提交
6045
// ** The savepoint to release or rollback need not be the most recently
6046 6047 6048 6049 6050 6051 6052
// ** created savepoint.
// **
// ** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
// ** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
// ** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
// ** that have occurred since the specified savepoint was created.
// **
H
more  
Hongze Cheng 已提交
6053
// ** The savepoint to rollback or release is identified by parameter
6054 6055 6056 6057 6058 6059
// ** iSavepoint. A value of 0 means to operate on the outermost savepoint
// ** (the first created). A value of (Pager.nSavepoint-1) means operate
// ** on the most recently created savepoint. If iSavepoint is greater than
// ** (Pager.nSavepoint-1), then this function is a no-op.
// **
// ** If a negative value is passed to this function, then the current
H
more  
Hongze Cheng 已提交
6060
// ** transaction is rolled back. This is different to calling
6061
// ** sqlite3PagerRollback() because this function does not terminate
H
more  
Hongze Cheng 已提交
6062 6063
// ** the transaction or unlock the database, it just restores the
// ** contents of the database to its original state.
6064
// **
H
more  
Hongze Cheng 已提交
6065
// ** In any case, all savepoints with an index greater than iSavepoint
6066 6067 6068 6069
// ** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
// ** then savepoint iSavepoint is also destroyed.
// **
// ** This function may return SQLITE_NOMEM if a memory allocation fails,
H
more  
Hongze Cheng 已提交
6070
// ** or an IO error code if an IO error occurs while rolling back a
6071
// ** savepoint. If no errors occur, SQLITE_OK is returned.
H
more  
Hongze Cheng 已提交
6072
// */
6073 6074
// int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
//   int rc = pPager->errCode;
H
more  
Hongze Cheng 已提交
6075

6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087
// #ifdef SQLITE_ENABLE_ZIPVFS
//   if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK;
// #endif

//   assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
//   assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );

//   if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
//     int ii;            /* Iterator variable */
//     int nNew;          /* Number of remaining savepoints after this op. */

//     /* Figure out how many savepoints will still be active after this
H
more  
Hongze Cheng 已提交
6088
//     ** operation. Store this value in nNew. Then free resources associated
6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120
//     ** with any savepoints that are destroyed by this operation.
//     */
//     nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
//     for(ii=nNew; ii<pPager->nSavepoint; ii++){
//       sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
//     }
//     pPager->nSavepoint = nNew;

//     /* Truncate the sub-journal so that it only includes the parts
//     ** that are still in use. */
//     if( op==SAVEPOINT_RELEASE ){
//       PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
//       if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
//         /* Only truncate if it is an in-memory sub-journal. */
//         if( sqlite3JournalIsInMemory(pPager->sjfd) ){
//           i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec;
//           rc = sqlite3OsTruncate(pPager->sjfd, sz);
//           assert( rc==SQLITE_OK );
//         }
//         pPager->nSubRec = pRel->iSubRec;
//       }
//     }
//     /* Else this is a rollback operation, playback the specified savepoint.
//     ** If this is a temp-file, it is possible that the journal file has
//     ** not yet been opened. In this case there have been no changes to
//     ** the database file, so the playback operation can be skipped.
//     */
//     else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
//       PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
//       rc = pagerPlaybackSavepoint(pPager, pSavepoint);
//       assert(rc!=SQLITE_DONE);
//     }
H
more  
Hongze Cheng 已提交
6121

6122
// #ifdef SQLITE_ENABLE_ZIPVFS
H
more  
Hongze Cheng 已提交
6123
//     /* If the cache has been modified but the savepoint cannot be rolled
6124 6125 6126
//     ** back journal_mode=off, put the pager in the error state. This way,
//     ** if the VFS used by this pager includes ZipVFS, the entire transaction
//     ** can be rolled back at the ZipVFS level.  */
H
more  
Hongze Cheng 已提交
6127 6128
//     else if(
//         pPager->journalMode==PAGER_JOURNALMODE_OFF
6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212
//      && pPager->eState>=PAGER_WRITER_CACHEMOD
//     ){
//       pPager->errCode = SQLITE_ABORT;
//       pPager->eState = PAGER_ERROR;
//       setGetterMethod(pPager);
//     }
// #endif
//   }

//   return rc;
// }

// /*
// ** Return the full pathname of the database file.
// **
// ** Except, if the pager is in-memory only, then return an empty string if
// ** nullIfMemDb is true.  This routine is called with nullIfMemDb==1 when
// ** used to report the filename to the user, for compatibility with legacy
// ** behavior.  But when the Btree needs to know the filename for matching to
// ** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
// ** participate in shared-cache.
// **
// ** The return value to this routine is always safe to use with
// ** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
// */
// const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
//   static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
//   return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
// }

// /*
// ** Return the VFS structure for the pager.
// */
// sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
//   return pPager->pVfs;
// }

// /*
// ** Return the file handle for the database file associated
// ** with the pager.  This might return NULL if the file has
// ** not yet been opened.
// */
// sqlite3_file *sqlite3PagerFile(Pager *pPager){
//   return pPager->fd;
// }

// /*
// ** Return the file handle for the journal file (if it exists).
// ** This will be either the rollback journal or the WAL file.
// */
// sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
// #if SQLITE_OMIT_WAL
//   return pPager->jfd;
// #else
//   return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
// #endif
// }

// /*
// ** Return the full pathname of the journal file.
// */
// const char *sqlite3PagerJournalname(Pager *pPager){
//   return pPager->zJournal;
// }

// #ifndef SQLITE_OMIT_AUTOVACUUM
// /*
// ** Move the page pPg to location pgno in the file.
// **
// ** There must be no references to the page previously located at
// ** pgno (which we call pPgOld) though that page is allowed to be
// ** in cache.  If the page previously located at pgno is not already
// ** in the rollback journal, it is not put there by by this routine.
// **
// ** References to the page pPg remain valid. Updating any
// ** meta-data associated with pPg (i.e. data stored in the nExtra bytes
// ** allocated along with the page) is the responsibility of the caller.
// **
// ** A transaction must be active when this routine is called. It used to be
// ** required that a statement transaction was not active, but this restriction
// ** has been removed (CREATE INDEX needs to move a page when a statement
// ** transaction is active).
// **
// ** If the fourth argument, isCommit, is non-zero, then this page is being
H
more  
Hongze Cheng 已提交
6213 6214
// ** moved as part of a database reorganization just before the transaction
// ** is being committed. In this case, it is guaranteed that the database page
6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241
// ** pPg refers to will not be written to again within this transaction.
// **
// ** This function may return SQLITE_NOMEM or an IO error code if an error
// ** occurs. Otherwise, it returns SQLITE_OK.
// */
// int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
//   PgHdr *pPgOld;               /* The page being overwritten. */
//   Pgno needSyncPgno = 0;       /* Old value of pPg->pgno, if sync is required */
//   int rc;                      /* Return code */
//   Pgno origPgno;               /* The original page number */

//   assert( pPg->nRef>0 );
//   assert( pPager->eState==PAGER_WRITER_CACHEMOD
//        || pPager->eState==PAGER_WRITER_DBMOD
//   );
//   assert( assert_pager_state(pPager) );

//   /* In order to be able to rollback, an in-memory database must journal
//   ** the page we are moving from.
//   */
//   assert( pPager->tempFile || !MEMDB );
//   if( pPager->tempFile ){
//     rc = sqlite3PagerWrite(pPg);
//     if( rc ) return rc;
//   }

//   /* If the page being moved is dirty and has not been saved by the latest
H
more  
Hongze Cheng 已提交
6242
//   ** savepoint, then save the current contents of the page into the
6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264
//   ** sub-journal now. This is required to handle the following scenario:
//   **
//   **   BEGIN;
//   **     <journal page X, then modify it in memory>
//   **     SAVEPOINT one;
//   **       <Move page X to location Y>
//   **     ROLLBACK TO one;
//   **
//   ** If page X were not written to the sub-journal here, it would not
//   ** be possible to restore its contents when the "ROLLBACK TO one"
//   ** statement were is processed.
//   **
//   ** subjournalPage() may need to allocate space to store pPg->pgno into
//   ** one or more savepoint bitvecs. This is the reason this function
//   ** may return SQLITE_NOMEM.
//   */
//   if( (pPg->flags & PGHDR_DIRTY)!=0
//    && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg))
//   ){
//     return rc;
//   }

H
more  
Hongze Cheng 已提交
6265
//   PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
6266 6267 6268 6269 6270 6271 6272
//       PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
//   IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))

//   /* If the journal needs to be sync()ed before page pPg->pgno can
//   ** be written to, store pPg->pgno in local variable needSyncPgno.
//   **
//   ** If the isCommit flag is set, there is no need to remember that
H
more  
Hongze Cheng 已提交
6273
//   ** the journal needs to be sync()ed before database page pPg->pgno
6274 6275 6276 6277 6278 6279 6280 6281 6282 6283
//   ** can be written to. The caller has already promised not to write to it.
//   */
//   if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
//     needSyncPgno = pPg->pgno;
//     assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
//             pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
//     assert( pPg->flags&PGHDR_DIRTY );
//   }

//   /* If the cache contains a page with page-number pgno, remove it
H
more  
Hongze Cheng 已提交
6284 6285
//   ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
//   ** page pgno before the 'move' operation, it needs to be retained
6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319
//   ** for the page moved there.
//   */
//   pPg->flags &= ~PGHDR_NEED_SYNC;
//   pPgOld = sqlite3PagerLookup(pPager, pgno);
//   assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
//   if( pPgOld ){
//     if( NEVER(pPgOld->nRef>1) ){
//       sqlite3PagerUnrefNotNull(pPgOld);
//       return SQLITE_CORRUPT_BKPT;
//     }
//     pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
//     if( pPager->tempFile ){
//       /* Do not discard pages from an in-memory database since we might
//       ** need to rollback later.  Just move the page out of the way. */
//       sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
//     }else{
//       sqlite3PcacheDrop(pPgOld);
//     }
//   }

//   origPgno = pPg->pgno;
//   sqlite3PcacheMove(pPg, pgno);
//   sqlite3PcacheMakeDirty(pPg);

//   /* For an in-memory database, make sure the original page continues
//   ** to exist, in case the transaction needs to roll back.  Use pPgOld
//   ** as the original page since it has already been allocated.
//   */
//   if( pPager->tempFile && pPgOld ){
//     sqlite3PcacheMove(pPgOld, origPgno);
//     sqlite3PagerUnrefNotNull(pPgOld);
//   }

//   if( needSyncPgno ){
H
more  
Hongze Cheng 已提交
6320
//     /* If needSyncPgno is non-zero, then the journal file needs to be
6321
//     ** sync()ed before any data is written to database file page needSyncPgno.
H
more  
Hongze Cheng 已提交
6322
//     ** Currently, no such page exists in the page-cache and the
6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352
//     ** "is journaled" bitvec flag has been set. This needs to be remedied by
//     ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
//     ** flag.
//     **
//     ** If the attempt to load the page into the page-cache fails, (due
//     ** to a malloc() or IO failure), clear the bit in the pInJournal[]
//     ** array. Otherwise, if the page is loaded and written again in
//     ** this transaction, it may be written to the database file before
//     ** it is synced into the journal file. This way, it may end up in
//     ** the journal file twice, but that is not a problem.
//     */
//     PgHdr *pPgHdr;
//     rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0);
//     if( rc!=SQLITE_OK ){
//       if( needSyncPgno<=pPager->dbOrigSize ){
//         assert( pPager->pTmpSpace!=0 );
//         sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
//       }
//       return rc;
//     }
//     pPgHdr->flags |= PGHDR_NEED_SYNC;
//     sqlite3PcacheMakeDirty(pPgHdr);
//     sqlite3PagerUnrefNotNull(pPgHdr);
//   }

//   return SQLITE_OK;
// }
// #endif

// /*
H
more  
Hongze Cheng 已提交
6353 6354 6355
// ** The page handle passed as the first argument refers to a dirty page
// ** with a page number other than iNew. This function changes the page's
// ** page number to iNew and sets the value of the PgHdr.flags field to
6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372
// ** the value passed as the third parameter.
// */
// void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){
//   assert( pPg->pgno!=iNew );
//   pPg->flags = flags;
//   sqlite3PcacheMove(pPg, iNew);
// }

// /*
// ** Return a pointer to the data for the specified page.
// */
// void *sqlite3PagerGetData(DbPage *pPg){
//   assert( pPg->nRef>0 || pPg->pPager->memDb );
//   return pPg->pData;
// }

// /*
H
more  
Hongze Cheng 已提交
6373
// ** Return a pointer to the Pager.nExtra bytes of "extra" space
6374 6375 6376 6377 6378 6379 6380 6381
// ** allocated along with the specified page.
// */
// void *sqlite3PagerGetExtra(DbPage *pPg){
//   return pPg->pExtra;
// }

// /*
// ** Get/set the locking-mode for this pager. Parameter eMode must be one
H
more  
Hongze Cheng 已提交
6382
// ** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429
// ** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
// ** the locking-mode is set to the value specified.
// **
// ** The returned value is either PAGER_LOCKINGMODE_NORMAL or
// ** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
// ** locking-mode.
// */
// int sqlite3PagerLockingMode(Pager *pPager, int eMode){
//   assert( eMode==PAGER_LOCKINGMODE_QUERY
//             || eMode==PAGER_LOCKINGMODE_NORMAL
//             || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
//   assert( PAGER_LOCKINGMODE_QUERY<0 );
//   assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
//   assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
//   if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
//     pPager->exclusiveMode = (u8)eMode;
//   }
//   return (int)pPager->exclusiveMode;
// }

// /*
// ** Set the journal-mode for this pager. Parameter eMode must be one of:
// **
// **    PAGER_JOURNALMODE_DELETE
// **    PAGER_JOURNALMODE_TRUNCATE
// **    PAGER_JOURNALMODE_PERSIST
// **    PAGER_JOURNALMODE_OFF
// **    PAGER_JOURNALMODE_MEMORY
// **    PAGER_JOURNALMODE_WAL
// **
// ** The journalmode is set to the value specified if the change is allowed.
// ** The change may be disallowed for the following reasons:
// **
// **   *  An in-memory database can only have its journal_mode set to _OFF
// **      or _MEMORY.
// **
// **   *  Temporary databases cannot have _WAL journalmode.
// **
// ** The returned indicate the current (possibly updated) journal-mode.
// */
// int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
//   u8 eOld = pPager->journalMode;    /* Prior journalmode */

//   /* The eMode parameter is always valid */
//   assert(      eMode==PAGER_JOURNALMODE_DELETE
//             || eMode==PAGER_JOURNALMODE_TRUNCATE
//             || eMode==PAGER_JOURNALMODE_PERSIST
H
more  
Hongze Cheng 已提交
6430 6431
//             || eMode==PAGER_JOURNALMODE_OFF
//             || eMode==PAGER_JOURNALMODE_WAL
6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614
//             || eMode==PAGER_JOURNALMODE_MEMORY );

//   /* This routine is only called from the OP_JournalMode opcode, and
//   ** the logic there will never allow a temporary file to be changed
//   ** to WAL mode.
//   */
//   assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );

//   /* Do allow the journalmode of an in-memory database to be set to
//   ** anything other than MEMORY or OFF
//   */
//   if( MEMDB ){
//     assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
//     if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
//       eMode = eOld;
//     }
//   }

//   if( eMode!=eOld ){

//     /* Change the journal mode. */
//     assert( pPager->eState!=PAGER_ERROR );
//     pPager->journalMode = (u8)eMode;

//     /* When transistioning from TRUNCATE or PERSIST to any other journal
//     ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
//     ** delete the journal file.
//     */
//     assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
//     assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
//     assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
//     assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
//     assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
//     assert( (PAGER_JOURNALMODE_WAL & 5)==5 );

//     assert( isOpen(pPager->fd) || pPager->exclusiveMode );
//     if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){

//       /* In this case we would like to delete the journal file. If it is
//       ** not possible, then that is not a problem. Deleting the journal file
//       ** here is an optimization only.
//       **
//       ** Before deleting the journal file, obtain a RESERVED lock on the
//       ** database file. This ensures that the journal file is not deleted
//       ** while it is in use by some other client.
//       */
//       sqlite3OsClose(pPager->jfd);
//       if( pPager->eLock>=RESERVED_LOCK ){
//         sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
//       }else{
//         int rc = SQLITE_OK;
//         int state = pPager->eState;
//         assert( state==PAGER_OPEN || state==PAGER_READER );
//         if( state==PAGER_OPEN ){
//           rc = sqlite3PagerSharedLock(pPager);
//         }
//         if( pPager->eState==PAGER_READER ){
//           assert( rc==SQLITE_OK );
//           rc = pagerLockDb(pPager, RESERVED_LOCK);
//         }
//         if( rc==SQLITE_OK ){
//           sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
//         }
//         if( rc==SQLITE_OK && state==PAGER_READER ){
//           pagerUnlockDb(pPager, SHARED_LOCK);
//         }else if( state==PAGER_OPEN ){
//           pager_unlock(pPager);
//         }
//         assert( state==pPager->eState );
//       }
//     }else if( eMode==PAGER_JOURNALMODE_OFF ){
//       sqlite3OsClose(pPager->jfd);
//     }
//   }

//   /* Return the new journal mode */
//   return (int)pPager->journalMode;
// }

// /*
// ** Return the current journal mode.
// */
// int sqlite3PagerGetJournalMode(Pager *pPager){
//   return (int)pPager->journalMode;
// }

// /*
// ** Return TRUE if the pager is in a state where it is OK to change the
// ** journalmode.  Journalmode changes can only happen when the database
// ** is unmodified.
// */
// int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
//   assert( assert_pager_state(pPager) );
//   if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
//   if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
//   return 1;
// }

// /*
// ** Get/set the size-limit used for persistent journal files.
// **
// ** Setting the size limit to -1 means no limit is enforced.
// ** An attempt to set a limit smaller than -1 is a no-op.
// */
// i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
//   if( iLimit>=-1 ){
//     pPager->journalSizeLimit = iLimit;
//     sqlite3WalLimit(pPager->pWal, iLimit);
//   }
//   return pPager->journalSizeLimit;
// }

// /*
// ** Return a pointer to the pPager->pBackup variable. The backup module
// ** in backup.c maintains the content of this variable. This module
// ** uses it opaquely as an argument to sqlite3BackupRestart() and
// ** sqlite3BackupUpdate() only.
// */
// sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
//   return &pPager->pBackup;
// }

// #ifndef SQLITE_OMIT_VACUUM
// /*
// ** Unless this is an in-memory or temporary database, clear the pager cache.
// */
// void sqlite3PagerClearCache(Pager *pPager){
//   assert( MEMDB==0 || pPager->tempFile );
//   if( pPager->tempFile==0 ) pager_reset(pPager);
// }
// #endif

// #ifndef SQLITE_OMIT_WAL
// /*
// ** This function is called when the user invokes "PRAGMA wal_checkpoint",
// ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
// ** or wal_blocking_checkpoint() API functions.
// **
// ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
// */
// int sqlite3PagerCheckpoint(
//   Pager *pPager,                  /* Checkpoint on this pager */
//   sqlite3 *db,                    /* Db handle used to check for interrupts */
//   int eMode,                      /* Type of checkpoint */
//   int *pnLog,                     /* OUT: Final number of frames in log */
//   int *pnCkpt                     /* OUT: Final number of checkpointed frames */
// ){
//   int rc = SQLITE_OK;
//   if( pPager->pWal ){
//     rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
//         (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
//         pPager->pBusyHandlerArg,
//         pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
//         pnLog, pnCkpt
//     );
//   }
//   return rc;
// }

// int sqlite3PagerWalCallback(Pager *pPager){
//   return sqlite3WalCallback(pPager->pWal);
// }

// /*
// ** Return true if the underlying VFS for the given pager supports the
// ** primitives necessary for write-ahead logging.
// */
// int sqlite3PagerWalSupported(Pager *pPager){
//   const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
//   if( pPager->noLock ) return 0;
//   return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
// }

// /*
// ** Attempt to take an exclusive lock on the database file. If a PENDING lock
// ** is obtained instead, immediately release it.
// */
// static int pagerExclusiveLock(Pager *pPager){
//   int rc;                         /* Return code */

//   assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
//   rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
//   if( rc!=SQLITE_OK ){
H
more  
Hongze Cheng 已提交
6615
//     /* If the attempt to grab the exclusive lock failed, release the
6616 6617 6618 6619 6620 6621 6622 6623
//     ** pending lock that may have been obtained instead.  */
//     pagerUnlockDb(pPager, SHARED_LOCK);
//   }

//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
6624
// ** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
6625 6626 6627 6628 6629 6630 6631 6632 6633 6634
// ** exclusive-locking mode when this function is called, take an EXCLUSIVE
// ** lock on the database file and use heap-memory to store the wal-index
// ** in. Otherwise, use the normal shared-memory.
// */
// static int pagerOpenWal(Pager *pPager){
//   int rc = SQLITE_OK;

//   assert( pPager->pWal==0 && pPager->tempFile==0 );
//   assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );

H
more  
Hongze Cheng 已提交
6635 6636
//   /* If the pager is already in exclusive-mode, the WAL module will use
//   ** heap-memory for the wal-index instead of the VFS shared-memory
6637 6638 6639 6640 6641 6642 6643
//   ** implementation. Take the exclusive lock now, before opening the WAL
//   ** file, to make sure this is safe.
//   */
//   if( pPager->exclusiveMode ){
//     rc = pagerExclusiveLock(pPager);
//   }

H
more  
Hongze Cheng 已提交
6644
//   /* Open the connection to the log file. If this operation fails,
6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664
//   ** (e.g. due to malloc() failure), return an error code.
//   */
//   if( rc==SQLITE_OK ){
//     rc = sqlite3WalOpen(pPager->pVfs,
//         pPager->fd, pPager->zWal, pPager->exclusiveMode,
//         pPager->journalSizeLimit, &pPager->pWal
//     );
//   }
//   pagerFixMaplimit(pPager);

//   return rc;
// }

// /*
// ** The caller must be holding a SHARED lock on the database file to call
// ** this function.
// **
// ** If the pager passed as the first argument is open on a real database
// ** file (not a temp file or an in-memory database), and the WAL file
// ** is not already open, make an attempt to open it now. If successful,
H
more  
Hongze Cheng 已提交
6665
// ** return SQLITE_OK. If an error occurs or the VFS used by the pager does
6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706
// ** not support the xShmXXX() methods, return an error code. *pbOpen is
// ** not modified in either case.
// **
// ** If the pager is open on a temp-file (or in-memory database), or if
// ** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
// ** without doing anything.
// */
// int sqlite3PagerOpenWal(
//   Pager *pPager,                  /* Pager object */
//   int *pbOpen                     /* OUT: Set to true if call is a no-op */
// ){
//   int rc = SQLITE_OK;             /* Return code */

//   assert( assert_pager_state(pPager) );
//   assert( pPager->eState==PAGER_OPEN   || pbOpen );
//   assert( pPager->eState==PAGER_READER || !pbOpen );
//   assert( pbOpen==0 || *pbOpen==0 );
//   assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );

//   if( !pPager->tempFile && !pPager->pWal ){
//     if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;

//     /* Close any rollback journal previously open */
//     sqlite3OsClose(pPager->jfd);

//     rc = pagerOpenWal(pPager);
//     if( rc==SQLITE_OK ){
//       pPager->journalMode = PAGER_JOURNALMODE_WAL;
//       pPager->eState = PAGER_OPEN;
//     }
//   }else{
//     *pbOpen = 1;
//   }

//   return rc;
// }

// /*
// ** This function is called to close the connection to the log file prior
// ** to switching from WAL to rollback mode.
// **
H
more  
Hongze Cheng 已提交
6707
// ** Before closing the log file, this function attempts to take an
6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732
// ** EXCLUSIVE lock on the database file. If this cannot be obtained, an
// ** error (SQLITE_BUSY) is returned and the log connection is not closed.
// ** If successful, the EXCLUSIVE lock is not released before returning.
// */
// int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
//   int rc = SQLITE_OK;

//   assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );

//   /* If the log file is not already open, but does exist in the file-system,
//   ** it may need to be checkpointed before the connection can switch to
//   ** rollback mode. Open it now so this can happen.
//   */
//   if( !pPager->pWal ){
//     int logexists = 0;
//     rc = pagerLockDb(pPager, SHARED_LOCK);
//     if( rc==SQLITE_OK ){
//       rc = sqlite3OsAccess(
//           pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
//       );
//     }
//     if( rc==SQLITE_OK && logexists ){
//       rc = pagerOpenWal(pPager);
//     }
//   }
H
more  
Hongze Cheng 已提交
6733

6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752
//   /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
//   ** the database file, the log and log-summary files will be deleted.
//   */
//   if( rc==SQLITE_OK && pPager->pWal ){
//     rc = pagerExclusiveLock(pPager);
//     if( rc==SQLITE_OK ){
//       rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
//                            pPager->pageSize, (u8*)pPager->pTmpSpace);
//       pPager->pWal = 0;
//       pagerFixMaplimit(pPager);
//       if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
//     }
//   }
//   return rc;
// }

// #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
// /*
// ** If pager pPager is a wal-mode database not in exclusive locking mode,
H
more  
Hongze Cheng 已提交
6753
// ** invoke the sqlite3WalWriteLock() function on the associated Wal object
6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765
// ** with the same db and bLock parameters as were passed to this function.
// ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
// */
// int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
//   int rc = SQLITE_OK;
//   if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
//     rc = sqlite3WalWriteLock(pPager->pWal, bLock);
//   }
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
6766
// ** Set the database handle used by the wal layer to determine if
6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790
// ** blocking locks are required.
// */
// void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
//   if( pagerUseWal(pPager) ){
//     sqlite3WalDb(pPager->pWal, db);
//   }
// }
// #endif

// #ifdef SQLITE_ENABLE_SNAPSHOT
// /*
// ** If this is a WAL database, obtain a snapshot handle for the snapshot
// ** currently open. Otherwise, return an error.
// */
// int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){
//   int rc = SQLITE_ERROR;
//   if( pPager->pWal ){
//     rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot);
//   }
//   return rc;
// }

// /*
// ** If this is a WAL database, store a pointer to pSnapshot. Next time a
H
more  
Hongze Cheng 已提交
6791
// ** read transaction is opened, attempt to read from the snapshot it
6792 6793 6794
// ** identifies. If this is not a WAL database, return an error.
// */
// int sqlite3PagerSnapshotOpen(
H
more  
Hongze Cheng 已提交
6795
//   Pager *pPager,
6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807
//   sqlite3_snapshot *pSnapshot
// ){
//   int rc = SQLITE_OK;
//   if( pPager->pWal ){
//     sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
//   }else{
//     rc = SQLITE_ERROR;
//   }
//   return rc;
// }

// /*
H
more  
Hongze Cheng 已提交
6808
// ** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824
// ** is not a WAL database, return an error.
// */
// int sqlite3PagerSnapshotRecover(Pager *pPager){
//   int rc;
//   if( pPager->pWal ){
//     rc = sqlite3WalSnapshotRecover(pPager->pWal);
//   }else{
//     rc = SQLITE_ERROR;
//   }
//   return rc;
// }

// /*
// ** The caller currently has a read transaction open on the database.
// ** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise,
// ** this function takes a SHARED lock on the CHECKPOINTER slot and then
H
more  
Hongze Cheng 已提交
6825
// ** checks if the snapshot passed as the second argument is still
6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853
// ** available. If so, SQLITE_OK is returned.
// **
// ** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
// ** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error
// ** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER
// ** lock is released before returning.
// */
// int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){
//   int rc;
//   if( pPager->pWal ){
//     rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot);
//   }else{
//     rc = SQLITE_ERROR;
//   }
//   return rc;
// }

// /*
// ** Release a lock obtained by an earlier successful call to
// ** sqlite3PagerSnapshotCheck().
// */
// void sqlite3PagerSnapshotUnlock(Pager *pPager){
//   assert( pPager->pWal );
//   sqlite3WalSnapshotUnlock(pPager->pWal);
// }

// #endif /* SQLITE_ENABLE_SNAPSHOT */
// #endif /* !SQLITE_OMIT_WAL */