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 |