Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | When creating a new journal file, open a (read-only) file descriptor on the directory containing the journal and sync that directory once to make sure that the journal filename entry gets into the directory. Ticket #410. (CVS 1066) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
09c10fe3c99cffc64ed02c2929f206d9 |
User & Date: | drh 2003-07-27 18:59:43.000 |
Context
2003-07-30
| ||
12:34 | The {quote: SrcList} object was not being expanded correctly by a call to sqliteSrcListAppend() if the {quote: SrcList} had previously been duplicated by a call to sqliteSrcListDup(). Ticket #416. This check-in fixes that problem by keeping a separate nAlloc field on {quote: SrcList}. A similar change is made to {quote: IdList} and {quote: ExprList} to avoid future problems. (CVS 1067) (check-in: da62732554 user: drh tags: trunk) | |
2003-07-27
| ||
18:59 | When creating a new journal file, open a (read-only) file descriptor on the directory containing the journal and sync that directory once to make sure that the journal filename entry gets into the directory. Ticket #410. (CVS 1066) (check-in: 09c10fe3c9 user: drh tags: trunk) | |
17:26 | Make sure the schema loader callback can handle EMPTY_RESULT_CALLBACKS being on. Ticket #406. (CVS 1065) (check-in: 8c163fc0c7 user: drh tags: trunk) | |
Changes
Changes to src/os.c.
︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 | */ int sqliteOsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly ){ #if OS_UNIX id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); if( id->fd<0 ){ id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; | > | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | */ int sqliteOsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly ){ #if OS_UNIX id->dirfd = -1; id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); if( id->fd<0 ){ id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; |
︙ | ︙ | |||
446 447 448 449 450 451 452 453 454 455 456 457 458 459 | ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ #if OS_UNIX if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } id->fd = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); id->pLock = findLockInfo(id->fd); | > | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ #if OS_UNIX if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } id->dirfd = -1; id->fd = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); id->pLock = findLockInfo(id->fd); |
︙ | ︙ | |||
532 533 534 535 536 537 538 539 540 541 542 543 544 545 | ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){ #if OS_UNIX id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); id->pLock = findLockInfo(id->fd); sqliteOsLeaveMutex(); | > | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){ #if OS_UNIX id->dirfd = -1; id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); id->pLock = findLockInfo(id->fd); sqliteOsLeaveMutex(); |
︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 | } id->locked = 0; id->delOnClose = 0; OpenCounter(+1); return SQLITE_OK; #endif } /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqliteOsTempFileName(char *zBuf){ #if OS_UNIX | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 595 596 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 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | } id->locked = 0; id->delOnClose = 0; OpenCounter(+1); return SQLITE_OK; #endif } /* ** Attempt to open a file descriptor for the directory that contains a ** file. This file descriptor can be used to fsync() the directory ** in order to make sure the creation of a new file is actually written ** to disk. ** ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** ** On success, a handle for a previously open file is at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ int sqliteOsOpenDirectory( const char *zDirname, OsFile *id ){ #if OS_UNIX if( id->fd<0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } assert( id->dirfd<0 ); id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644); if( id->dirfd<0 ){ return SQLITE_CANTOPEN; } TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); #endif return SQLITE_OK; } /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqliteOsTempFileName(char *zBuf){ #if OS_UNIX |
︙ | ︙ | |||
702 703 704 705 706 707 708 709 710 711 712 713 714 715 | /* ** Close a file */ int sqliteOsClose(OsFile *id){ #if OS_UNIX close(id->fd); sqliteOsEnterMutex(); releaseLockInfo(id->pLock); sqliteOsLeaveMutex(); TRACE2("CLOSE %-3d\n", id->fd); OpenCounter(-1); return SQLITE_OK; #endif | > > | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | /* ** Close a file */ int sqliteOsClose(OsFile *id){ #if OS_UNIX close(id->fd); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqliteOsEnterMutex(); releaseLockInfo(id->pLock); sqliteOsLeaveMutex(); TRACE2("CLOSE %-3d\n", id->fd); OpenCounter(-1); return SQLITE_OK; #endif |
︙ | ︙ | |||
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 | } } #endif } /* ** Make sure all writes to a particular file are committed to disk. */ int sqliteOsSync(OsFile *id){ #if OS_UNIX SimulateIOError(SQLITE_IOERR); TRACE2("SYNC %-3d\n", id->fd); if( fsync(id->fd) ){ return SQLITE_IOERR; }else{ return SQLITE_OK; } #endif #if OS_WIN if( FlushFileBuffers(id->h) ){ return SQLITE_OK; }else{ | > > > > > > > > > > > > > > | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | } } #endif } /* ** Make sure all writes to a particular file are committed to disk. ** ** Under Unix, also make sure that the directory entry for the file ** has been created by fsync-ing the directory that contains the file. ** If we do not do this and we encounter a power failure, the directory ** entry for the journal might not exist after we reboot. The next ** SQLite to access the file will not know that the journal exists (because ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ int sqliteOsSync(OsFile *id){ #if OS_UNIX SimulateIOError(SQLITE_IOERR); TRACE2("SYNC %-3d\n", id->fd); if( fsync(id->fd) ){ return SQLITE_IOERR; }else{ if( id->dirfd>=0 ){ TRACE2("DIRSYNC %-3d\n", id->dirfd); fsync(id->dirfd); close(id->dirfd); /* Only need to sync once, so close the directory */ id->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } #endif #if OS_WIN if( FlushFileBuffers(id->h) ){ return SQLITE_OK; }else{ |
︙ | ︙ |
Changes to src/os.h.
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 | # include <fcntl.h> # include <unistd.h> typedef struct OsFile OsFile; struct OsFile { struct lockInfo *pLock; /* Information about locks on this inode */ int fd; /* The file descriptor */ int locked; /* True if this user holds the lock */ }; # define SQLITE_TEMPNAME_SIZE 200 # if defined(HAVE_USLEEP) && HAVE_USLEEP # define SQLITE_MIN_SLEEP_MS 1 # else # define SQLITE_MIN_SLEEP_MS 1000 # endif | > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # include <fcntl.h> # include <unistd.h> typedef struct OsFile OsFile; struct OsFile { struct lockInfo *pLock; /* Information about locks on this inode */ int fd; /* The file descriptor */ int locked; /* True if this user holds the lock */ int dirfd; /* File descriptor for the directory */ }; # define SQLITE_TEMPNAME_SIZE 200 # if defined(HAVE_USLEEP) && HAVE_USLEEP # define SQLITE_MIN_SLEEP_MS 1 # else # define SQLITE_MIN_SLEEP_MS 1000 # endif |
︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | int sqliteOsDelete(const char*); int sqliteOsFileExists(const char*); int sqliteOsFileRename(const char*, const char*); int sqliteOsOpenReadWrite(const char*, OsFile*, int*); int sqliteOsOpenExclusive(const char*, OsFile*, int); int sqliteOsOpenReadOnly(const char*, OsFile*); int sqliteOsTempFileName(char*); int sqliteOsClose(OsFile*); int sqliteOsRead(OsFile*, void*, int amt); int sqliteOsWrite(OsFile*, const void*, int amt); int sqliteOsSeek(OsFile*, off_t offset); int sqliteOsSync(OsFile*); int sqliteOsTruncate(OsFile*, off_t size); | > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | int sqliteOsDelete(const char*); int sqliteOsFileExists(const char*); int sqliteOsFileRename(const char*, const char*); int sqliteOsOpenReadWrite(const char*, OsFile*, int*); int sqliteOsOpenExclusive(const char*, OsFile*, int); int sqliteOsOpenReadOnly(const char*, OsFile*); int sqliteOsOpenDirectory(const char*, OsFile*); int sqliteOsTempFileName(char*); int sqliteOsClose(OsFile*); int sqliteOsRead(OsFile*, void*, int amt); int sqliteOsWrite(OsFile*, const void*, int amt); int sqliteOsSeek(OsFile*, off_t offset); int sqliteOsSync(OsFile*); int sqliteOsTruncate(OsFile*, off_t size); |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** 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. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** 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. ** ** @(#) $Id: pager.c,v 1.87 2003/07/27 18:59:43 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 | /* ** A open page cache is an instance of the following structure. */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ OsFile fd, jfd; /* File descriptors for database and journal */ OsFile cpfd; /* File descriptor for the checkpoint journal */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int ckptSize; /* Size of database (in pages) at ckpt_begin() */ off_t ckptJSize; /* Size of journal at ckpt_begin() */ int nRec; /* Number of pages written to the journal */ | > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | /* ** A open page cache is an instance of the following structure. */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ OsFile fd, jfd; /* File descriptors for database and journal */ OsFile cpfd; /* File descriptor for the checkpoint journal */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int ckptSize; /* Size of database (in pages) at ckpt_begin() */ off_t ckptJSize; /* Size of journal at ckpt_begin() */ int nRec; /* Number of pages written to the journal */ |
︙ | ︙ | |||
824 825 826 827 828 829 830 | int nExtra, /* Extra bytes append to each in-memory page */ int useJournal /* TRUE to use a rollback journal on this file */ ){ Pager *pPager; char *zFullPathname; int nameLen; OsFile fd; | | | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 | int nExtra, /* Extra bytes append to each in-memory page */ int useJournal /* TRUE to use a rollback journal on this file */ ){ Pager *pPager; char *zFullPathname; int nameLen; OsFile fd; int rc, i; int tempFile; int readOnly = 0; char zTemp[SQLITE_TEMPNAME_SIZE]; *ppPager = 0; if( sqlite_malloc_failed ){ return SQLITE_NOMEM; |
︙ | ︙ | |||
851 852 853 854 855 856 857 | return SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqliteFree(zFullPathname); return SQLITE_CANTOPEN; } nameLen = strlen(zFullPathname); | | > | > > > | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | return SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqliteFree(zFullPathname); return SQLITE_CANTOPEN; } nameLen = strlen(zFullPathname); pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); if( pPager==0 ){ sqliteOsClose(&fd); sqliteFree(zFullPathname); return SQLITE_NOMEM; } SET_PAGER(pPager); pPager->zFilename = (char*)&pPager[1]; pPager->zDirectory = &pPager->zFilename[nameLen+1]; pPager->zJournal = &pPager->zDirectory[nameLen+1]; strcpy(pPager->zFilename, zFullPathname); strcpy(pPager->zDirectory, zFullPathname); for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; pPager->journalOpen = 0; pPager->useJournal = useJournal; pPager->ckptOpen = 0; |
︙ | ︙ | |||
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 | /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqliteOsDelete(pPager->zFilename); ** } */ CLR_PAGER(pPager); if( pPager->zFilename!=(char*)&pPager[1] ){ sqliteFree(pPager->zFilename); sqliteFree(pPager->zJournal); } sqliteFree(pPager); return SQLITE_OK; } /* ** Return the page number for the given page data. | > > | 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 | /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqliteOsDelete(pPager->zFilename); ** } */ CLR_PAGER(pPager); if( pPager->zFilename!=(char*)&pPager[1] ){ assert( 0 ); /* Cannot happen */ sqliteFree(pPager->zFilename); sqliteFree(pPager->zJournal); sqliteFree(pPager->zDirectory); } sqliteFree(pPager); return SQLITE_OK; } /* ** Return the page number for the given page data. |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | if( rc!=SQLITE_OK ){ sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; sqliteOsReadLock(&pPager->fd); pPager->state = SQLITE_READLOCK; return SQLITE_CANTOPEN; } pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); | > | 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 | if( rc!=SQLITE_OK ){ sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; sqliteOsReadLock(&pPager->fd); pPager->state = SQLITE_READLOCK; return SQLITE_CANTOPEN; } sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); |
︙ | ︙ |