Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update the file change counter just before each transaction is committed. (CVS 1582) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4649abcbfd032836b196b5d690ef66e4 |
User & Date: | danielk1977 2004-06-14 05:10:43.000 |
Context
2004-06-14
| ||
06:03 | Ensure the master journal directory is synced. Also, change the master journal format to store journal file names. (CVS 1583) (check-in: 73cd0aabb2 user: danielk1977 tags: trunk) | |
05:10 | Update the file change counter just before each transaction is committed. (CVS 1582) (check-in: 4649abcbfd user: danielk1977 tags: trunk) | |
2004-06-13
| ||
23:07 | os_win.c is now working with the new locking protocol. (CVS 1581) (check-in: 77c5eaa10a 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.125 2004/06/14 05:10:43 danielk1977 Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ** processes may still be reading the on-disk ** database file. ** ** PAGER_EXCLUSIVE The page cache is writing the database. ** Access is exclusive. No other processes or ** threads can be reading or writing while one ** process is writing. ** ** The page cache comes up in PAGER_UNLOCK. The first time a ** sqlite3pager_get() occurs, the state transitions to PAGER_SHARED. ** After all pages have been released using sqlite_page_unref(), ** the state transitions back to PAGER_UNLOCK. The first time ** that sqlite3pager_write() is called, the state transitions to ** PAGER_RESERVED. (Note that sqlite_page_write() can only be ** called on an outstanding page which means that the pager must ** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) ** The transition to PAGER_EXCLUSIVE occurs when before any changes ** are made to the database file. After an sqlite3pager_rollback() ** or sqlite_pager_commit(), the state goes back to PAGER_SHARED. */ #define PAGER_UNLOCK 0 #define PAGER_SHARED 1 #define PAGER_RESERVED 2 #define PAGER_EXCLUSIVE 3 /* ** Each in-memory image of a page begins with the following header. ** This header is only visible to this pager module. The client ** code that calls pager sees only the data that follows the header. ** | > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | ** processes may still be reading the on-disk ** database file. ** ** PAGER_EXCLUSIVE The page cache is writing the database. ** Access is exclusive. No other processes or ** threads can be reading or writing while one ** process is writing. ** ** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE ** after all dirty pages have been written to the ** database file and the file has been synced to ** disk. All that remains to do is to remove the ** journal file and the transaction will be ** committed. ** ** The page cache comes up in PAGER_UNLOCK. The first time a ** sqlite3pager_get() occurs, the state transitions to PAGER_SHARED. ** After all pages have been released using sqlite_page_unref(), ** the state transitions back to PAGER_UNLOCK. The first time ** that sqlite3pager_write() is called, the state transitions to ** PAGER_RESERVED. (Note that sqlite_page_write() can only be ** called on an outstanding page which means that the pager must ** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) ** The transition to PAGER_EXCLUSIVE occurs when before any changes ** are made to the database file. After an sqlite3pager_rollback() ** or sqlite_pager_commit(), the state goes back to PAGER_SHARED. */ #define PAGER_UNLOCK 0 #define PAGER_SHARED 1 #define PAGER_RESERVED 2 #define PAGER_EXCLUSIVE 3 #define PAGER_SYNCED 4 /* ** Each in-memory image of a page begins with the following header. ** This header is only visible to this pager module. The client ** code that calls pager sees only the data that follows the header. ** |
︙ | ︙ | |||
319 320 321 322 323 324 325 | ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; return sqlite3OsWrite(fd, ac, 4); } /* | | | > > > > > > > > > > | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; return sqlite3OsWrite(fd, ac, 4); } /* ** Write the 32-bit integer 'val' into the page identified by page header ** 'p' at offset 'offset'. */ 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; } /* ** Read a 32-bit integer at offset 'offset' from the page identified by ** page header 'p'. */ static u32 retrieve32bits(PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } /* ** Convert the bits in the pPager->errMask into an approprate ** return code. */ static int pager_errcode(Pager *pPager){ |
︙ | ︙ | |||
528 529 530 531 532 533 534 | rc = read32bits(jfd, &cksum); if( rc ) return rc; if( pager_cksum(pPager, pgno, aData)!=cksum ){ return SQLITE_DONE; } } | | | | | | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | rc = read32bits(jfd, &cksum); if( rc ) return rc; if( pager_cksum(pPager, pgno, aData)!=cksum ){ return SQLITE_DONE; } } assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); /* If the pager is in RESERVED state, then there must be a copy of this ** page in the pager cache. In this case just update the pager cache, ** not the database file. The page is left marked dirty in this case. ** ** FIX ME: Ideally the page would only be left marked dirty when the ** pager is in RESERVED state if it was dirty when this statement ** transaction was started. ** ** If in EXCLUSIVE state, then we update the pager cache if it exists ** and the main file. The page is then marked not dirty. */ pPg = pager_lookup(pPager, pgno); assert( pPager->state>=PAGER_EXCLUSIVE || pPg ); TRACE2("PLAYBACK page %d\n", pgno); if( pPager->state>=PAGER_EXCLUSIVE ){ 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 ){ /*** FIX ME: Should this be xReinit? ***/ pPager->xDestructor(pData, pPager->pageSize); } if( pPager->state>=PAGER_EXCLUSIVE ){ pPg->dirty = 0; pPg->needSync = 0; } CODEC(pPager, pData, pPg->pgno, 3); } return rc; } |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | ** with this page cache after this function returns will likely ** result in a coredump. */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); if( !pPager->memDb ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; | > | 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 | ** with this page cache after this function returns will likely ** result in a coredump. */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); if( !pPager->memDb ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; |
︙ | ︙ | |||
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 | Pager *pPager, void (*xCodec)(void*,void*,Pgno,int), void *pCodecArg ){ pPager->xCodec = xCodec; pPager->pCodecArg = pCodecArg; } /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual ** journal file. zMaster may be NULL, which is interpreted as no master ** journal (a single database transaction). ** ** This routine ensures that the journal is synced, all dirty pages written ** to the database file and the database file synced. The only thing that ** remains to commit the transaction is to delete the journal file (or ** master journal file if specified). ** ** Note that if zMaster==NULL, this does not overwrite a previous value ** passed to an sqlite3pager_sync() call. */ int sqlite3pager_sync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > | | > > | 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 | Pager *pPager, void (*xCodec)(void*,void*,Pgno,int), void *pCodecArg ){ pPager->xCodec = xCodec; pPager->pCodecArg = pCodecArg; } /* ** This routine is called to increment the database file change-counter, ** stored at byte 24 of the pager file. */ static int pager_incr_changecounter(Pager *pPager){ void *pPage; PgHdr *pPgHdr; u32 change_counter; int rc; /* Open page 1 of the file for writing. */ rc = sqlite3pager_get(pPager, 1, &pPage); if( rc!=SQLITE_OK ) return rc; rc = sqlite3pager_write(pPage); if( rc!=SQLITE_OK ) return rc; /* Read the current value at byte 24. */ pPgHdr = DATA_TO_PGHDR(pPage); change_counter = retrieve32bits(pPgHdr, 24); /* Increment the value just read and write it back to byte 24. */ change_counter++; store32bits(change_counter, pPgHdr, 24); /* Release the page reference. */ sqlite3pager_unref(pPage); return SQLITE_OK; } /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual ** journal file. zMaster may be NULL, which is interpreted as no master ** journal (a single database transaction). ** ** This routine ensures that the journal is synced, all dirty pages written ** to the database file and the database file synced. The only thing that ** remains to commit the transaction is to delete the journal file (or ** master journal file if specified). ** ** Note that if zMaster==NULL, this does not overwrite a previous value ** passed to an sqlite3pager_sync() call. */ int sqlite3pager_sync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is a no-op. */ if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){ PgHdr *pPg; assert( pPager->journalOpen ); rc = pager_incr_changecounter(pPager); if( rc!=SQLITE_OK ) goto sync_exit; /* Sync the journal file */ rc = syncJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto sync_exit; /* Write all dirty pages to the database file */ pPg = pager_get_all_dirty_pages(pPager); rc = pager_write_pagelist(pPg); if( rc!=SQLITE_OK ) goto sync_exit; /* Sync the database file. */ if( !pPager->noSync ){ rc = sqlite3OsSync(&pPager->fd); } pPager->state = PAGER_SYNCED; } sync_exit: return rc; } #ifdef SQLITE_DEBUG |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.371 2004/06/14 05:10:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
2132 2133 2134 2135 2136 2137 2138 | ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC ** 'i' INTEGER ** 't' TEXT ** 'o' NONE ** | | | 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 | ** Character Column affinity ** ------------------------------ ** 'n' NUMERIC ** 'i' INTEGER ** 't' TEXT ** 'o' NONE ** ** If P3 is NULL then no datatype coercion occurs. */ /* Opcode MakeRecord P1 * P3 ** ** Convert the top P1 entries of the stack into a single entry ** suitable for use as a data record in a database table. The ** details of the format are irrelavant as long as the OP_Column ** opcode can decode the record later. Refer to source code |
︙ | ︙ |