From 94f3331a0b5efd84b7f3f7d571b910c245d29ff8 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 12 Aug 2002 12:29:56 +0000 Subject: [PATCH] Fix for ticket #9 (again). The rollback journal files should now also be byte-order independent. (CVS 705) FossilOrigin-Name: 2fb3fdcdf06c1206bf14da640c2f9e599455f0eb --- manifest | 20 +++++------ manifest.uuid | 2 +- src/pager.c | 94 ++++++++++++++++++++++++++++++++++++++++++++----- src/pager.h | 3 +- src/test2.c | 6 +++- test/trans.test | 3 +- www/index.tcl | 8 +---- 7 files changed, 106 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 53517d7138..7722b2620a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfor\sticket\s#9:\sAdd\sthe\sability\sto\sread\slittle-endian\sdatabase\sfiles\nfrom\sa\sbig-endian\smachine\sand\svice\sversa.\s(CVS\s704) -D 2002-08-11T20:10:47 +C Fix\sfor\sticket\s#9\s(again).\s\sThe\srollback\sjournal\sfiles\sshould\snow\salso\sbe\nbyte-order\sindependent.\s(CVS\s705) +D 2002-08-12T12:29:57 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -32,8 +32,8 @@ F src/main.c 0f5d0f6f27333a851d848bfdd7bfa67a37cea12b F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/os.c 9665974085ebe1d40d56d1145045b3d64f12cbce F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10 -F src/pager.c b8415b02a2a5c4e9d8bfd45311a5f15e785c7f1f -F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e +F src/pager.c ca54e21cad43270027b6872ffe3b6e86a5099dfb +F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32 F src/parse.y 66e7da55b34b57f81ca07e50d1dcc430b1c1bf74 F src/printf.c 06f4c8725063e0faf0e34824ab70feace7146bf7 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe @@ -45,7 +45,7 @@ F src/sqliteInt.h b40ef4cdcfc98e2e9417e73b896c8b2bfec545eb F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c c502819c209011659e1bbb428cbac5670cce7f79 F src/test1.c 456cb080db85056be723e770435d9509afc3a83a -F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730 +F src/test2.c 279057a854359665b89122070ac1fc472acce1b2 F src/test3.c b99d5ab68ee672f1fbb00520723b5c21bac35822 F src/threadtest.c 72bce0a284647314847bbea44616ceb056bfb77f F src/tokenize.c b5500e193a82b5b9888fbf947efd90d3b4858178 @@ -100,7 +100,7 @@ F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tclsqlite.test 6f4b9760681c7dbca52a18d0ab46a1679cdc79b9 F test/temptable.test 9ed7ec0288f887e132de66d90c428ad109105f67 F test/tester.tcl 6f603d90881bd835ea27c568a7fecaa57dce91cc -F test/trans.test 1fd1ecdece1eca22abe631674c3bd24046df4150 +F test/trans.test b8a51e9f61d55d0185a813695a55a7fad8fe8ab7 F test/trigger1.test bb63749fa8a395a60541100607d86381604b7194 F test/trigger2.test f739876942a26c63d42387321a89b75ec93af48a F test/trigger3.test 7dfe798d7e72c13720394685fe353112e3f31adf @@ -135,7 +135,7 @@ F www/download.tcl 29aa6679ca29621d10613f60ebbbda18f4b91c49 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/faq.tcl 5e3f71ced26a6dc863bd8d7afd711bf16c99acf6 F www/formatchng.tcl 502847353450adaf76d187d87374bce20dd07e0e -F www/index.tcl 72684d0dbad02f58edd27e71ccf11a797c4bd6e9 +F www/index.tcl 6c9b78fa8cb117fa5af2ccff56a47eef798f39a4 F www/lang.tcl 8c3d0bda030f110c754b5edbad75eddf5dbe2ed1 F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc F www/opcode.tcl 33c5f2061a05c5d227c72b84c080b3bf74c74f8b @@ -143,7 +143,7 @@ F www/speed.tcl 7fc83f1b018e1ecc451838449542c3079ed12425 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 61bb3af7405aa7b54f3e5519537ea483879eed39 -R c9670f7561402c0ee88efdafe6f79692 +P ce4b943bf68c160445a58ffccfbabbbd30d9829b +R eceb789f2b856b82ace2f266f575aef0 U drh -Z 718b1cc10029822de3a6f0da6b7466de +Z 583bd24d9680709c13934b197d486934 diff --git a/manifest.uuid b/manifest.uuid index 472ad48ee1..436f1e8a77 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce4b943bf68c160445a58ffccfbabbbd30d9829b \ No newline at end of file +2fb3fdcdf06c1206bf14da640c2f9e599455f0eb \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index b91dfe8c61..dafdfb6182 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.49 2002/07/07 16:52:47 drh Exp $ +** @(#) $Id: pager.c,v 1.50 2002/08/12 12:29:57 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -124,6 +124,7 @@ struct Pager { u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyFile; /* True if database file has changed in any way */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ + u8 journalFormat; /* Version number of the journal file */ u8 *aInJournal; /* One bit for each page in the database file */ u8 *aInCkpt; /* One bit for each page in the database */ PgHdr *pFirst, *pLast; /* List of free pages */ @@ -153,10 +154,30 @@ struct PageRecord { /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. +** +** There are two journal formats. The older journal format writes +** 32-bit integers in the byte-order of the host machine. The new +** format writes integers as big-endian. All new journals use the +** new format, but we have to be able to read an older journal in order +** to roll it back. */ -static const unsigned char aJournalMagic[] = { +static const unsigned char aOldJournalMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4, }; +static const unsigned char aJournalMagic[] = { + 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd5, +}; +#define SQLITE_NEW_JOURNAL_FORMAT 1 +#define SQLITE_OLD_JOURNAL_FORMAT 0 + +/* +** The following integer, if set, causes journals to be written in the +** old format. This is used for testing purposes only - to make sure +** the code is able to rollback an old journal. +*/ +#ifdef SQLITE_TEST +int pager_old_format = 0; +#endif /* ** Hash a page number @@ -182,6 +203,41 @@ static const unsigned char aJournalMagic[] = { # define REFINFO(X) #endif +/* +** Read a 32-bit integer from the given file descriptor +*/ +static int read32bits(Pager *pPager, OsFile *fd, u32 *pRes){ + u32 res; + int rc; + rc = sqliteOsRead(fd, &res, sizeof(res)); + if( rc==SQLITE_OK && pPager->journalFormat==SQLITE_NEW_JOURNAL_FORMAT ){ + unsigned char ac[4]; + memcpy(ac, &res, 4); + res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; + } + *pRes = res; + return rc; +} + +/* +** Write a 32-bit integer into the given file descriptor. Writing +** is always done using the new journal format. +*/ +static int write32bits(OsFile *fd, u32 val){ + unsigned char ac[4]; +#ifdef SQLITE_TEST + if( pager_old_format ){ + return sqliteOsWrite(fd, &val, 4); + } +#endif + ac[0] = (val>>24) & 0xff; + ac[1] = (val>>16) & 0xff; + ac[2] = (val>>8) & 0xff; + ac[3] = val & 0xff; + return sqliteOsWrite(fd, ac, 4); +} + + /* ** Convert the bits in the pPager->errMask into an approprate ** return code. @@ -281,7 +337,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd){ PgHdr *pPg; /* An existing page in the cache */ PageRecord pgRec; - rc = sqliteOsRead(jfd, &pgRec, sizeof(pgRec)); + rc = read32bits(pPager, jfd, &pgRec.pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData)); if( rc!=SQLITE_OK ) return rc; /* Sanity checking on the page */ @@ -347,11 +405,19 @@ static int pager_playback(Pager *pPager){ ** database file back to its original size. */ rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic)); - if( rc!=SQLITE_OK || memcmp(aMagic,aJournalMagic,sizeof(aMagic))!=0 ){ + if( rc!=SQLITE_OK ){ rc = SQLITE_PROTOCOL; goto end_playback; } - rc = sqliteOsRead(&pPager->jfd, &mxPg, sizeof(mxPg)); + if( memcmp(aMagic, aOldJournalMagic, sizeof(aMagic))==0 ){ + pPager->journalFormat = SQLITE_OLD_JOURNAL_FORMAT; + }else if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))==0 ){ + pPager->journalFormat = SQLITE_NEW_JOURNAL_FORMAT; + }else{ + rc = SQLITE_PROTOCOL; + goto end_playback; + } + rc = read32bits(pPager, &pPager->jfd, &mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -416,6 +482,7 @@ static int pager_ckpt_playback(Pager *pPager){ /* Copy original pages out of the checkpoint journal and back into the ** database file. */ + pPager->journalFormat = SQLITE_NEW_JOURNAL_FORMAT; for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->cpfd); if( rc!=SQLITE_OK ) goto end_ckpt_playback; @@ -847,7 +914,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** database. But syncing is a very slow operation. So after a ** sync, it is best to write everything we can back to the main ** database to minimize the risk of having to sync again in the - ** near future. That is way we write all dirty pages after a + ** near future. That is why we write all dirty pages after a ** sync. */ if( pPg==0 ){ @@ -1073,9 +1140,18 @@ int sqlitepager_begin(void *pData){ pPager->state = SQLITE_WRITELOCK; sqlitepager_pagecount(pPager); pPager->origDbSize = pPager->dbSize; +#ifdef SQLITE_TEST + if( pager_old_format ){ + rc = sqliteOsWrite(&pPager->jfd, aOldJournalMagic, + sizeof(aOldJournalMagic)); + }else{ + rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + } +#else rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); +#endif if( rc==SQLITE_OK ){ - rc = sqliteOsWrite(&pPager->jfd, &pPager->dbSize, sizeof(Pgno)); + rc = write32bits(&pPager->jfd, pPager->dbSize); } if( rc!=SQLITE_OK ){ rc = pager_unwritelock(pPager); @@ -1144,7 +1220,7 @@ int sqlitepager_write(void *pData){ ** journal if it is not there already. */ if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ - rc = sqliteOsWrite(&pPager->jfd, &pPg->pgno, sizeof(Pgno)); + rc = write32bits(&pPager->jfd, pPg->pgno); if( rc==SQLITE_OK ){ rc = sqliteOsWrite(&pPager->jfd, pData, SQLITE_PAGE_SIZE); } @@ -1168,7 +1244,7 @@ int sqlitepager_write(void *pData){ */ if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); - rc = sqliteOsWrite(&pPager->cpfd, &pPg->pgno, sizeof(Pgno)); + rc = write32bits(&pPager->cpfd, pPg->pgno); if( rc==SQLITE_OK ){ rc = sqliteOsWrite(&pPager->cpfd, pData, SQLITE_PAGE_SIZE); } diff --git a/src/pager.h b/src/pager.h index d10d0d119c..19311967f1 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.16 2002/03/05 12:41:20 drh Exp $ +** @(#) $Id: pager.h,v 1.17 2002/08/12 12:29:57 drh Exp $ */ /* @@ -73,4 +73,5 @@ int *sqlitepager_stats(Pager*); #ifdef SQLITE_TEST void sqlitepager_refdump(Pager*); int pager_refinfo_enable; +int pager_old_format; #endif diff --git a/src/test2.c b/src/test2.c index cef66990f2..fc7eb0cef9 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.8 2002/05/10 05:44:56 drh Exp $ +** $Id: test2.c,v 1.9 2002/08/12 12:29:57 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -493,5 +493,9 @@ int Sqlitetest2_Init(Tcl_Interp *interp){ Tcl_CreateCommand(interp, "page_number", page_number, 0, 0); Tcl_LinkVar(interp, "sqlite_io_error_pending", (char*)&sqlite_io_error_pending, TCL_LINK_INT); +#ifdef SQLITE_TEST + Tcl_LinkVar(interp, "pager_old_format", + (char*)&pager_old_format, TCL_LINK_INT); +#endif return TCL_OK; } diff --git a/test/trans.test b/test/trans.test index c95a9fef86..7e36e6a541 100644 --- a/test/trans.test +++ b/test/trans.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: trans.test,v 1.13 2002/07/07 16:52:47 drh Exp $ +# $Id: trans.test,v 1.14 2002/08/12 12:29:57 drh Exp $ set testdir [file dirname $argv0] @@ -857,6 +857,7 @@ if {[info exists ISQUICK]} { for {set i 2} {$i<=$limit} {incr i} { set ::sig [signature] set cnt [lindex $::sig 0] + set ::pager_old_format [expr {($i%4)==0}] do_test trans-9.$i.1-$cnt { execsql { BEGIN; diff --git a/www/index.tcl b/www/index.tcl index aad5d6ff79..c4efd04f10 100644 --- a/www/index.tcl +++ b/www/index.tcl @@ -1,7 +1,7 @@ # # Run this TCL script to generate HTML for the index.html file. # -set rcsid {$Id: index.tcl,v 1.61 2002/08/11 20:10:49 drh Exp $} +set rcsid {$Id: index.tcl,v 1.62 2002/08/12 12:29:58 drh Exp $} puts { SQLite: An SQL Database Engine In A C Library @@ -213,10 +213,4 @@ puts {

Related Sites

} puts { -


-

- -More Open Source Software from Hwaci. -

- }