Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do not sync any files in wal mode if "PRAGMA synchronous=off" is set. If files are synced, pass either SQLITE_SYNC_FULL or SQLITE_SYNC_NORMAL to the xSync() callback as configured by "PRAGMA fullfsync". |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | wal |
Files: | files | file ages | folders |
SHA1: |
0ae91b0008b242a47385fc1f295c6b64 |
User & Date: | dan 2010-04-17 17:34:42.000 |
Context
2010-04-17
| ||
18:50 | Add some comments regarding file-locks to log.c. (check-in: 9d51c3b754 user: dan tags: wal) | |
17:34 | Do not sync any files in wal mode if "PRAGMA synchronous=off" is set. If files are synced, pass either SQLITE_SYNC_FULL or SQLITE_SYNC_NORMAL to the xSync() callback as configured by "PRAGMA fullfsync". (check-in: 0ae91b0008 user: dan tags: wal) | |
15:45 | Merge with trunk commit [3e646e3f4c]. (check-in: 43463970f5 user: dan tags: wal) | |
Changes
Changes to src/log.c.
︙ | ︙ | |||
136 137 138 139 140 141 142 | u32 mLock; /* Mask of locks */ }; struct Log { LogSummary *pSummary; /* Log file summary data */ sqlite3_vfs *pVfs; /* The VFS used to create pFd */ sqlite3_file *pFd; /* File handle for log file */ | < | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | u32 mLock; /* Mask of locks */ }; struct Log { LogSummary *pSummary; /* Log file summary data */ sqlite3_vfs *pVfs; /* The VFS used to create pFd */ sqlite3_file *pFd; /* File handle for log file */ int isLocked; /* Non-zero if a snapshot is held open */ int isWriteLocked; /* True if this is the writer connection */ LogSummaryHdr hdr; /* Log summary header for current snapshot */ LogLock lock; /* Lock held by this connection (if any) */ }; |
︙ | ︙ | |||
238 239 240 241 242 243 244 | } } z[j++] = z[i]; } z[j] = 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | } } z[j++] = z[i]; } z[j] = 0; } /* ** Memory map the first nByte bytes of the summary file opened with ** pSummary->fd at pSummary->aData. If the summary file is smaller than ** nByte bytes in size when this function is called, ftruncate() is ** used to expand it before it is mapped. ** ** It is assumed that an exclusive lock is held on the summary file |
︙ | ︙ | |||
871 872 873 874 875 876 877 | /* Allocate an instance of struct Log to return. */ *ppLog = 0; pRet = (Log *)sqlite3MallocZero(sizeof(Log) + pVfs->szOsFile); if( !pRet ) goto out; pRet->pVfs = pVfs; pRet->pFd = (sqlite3_file *)&pRet[1]; | < | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | /* Allocate an instance of struct Log to return. */ *ppLog = 0; pRet = (Log *)sqlite3MallocZero(sizeof(Log) + pVfs->szOsFile); if( !pRet ) goto out; pRet->pVfs = pVfs; pRet->pFd = (sqlite3_file *)&pRet[1]; /* Normalize the path name. */ zWal = sqlite3_mprintf("%s-wal", zDb); if( !zWal ) goto out; logNormalizePath(zWal); flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL); nWal = sqlite3Strlen30(zWal); |
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 | /* ** Checkpoint the contents of the log file. */ static int logCheckpoint( Log *pLog, /* Log connection */ sqlite3_file *pFd, /* File descriptor open on db file */ u8 *zBuf /* Temporary buffer to use */ ){ int rc; /* Return code */ int pgsz = pLog->hdr.pgsz; /* Database page-size */ LogIterator *pIter = 0; /* Log iterator context */ u32 iDbpage = 0; /* Next database page to write */ u32 iFrame = 0; /* Log frame containing data for iDbpage */ if( pLog->hdr.iLastPg==0 ){ return SQLITE_OK; } /* Allocate the iterator */ pIter = logIteratorInit(pLog); if( !pIter ) return SQLITE_NOMEM; /* Sync the log file to disk */ | > > | | > > | | > | 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 | /* ** Checkpoint the contents of the log file. */ static int logCheckpoint( Log *pLog, /* Log connection */ sqlite3_file *pFd, /* File descriptor open on db file */ int sync_flags, /* Flags for OsSync() (or 0) */ u8 *zBuf /* Temporary buffer to use */ ){ int rc; /* Return code */ int pgsz = pLog->hdr.pgsz; /* Database page-size */ LogIterator *pIter = 0; /* Log iterator context */ u32 iDbpage = 0; /* Next database page to write */ u32 iFrame = 0; /* Log frame containing data for iDbpage */ if( pLog->hdr.iLastPg==0 ){ return SQLITE_OK; } /* Allocate the iterator */ pIter = logIteratorInit(pLog); if( !pIter ) return SQLITE_NOMEM; /* Sync the log file to disk */ if( sync_flags ){ rc = sqlite3OsSync(pLog->pFd, sync_flags); if( rc!=SQLITE_OK ) goto out; } /* Iterate through the contents of the log, copying data to the db file. */ while( 0==logIteratorNext(pIter, &iDbpage, &iFrame) ){ rc = sqlite3OsRead(pLog->pFd, zBuf, pgsz, logFrameOffset(iFrame, pgsz) + LOG_FRAME_HDRSIZE ); if( rc!=SQLITE_OK ) goto out; rc = sqlite3OsWrite(pFd, zBuf, pgsz, (iDbpage-1)*pgsz); if( rc!=SQLITE_OK ) goto out; } /* Truncate the database file */ rc = sqlite3OsTruncate(pFd, ((i64)pLog->hdr.nPage*(i64)pgsz)); if( rc!=SQLITE_OK ) goto out; /* Sync the database file. If successful, update the log-summary. */ if( sync_flags ){ rc = sqlite3OsSync(pFd, sync_flags); if( rc!=SQLITE_OK ) goto out; } pLog->hdr.iLastPg = 0; pLog->hdr.iCheck1 = 2; pLog->hdr.iCheck2 = 3; logSummaryWriteHdr(pLog->pSummary, &pLog->hdr); /* TODO: If a crash occurs and the current log is copied into the ** database there is no problem. However, if a crash occurs while |
︙ | ︙ | |||
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 | /* ** Close a connection to a log file. */ int sqlite3LogClose( Log *pLog, /* Log to close */ sqlite3_file *pFd, /* Database file */ u8 *zBuf /* Buffer of at least page-size bytes */ ){ int rc = SQLITE_OK; if( pLog ){ LogLock **ppL; LogSummary *pSummary = pLog->pSummary; sqlite3_mutex *mutex = 0; | > | 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | /* ** Close a connection to a log file. */ int sqlite3LogClose( Log *pLog, /* Log to close */ sqlite3_file *pFd, /* Database file */ int sync_flags, /* Flags to pass to OsSync() (or 0) */ u8 *zBuf /* Buffer of at least page-size bytes */ ){ int rc = SQLITE_OK; if( pLog ){ LogLock **ppL; LogSummary *pSummary = pLog->pSummary; sqlite3_mutex *mutex = 0; |
︙ | ︙ | |||
1150 1151 1152 1153 1154 1155 1156 | /* This is the last connection to the database (including other ** processes). Do three things: ** ** 1. Checkpoint the db. ** 2. Truncate the log file. ** 3. Unlink the log-summary file. */ | | | 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 | /* This is the last connection to the database (including other ** processes). Do three things: ** ** 1. Checkpoint the db. ** 2. Truncate the log file. ** 3. Unlink the log-summary file. */ rc = logCheckpoint(pLog, pFd, sync_flags, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(pLog->pVfs, pSummary->zPath, 0); } logSummaryUnmap(pSummary, 1); }else{ if( rc==SQLITE_BUSY ){ |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | /* Close the connection to the log file and free the Log handle. */ sqlite3OsClose(pLog->pFd); sqlite3_free(pLog); } return rc; } | < < < < < < < < < < < | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 | /* Close the connection to the log file and free the Log handle. */ sqlite3OsClose(pLog->pFd); sqlite3_free(pLog); } return rc; } /* ** Enter and leave the log-summary mutex. In this context, entering the ** log-summary mutex means: ** ** 1. Obtaining mutex pLog->pSummary->mutex, and ** 2. Taking an exclusive lock on the log-summary file. ** |
︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 | */ int sqlite3LogFrames( Log *pLog, /* Log handle to write to */ int nPgsz, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ Pgno nTruncate, /* Database size after this commit */ int isCommit, /* True if this is a commit */ | | | 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 | */ int sqlite3LogFrames( Log *pLog, /* Log handle to write to */ int nPgsz, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ Pgno nTruncate, /* Database size after this commit */ int isCommit, /* True if this is a commit */ int sync_flags /* Flags to pass to OsSync() (or 0) */ ){ int rc; /* Used to catch return codes */ u32 iFrame; /* Next frame address */ u8 aFrame[LOG_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ PgHdr *p; /* Iterator to run through pList with. */ u32 aCksum[2]; /* Checksums */ PgHdr *pLast; /* Last frame in list */ |
︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 | if( rc!=SQLITE_OK ){ return rc; } pLast = p; } /* Sync the log file if the 'isSync' flag was specified. */ | | | 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 | if( rc!=SQLITE_OK ){ return rc; } pLast = p; } /* Sync the log file if the 'isSync' flag was specified. */ if( sync_flags ){ i64 iSegment = sqlite3OsSectorSize(pLog->pFd); i64 iOffset = logFrameOffset(iFrame+1, nPgsz); assert( isCommit ); if( iSegment<SQLITE_DEFAULT_SECTOR_SIZE ){ iSegment = SQLITE_DEFAULT_SECTOR_SIZE; |
︙ | ︙ | |||
1566 1567 1568 1569 1570 1571 1572 | if( rc!=SQLITE_OK ){ return rc; } nLast++; iOffset += nPgsz; } | | | 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 | if( rc!=SQLITE_OK ){ return rc; } nLast++; iOffset += nPgsz; } rc = sqlite3OsSync(pLog->pFd, sync_flags); if( rc!=SQLITE_OK ){ return rc; } } /* Append data to the log summary. It is not necessary to lock the ** log-summary to do this as the RESERVED lock held on the db file |
︙ | ︙ | |||
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 | ** 3. Copy the contents of the log into the database file. ** 4. Zero the log-summary header (so new readers will ignore the log). ** 5. Drop the locks obtained in steps 1 and 2. */ int sqlite3LogCheckpoint( Log *pLog, /* Log connection */ sqlite3_file *pFd, /* File descriptor open on db file */ u8 *zBuf, /* Temporary buffer to use */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ){ int rc; /* Return code */ assert( !pLog->isLocked ); | > | 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 | ** 3. Copy the contents of the log into the database file. ** 4. Zero the log-summary header (so new readers will ignore the log). ** 5. Drop the locks obtained in steps 1 and 2. */ int sqlite3LogCheckpoint( Log *pLog, /* Log connection */ sqlite3_file *pFd, /* File descriptor open on db file */ int sync_flags, /* Flags to sync db file with (or 0) */ u8 *zBuf, /* Temporary buffer to use */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ){ int rc; /* Return code */ assert( !pLog->isLocked ); |
︙ | ︙ | |||
1645 1646 1647 1648 1649 1650 1651 | logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK); return rc; } /* Copy data from the log to the database file. */ rc = logSummaryReadHdr(pLog, 0); if( rc==SQLITE_OK ){ | | | 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 | logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK); return rc; } /* Copy data from the log to the database file. */ rc = logSummaryReadHdr(pLog, 0); if( rc==SQLITE_OK ){ rc = logCheckpoint(pLog, pFd, sync_flags, zBuf); } /* Release the locks. */ logLockRegion(pLog, LOG_REGION_A|LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK); return rc; } |
Changes to src/log.h.
︙ | ︙ | |||
15 16 17 18 19 20 21 | */ #ifndef _LOG_H_ #define _LOG_H_ #include "sqliteInt.h" | < < < < < < < < | < < < | | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | */ #ifndef _LOG_H_ #define _LOG_H_ #include "sqliteInt.h" /* Connection to a log file. There is one object of this type for each pager. */ typedef struct Log Log; /* Open and close a connection to a log file. */ int sqlite3LogOpen(sqlite3_vfs*, const char *zDb, Log **ppLog); int sqlite3LogClose(Log *pLog, sqlite3_file *pFd, int sync_flags, u8 *zBuf); /* Used by readers to open (lock) and close (unlock) a snapshot. */ int sqlite3LogOpenSnapshot(Log *pLog, int *); void sqlite3LogCloseSnapshot(Log *pLog); /* Read a page from the log, if it is present. */ int sqlite3LogRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut); void sqlite3LogMaxpgno(Log *pLog, Pgno *pPgno); /* Obtain or release the WRITER lock. */ int sqlite3LogWriteLock(Log *pLog, int op); /* Write a frame or frames to the log. */ int sqlite3LogFrames(Log *pLog, int, PgHdr *, Pgno, int, int); /* Copy pages from the log to the database file */ int sqlite3LogCheckpoint( Log *pLog, /* Log connection */ sqlite3_file *pFd, /* File descriptor open on db file */ int sync_flags, /* Flags to sync db file with (or 0) */ u8 *zBuf, /* Temporary buffer to use */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ); #endif /* _LOG_H_ */ |
Changes to src/pager.c.
︙ | ︙ | |||
2867 2868 2869 2870 2871 2872 2873 | int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pPager->errCode = 0; pPager->exclusiveMode = 0; | | > > | 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 | int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pPager->errCode = 0; pPager->exclusiveMode = 0; sqlite3LogClose(pPager->pLog, pPager->fd, (pPager->noSync ? 0 : pPager->sync_flags), pTmp ); pPager->pLog = 0; pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); }else{ /* Set Pager.journalHdr to -1 for the benefit of the pager_playback() ** call which may be made from within pagerUnlockAndRollback(). If it |
︙ | ︙ | |||
4877 4878 4879 4880 4881 4882 4883 | */ sqlite3BackupRestart(pPager->pBackup); }else if( pPager->state!=PAGER_SYNCED && pPager->dbModified ){ if( pagerUseLog(pPager) ){ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); if( pList ){ rc = sqlite3LogFrames(pPager->pLog, pPager->pageSize, pList, | | | 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 | */ sqlite3BackupRestart(pPager->pBackup); }else if( pPager->state!=PAGER_SYNCED && pPager->dbModified ){ if( pagerUseLog(pPager) ){ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); if( pList ){ rc = sqlite3LogFrames(pPager->pLog, pPager->pageSize, pList, pPager->dbSize, 1, (pPager->fullSync ? pPager->sync_flags : 0) ); } sqlite3PcacheCleanAll(pPager->pPCache); }else{ /* The following block updates the change-counter. Exactly how it ** does this depends on whether or not the atomic-update optimization ** was enabled at compile time, and if this transaction meets the |
︙ | ︙ | |||
5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 | ** This function is called when the user invokes "PRAGMA checkpoint". */ int sqlite3PagerCheckpoint(Pager *pPager){ int rc = SQLITE_OK; if( pPager->pLog ){ u8 *zBuf = (u8 *)pPager->pTmpSpace; rc = sqlite3LogCheckpoint(pPager->pLog, pPager->fd, zBuf, pPager->xBusyHandler, pPager->pBusyHandlerArg ); } return rc; } #endif /* SQLITE_OMIT_DISKIO */ | > | 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 | ** This function is called when the user invokes "PRAGMA checkpoint". */ int sqlite3PagerCheckpoint(Pager *pPager){ int rc = SQLITE_OK; if( pPager->pLog ){ u8 *zBuf = (u8 *)pPager->pTmpSpace; rc = sqlite3LogCheckpoint(pPager->pLog, pPager->fd, (pPager->noSync ? 0 : pPager->sync_flags), zBuf, pPager->xBusyHandler, pPager->pBusyHandlerArg ); } return rc; } #endif /* SQLITE_OMIT_DISKIO */ |