Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for ticket #9 (again). The rollback journal files should now also be byte-order independent. (CVS 705) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
2fb3fdcdf06c1206bf14da640c2f9e59 |
User & Date: | drh 2002-08-12 12:29:57.000 |
Context
2002-08-13
| ||
00:01 | Updates prior to release 2.6.3. (CVS 706) (check-in: 34c4149eea user: drh tags: trunk) | |
2002-08-12
| ||
12:29 | Fix for ticket #9 (again). The rollback journal files should now also be byte-order independent. (CVS 705) (check-in: 2fb3fdcdf0 user: drh tags: trunk) | |
2002-08-11
| ||
20:10 | Fix for ticket #9: Add the ability to read little-endian database files from a big-endian machine and vice versa. (CVS 704) (check-in: ce4b943bf6 user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | |||
14 15 16 17 18 19 20 | 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. ** |
︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | + | u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ u8 errMask; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ 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 */ PgHdr *pAll; /* List of all pages */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */ }; |
︙ | |||
149 150 151 152 153 154 155 156 157 | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | + + + + + + + + + - + + + + + + + + + + + + | Pgno pgno; /* The page number */ char aData[SQLITE_PAGE_SIZE]; /* Original data for page pgno */ }; /* ** 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 aOldJournalMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4, }; static const unsigned char aJournalMagic[] = { |
︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ); cnt++; /* Something to set a breakpoint on */ } # define REFINFO(X) pager_refinfo(X) #else # 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. */ static int pager_errcode(Pager *pPager){ int rc = SQLITE_OK; |
︙ | |||
277 278 279 280 281 282 283 | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | + + - + | ** jfd. Playback this one page. */ static int pager_playback_one_page(Pager *pPager, OsFile *jfd){ int rc; PgHdr *pPg; /* An existing page in the cache */ PageRecord pgRec; rc = read32bits(pPager, jfd, &pgRec.pgno); if( rc!=SQLITE_OK ) return rc; |
︙ | |||
343 344 345 346 347 348 349 | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | - + + + + + + + + + - + | goto end_playback; } /* Read the beginning of the journal and truncate the ** database file back to its original size. */ rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic)); |
︙ | |||
412 413 414 415 416 417 418 419 420 421 422 423 424 425 | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | + | goto end_ckpt_playback; } nRec /= sizeof(PageRecord); /* 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; } /* Figure out how many pages need to be copied out of the transaction ** journal. |
︙ | |||
843 844 845 846 847 848 849 | 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 | - + | ** dirty free pages into the database file, thus making them ** clean pages and available for recycling. ** ** We have to sync the journal before writing a page to the main ** 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 |
︙ | |||
1069 1070 1071 1072 1073 1074 1075 | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | + + + + + - + + + + + - + | pPager->journalOpen = 1; pPager->needSync = 0; pPager->dirtyFile = 0; pPager->alwaysRollback = 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{ |
︙ | |||
1140 1141 1142 1143 1144 1145 1146 | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | - + | assert( pPager->journalOpen ); /* The transaction journal now exists and we have a write lock on the ** main database file. Write the current page to the transaction ** journal if it is not there already. */ if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ |
︙ | |||
1164 1165 1166 1167 1168 1169 1170 | 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 | - + | } /* If the checkpoint journal is open and the page is not in it, ** then write the current page to the checkpoint journal. */ if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); |
︙ |
Changes to src/pager.h.
︙ | |||
9 10 11 12 13 14 15 | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - + | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** |
︙ | |||
69 70 71 72 73 74 75 76 | 69 70 71 72 73 74 75 76 77 | + | void sqlitepager_dont_rollback(void*); void sqlitepager_dont_write(Pager*, Pgno); int *sqlitepager_stats(Pager*); #ifdef SQLITE_TEST void sqlitepager_refdump(Pager*); int pager_refinfo_enable; int pager_old_format; #endif |
Changes to src/test2.c.
︙ | |||
9 10 11 12 13 14 15 | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - + | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the pager.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** |
︙ | |||
489 490 491 492 493 494 495 496 497 | 489 490 491 492 493 494 495 496 497 498 499 500 501 | + + + + | Tcl_CreateCommand(interp, "page_lookup", page_lookup, 0, 0); Tcl_CreateCommand(interp, "page_unref", page_unref, 0, 0); Tcl_CreateCommand(interp, "page_read", page_read, 0, 0); Tcl_CreateCommand(interp, "page_write", page_write, 0, 0); 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; } |
Changes to test/trans.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | - + | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # |
︙ | |||
853 854 855 856 857 858 859 860 861 862 863 864 865 866 | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | + | } # Do rollbacks. Make sure the signature does not change. # 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; DELETE FROM t3 WHERE random()%10!=0; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; ROLLBACK; |
︙ |
Changes to www/index.tcl.
1 2 3 | 1 2 3 4 5 6 7 8 9 10 11 | - + | # # Run this TCL script to generate HTML for the index.html file. # |
︙ | |||
209 210 211 212 213 214 215 | 209 210 211 212 213 214 215 216 | - - - - - - | <li><p>A PHP module for SQLite can be found at <a href="http://freshmeat.net/projects/sqlite-php"> http://freshmeat.net/projects/sqlite-php</a></li> </ul>} puts { |