mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
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) FossilOrigin-Name: 09c10fe3c99cffc64ed02c2929f206d99c8e3309
This commit is contained in:
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Make\ssure\sthe\sschema\sloader\scallback\scan\shandle\sEMPTY_RESULT_CALLBACKS\sbeing\non.\s\sTicket\s#406.\s(CVS\s1065)
|
C When\screating\sa\snew\sjournal\sfile,\sopen\sa\s(read-only)\sfile\sdescriptor\son\sthe\ndirectory\scontaining\sthe\sjournal\sand\ssync\sthat\sdirectory\sonce\sto\smake\ssure\nthat\sthe\sjournal\sfilename\sentry\sgets\sinto\sthe\sdirectory.\s\sTicket\s#410.\s(CVS\s1066)
|
||||||
D 2003-07-27T17:26:23
|
D 2003-07-27T18:59:43
|
||||||
F Makefile.in 9ad23ed4ca97f9670c4496432e3fbd4b3760ebde
|
F Makefile.in 9ad23ed4ca97f9670c4496432e3fbd4b3760ebde
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -35,9 +35,9 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
|
|||||||
F src/insert.c fc4c26a0bb505fb802babfb9a7b7a1d4be2e3061
|
F src/insert.c fc4c26a0bb505fb802babfb9a7b7a1d4be2e3061
|
||||||
F src/main.c 2500392bad5629b6d70b06ac5a076958acb49b92
|
F src/main.c 2500392bad5629b6d70b06ac5a076958acb49b92
|
||||||
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
||||||
F src/os.c 2f24ede4d3464ac38d24d113e0d44d3c7d460be4
|
F src/os.c b0ae51da6e2ec7dd9f48f92ac88985d5fde8c1d5
|
||||||
F src/os.h 9e5bbddff123187295e3d00d49af06192cd1cd49
|
F src/os.h 8aed1c928449433acf19d30f76bc86d549041167
|
||||||
F src/pager.c 9512e789dbd5acaf91e74c4665e03c2734d3da25
|
F src/pager.c a4fd3a61d63879365f775875edfffaa8c6f3d7f8
|
||||||
F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
|
F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
|
||||||
F src/parse.y 16aed0e3ed05445fa7f6a4209cc054208c7083c0
|
F src/parse.y 16aed0e3ed05445fa7f6a4209cc054208c7083c0
|
||||||
F src/pragma.c 3b4f5a800e7a2145bc1930f323232e297d4eb782
|
F src/pragma.c 3b4f5a800e7a2145bc1930f323232e297d4eb782
|
||||||
@ -168,7 +168,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
|
|||||||
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||||
P 7514c3db165e8cc5c696b2b345844949a0e45a61
|
P 8c163fc0c7c721b7a5fa6727b0e90bff4484c782
|
||||||
R 85b9f91d179fe7af6d0cda86f9bcda89
|
R 8fa888001788f8c7b2a2f5a0b6144c1c
|
||||||
U drh
|
U drh
|
||||||
Z 4a83ca4578ca29e5406602c40689d847
|
Z 5beb2c4636d8c2b6025132999d440be1
|
||||||
|
@ -1 +1 @@
|
|||||||
8c163fc0c7c721b7a5fa6727b0e90bff4484c782
|
09c10fe3c99cffc64ed02c2929f206d99c8e3309
|
55
src/os.c
55
src/os.c
@ -326,6 +326,7 @@ int sqliteOsOpenReadWrite(
|
|||||||
int *pReadonly
|
int *pReadonly
|
||||||
){
|
){
|
||||||
#if OS_UNIX
|
#if OS_UNIX
|
||||||
|
id->dirfd = -1;
|
||||||
id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
|
id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
|
||||||
if( id->fd<0 ){
|
if( id->fd<0 ){
|
||||||
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
||||||
@ -450,6 +451,7 @@ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
|
|||||||
if( access(zFilename, 0)==0 ){
|
if( access(zFilename, 0)==0 ){
|
||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
|
id->dirfd = -1;
|
||||||
id->fd = open(zFilename,
|
id->fd = open(zFilename,
|
||||||
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
|
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
|
||||||
if( id->fd<0 ){
|
if( id->fd<0 ){
|
||||||
@ -536,6 +538,7 @@ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
|
|||||||
*/
|
*/
|
||||||
int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
|
int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
|
||||||
#if OS_UNIX
|
#if OS_UNIX
|
||||||
|
id->dirfd = -1;
|
||||||
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
||||||
if( id->fd<0 ){
|
if( id->fd<0 ){
|
||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
@ -597,6 +600,42 @@ int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
|
|||||||
#endif
|
#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
|
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||||
** hold at least SQLITE_TEMPNAME_SIZE characters.
|
** hold at least SQLITE_TEMPNAME_SIZE characters.
|
||||||
@ -706,6 +745,8 @@ int sqliteOsTempFileName(char *zBuf){
|
|||||||
int sqliteOsClose(OsFile *id){
|
int sqliteOsClose(OsFile *id){
|
||||||
#if OS_UNIX
|
#if OS_UNIX
|
||||||
close(id->fd);
|
close(id->fd);
|
||||||
|
if( id->dirfd>=0 ) close(id->dirfd);
|
||||||
|
id->dirfd = -1;
|
||||||
sqliteOsEnterMutex();
|
sqliteOsEnterMutex();
|
||||||
releaseLockInfo(id->pLock);
|
releaseLockInfo(id->pLock);
|
||||||
sqliteOsLeaveMutex();
|
sqliteOsLeaveMutex();
|
||||||
@ -892,6 +933,14 @@ int sqliteOsSeek(OsFile *id, off_t offset){
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Make sure all writes to a particular file are committed to disk.
|
** 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){
|
int sqliteOsSync(OsFile *id){
|
||||||
#if OS_UNIX
|
#if OS_UNIX
|
||||||
@ -900,6 +949,12 @@ int sqliteOsSync(OsFile *id){
|
|||||||
if( fsync(id->fd) ){
|
if( fsync(id->fd) ){
|
||||||
return SQLITE_IOERR;
|
return SQLITE_IOERR;
|
||||||
}else{
|
}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;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
2
src/os.h
2
src/os.h
@ -104,6 +104,7 @@
|
|||||||
struct lockInfo *pLock; /* Information about locks on this inode */
|
struct lockInfo *pLock; /* Information about locks on this inode */
|
||||||
int fd; /* The file descriptor */
|
int fd; /* The file descriptor */
|
||||||
int locked; /* True if this user holds the lock */
|
int locked; /* True if this user holds the lock */
|
||||||
|
int dirfd; /* File descriptor for the directory */
|
||||||
};
|
};
|
||||||
# define SQLITE_TEMPNAME_SIZE 200
|
# define SQLITE_TEMPNAME_SIZE 200
|
||||||
# if defined(HAVE_USLEEP) && HAVE_USLEEP
|
# if defined(HAVE_USLEEP) && HAVE_USLEEP
|
||||||
@ -156,6 +157,7 @@ int sqliteOsFileRename(const char*, const char*);
|
|||||||
int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
|
int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
|
||||||
int sqliteOsOpenExclusive(const char*, OsFile*, int);
|
int sqliteOsOpenExclusive(const char*, OsFile*, int);
|
||||||
int sqliteOsOpenReadOnly(const char*, OsFile*);
|
int sqliteOsOpenReadOnly(const char*, OsFile*);
|
||||||
|
int sqliteOsOpenDirectory(const char*, OsFile*);
|
||||||
int sqliteOsTempFileName(char*);
|
int sqliteOsTempFileName(char*);
|
||||||
int sqliteOsClose(OsFile*);
|
int sqliteOsClose(OsFile*);
|
||||||
int sqliteOsRead(OsFile*, void*, int amt);
|
int sqliteOsRead(OsFile*, void*, int amt);
|
||||||
|
16
src/pager.c
16
src/pager.c
@ -18,7 +18,7 @@
|
|||||||
** file simultaneously, or one process from reading the database while
|
** file simultaneously, or one process from reading the database while
|
||||||
** another is writing.
|
** another is writing.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.c,v 1.86 2003/07/07 10:47:10 drh Exp $
|
** @(#) $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 "os.h" /* Must be first to enable large file support */
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -129,6 +129,7 @@ struct PgHdr {
|
|||||||
struct Pager {
|
struct Pager {
|
||||||
char *zFilename; /* Name of the database file */
|
char *zFilename; /* Name of the database file */
|
||||||
char *zJournal; /* Name of the journal 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 fd, jfd; /* File descriptors for database and journal */
|
||||||
OsFile cpfd; /* File descriptor for the checkpoint journal */
|
OsFile cpfd; /* File descriptor for the checkpoint journal */
|
||||||
int dbSize; /* Number of pages in the file */
|
int dbSize; /* Number of pages in the file */
|
||||||
@ -828,7 +829,7 @@ int sqlitepager_open(
|
|||||||
char *zFullPathname;
|
char *zFullPathname;
|
||||||
int nameLen;
|
int nameLen;
|
||||||
OsFile fd;
|
OsFile fd;
|
||||||
int rc;
|
int rc, i;
|
||||||
int tempFile;
|
int tempFile;
|
||||||
int readOnly = 0;
|
int readOnly = 0;
|
||||||
char zTemp[SQLITE_TEMPNAME_SIZE];
|
char zTemp[SQLITE_TEMPNAME_SIZE];
|
||||||
@ -855,7 +856,7 @@ int sqlitepager_open(
|
|||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
nameLen = strlen(zFullPathname);
|
nameLen = strlen(zFullPathname);
|
||||||
pPager = sqliteMalloc( sizeof(*pPager) + nameLen*2 + 30 );
|
pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
|
||||||
if( pPager==0 ){
|
if( pPager==0 ){
|
||||||
sqliteOsClose(&fd);
|
sqliteOsClose(&fd);
|
||||||
sqliteFree(zFullPathname);
|
sqliteFree(zFullPathname);
|
||||||
@ -863,8 +864,12 @@ int sqlitepager_open(
|
|||||||
}
|
}
|
||||||
SET_PAGER(pPager);
|
SET_PAGER(pPager);
|
||||||
pPager->zFilename = (char*)&pPager[1];
|
pPager->zFilename = (char*)&pPager[1];
|
||||||
pPager->zJournal = &pPager->zFilename[nameLen+1];
|
pPager->zDirectory = &pPager->zFilename[nameLen+1];
|
||||||
|
pPager->zJournal = &pPager->zDirectory[nameLen+1];
|
||||||
strcpy(pPager->zFilename, zFullPathname);
|
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);
|
strcpy(pPager->zJournal, zFullPathname);
|
||||||
sqliteFree(zFullPathname);
|
sqliteFree(zFullPathname);
|
||||||
strcpy(&pPager->zJournal[nameLen], "-journal");
|
strcpy(&pPager->zJournal[nameLen], "-journal");
|
||||||
@ -995,8 +1000,10 @@ int sqlitepager_close(Pager *pPager){
|
|||||||
*/
|
*/
|
||||||
CLR_PAGER(pPager);
|
CLR_PAGER(pPager);
|
||||||
if( pPager->zFilename!=(char*)&pPager[1] ){
|
if( pPager->zFilename!=(char*)&pPager[1] ){
|
||||||
|
assert( 0 ); /* Cannot happen */
|
||||||
sqliteFree(pPager->zFilename);
|
sqliteFree(pPager->zFilename);
|
||||||
sqliteFree(pPager->zJournal);
|
sqliteFree(pPager->zJournal);
|
||||||
|
sqliteFree(pPager->zDirectory);
|
||||||
}
|
}
|
||||||
sqliteFree(pPager);
|
sqliteFree(pPager);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1535,6 +1542,7 @@ static int pager_open_journal(Pager *pPager){
|
|||||||
pPager->state = SQLITE_READLOCK;
|
pPager->state = SQLITE_READLOCK;
|
||||||
return SQLITE_CANTOPEN;
|
return SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
|
sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd);
|
||||||
pPager->journalOpen = 1;
|
pPager->journalOpen = 1;
|
||||||
pPager->journalStarted = 0;
|
pPager->journalStarted = 0;
|
||||||
pPager->needSync = 0;
|
pPager->needSync = 0;
|
||||||
|
Reference in New Issue
Block a user