| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2008 Jan 22 | 2 ** 2008 Jan 22 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 static int jtAccess(sqlite3_vfs*, const char *zName, int flags, int *); | 153 static int jtAccess(sqlite3_vfs*, const char *zName, int flags, int *); |
| 154 static int jtFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); | 154 static int jtFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); |
| 155 static void *jtDlOpen(sqlite3_vfs*, const char *zFilename); | 155 static void *jtDlOpen(sqlite3_vfs*, const char *zFilename); |
| 156 static void jtDlError(sqlite3_vfs*, int nByte, char *zErrMsg); | 156 static void jtDlError(sqlite3_vfs*, int nByte, char *zErrMsg); |
| 157 static void (*jtDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); | 157 static void (*jtDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); |
| 158 static void jtDlClose(sqlite3_vfs*, void*); | 158 static void jtDlClose(sqlite3_vfs*, void*); |
| 159 static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut); | 159 static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut); |
| 160 static int jtSleep(sqlite3_vfs*, int microseconds); | 160 static int jtSleep(sqlite3_vfs*, int microseconds); |
| 161 static int jtCurrentTime(sqlite3_vfs*, double*); | 161 static int jtCurrentTime(sqlite3_vfs*, double*); |
| 162 static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); | 162 static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); |
| 163 static int jtGetLastError(sqlite3_vfs*, int, char*); |
| 163 | 164 |
| 164 static sqlite3_vfs jt_vfs = { | 165 static sqlite3_vfs jt_vfs = { |
| 165 2, /* iVersion */ | 166 2, /* iVersion */ |
| 166 sizeof(jt_file), /* szOsFile */ | 167 sizeof(jt_file), /* szOsFile */ |
| 167 JT_MAX_PATHNAME, /* mxPathname */ | 168 JT_MAX_PATHNAME, /* mxPathname */ |
| 168 0, /* pNext */ | 169 0, /* pNext */ |
| 169 JT_VFS_NAME, /* zName */ | 170 JT_VFS_NAME, /* zName */ |
| 170 0, /* pAppData */ | 171 0, /* pAppData */ |
| 171 jtOpen, /* xOpen */ | 172 jtOpen, /* xOpen */ |
| 172 jtDelete, /* xDelete */ | 173 jtDelete, /* xDelete */ |
| 173 jtAccess, /* xAccess */ | 174 jtAccess, /* xAccess */ |
| 174 jtFullPathname, /* xFullPathname */ | 175 jtFullPathname, /* xFullPathname */ |
| 175 jtDlOpen, /* xDlOpen */ | 176 jtDlOpen, /* xDlOpen */ |
| 176 jtDlError, /* xDlError */ | 177 jtDlError, /* xDlError */ |
| 177 jtDlSym, /* xDlSym */ | 178 jtDlSym, /* xDlSym */ |
| 178 jtDlClose, /* xDlClose */ | 179 jtDlClose, /* xDlClose */ |
| 179 jtRandomness, /* xRandomness */ | 180 jtRandomness, /* xRandomness */ |
| 180 jtSleep, /* xSleep */ | 181 jtSleep, /* xSleep */ |
| 181 jtCurrentTime, /* xCurrentTime */ | 182 jtCurrentTime, /* xCurrentTime */ |
| 182 0, /* xGetLastError */ | 183 jtGetLastError, /* xGetLastError */ |
| 183 jtCurrentTimeInt64 /* xCurrentTimeInt64 */ | 184 jtCurrentTimeInt64 /* xCurrentTimeInt64 */ |
| 184 }; | 185 }; |
| 185 | 186 |
| 186 static sqlite3_io_methods jt_io_methods = { | 187 static sqlite3_io_methods jt_io_methods = { |
| 187 1, /* iVersion */ | 188 1, /* iVersion */ |
| 188 jtClose, /* xClose */ | 189 jtClose, /* xClose */ |
| 189 jtRead, /* xRead */ | 190 jtRead, /* xRead */ |
| 190 jtWrite, /* xWrite */ | 191 jtWrite, /* xWrite */ |
| 191 jtTruncate, /* xTruncate */ | 192 jtTruncate, /* xTruncate */ |
| 192 jtSync, /* xSync */ | 193 jtSync, /* xSync */ |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 jt_file **pp; | 250 jt_file **pp; |
| 250 jt_file *p = (jt_file *)pFile; | 251 jt_file *p = (jt_file *)pFile; |
| 251 | 252 |
| 252 closeTransaction(p); | 253 closeTransaction(p); |
| 253 enterJtMutex(); | 254 enterJtMutex(); |
| 254 if( p->zName ){ | 255 if( p->zName ){ |
| 255 for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext); | 256 for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext); |
| 256 *pp = p->pNext; | 257 *pp = p->pNext; |
| 257 } | 258 } |
| 258 leaveJtMutex(); | 259 leaveJtMutex(); |
| 259 return sqlite3OsClose(p->pReal); | 260 sqlite3OsClose(p->pReal); |
| 261 return SQLITE_OK; |
| 260 } | 262 } |
| 261 | 263 |
| 262 /* | 264 /* |
| 263 ** Read data from an jt-file. | 265 ** Read data from an jt-file. |
| 264 */ | 266 */ |
| 265 static int jtRead( | 267 static int jtRead( |
| 266 sqlite3_file *pFile, | 268 sqlite3_file *pFile, |
| 267 void *zBuf, | 269 void *zBuf, |
| 268 int iAmt, | 270 int iAmt, |
| 269 sqlite_int64 iOfst | 271 sqlite_int64 iOfst |
| 270 ){ | 272 ){ |
| 271 jt_file *p = (jt_file *)pFile; | 273 jt_file *p = (jt_file *)pFile; |
| 272 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); | 274 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); |
| 273 } | 275 } |
| 274 | 276 |
| 275 /* | 277 /* |
| 276 ** Parameter zJournal is the name of a journal file that is currently | 278 ** Parameter zJournal is the name of a journal file that is currently |
| 277 ** open. This function locates and returns the handle opened on the | 279 ** open. This function locates and returns the handle opened on the |
| 278 ** corresponding database file by the pager that currently has the | 280 ** corresponding database file by the pager that currently has the |
| 279 ** journal file opened. This file-handle is identified by the | 281 ** journal file opened. This file-handle is identified by the |
| 280 ** following properties: | 282 ** following properties: |
| 281 ** | 283 ** |
| 282 ** a) SQLITE_OPEN_MAIN_DB was specified when the file was opened. | 284 ** a) SQLITE_OPEN_MAIN_DB was specified when the file was opened. |
| 283 ** | 285 ** |
| 284 ** b) The file-name specified when the file was opened matches | 286 ** b) The file-name specified when the file was opened matches |
| 285 ** all but the final 8 characters of the journal file name. | 287 ** all but the final 8 characters of the journal file name. |
| 286 ** | 288 ** |
| 287 ** c) There is currently a reserved lock on the file. | 289 ** c) There is currently a reserved lock on the file. This |
| 290 ** condition is waived if the noLock argument is non-zero. |
| 288 **/ | 291 **/ |
| 289 static jt_file *locateDatabaseHandle(const char *zJournal){ | 292 static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){ |
| 290 jt_file *pMain = 0; | 293 jt_file *pMain = 0; |
| 291 enterJtMutex(); | 294 enterJtMutex(); |
| 292 for(pMain=g.pList; pMain; pMain=pMain->pNext){ | 295 for(pMain=g.pList; pMain; pMain=pMain->pNext){ |
| 293 int nName = (int)(strlen(zJournal) - strlen("-journal")); | 296 int nName = (int)(strlen(zJournal) - strlen("-journal")); |
| 294 if( (pMain->flags&SQLITE_OPEN_MAIN_DB) | 297 if( (pMain->flags&SQLITE_OPEN_MAIN_DB) |
| 295 && ((int)strlen(pMain->zName)==nName) | 298 && ((int)strlen(pMain->zName)==nName) |
| 296 && 0==memcmp(pMain->zName, zJournal, nName) | 299 && 0==memcmp(pMain->zName, zJournal, nName) |
| 297 && (pMain->eLock>=SQLITE_LOCK_RESERVED) | 300 && ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock) |
| 298 ){ | 301 ){ |
| 299 break; | 302 break; |
| 300 } | 303 } |
| 301 } | 304 } |
| 302 leaveJtMutex(); | 305 leaveJtMutex(); |
| 303 return pMain; | 306 return pMain; |
| 304 } | 307 } |
| 305 | 308 |
| 306 /* | 309 /* |
| 307 ** Parameter z points to a buffer of 4 bytes in size containing a | 310 ** Parameter z points to a buffer of 4 bytes in size containing a |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 static int jtWrite( | 512 static int jtWrite( |
| 510 sqlite3_file *pFile, | 513 sqlite3_file *pFile, |
| 511 const void *zBuf, | 514 const void *zBuf, |
| 512 int iAmt, | 515 int iAmt, |
| 513 sqlite_int64 iOfst | 516 sqlite_int64 iOfst |
| 514 ){ | 517 ){ |
| 515 int rc; | 518 int rc; |
| 516 jt_file *p = (jt_file *)pFile; | 519 jt_file *p = (jt_file *)pFile; |
| 517 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ | 520 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ |
| 518 if( iOfst==0 ){ | 521 if( iOfst==0 ){ |
| 519 jt_file *pMain = locateDatabaseHandle(p->zName); | 522 jt_file *pMain = locateDatabaseHandle(p->zName, 0); |
| 520 assert( pMain ); | 523 assert( pMain ); |
| 521 | 524 |
| 522 if( iAmt==28 ){ | 525 if( iAmt==28 ){ |
| 523 /* Zeroing the first journal-file header. This is the end of a | 526 /* Zeroing the first journal-file header. This is the end of a |
| 524 ** transaction. */ | 527 ** transaction. */ |
| 525 closeTransaction(pMain); | 528 closeTransaction(pMain); |
| 526 }else if( iAmt!=12 ){ | 529 }else if( iAmt!=12 ){ |
| 527 /* Writing the first journal header to a journal file. This happens | 530 /* Writing the first journal header to a journal file. This happens |
| 528 ** when a transaction is first started. */ | 531 ** when a transaction is first started. */ |
| 529 u8 *z = (u8 *)zBuf; | 532 u8 *z = (u8 *)zBuf; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 554 u32 pgno = (u32)(iOfst/p->nPagesize + 1); | 557 u32 pgno = (u32)(iOfst/p->nPagesize + 1); |
| 555 assert( (iAmt==1||iAmt==(int)p->nPagesize) && | 558 assert( (iAmt==1||iAmt==(int)p->nPagesize) && |
| 556 ((iOfst+iAmt)%p->nPagesize)==0 ); | 559 ((iOfst+iAmt)%p->nPagesize)==0 ); |
| 557 assert( pgno<=p->nPage || p->nSync>0 ); | 560 assert( pgno<=p->nPage || p->nSync>0 ); |
| 558 assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) ); | 561 assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) ); |
| 559 } | 562 } |
| 560 } | 563 } |
| 561 | 564 |
| 562 rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); | 565 rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); |
| 563 if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){ | 566 if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){ |
| 564 jt_file *pMain = locateDatabaseHandle(p->zName); | 567 jt_file *pMain = locateDatabaseHandle(p->zName, 0); |
| 565 int rc2 = readJournalFile(p, pMain); | 568 int rc2 = readJournalFile(p, pMain); |
| 566 if( rc==SQLITE_OK ) rc = rc2; | 569 if( rc==SQLITE_OK ) rc = rc2; |
| 567 } | 570 } |
| 568 return rc; | 571 return rc; |
| 569 } | 572 } |
| 570 | 573 |
| 571 /* | 574 /* |
| 572 ** Truncate an jt-file. | 575 ** Truncate an jt-file. |
| 573 */ | 576 */ |
| 574 static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ | 577 static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
| 575 jt_file *p = (jt_file *)pFile; | 578 jt_file *p = (jt_file *)pFile; |
| 576 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){ | 579 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){ |
| 577 /* Truncating a journal file. This is the end of a transaction. */ | 580 /* Truncating a journal file. This is the end of a transaction. */ |
| 578 jt_file *pMain = locateDatabaseHandle(p->zName); | 581 jt_file *pMain = locateDatabaseHandle(p->zName, 0); |
| 579 closeTransaction(pMain); | 582 closeTransaction(pMain); |
| 580 } | 583 } |
| 581 if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ | 584 if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ |
| 582 u32 pgno; | 585 u32 pgno; |
| 583 u32 locking_page = (u32)(PENDING_BYTE/p->nPagesize+1); | 586 u32 locking_page = (u32)(PENDING_BYTE/p->nPagesize+1); |
| 584 for(pgno=(u32)(size/p->nPagesize+1); pgno<=p->nPage; pgno++){ | 587 for(pgno=(u32)(size/p->nPagesize+1); pgno<=p->nPage; pgno++){ |
| 585 assert( pgno==locking_page || sqlite3BitvecTest(p->pWritable, pgno) ); | 588 assert( pgno==locking_page || sqlite3BitvecTest(p->pWritable, pgno) ); |
| 586 } | 589 } |
| 587 } | 590 } |
| 588 return sqlite3OsTruncate(p->pReal, size); | 591 return sqlite3OsTruncate(p->pReal, size); |
| 589 } | 592 } |
| 590 | 593 |
| 591 /* | 594 /* |
| 592 ** Sync an jt-file. | 595 ** Sync an jt-file. |
| 593 */ | 596 */ |
| 594 static int jtSync(sqlite3_file *pFile, int flags){ | 597 static int jtSync(sqlite3_file *pFile, int flags){ |
| 595 jt_file *p = (jt_file *)pFile; | 598 jt_file *p = (jt_file *)pFile; |
| 596 | 599 |
| 597 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ | 600 if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ |
| 598 int rc; | 601 int rc; |
| 599 jt_file *pMain; /* The associated database file */ | 602 jt_file *pMain; /* The associated database file */ |
| 600 | 603 |
| 601 /* The journal file is being synced. At this point, we inspect the | 604 /* The journal file is being synced. At this point, we inspect the |
| 602 ** contents of the file up to this point and set each bit in the | 605 ** contents of the file up to this point and set each bit in the |
| 603 ** jt_file.pWritable bitvec of the main database file associated with | 606 ** jt_file.pWritable bitvec of the main database file associated with |
| 604 ** this journal file. | 607 ** this journal file. |
| 605 */ | 608 */ |
| 606 pMain = locateDatabaseHandle(p->zName); | 609 pMain = locateDatabaseHandle(p->zName, 0); |
| 607 assert(pMain); | |
| 608 | 610 |
| 609 /* Set the bitvec values */ | 611 /* Set the bitvec values */ |
| 610 if( pMain->pWritable ){ | 612 if( pMain && pMain->pWritable ){ |
| 611 pMain->nSync++; | 613 pMain->nSync++; |
| 612 rc = readJournalFile(p, pMain); | 614 rc = readJournalFile(p, pMain); |
| 613 if( rc!=SQLITE_OK ){ | 615 if( rc!=SQLITE_OK ){ |
| 614 return rc; | 616 return rc; |
| 615 } | 617 } |
| 616 } | 618 } |
| 617 } | 619 } |
| 618 | 620 |
| 619 return sqlite3OsSync(p->pReal, flags); | 621 return sqlite3OsSync(p->pReal, flags); |
| 620 } | 622 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 | 724 |
| 723 /* | 725 /* |
| 724 ** Delete the file located at zPath. If the dirSync argument is true, | 726 ** Delete the file located at zPath. If the dirSync argument is true, |
| 725 ** ensure the file-system modifications are synced to disk before | 727 ** ensure the file-system modifications are synced to disk before |
| 726 ** returning. | 728 ** returning. |
| 727 */ | 729 */ |
| 728 static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ | 730 static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 729 int nPath = (int)strlen(zPath); | 731 int nPath = (int)strlen(zPath); |
| 730 if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ | 732 if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ |
| 731 /* Deleting a journal file. The end of a transaction. */ | 733 /* Deleting a journal file. The end of a transaction. */ |
| 732 jt_file *pMain = locateDatabaseHandle(zPath); | 734 jt_file *pMain = locateDatabaseHandle(zPath, 0); |
| 733 if( pMain ){ | 735 if( pMain ){ |
| 734 closeTransaction(pMain); | 736 closeTransaction(pMain); |
| 735 } | 737 } |
| 736 } | 738 } |
| 737 | 739 |
| 738 return sqlite3OsDelete(g.pVfs, zPath, dirSync); | 740 return sqlite3OsDelete(g.pVfs, zPath, dirSync); |
| 739 } | 741 } |
| 740 | 742 |
| 741 /* | 743 /* |
| 742 ** Test for access permissions. Return true if the requested permission | 744 ** Test for access permissions. Return true if the requested permission |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 static int jtCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ | 819 static int jtCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ |
| 818 return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); | 820 return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); |
| 819 } | 821 } |
| 820 /* | 822 /* |
| 821 ** Return the current time as a Julian Day number in *pTimeOut. | 823 ** Return the current time as a Julian Day number in *pTimeOut. |
| 822 */ | 824 */ |
| 823 static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ | 825 static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ |
| 824 return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut); | 826 return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut); |
| 825 } | 827 } |
| 826 | 828 |
| 829 static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){ |
| 830 return g.pVfs->xGetLastError(g.pVfs, n, z); |
| 831 } |
| 832 |
| 827 /************************************************************************** | 833 /************************************************************************** |
| 828 ** Start of public API. | 834 ** Start of public API. |
| 829 */ | 835 */ |
| 830 | 836 |
| 831 /* | 837 /* |
| 832 ** Configure the jt VFS as a wrapper around the VFS named by parameter | 838 ** Configure the jt VFS as a wrapper around the VFS named by parameter |
| 833 ** zWrap. If the isDefault parameter is true, then the jt VFS is installed | 839 ** zWrap. If the isDefault parameter is true, then the jt VFS is installed |
| 834 ** as the new default VFS for SQLite connections. If isDefault is not | 840 ** as the new default VFS for SQLite connections. If isDefault is not |
| 835 ** true, then the jt VFS is installed as non-default. In this case it | 841 ** true, then the jt VFS is installed as non-default. In this case it |
| 836 ** is available via its name, "jt". | 842 ** is available via its name, "jt". |
| (...skipping 14 matching lines...) Expand all Loading... |
| 851 } | 857 } |
| 852 | 858 |
| 853 /* | 859 /* |
| 854 ** Uninstall the jt VFS, if it is installed. | 860 ** Uninstall the jt VFS, if it is installed. |
| 855 */ | 861 */ |
| 856 void jt_unregister(void){ | 862 void jt_unregister(void){ |
| 857 sqlite3_vfs_unregister(&jt_vfs); | 863 sqlite3_vfs_unregister(&jt_vfs); |
| 858 } | 864 } |
| 859 | 865 |
| 860 #endif | 866 #endif |
| OLD | NEW |