Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add the Bitvec object for tracking which pages have been journalled. This reduces memory consumption and runs faster than the bitmap approach it replaced. (CVS 4794) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7c57bdbcdb84d95419ec7029d2e13c59 |
User & Date: | drh 2008-02-18 14:47:34.000 |
Context
2008-02-18
| ||
22:24 | Add the memory fault simulator to mem5.c. Enable soft heap limit on mem5.c. Limit the size of hash tables and the vdbefifo when using mem5.c. (CVS 4795) (check-in: 63da5d9754 user: drh tags: trunk) | |
14:47 | Add the Bitvec object for tracking which pages have been journalled. This reduces memory consumption and runs faster than the bitmap approach it replaced. (CVS 4794) (check-in: 7c57bdbcdb user: drh tags: trunk) | |
2008-02-16
| ||
16:21 | The power-of-two first-fit memory allocator is now working. (CVS 4793) (check-in: d134d29cea user: drh tags: trunk) | |
Changes
Changes to main.mk.
︙ | ︙ | |||
44 45 46 47 48 49 50 | # This is how we compile # TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src # Object files for the SQLite library. # | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # This is how we compile # TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src # Object files for the SQLite library. # LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \ callback.o complete.o date.o delete.o \ expr.o fault.o func.o hash.o insert.o journal.o loadext.o \ main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o \ mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \ opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pragma.o prepare.o printf.o random.o \ select.o table.o $(TCLOBJ) tokenize.o trigger.o \ |
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ $(TOP)/src/auth.c \ $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/btreeInt.h \ $(TOP)/src/build.c \ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ $(TOP)/src/auth.c \ $(TOP)/src/bitvec.c \ $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/btreeInt.h \ $(TOP)/src/build.c \ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ |
︙ | ︙ |
Added src/bitvec.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | /* ** 2008 February 16 ** ** 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 an object that represents a fixed-length ** bitmap. Bits are numbered starting with 1. ** ** A bitmap is used to record what pages a database file have been ** journalled during a transaction. Usually only a few pages are ** journalled. So the bitmap is usually sparse and has low cardinality. ** But sometimes (for example when during a DROP of a large table) most ** or all of the pages get journalled. In those cases, the bitmap becomes ** dense. The algorithm needs to handle both cases well. ** ** The size of the bitmap is fixed when the object is created. ** ** All bits are clear when the bitmap is created. Individual bits ** may be set or cleared one at a time. ** ** Test operations are about 100 times more common that set operations. ** Clear operations are exceedingly rare. There are usually between ** 5 and 500 set operations per Bitvec object, though the number of sets can ** sometimes grow into tens of thousands or larger. The size of the ** Bitvec object is the number of pages in the database file at the ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** ** @(#) $Id: bitvec.c,v 1.1 2008/02/18 14:47:34 drh Exp $ */ #include "sqliteInt.h" #define BITVEC_SZ 512 #define BITVEC_NCHAR (BITVEC_SZ-12) #define BITVEC_NBIT (BITVEC_NCHAR*8) #define BITVEC_NINT ((BITVEC_SZ-12)/4) #define BITVEC_MXHASH (BITVEC_NINT/2) #define BITVEC_NPTR ((BITVEC_SZ-12)/8) #define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT) /* ** A bitmap is an instance of the following structure. ** ** This bitmap records the existance of zero or more bits ** with values between 1 and iSize, inclusive. ** ** There are three possible representations of the bitmap. ** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight ** bitmap. The least significant bit is bit 1. ** ** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is ** a hash table that will hold up to BITVEC_MXHASH distinct values. ** ** Otherwise, the value i is redirected into one of BITVEC_NPTR ** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap ** handles up to iDivisor separate values of i. apSub[0] holds ** values between 1 and iDivisor. apSub[1] holds values between ** iDivisor+1 and 2*iDivisor. apSub[N] holds values between ** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized ** to hold deal with values between 1 and iDivisor. */ struct Bitvec { u32 iSize; /* Maximum bit index */ u32 nSet; /* Number of bits that are set */ u32 iDivisor; /* Number of bits handled by each apSub[] entry */ union { u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */ u32 aHash[BITVEC_NINT]; /* Hash table representation */ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ } u; }; /* ** Create a new bitmap object able to handle bits between 0 and iSize, ** inclusive. Return a pointer to the new object. Return NULL if ** malloc fails. */ Bitvec *sqlite3BitvecCreate(u32 iSize){ Bitvec *p; assert( sizeof(*p)==BITVEC_SZ ); p = sqlite3MallocZero( sizeof(*p) ); if( p ){ p->iSize = iSize; } return p; } /* ** Check to see if the i-th bit is set. Return true or false. ** If p is NULL (if the bitmap has not been created) or if ** i is out of range, then return false. */ int sqlite3BitvecTest(Bitvec *p, u32 i){ assert( i>0 ); if( p==0 ) return 0; if( i>p->iSize ) return 0; if( p->iSize<=BITVEC_NBIT ){ i--; return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0; } if( p->iDivisor>0 ){ u32 bin = (i-1)/p->iDivisor; i = (i-1)%p->iDivisor + 1; return sqlite3BitvecTest(p->u.apSub[bin], i); }else{ u32 h = BITVEC_HASH(i); while( p->u.aHash[h] ){ if( p->u.aHash[h]==i ) return 1; h++; if( h>=BITVEC_NINT ) h = 0; } return 0; } } /* ** Set the i-th bit. Return 0 on success and an error code if ** anything goes wrong. */ int sqlite3BitvecSet(Bitvec *p, u32 i){ u32 h; assert( p!=0 ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] |= 1 << (i&7); return SQLITE_OK; } if( p->iDivisor ){ u32 bin = (i-1)/p->iDivisor; i = (i-1)%p->iDivisor + 1; if( p->u.apSub[bin]==0 ){ sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1); p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; } return sqlite3BitvecSet(p->u.apSub[bin], i); } h = BITVEC_HASH(i); while( p->u.aHash[h] ){ if( p->u.aHash[h]==i ) return SQLITE_OK; h++; if( h==BITVEC_NINT ) h = 0; } p->nSet++; if( p->nSet>=BITVEC_MXHASH ){ int j, rc; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; sqlite3BitvecSet(p, i); for(rc=j=0; j<BITVEC_NINT; j++){ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); } return rc; } p->u.aHash[h] = i; return SQLITE_OK; } /* ** Clear the i-th bit. Return 0 on success and an error code if ** anything goes wrong. */ void sqlite3BitvecClear(Bitvec *p, u32 i){ assert( p!=0 ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] &= ~(1 << (i&7)); }else if( p->iDivisor ){ u32 bin = (i-1)/p->iDivisor; i = (i-1)%p->iDivisor + 1; if( p->u.apSub[bin] ){ sqlite3BitvecClear(p->u.apSub[bin], i); } }else{ int j; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); p->nSet = 0; for(j=0; j<BITVEC_NINT; j++){ if( aiValues[j] && aiValues[j]!=i ) sqlite3BitvecSet(p, aiValues[j]); } } } /* ** Destroy a bitmap object. Reclaim all memory used. */ void sqlite3BitvecDestroy(Bitvec *p){ if( p==0 ) return; if( p->iDivisor ){ int i; for(i=0; i<BITVEC_NPTR; i++){ sqlite3BitvecDestroy(p->u.apSub[i]); } } sqlite3_free(p); } |
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.407 2008/02/18 14:47:34 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
209 210 211 212 213 214 215 | ** This is true if the original page has been written into the main ** rollback journal. This is always false for new pages added to ** the end of the database file during the current transaction. ** And this flag says nothing about whether or not the journal ** has been synced to disk. For pages that are in the original ** database file, the following expression should always be true: ** | | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | ** This is true if the original page has been written into the main ** rollback journal. This is always false for new pages added to ** the end of the database file during the current transaction. ** And this flag says nothing about whether or not the journal ** has been synced to disk. For pages that are in the original ** database file, the following expression should always be true: ** ** inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno) ** ** The pPager->pInJournal object is only valid for the original ** pages of the database, not new pages that are added to the end ** of the database, so obviously the above expression cannot be ** valid for new pages. For new pages inJournal is always 0. ** ** dirty ** ** When true, this means that the content of the page has been |
︙ | ︙ | |||
361 362 363 364 365 366 367 | int stmtNRec; /* Number of records in stmt subjournal */ int nExtra; /* Add this many bytes to each in-memory page */ int pageSize; /* Number of bytes in a page */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ Pgno mxPgno; /* Maximum allowed size of the database */ | | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | int stmtNRec; /* Number of records in stmt subjournal */ int nExtra; /* Add this many bytes to each in-memory page */ int pageSize; /* Number of bytes in a page */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ Pgno mxPgno; /* Maximum allowed size of the database */ Bitvec *pInJournal; /* One bit for each page in the database file */ Bitvec *pInStmt; /* One bit for each page in the database */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ char *zStmtJrnl; /* Name of the statement journal file */ sqlite3_file *fd, *jfd; /* File descriptors for database and journal */ sqlite3_file *stfd; /* File descriptor for the statement subjournal*/ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ |
︙ | ︙ | |||
662 663 664 665 666 667 668 | ** of an in-memory database). */ static int pageInStatement(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( MEMDB ){ return PGHDR_TO_HIST(pPg, pPager)->inStmt; }else{ | < | < | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | ** of an in-memory database). */ static int pageInStatement(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( MEMDB ){ return PGHDR_TO_HIST(pPg, pPager)->inStmt; }else{ return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno); } } /* ** Change the size of the pager hash table to N. N must be a power ** of two. */ |
︙ | ︙ | |||
1248 1249 1250 1251 1252 1253 1254 | ** cache can be discarded and the error code safely cleared. */ if( pPager->errCode ){ pPager->errCode = SQLITE_OK; pager_reset(pPager); if( pPager->stmtOpen ){ sqlite3OsClose(pPager->stfd); | | | | | | 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 | ** cache can be discarded and the error code safely cleared. */ if( pPager->errCode ){ pPager->errCode = SQLITE_OK; pager_reset(pPager); if( pPager->stmtOpen ){ sqlite3OsClose(pPager->stfd); sqlite3BitvecDestroy(pPager->pInStmt); pPager->pInStmt = 0; } if( pPager->journalOpen ){ sqlite3OsClose(pPager->jfd); pPager->journalOpen = 0; sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; } pPager->stmtOpen = 0; pPager->stmtInUse = 0; pPager->journalOff = 0; pPager->journalStarted = 0; pPager->stmtAutoopen = 0; pPager->origDbSize = 0; |
︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 | }else{ sqlite3OsClose(pPager->jfd); pPager->journalOpen = 0; if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } | | | | | 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | }else{ sqlite3OsClose(pPager->jfd); pPager->journalOpen = 0; if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->inJournal = 0; pPg->dirty = 0; pPg->needSync = 0; pPg->alwaysRollback = 0; #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } pPager->pDirty = 0; pPager->dirtyCache = 0; pPager->nRec = 0; }else{ assert( pPager->pInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } if( !pPager->exclusiveMode ){ rc2 = osUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; }else if( pPager->state==PAGER_SYNCED ){ |
︙ | ︙ | |||
2657 2658 2659 2660 2661 2662 2663 | enable_simulated_io_errors(); PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); IOTRACE(("CLOSE %p\n", pPager)) assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(pPager->jfd); } | | | 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 | enable_simulated_io_errors(); PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); IOTRACE(("CLOSE %p\n", pPager)) assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(pPager->jfd); } sqlite3BitvecDestroy(pPager->pInJournal); if( pPager->stmtOpen ){ sqlite3OsClose(pPager->stfd); } sqlite3OsClose(pPager->fd); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqlite3OsDelete(pPager->zFilename); |
︙ | ︙ | |||
3621 3622 3623 3624 3625 3626 3627 | rc = pagerAllocatePage(pPager, &pPg); if( rc!=SQLITE_OK ){ return rc; } pPg->pgno = pgno; assert( !MEMDB || pgno>pPager->stmtSize ); | < < < < < < < < | | < | 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 | rc = pagerAllocatePage(pPager, &pPg); if( rc!=SQLITE_OK ){ return rc; } pPg->pgno = pgno; assert( !MEMDB || pgno>pPager->stmtSize ); pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno); pPg->needSync = 0; makeClean(pPg); pPg->nRef = 1; pPager->nRef++; if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); |
︙ | ︙ | |||
3797 3798 3799 3800 3801 3802 3803 | int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE); int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); | | | | | 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 | int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE); int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); assert( pPager->pInJournal==0 ); sqlite3PagerPagecount(pPager); pagerLeave(pPager); pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); pagerEnter(pPager); if( pPager->pInJournal==0 ){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); }else{ |
︙ | ︙ | |||
3854 3855 3856 3857 3858 3859 3860 | if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } } return rc; failed_to_open_journal: | | | | 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 | if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } } return rc; failed_to_open_journal: sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; return rc; } /* ** Acquire a write-lock on the database. The lock is removed when ** the any of the following happen: ** |
︙ | ︙ | |||
3893 3894 3895 3896 3897 3898 3899 | int sqlite3PagerBegin(DbPage *pPg, int exFlag){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; pagerEnter(pPager); assert( pPg->nRef>0 ); assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ | | | 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 | int sqlite3PagerBegin(DbPage *pPg, int exFlag){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; pagerEnter(pPager); assert( pPg->nRef>0 ); assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->pInJournal==0 ); if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; |
︙ | ︙ | |||
3923 3924 3925 3926 3927 3928 3929 | /* This happens when the pager was in exclusive-access mode last ** time a (read or write) transaction was successfully concluded ** by this connection. Instead of deleting the journal file it was ** kept open and truncated to 0 bytes. */ assert( pPager->nRec==0 ); assert( pPager->origDbSize==0 ); | | | | | 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 | /* This happens when the pager was in exclusive-access mode last ** time a (read or write) transaction was successfully concluded ** by this connection. Instead of deleting the journal file it was ** kept open and truncated to 0 bytes. */ assert( pPager->nRec==0 ); assert( pPager->origDbSize==0 ); assert( pPager->pInJournal==0 ); sqlite3PagerPagecount(pPager); pagerLeave(pPager); pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize ); pagerEnter(pPager); if( !pPager->pInJournal ){ rc = SQLITE_NOMEM; }else{ pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); } } assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); |
︙ | ︙ | |||
4104 4105 4106 4107 4108 4109 4110 | ** transaction will be rolled back by the layer above. */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; | | | | | 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 | ** transaction will be rolled back by the layer above. */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); pPg->needSync = !pPager->noSync; if( pPager->stmtInUse ){ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); } } }else{ pPg->needSync = !pPager->journalStarted && !pPager->noSync; PAGERTRACE4("APPEND %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); } |
︙ | ︙ | |||
4153 4154 4155 4156 4157 4158 4159 | rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4); } PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc!=SQLITE_OK ){ return rc; } pPager->stmtNRec++; | | | | 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 | rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4); } PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc!=SQLITE_OK ){ return rc; } pPager->stmtNRec++; assert( pPager->pInStmt!=0 ); sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); } } } /* Update the database size and return. */ assert( pPager->state>=PAGER_SHARED ); |
︙ | ︙ | |||
4223 4224 4225 4226 4227 4228 4229 | assert(nPage>0); assert(pg1<=pPg->pgno); assert((pg1+nPage)>pPg->pgno); for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){ Pgno pg = pg1+ii; PgHdr *pPage; | | < < | 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 | assert(nPage>0); assert(pg1<=pPg->pgno); assert((pg1+nPage)>pPg->pgno); for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){ Pgno pg = pg1+ii; PgHdr *pPage; if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ if( pg!=PAGER_MJ_PGNO(pPager) ){ rc = sqlite3PagerGet(pPager, pg, &pPage); if( rc==SQLITE_OK ){ rc = pager_write(pPage); if( pPage->needSync ){ needSync = 1; } |
︙ | ︙ | |||
4399 4400 4401 4402 4403 4404 4405 | assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ /* Check that PagerWrite() has not yet been called on this page, and ** that the page existed when the transaction started. */ assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); | | | | | 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 | assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ /* Check that PagerWrite() has not yet been called on this page, and ** that the page existed when the transaction started. */ assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); pPg->inJournal = 1; pPg->needRead = 0; if( pPager->stmtInUse ){ assert( pPager->stmtSize <= pPager->origDbSize ); sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); } PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno)) pagerLeave(pPager); } |
︙ | ︙ | |||
4541 4542 4543 4544 4545 4546 4547 | /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. */ Pgno i; int iSkip = PAGER_MJ_PGNO(pPager); for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ | | | 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 | /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. */ Pgno i; int iSkip = PAGER_MJ_PGNO(pPager); for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ rc = sqlite3PagerGet(pPager, i, &pPg); if( rc!=SQLITE_OK ) goto sync_exit; rc = sqlite3PagerWrite(pPg); sqlite3PagerUnref(pPg); if( rc!=SQLITE_OK ) goto sync_exit; } } |
︙ | ︙ | |||
4799 4800 4801 4802 4803 4804 4805 | } if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pagerLeave(pPager); | | | | | 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 | } if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pagerLeave(pPager); assert( pPager->pInStmt==0 ); pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize); pagerEnter(pPager); if( pPager->pInStmt==0 ){ /* 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->journalOff ); |
︙ | ︙ | |||
4828 4829 4830 4831 4832 4833 4834 | pPager->stmtOpen = 1; pPager->stmtNRec = 0; } pPager->stmtInUse = 1; return SQLITE_OK; stmt_begin_failed: | | | | | 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 | pPager->stmtOpen = 1; pPager->stmtNRec = 0; } pPager->stmtInUse = 1; return SQLITE_OK; stmt_begin_failed: if( pPager->pInStmt ){ sqlite3BitvecDestroy(pPager->pInStmt); pPager->pInStmt = 0; } return rc; } int sqlite3PagerStmtBegin(Pager *pPager){ int rc; pagerEnter(pPager); rc = pagerStmtBegin(pPager); |
︙ | ︙ | |||
4852 4853 4854 4855 4856 4857 4858 | int sqlite3PagerStmtCommit(Pager *pPager){ pagerEnter(pPager); if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ /* sqlite3OsTruncate(pPager->stfd, 0); */ | | | | 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 | int sqlite3PagerStmtCommit(Pager *pPager){ pagerEnter(pPager); if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ /* sqlite3OsTruncate(pPager->stfd, 0); */ sqlite3BitvecDestroy(pPager->pInStmt); pPager->pInStmt = 0; }else{ for(pPg=pPager->pStmt; pPg; pPg=pNext){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); pNext = pHist->pNextStmt; assert( pHist->inStmt ); pHist->inStmt = 0; pHist->pPrevStmt = pHist->pNextStmt = 0; |
︙ | ︙ | |||
5023 5024 5025 5026 5027 5028 5029 | assert( pPgOld->nRef==0 ); unlinkHashChain(pPager, pPgOld); makeClean(pPgOld); pPg->needSync = pPgOld->needSync; }else{ pPg->needSync = 0; } | < < < | < < | | | | | 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 | assert( pPgOld->nRef==0 ); unlinkHashChain(pPager, pPgOld); makeClean(pPgOld); pPg->needSync = pPgOld->needSync; }else{ pPg->needSync = 0; } pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno); /* Change the page number for pPg and insert it into the new hash-chain. */ assert( pgno!=0 ); pPg->pgno = pgno; h = pgno & (pPager->nHash-1); if( pPager->aHash[h] ){ assert( pPager->aHash[h]->pPrevHash==0 ); pPager->aHash[h]->pPrevHash = pPg; } pPg->pNextHash = pPager->aHash[h]; pPager->aHash[h] = pPg; pPg->pPrevHash = 0; makeDirty(pPg); pPager->dirtyCache = 1; if( needSyncPgno ){ /* If needSyncPgno is non-zero, then the journal file needs to be ** sync()ed before any data is written to database file page needSyncPgno. ** Currently, no such page exists in the page-cache and the ** Pager.pInJournal bit has been set. This needs to be remedied by loading ** the page into the pager-cache and setting the PgHdr.needSync flag. ** ** If the attempt to load the page into the page-cache fails, (due ** to a malloc() or IO failure), clear the bit in the pInJournal[] ** array. Otherwise, if the page is loaded and written again in ** this transaction, it may be written to the database file before ** it is synced into the journal file. This way, it may end up in ** the journal file twice, but that is not a problem. ** ** The sqlite3PagerGet() call may cause the journal to sync. So make ** sure the Pager.needSync flag is set too. */ int rc; PgHdr *pPgHdr; assert( pPager->needSync ); rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); if( rc!=SQLITE_OK ){ if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno); } pagerLeave(pPager); return rc; } pPager->needSync = 1; pPgHdr->needSync = 1; pPgHdr->inJournal = 1; |
︙ | ︙ |
Changes to src/sqliteInt.h.
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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.663 2008/02/18 14:47:34 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds |
︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 | #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; | > | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct Bitvec Bitvec; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; |
︙ | ︙ | |||
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 | void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,Select*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) int sqlite3ViewGetColumnNames(Parse*,Table*); #else # define sqlite3ViewGetColumnNames(A,B) 0 #endif | > > > > > > | 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 | void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,Select*); Bitvec *sqlite3BitvecCreate(u32); int sqlite3BitvecTest(Bitvec*, u32); int sqlite3BitvecSet(Bitvec*, u32); void sqlite3BitvecClear(Bitvec*, u32); void sqlite3BitvecDestroy(Bitvec*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) int sqlite3ViewGetColumnNames(Parse*,Table*); #else # define sqlite3ViewGetColumnNames(A,B) 0 #endif |
︙ | ︙ |
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.53 2008/02/18 14:47:34 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
557 558 559 560 561 562 563 564 565 566 567 568 569 570 | Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); return TCL_ERROR; } return TCL_OK; } #endif /* ** Register commands with the TCL interpreter. */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_persist; extern int sqlite3_io_error_pending; extern int sqlite3_io_error_hit; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 593 594 595 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 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); return TCL_ERROR; } return TCL_OK; } #endif /* ** sqlite3BitvecCreate SIZE ** sqlite3BitvecTest POINTER N ** sqlite3BitvecSet POINTER N ** sqlite3BitvecClear POINTER N ** sqlite3BitvecDestroy POINTER */ static int testBitvecCreate( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ int size; Bitvec *p; char zBuf[100]; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", (void*)0); } if( Tcl_GetInt(interp, argv[1], &size) ) return TCL_ERROR; p = sqlite3BitvecCreate(size); sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",p); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } static int testBitvecTest( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ int N; Bitvec *p; char zBuf[100]; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", (void*)0); } p = (Bitvec*)sqlite3TextToPtr(argv[1]); if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3BitvecTest(p,N)); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } static int testBitvecSet( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ int N; Bitvec *p; char zBuf[100]; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", (void*)0); } p = (Bitvec*)sqlite3TextToPtr(argv[1]); if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3BitvecSet(p,N)); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } static int testBitvecClear( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ int N; Bitvec *p; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR N\"", (void*)0); } p = (Bitvec*)sqlite3TextToPtr(argv[1]); if( Tcl_GetInt(interp, argv[2], &N) ) return TCL_ERROR; sqlite3BitvecClear(p,N); return TCL_OK; } static int testBitvecDestroy( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ Bitvec *p; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " PTR\"", (void*)0); } p = (Bitvec*)sqlite3TextToPtr(argv[1]); sqlite3BitvecDestroy(p); return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_persist; extern int sqlite3_io_error_pending; extern int sqlite3_io_error_hit; |
︙ | ︙ | |||
590 591 592 593 594 595 596 597 598 599 600 601 602 603 | { "page_read", (Tcl_CmdProc*)page_read }, { "page_write", (Tcl_CmdProc*)page_write }, { "page_number", (Tcl_CmdProc*)page_number }, { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, #ifndef SQLITE_OMIT_DISKIO { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, #endif }; 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, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); | > > > > > | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | { "page_read", (Tcl_CmdProc*)page_read }, { "page_write", (Tcl_CmdProc*)page_write }, { "page_number", (Tcl_CmdProc*)page_number }, { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, #ifndef SQLITE_OMIT_DISKIO { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, #endif { "sqlite3BitvecCreate", (Tcl_CmdProc*)testBitvecCreate }, { "sqlite3BitvecTest", (Tcl_CmdProc*)testBitvecTest }, { "sqlite3BitvecSet", (Tcl_CmdProc*)testBitvecSet }, { "sqlite3BitvecClear", (Tcl_CmdProc*)testBitvecClear }, { "sqlite3BitvecDestroy", (Tcl_CmdProc*)testBitvecDestroy }, }; 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, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); |
︙ | ︙ |
Added test/bitvec.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | # 2008 February 18 # # 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. # #*********************************************************************** # # Unit testing of the Bitvec object. # # $Id: bitvec.test,v 1.1 2008/02/18 14:47:34 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl #ifcapable !subquery { # finish_test # return #} do_test bitvec-1.1 { set PTR [sqlite3BitvecCreate 4000] for {set i 1} {$i<=4000} {incr i} { if {$i%1000==999} continue sqlite3BitvecSet $PTR $i } set r {} for {set i 1} {$i<=4000} {incr i} { if {![sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {999 1999 2999 3999} do_test bitvec-1.2 { set PTR [sqlite3BitvecCreate 4001] for {set i 1} {$i<=4001} {incr i} { if {$i%1000==999} continue sqlite3BitvecSet $PTR $i } set r {} for {set i 1} {$i<=4001} {incr i} { if {![sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {999 1999 2999 3999} do_test bitvec-1.3 { set PTR [sqlite3BitvecCreate 40000] for {set i 1} {$i<=40000} {incr i} { if {$i%10000==9999} continue sqlite3BitvecSet $PTR $i } set r {} for {set i 1} {$i<=40000} {incr i} { if {![sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {9999 19999 29999 39999} do_test bitvec-1.4 { set PTR [sqlite3BitvecCreate 2000000000] for {set i 1000000} {$i<=1001000} {incr i} { if {$i%1000==789} continue sqlite3BitvecSet $PTR $i } set r {} for {set i 1000000} {$i<=1001000} {incr i} { if {![sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {1000789} do_test bitvec-2.1 { set PTR [sqlite3BitvecCreate 4000] for {set i 1} {$i<=4000} {incr i 2} { sqlite3BitvecSet $PTR $i } for {set i 1} {$i<=4000} {incr i} { sqlite3BitvecClear $PTR $i } set r {} for {set i 1} {$i<=4000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {} do_test bitvec-2.2 { set PTR [sqlite3BitvecCreate 4001] for {set i 1} {$i<=101} {incr i 2} { sqlite3BitvecSet $PTR $i } for {set i 1} {$i<=99} {incr i} { sqlite3BitvecClear $PTR $i } set r {} for {set i 1} {$i<=4000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {101} do_test bitvec-2.3 { set PTR [sqlite3BitvecCreate 4001] for {set i 1} {$i<=101} {incr i} { sqlite3BitvecSet $PTR $i } for {set i 1} {$i<=99} {incr i} { sqlite3BitvecClear $PTR $i } set r {} for {set i 1} {$i<=4000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {100 101} do_test bitvec-2.4 { set PTR [sqlite3BitvecCreate 5000] for {set i 1} {$i<=5000} {incr i} { sqlite3BitvecSet $PTR $i if {$i%1000!=456} {sqlite3BitvecClear $PTR $i} } set r {} for {set i 1} {$i<=5000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {456 1456 2456 3456 4456} do_test bitvec-3.1 { set PTR [sqlite3BitvecCreate 2000000000] for {set i 2000000} {$i<=3000000} {incr i 100000} { for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecSet $PTR $i } for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecClear $PTR $i } } set r {} for {set i 2000000} {$i<=3000000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {} do_test bitvec-3.2 { set PTR [sqlite3BitvecCreate 200000] for {set i 1000} {$i<=190000} {incr i 10000} { for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecSet $PTR $i } for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecClear $PTR $i } } set r {} for {set i 1} {$i<=200000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {} do_test bitvec-3.3 { set PTR [sqlite3BitvecCreate 200000] for {set i 1000} {$i<=190000} {incr i 10000} { for {set j $i} {$j<=$i+500} {incr j} { sqlite3BitvecSet $PTR $i } for {set j $i} {$j<=$i+500} {incr j} { sqlite3BitvecClear $PTR $i } } set r {} for {set i 1} {$i<=200000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {} do_test bitvec-3.4 { set PTR [sqlite3BitvecCreate 2000] for {set i 10} {$i<=1900} {incr i 100} { for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecSet $PTR $i } for {set j $i} {$j<=$i+50} {incr j} { sqlite3BitvecClear $PTR $i } } set r {} for {set i 1} {$i<=2000} {incr i} { if {[sqlite3BitvecTest $PTR $i]} {lappend r $i} } sqlite3BitvecDestroy $PTR set r } {} finish_test |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 | hash.c opcodes.c os_os2.c os_unix.c os_win.c pager.c btmutex.c btree.c vdbefifo.c vdbemem.c | > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | hash.c opcodes.c os_os2.c os_unix.c os_win.c bitvec.c pager.c btmutex.c btree.c vdbefifo.c vdbemem.c |
︙ | ︙ |