Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove legacy journal formats. (CVS 1549) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a12bef4a0877fb1dca531509a1186e09 |
User & Date: | drh 2004-06-09 19:03:55.000 |
Context
2004-06-09
| ||
20:03 | Turn on the atomic multifile commit logic. It does not work right yet, but it has at least stopped failing asserts. (CVS 1550) (check-in: 3674b25edc user: drh tags: trunk) | |
19:03 | Remove legacy journal formats. (CVS 1549) (check-in: a12bef4a08 user: drh tags: trunk) | |
17:37 | Fixes to the file locking. 109 tests are now failing. (CVS 1548) (check-in: dc0763455b user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** 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. ** | | | 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. ** ** @(#) $Id: pager.c,v 1.116 2004/06/09 19:03:55 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
229 230 231 232 233 234 235 | */ #define PAGER_ERR_FULL 0x01 /* a write() failed */ #define PAGER_ERR_MEM 0x02 /* malloc() failed */ #define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ #define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ #define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ | < < < < < < < < < < < < < < < < < < < < | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | */ #define PAGER_ERR_FULL 0x01 /* a write() failed */ #define PAGER_ERR_MEM 0x02 /* malloc() failed */ #define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ #define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ #define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity ** checking information. If the power fails while the journal is begin ** written, semi-random garbage data might appear in the journal ** file after power is restored. If an attempt is then made ** to roll the journal back, the database could be corrupted. The additional ** sanity checking data is an attempt to discover the garbage in the ** journal and ignore it. ** ** The sanity checking information for the new journal format consists ** of a 32-bit checksum on each page of data. The checksum covers both ** the page number and the SQLITE_PAGE_SIZE bytes of data for the page. ** This cksum is initialized to a 32-bit random value that appears in the ** journal file right after the header. The random initializer is important, ** because garbage data that appears at the end of a journal is likely ** data that was once in other files that have now been deleted. If the ** garbage data came from an obsolete journal file, the checksums might ** be correct. But by initializing the checksum to random value which ** is different for every journal, we minimize that risk. */ static const unsigned char aJournalMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, }; /* ** The size of the header and of each page in the journal varies according ** to which journal format is being used. The following macros figure out ** the sizes based on format numbers. */ #define JOURNAL_HDR_SZ(pPager) (24 + (pPager)->nMaster) #define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) /* ** Enable reference count tracking here: */ #ifdef SQLITE_TEST int pager3_refinfo_enable = 0; |
︙ | ︙ | |||
340 341 342 343 344 345 346 | # define REFINFO(X) #endif /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. | < < < < | | < < < < < < < < < < < < < < | | | | < | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | # define REFINFO(X) #endif /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. */ static int read32bits(OsFile *fd, u32 *pRes){ u32 res; int rc; rc = sqlite3OsRead(fd, &res, sizeof(res)); if( rc==SQLITE_OK ){ 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. Return SQLITE_OK ** on success or an error code is something goes wrong. */ static int write32bits(OsFile *fd, u32 val){ unsigned char ac[4]; ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; return sqlite3OsWrite(fd, ac, 4); } /* ** Write a 32-bit integer into a page header right before the ** page data. This will overwrite the PgHdr.pDirty pointer. */ static void store32bits(u32 val, PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; } /* ** Convert the bits in the pPager->errMask into an approprate ** return code. */ |
︙ | ︙ | |||
548 549 550 551 552 553 554 555 556 557 | return cksum; } /* ** Read a single page from the journal file opened on file descriptor ** jfd. Playback this one page. ** ** There are three different journal formats. The format parameter determines ** which format is used by the journal that is played back. */ | > > | | | | > | | | | | | | | | | | | | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | return cksum; } /* ** Read a single page from the journal file opened on file descriptor ** jfd. Playback this one page. ** ** ** ** There are three different journal formats. The format parameter determines ** which format is used by the journal that is played back. */ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ int rc; PgHdr *pPg; /* An existing page in the cache */ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ u8 aData[SQLITE_PAGE_SIZE]; /* Store data here */ rc = read32bits(jfd, &pgno); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsRead(jfd, &aData, pPager->pageSize); if( rc!=SQLITE_OK ) return rc; /* Sanity checking on the page. This is more important that I originally ** thought. If a power failure occurs while the journal is being written, ** it could cause invalid data to be written into the journal. We need to ** detect this invalid data (with high probability) and ignore it. */ if( pgno==0 ){ return SQLITE_DONE; } if( pgno>(unsigned)pPager->dbSize ){ return SQLITE_OK; } if( useCksum ){ rc = read32bits(jfd, &cksum); if( rc ) return rc; if( pager_cksum(pPager, pgno, aData)!=cksum ){ return SQLITE_DONE; } } /* Playback the page. Update the in-memory copy of the page ** at the same time, if there is one. */ pPg = pager_lookup(pPager, pgno); TRACE2("PLAYBACK page %d\n", pgno); sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE); rc = sqlite3OsWrite(&pPager->fd, aData, SQLITE_PAGE_SIZE); if( pPg ){ /* No page should ever be rolled back that is in use, except for page ** 1 which is held in use in order to keep the lock on the database ** active. */ void *pData; assert( pPg->nRef==0 || pPg->pgno==1 ); pData = PGHDR_TO_DATA(pPg); memcpy(pData, aData, pPager->pageSize); if( pPager->xDestructor ){ pPager->xDestructor(pData, pPager->pageSize); } pPg->dirty = 0; pPg->needSync = 0; CODEC(pPager, pData, pPg->pgno, 3); } |
︙ | ︙ | |||
664 665 666 667 668 669 670 | rc = sqlite3OsOpenReadOnly(zJournal, &journal); sqliteFree(zJournal); if( rc!=SQLITE_OK ){ sqlite3OsClose(&journal); goto delmaster_out; } | | | | | | | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | rc = sqlite3OsOpenReadOnly(zJournal, &journal); sqliteFree(zJournal); if( rc!=SQLITE_OK ){ sqlite3OsClose(&journal); goto delmaster_out; } /* Check if the file is big enough to be a journal file ** with the required master journal name. If not, ignore it. */ rc = sqlite3OsFileSize(&journal, &jsz); if( rc!=SQLITE_OK ){ sqlite3OsClose(&journal); goto delmaster_out; } if( jsz<(25+strlen(zMaster)) ){ sqlite3OsClose(&journal); continue; } /* Seek to the point in the journal where the master journal name ** is stored. Read the master journal name into memory obtained ** from malloc. */ rc = sqlite3OsSeek(&journal, 20); if( rc!=SQLITE_OK ) goto delmaster_out; rc = read32bits(&journal, (u32*)&nMaster); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMaster>0 && nMaster>=strlen(zMaster)+1 ){ char *zMasterPtr = (char *)sqliteMalloc(nMaster); if( !zMasterPtr ){ rc = SQLITE_NOMEM; } rc = sqlite3OsRead(&journal, zMasterPtr, nMaster); if( rc!=SQLITE_OK ){ sqliteFree(zMasterPtr); |
︙ | ︙ | |||
763 764 765 766 767 768 769 | /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. ** ** The journal file format is as follows: ** | | < < | | < | | | > > > > > > > | | | | | < < < < < < < | | > | | | < | | < < < < < < > | | > > < | | | < < < < | | > > | | < | < < | | | < | | | | | | | | | | | | | < < < | < < < < > | | 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. ** ** The journal file format is as follows: ** ** (1) 8 byte prefix. A copy of aJournalMagic[]. ** (2) 4 byte big-endian integer which is the number of valid page records ** in the journal. If this value is 0xffffffff, then compute the ** number of page records from the journal size. ** (3) 4 byte big-endian integer which is the initial value for the ** sanity checksum. ** (4) 4 byte integer which is the number of pages to truncate the ** database to during a rollback. ** (5) 4 byte integer which is the number of bytes in the master journal ** name. The value may be zero (indicate that there is no master ** journal.) ** (6) N bytes of the master journal name. The name will be nul-terminated ** and might be shorter than the value read from (5). If the first byte ** of the name is \000 then there is no master journal. The master ** journal name is stored in UTF-8. ** (7) Zero or more pages instances, each as follows: ** + 4 byte page number. ** + pPager->pageSize bytes of data. ** + 4 byte checksum ** ** When we speak of the journal header, we mean the first 6 items above. ** Each entry in the journal is an instance of the 7th item. ** ** Call the value from the second bullet "nRec". nRec is the number of ** valid page entries in the journal. In most cases, you can compute the ** value of nRec from the size of the journal file. But if a power ** failure occurred while the journal was being written, it could be the ** case that the size of the journal file had already been increased but ** the extra entries had not yet made it safely to disk. In such a case, ** the value of nRec computed from the file size would be too large. For ** that reason, we always use the nRec value in the header. ** ** If the nRec value is 0xffffffff it means that nRec should be computed ** from the file size. This value is used when the user selects the ** no-sync option for the journal. A power failure could lead to corruption ** in this case. But for things like temporary table (which will be ** deleted when the power is restored) we don't care. ** ** If the file opened as the journal file is not a well-formed ** journal file then the database will likely already be ** corrupted, so the PAGER_ERR_CORRUPT bit is set in pPager->errMask ** and SQLITE_CORRUPT is returned. If it all works, then this routine ** returns SQLITE_OK. */ static int pager_playback(Pager *pPager, int useJournalSize){ off_t szJ; /* Size of the journal file in bytes */ int nRec; /* Number of Records in the journal */ int i; /* Loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ unsigned char aMagic[8]; /* A buffer to hold the magic header */ int rc; /* Result code of a subroutine */ int nMaster; /* Number of bytes in the name of master journal */ char *zMaster = 0; /* Name of master journal file if any */ /* Figure out how many records are in the journal. Abort early if ** the journal is empty. */ assert( pPager->journalOpen ); sqlite3OsSeek(&pPager->jfd, 0); rc = sqlite3OsFileSize(&pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } /* If the journal file is too small to contain a complete header, ** it must mean that the process that created the journal was just ** beginning to write the journal file when it died. In that case, ** the database file should have still been completely unchanged. ** Nothing needs to be rolled back. We can safely ignore this journal. */ if( szJ < 24 ){ goto end_playback; } /* (1) Read the beginning of the journal and verify the magic string ** at the beginning of the journal. */ rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic)); if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ rc = SQLITE_PROTOCOL; goto end_playback; } /* (2) Read the number of pages stored in the journal. */ rc = read32bits(&pPager->jfd, (u32*)&nRec); if( rc ) goto end_playback; if( nRec==0xffffffff || useJournalSize ){ nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager); } /* (3) Read the initial value for the sanity checksum */ rc = read32bits(&pPager->jfd, &pPager->cksumInit); if( rc ) goto end_playback; /* (4) Read the number of pages in the database file prior to the ** start of the transaction */ rc = read32bits(&pPager->jfd, &mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } /* (5) and (6): Check if a master journal file is specified. If one is ** specified, only proceed with the playback if it still exists. */ rc = read32bits(&pPager->jfd, &nMaster); if( rc ) goto end_playback; if( nMaster>0 ){ zMaster = sqliteMalloc(nMaster); if( !zMaster ){ rc = SQLITE_NOMEM; goto end_playback; } rc = sqlite3OsRead(&pPager->jfd, zMaster, pPager->nMaster); if( rc!=SQLITE_OK || (zMaster[0] && !sqlite3OsFileExists(zMaster)) ){ goto end_playback; } } /* Truncate the database file back to it's original size */ assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } pPager->dbSize = mxPg; /* Copy original pages out of the journal and back into the database file. */ for(i=0; i<nRec; i++){ rc = pager_playback_one_page(pPager, &pPager->jfd, 1); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; } break; } } |
︙ | ︙ | |||
983 984 985 986 987 988 989 | /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); sqlite3OsSeek(&pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the | | | | | | | | 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 | /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); sqlite3OsSeek(&pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the ** database file. Note that the statement journal omits checksums from ** each record since power-failure recovery is not important to statement ** journals. */ for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->stfd, 0); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } /* Figure out how many pages need to be copied out of the transaction ** journal. */ rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } rc = sqlite3OsFileSize(&pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } nRec = (szJ - pPager->stmtJSize)/JOURNAL_PG_SZ(pPager); for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->jfd, 1); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_DONE ); goto end_stmt_playback; } } end_stmt_playback: |
︙ | ︙ | |||
1132 1133 1134 1135 1136 1137 1138 | if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } if( zFilename && zFilename[0] ){ if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zFullPathname = sqliteMalloc(4); | | | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } if( zFilename && zFilename[0] ){ if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zFullPathname = sqliteMalloc(4); if( zFullPathname ) strcpy(zFullPathname, ""); rc = SQLITE_OK; }else{ zFullPathname = sqlite3OsFullPathname(zFilename); rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); tempFile = 0; } }else{ |
︙ | ︙ | |||
1503 1504 1505 1506 1507 1508 1509 | ** was turned off after the transaction was started. Ticket #615 */ #ifndef NDEBUG { /* Make sure the pPager->nRec counter we are keeping agrees ** with the nRec computed from the size of the journal file. */ off_t hdrSz, pgSz, jSz; | | | < > | | | < | 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | ** was turned off after the transaction was started. Ticket #615 */ #ifndef NDEBUG { /* Make sure the pPager->nRec counter we are keeping agrees ** with the nRec computed from the size of the journal file. */ off_t hdrSz, pgSz, jSz; hdrSz = JOURNAL_HDR_SZ(pPager); pgSz = JOURNAL_PG_SZ(pPager); rc = sqlite3OsFileSize(&pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->nRec*pgSz+hdrSz==jSz ); } #endif { /* Write the nRec value into the journal file header */ off_t szJ; if( pPager->fullSync ){ TRACE2("SYNC journal of %d\n", pPager->fd.h); rc = sqlite3OsSync(&pPager->jfd); if( rc!=0 ) return rc; } sqlite3OsSeek(&pPager->jfd, sizeof(aJournalMagic)); rc = write32bits(&pPager->jfd, pPager->nRec); if( rc ) return rc; /* Write the name of the master journal file if one is specified */ if( zMaster ){ assert( strlen(zMaster)<pPager->nMaster ); rc = sqlite3OsSeek(&pPager->jfd, 20); if( rc ) return rc; rc = sqlite3OsWrite(&pPager->jfd, zMaster, strlen(zMaster)+1); if( rc ) return rc; } szJ = JOURNAL_HDR_SZ(pPager) + pPager->nRec*JOURNAL_PG_SZ(pPager); sqlite3OsSeek(&pPager->jfd, szJ); } TRACE2("SYNC journal of %d\n", pPager->fd.h); rc = sqlite3OsSync(&pPager->jfd); if( rc!=0 ) return rc; pPager->journalStarted = 1; } |
︙ | ︙ | |||
1994 1995 1996 1997 1998 1999 2000 | pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } pPager->origDbSize = pPager->dbSize; | | | | | | > | | < | | | | | | | | | | | | < < < < < < | | | | | < | < < < < < < < < < | 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 | pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } pPager->origDbSize = pPager->dbSize; /* Create the header for the journal: ** - 8 bytes: Magic identifying journal format. ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. ** - 4 bytes: Magic used for page checksums. ** - 4 bytes: Initial database page count. ** - 4 bytes: Number of bytes reserved for master journal ptr (nMaster) ** - nMaster bytes: Space for a master journal pointer. */ rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); } if( rc==SQLITE_OK ){ sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); rc = write32bits(&pPager->jfd, pPager->cksumInit); } if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->dbSize); } if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->nMaster); } if( rc==SQLITE_OK ){ rc = sqlite3OsSeek(&pPager->jfd, 24 + pPager->nMaster); } if( pPager->stmtAutoopen && rc==SQLITE_OK ){ rc = sqlite3pager_stmt_begin(pPager); } if( rc!=SQLITE_OK ){ rc = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; |
︙ | ︙ | |||
2185 2186 2187 2188 2189 2190 2191 | assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } pPg->inJournal = 1; }else{ | < | | | | < < < < | < | 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 | assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } pPg->inJournal = 1; }else{ u32 cksum = pager_cksum(pPager, pPg->pgno, pData); saved = *(u32*)PGHDR_TO_EXTRA(pPg); store32bits(cksum, pPg, SQLITE_PAGE_SIZE); szPg = SQLITE_PAGE_SIZE+8; store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); TRACE3("JOURNAL page %d needSync=%d\n", pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); *(u32*)PGHDR_TO_EXTRA(pPg) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); |
︙ | ︙ | |||
2227 2228 2229 2230 2231 2232 2233 | if( pPg->needSync ){ pPager->needSync = 1; } } /* If the statement journal is open and the page is not in it, ** then write the current page to the statement journal. Note that | | | | 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 | if( pPg->needSync ){ pPager->needSync = 1; } } /* If the statement journal is open and the page is not in it, ** then write the current page to the statement journal. Note that ** the statement journal format differs from the standard journal format ** in that it omits the checksums and the header. */ if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); if( pPager->memDb ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); assert( pHist->pStmt==0 ); pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); |
︙ | ︙ | |||
2589 2590 2591 2592 2593 2594 2595 | sqlite3OsLock(&pPager->fd, SHARED_LOCK); return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqlite3OsFileSize(&pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == | | < | | | 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 | sqlite3OsLock(&pPager->fd, SHARED_LOCK); return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqlite3OsFileSize(&pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->nRec*JOURNAL_PG_SZ(pPager) + JOURNAL_HDR_SZ(pPager) ); #endif pPager->stmtJSize = pPager->nRec*JOURNAL_PG_SZ(pPager) + JOURNAL_HDR_SZ(pPager); pPager->stmtSize = pPager->dbSize; if( !pPager->stmtOpen ){ rc = sqlite3pager_opentemp(zTemp, &pPager->stfd); if( rc ) goto stmt_begin_failed; pPager->stmtOpen = 1; pPager->stmtNRec = 0; } |
︙ | ︙ |
Changes to src/test2.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** 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. ** | | | 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. ** ** $Id: test2.c,v 1.21 2004/06/09 19:03:55 drh Exp $ */ #include "os.h" #include "sqliteInt.h" #include "pager.h" #include "tcl.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
549 550 551 552 553 554 555 | }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } Tcl_LinkVar(interp, "sqlite3_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); | < < < < < < < < < < | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } Tcl_LinkVar(interp, "sqlite3_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); sprintf(zBuf, "%d", SQLITE_PAGE_SIZE); Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE); Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY); sprintf(zBuf, "%d", SQLITE_USABLE_SIZE); Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY); return TCL_OK; } |
Changes to test/memdb.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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 in-memory database backend. # | | | 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 in-memory database backend. # # $Id: memdb.test,v 1.7 2004/06/09 19:03:55 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # In the following sequence of tests, compute the MD5 sum of the content # of a table, make lots of modifications to that table, then do a rollback. |
︙ | ︙ | |||
69 70 71 72 73 74 75 | # Do rollbacks. Make sure the signature does not change. # set limit 10 for {set i 2} {$i<=$limit} {incr i} { set ::sig [signature one] # puts "sig=$sig" set cnt [lindex $::sig 0] | < | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | # Do rollbacks. Make sure the signature does not change. # set limit 10 for {set i 2} {$i<=$limit} {incr i} { set ::sig [signature one] # puts "sig=$sig" set cnt [lindex $::sig 0] if {$i%2==0} { execsql {PRAGMA synchronous=FULL} } else { execsql {PRAGMA synchronous=NORMAL} } do_test memdb-1.$i.1-$cnt { execsql { |
︙ | ︙ |
Changes to test/trans.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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. # | | | 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. # # $Id: trans.test,v 1.21 2004/06/09 19:03:55 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create several tables to work with. |
︙ | ︙ | |||
860 861 862 863 864 865 866 | } # 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] | < | 860 861 862 863 864 865 866 867 868 869 870 871 872 873 | } # 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] if {$i%2==0} { execsql {PRAGMA synchronous=FULL} } else { execsql {PRAGMA synchronous=NORMAL} } do_test trans-9.$i.1-$cnt { execsql { |
︙ | ︙ |