Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Pager performance enhancements. (CVS 3125) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9c26570743d878dee963e37728969fb3 |
User & Date: | drh 2006-03-06 18:23:17.000 |
Context
2006-03-06
| ||
20:55 | Code changes resulting from Coverity analysis. http://scan.coverity.com/ Found 1 potential segfault in sqlite3_mprintf(). Also 2 failures to fclose() following a malloc() failure. And lots of cases where unnecessary conditionals could be removed from the code. (CVS 3126) (check-in: e510e6dd9d user: drh tags: trunk) | |
18:23 | Pager performance enhancements. (CVS 3125) (check-in: 9c26570743 user: drh tags: trunk) | |
2006-03-03
| ||
21:39 | Fix typo in documentation. Ticket #1578. (CVS 3124) (check-in: cb2e009f17 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.261 2006/03/06 18:23:17 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
48 49 50 51 52 53 54 | ** The following two macros are used within the TRACEX() macros above ** to print out file-descriptors. ** ** PAGERID() takes a pointer to a Pager struct as it's argument. The ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile ** struct as it's argument. */ | | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | ** The following two macros are used within the TRACEX() macros above ** to print out file-descriptors. ** ** PAGERID() takes a pointer to a Pager struct as it's argument. The ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile ** struct as it's argument. */ #define PAGERID(p) ((int)(p->fd)) #define FILEHANDLEID(fd) ((int)fd) /* ** The page cache as a whole is always in one of the following ** states: ** ** PAGER_UNLOCK The page cache is not currently reading or ** writing the database file. There is no |
︙ | ︙ | |||
186 187 188 189 190 191 192 | u8 *pStmt; /* Text as it was at the beginning of the current statement */ }; /* ** A macro used for invoking the codec if there is one */ #ifdef SQLITE_HAS_CODEC | | > | > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | u8 *pStmt; /* Text as it was at the beginning of the current statement */ }; /* ** A macro used for invoking the codec if there is one */ #ifdef SQLITE_HAS_CODEC # define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } # define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) #else # define CODEC1(P,D,N,X) /* NO-OP */ # define CODEC2(P,D,N,X) ((char*)D) #endif /* ** Convert a pointer to a PgHdr into a pointer to its data ** and back again. */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) |
︙ | ︙ | |||
286 287 288 289 290 291 292 | int sectorSize; /* Assumed sector size during rollback */ #ifdef SQLITE_TEST int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ int nRead,nWrite; /* Database pages read/written */ #endif void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | int sectorSize; /* Assumed sector size during rollback */ #ifdef SQLITE_TEST int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ int nRead,nWrite; /* Database pages read/written */ #endif void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT Pager *pNext; /* Linked list of pagers in this thread */ #endif }; |
︙ | ︙ | |||
431 432 433 434 435 436 437 | */ static int write32bits(OsFile *fd, u32 val){ char ac[4]; put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4); } | < < < < < < < < < < | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | */ static int write32bits(OsFile *fd, u32 val){ char ac[4]; put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4); } /* ** 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]; |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | memcpy(pData, aData, pPager->pageSize); if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/ pPager->xDestructor(pData, pPager->pageSize); } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif | | | 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 | memcpy(pData, aData, pPager->pageSize); if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/ pPager->xDestructor(pData, pPager->pageSize); } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif CODEC1(pPager, pData, pPg->pgno, 3); } return rc; } /* ** Parameter zMaster is the name of a master journal file. A single journal ** file that referred to the master journal file has just been rolled back. |
︙ | ︙ | |||
1150 1151 1152 1153 1154 1155 1156 | if( (int)pPg->pgno <= pPager->origDbSize ){ rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; | | | 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | if( (int)pPg->pgno <= pPager->origDbSize ){ rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; CODEC1(pPager, zBuf, pPg->pgno, 2); }else{ memset(zBuf, 0, pPager->pageSize); } if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){ memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize); if( pPager->xReiniter ){ pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize); |
︙ | ︙ | |||
2270 2271 2272 2273 2274 2275 2276 | if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ | | | < < | 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 | if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize); TEST_INCR(pPager->nWrite); } #ifndef NDEBUG else{ TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); } #endif |
︙ | ︙ | |||
2679 2680 2681 2682 2683 2684 2685 | assert( MEMDB==0 ); rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); | | | 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 | assert( MEMDB==0 ); rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ i64 fileSize; int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize); if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ /* An IO error occured in one of the the sqlite3OsSeek() or ** sqlite3OsRead() calls above. */ pPg->pgno = 0; |
︙ | ︙ | |||
2998 2999 3000 3001 3002 3003 3004 | /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ if( (int)pPg->pgno <= pPager->origDbSize ){ int szPg; | < | > | | > > | | < | | < | | 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 | /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ if( (int)pPg->pgno <= pPager->origDbSize ){ int szPg; if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); TRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } }else{ u32 cksum, saved; char *pData2, *pEnd; /* We should never write to the journal file the page that ** contains the database locks. The following assert verifies ** that we do not. */ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); pData2 = CODEC2(pPager, pData, pPg->pgno, 7); cksum = pager_cksum(pPager, pData2); pEnd = pData2 + pPager->pageSize; pData2 -= 4; saved = *(u32*)pEnd; put32bits(pEnd, cksum); szPg = pPager->pageSize+8; put32bits(pData2, pPg->pgno); rc = sqlite3OsWrite(pPager->jfd, pData2, szPg); pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); *(u32*)pEnd = saved; /* An error has occured writing to the journal file. The ** transaction will be rolled back by the layer above. */ if( rc!=SQLITE_OK ){ return rc; } |
︙ | ︙ | |||
3070 3071 3072 3073 3074 3075 3076 | assert( pHist->pStmt==0 ); pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); if( pHist->pStmt ){ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); }else{ | < | > | < < | 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 | assert( pHist->pStmt==0 ); pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); if( pHist->pStmt ){ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); } TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); }else{ char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4; put32bits(pData2, pPg->pgno); rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc!=SQLITE_OK ){ return rc; } pPager->stmtNRec++; assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } |
︙ | ︙ | |||
3547 3548 3549 3550 3551 3552 3553 | } /* ** Set the codec for this pager */ void sqlite3pager_set_codec( Pager *pPager, | | | 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 | } /* ** Set the codec for this pager */ void sqlite3pager_set_codec( Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), void *pCodecArg ){ pPager->xCodec = xCodec; pPager->pCodecArg = pCodecArg; } /* |
︙ | ︙ | |||
3576 3577 3578 3579 3580 3581 3582 | /* 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++; | | | 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 | /* 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++; put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); /* Release the page reference. */ sqlite3pager_unref(pPage); return SQLITE_OK; } /* |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** 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. ** | | | 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. ** ** @(#) $Id: pager.h,v 1.50 2006/03/06 18:23:17 drh Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ /* ** The default size of a database page. |
︙ | ︙ | |||
101 102 103 104 105 106 107 | int *sqlite3pager_stats(Pager*); void sqlite3pager_set_safety_level(Pager*,int,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); int sqlite3pager_nosync(Pager*); int sqlite3pager_rename(Pager*, const char *zNewName); | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | int *sqlite3pager_stats(Pager*); void sqlite3pager_set_safety_level(Pager*,int,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); int sqlite3pager_nosync(Pager*); int sqlite3pager_rename(Pager*, const char *zNewName); void sqlite3pager_set_codec(Pager*,void*(*)(void*,void*,Pgno,int),void*); int sqlite3pager_movepage(Pager*,void*,Pgno); int sqlite3pager_reset(Pager*); int sqlite3pager_release_memory(int); #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) int sqlite3pager_lockstate(Pager*); #endif |
︙ | ︙ |