-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
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
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
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
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
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
** 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"
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 */
/*
** 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
# 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.
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 */
** 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;
}
/* 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;
** 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 ){
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);
** 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);
}
*/
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);
}