From 962398d395324ee4bc1827a619cab34e6ae01650 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Mon, 14 Jun 2004 09:35:16 +0000 Subject: [PATCH] Ensure master journal file is deleted when a transaction is committed. (CVS 1586) FossilOrigin-Name: cb3cbe00be9a42e974688016a056053cedb55eef --- manifest | 24 +++++++++++------------ manifest.uuid | 2 +- src/main.c | 4 ++-- src/os.h | 1 + src/os_mac.c | 8 ++++++++ src/os_unix.c | 16 +++++++++++++++ src/os_win.c | 8 ++++++++ src/vdbeaux.c | 24 ++++++++++++++++++++--- test/attach2.test | 50 ++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 118 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 0f69873f72..607819ae61 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Check\sthe\svalue\sof\sthe\sschema\scookie\sbefore\sreading\sthe\ssqlite_master\stable.\s(CVS\s1585) -D 2004-06-14T08:26:35 +C Ensure\smaster\sjournal\sfile\sis\sdeleted\swhen\sa\stransaction\sis\scommitted.\s(CVS\s1586) +D 2004-06-14T09:35:17 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -38,15 +38,15 @@ F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c 68c7f3ddd6a7f1e5596d6996da1a2861b3789a3a F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f -F src/main.c c68c873165e0ee0bdf4f6c2bc79b95c1d6c010c6 +F src/main.c a62c08c9d315c3ebc58bfb6b52ab5953ee8a3089 F src/md5.c d77a389955759c8329bb357e3d71bac3d6eb710b -F src/os.h 23c69c5084e71b5fe199ff1c4e35a4aded0f1380 +F src/os.h 5df666d324f9c75bb21e0fab88e7028ee78149fb F src/os_common.h ba1b7306e16e2091718f2c48db0fe6c1d7a31bb8 -F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0 +F src/os_mac.c 129029f9faecf1133edcf72eaedd54c1c838b140 F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4 -F src/os_unix.c 7ece785e36c4ecb57c73db8d374b56912d742c4a +F src/os_unix.c 558006f887570435a8d546a1785b3798ee8cac01 F src/os_unix.h 1cd6133cf66dea704b8646b70b2dfdcbdd9b3738 -F src/os_win.c d4009586dfd0543ca8956ff0be30f9d23e2cbbdd +F src/os_win.c 44b9291d5c10797fd0df932f22693406719c3958 F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c F src/pager.c d42af374b23b50805b42c08cbba5bd70dd73964f F src/pager.h bc58d32a9dee464f7268fb68652c130a4216e438 @@ -75,12 +75,12 @@ F src/vdbe.c e6b6702fb2c2e2702e312f52c2cc08353c580736 F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde F src/vdbeInt.h ffc7b8ed911c5bf804796a768fdb6f0568010fa2 F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829 -F src/vdbeaux.c d792de3b042ffc49c344e147543af6cf2a3dc5de +F src/vdbeaux.c 71f78da2fa03782ff1e1e8a6c0cb9515476dcc63 F src/vdbemem.c 34f59988831ea032b7f526c2c73175f9f4c0f3ad F src/where.c 7fee7aeb9278f27324f228c55ab453b5f183b486 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test aed659e52635662bcd5069599aaca823533edf5a -F test/attach2.test e6b5f0d735cf8f6c14acfa2ce69b925dbe316b3e +F test/attach2.test e05d729cb0caba21cfd22f31514e4c5a8fb5ca46 F test/attach3.test 8259ab833b5dcdf4acd75d9653f42f703ce2e013 F test/auth.test 95809b8f6a9bec18b94d28cafd03fe27d2f8a9e9 F test/bigfile.test 5b079dfe7354a6c43b92a3ea5e49e4e5d88c789e @@ -223,7 +223,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 76ac9a787b42da3bfa94192b26ed48483b5ff189 -R cb43c2ac061bba3c7f2b42fc3c617478 +P 80c299f8839d920c61854f575498340b28db98d7 +R 2a26bd56f402531968f23465e08b6082 U danielk1977 -Z d6b1db4c3da9986bdf5a43e04901c9a9 +Z 8b29c6d3832661f7081a99e40be4ebed diff --git a/manifest.uuid b/manifest.uuid index 297a260814..78e6d5fdb8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80c299f8839d920c61854f575498340b28db98d7 \ No newline at end of file +cb3cbe00be9a42e974688016a056053cedb55eef \ No newline at end of file diff --git a/src/main.c b/src/main.c index 5319fc58b2..500dcd822d 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.219 2004/06/13 23:07:04 drh Exp $ +** $Id: main.c,v 1.220 2004/06/14 09:35:17 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -225,7 +225,7 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ ** meta[3] Synchronous setting. 1:off, 2:normal, 3:full ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE ** meta[5] Pragma temp_store value. See comments on BtreeFactory - ** meta[6] + ** meta[6] ** meta[7] ** meta[8] ** meta[9] diff --git a/src/os.h b/src/os.h index ea3a457832..ea367be945 100644 --- a/src/os.h +++ b/src/os.h @@ -148,6 +148,7 @@ int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); int sqlite3OsOpenExclusive(const char*, OsFile*, int); int sqlite3OsOpenReadOnly(const char*, OsFile*); int sqlite3OsOpenDirectory(const char*, OsFile*); +int sqlite3OsSyncDirectory(const char*); int sqlite3OsTempFileName(char*); int sqlite3OsClose(OsFile*); int sqlite3OsRead(OsFile*, void*, int amt); diff --git a/src/os_mac.c b/src/os_mac.c index cd88d569af..75ddb163a9 100644 --- a/src/os_mac.c +++ b/src/os_mac.c @@ -392,6 +392,14 @@ int sqlite3OsSync(OsFile *id){ } } +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ + return SQLITE_OK; +} + /* ** Truncate an open file to a specified size */ diff --git a/src/os_unix.c b/src/os_unix.c index 37a04f38b2..1a05411314 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -620,6 +620,22 @@ int sqlite3OsSync(OsFile *id){ } } +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ + int fd; + int r; + fd = open(zDirname, O_RDONLY|O_BINARY, 0644); + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + r = fsync(fd); + close(fd); + return ((r==0)?SQLITE_OK:SQLITE_IOERR); +} + /* ** Truncate an open file to a specified size */ diff --git a/src/os_win.c b/src/os_win.c index b729c0f689..394be52715 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -290,6 +290,14 @@ int sqlite3OsSync(OsFile *id){ } } +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3OsSyncDirectory(const char *zDirname){ + return SQLITE_OK; +} + /* ** Truncate an open file to a specified size */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 26dde13ecb..dc789eec63 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1087,10 +1087,10 @@ static int vdbeCommit(sqlite *db){ } rc = sqlite3OsSync(&master); if( rc!=SQLITE_OK ){ + sqlite3OsClose(&master); sqliteFree(zMaster); return rc; } - sqlite3OsClose(&master); /* Sync all the db files involved in the transaction. The same call ** sets the master journal pointer in each individual journal. If @@ -1107,22 +1107,40 @@ static int vdbeCommit(sqlite *db){ if( pBt && sqlite3BtreeIsInTrans(pBt) ){ rc = sqlite3BtreeSync(pBt, zMaster); if( rc!=SQLITE_OK ){ + sqlite3OsClose(&master); sqliteFree(zMaster); return rc; } } } + sqlite3OsClose(&master); sqliteFree(zMaster); zMaster = 0; - /* Delete the master journal file. This commits the transaction. */ + /* Delete the master journal file. This commits the transaction. After + ** doing this the directory is synced again before any individual + ** transaction files are deleted. + */ rc = sqlite3OsDelete(zMaster); assert( rc==SQLITE_OK ); + rc = sqlite3OsSyncDirectory(zMainFile); + if( rc!=SQLITE_OK ){ + /* This is not good. The master journal file has been deleted, but + ** the directory sync failed. There is no completely safe course of + ** action from here. The individual journals contain the name of the + ** master journal file, but there is no way of knowing if that + ** master journal exists now or if it will exist after the operating + ** system crash that may follow the fsync() failure. + */ + assert(0); + sqliteFree(zMaster); + return rc; + } /* All files and directories have already been synced, so the following ** calls to sqlite3BtreeCommit() are only closing files and deleting ** journals. If something goes wrong while this is happening we don't - ** really care. The integrity of the transaction is already guarenteed, + ** really care. The integrity of the transaction is already guaranteed, ** but some stray 'cold' journals may be lying around. Returning an ** error code won't help matters. */ diff --git a/test/attach2.test b/test/attach2.test index 4a8b9c034d..c22ef4af81 100644 --- a/test/attach2.test +++ b/test/attach2.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach2.test,v 1.16 2004/06/12 02:17:15 drh Exp $ +# $Id: attach2.test,v 1.17 2004/06/14 09:35:17 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -304,4 +304,52 @@ db close db2 close file delete -force test2.db +if 0 { + +# These tests - attach2-5.* - check that the master journal file is deleted +# correctly when a multi-file transaction is committed or rolled back. +# +# Update: It's not actually created if a rollback occurs, so that test +# doesn't really prove too much. +foreach f [glob test.db*] {file delete -force $f} +do_test attach2-5.1 { + sqlite db test.db + execsql { + ATTACH 'test.db2' AS aux; + } +} {} +do_test attach2-5.2 { + execsql { + BEGIN; + CREATE TABLE tbl(a, b, c); + CREATE TABLE aux.tbl(a, b, c); + COMMIT; + } +} {} +do_test attach2-5.3 { + glob test.db* +} {test.db test.db2} +do_test attach2-5.4 { + execsql { + BEGIN; + DROP TABLE aux.tbl; + DROP TABLE tbl; + ROLLBACK; + } +} {} +do_test attach2-5.5 { + glob test.db* +} {test.db test.db2} + +db close + +} + + finish_test + + + + + +