From b5b452cb5899b3c4050d88d98e28d142ec41fb75 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Jan 2001 01:45:40 +0000 Subject: [PATCH] :-) (CVS 1712) FossilOrigin-Name: edb01b1275c3de7c398522b5826c898917811247 --- manifest | 16 +- manifest.uuid | 2 +- src/db.c | 592 +++++++++++++++++++++++++++++++------------------- src/db.h | 14 +- src/pg.c | 11 +- 5 files changed, 391 insertions(+), 244 deletions(-) diff --git a/manifest b/manifest index 045776eb8d..c83c70d72c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C :-)\s(CVS\s180) -D 2001-01-22T00:31:53 +C :-)\s(CVS\s1712) +D 2001-01-25T01:45:40 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 F Makefile.in 7efa81e2985b45ba73db27d55b70cc927f5abfd7 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 @@ -10,8 +10,8 @@ F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47 F doc/report1.txt ad0a41513479f1be0355d1f3f074e66779ff2282 F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4 F src/build.c 7aa5879bf58ea6bbff22c26c59d1130021fa6ca4 -F src/db.c 8e841538cc1079c99b050ba8694c7bd544b0a355 -F src/db.h 488f01d3c0182568b0ec1186149603e271e79c43 +F src/db.c 387cbf95f95bf4d2668cd01f64a60ffd59f43874 +F src/db.h f5ab793ad888c7905fbaaf9a675f576f4a3918bc F src/dbbe.c 162d29b09ac379f160892c5795efc14099dcc8eb F src/dbbe.h 0435a36906a839cce062608f51bd9d3e79878fec F src/dbbegdbm.c 5bfcb1b4ee47a98c5eae83041e9716cd3233fd0e @@ -21,7 +21,7 @@ F src/expr.c 49bc261fdc4f4fb91c74cd668a9a952c00e85931 F src/insert.c 4bc1cab84f7805d560a1417734a532843e30b762 F src/main.c 92fcd6d967ceee1f96a5b9543779eef6e9b56913 F src/parse.y 25ee4d8efccc4b247c32fe4ab194e3dd8fd5a4ee -F src/pg.c 8bf498216976bea261e7a02724c4fdcc96f6ee2f +F src/pg.c 2981173b2a752ef3578168e7af1a32ff22b70db6 F src/pg.h a95c4803a1aae99449aa2c0a1af0c8d863a3f340 F src/printf.c 1efb6b3e7f28a93be57132de3f8f400d2ac1460e F src/random.c 3dc42fb35d834901577aa547308ff3c8941fea25 @@ -84,7 +84,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2 F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad -P 0529c979fd17995aff82e21b91b5cc833f23d8ef -R 190eb04a63af8235aad9df6267107e4c +P 98da825312fd4bb8a20ff33293131c02beb3ae63 +R 65625e73d51d03039a82df767d26bb25 U drh -Z da6be622c2a2caa5949500b0c0127edd +Z aad6c859441db92bc7fcd45e2633d4de diff --git a/manifest.uuid b/manifest.uuid index fd1845f763..d1cb80e42d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -98da825312fd4bb8a20ff33293131c02beb3ae63 \ No newline at end of file +edb01b1275c3de7c398522b5826c898917811247 \ No newline at end of file diff --git a/src/db.c b/src/db.c index 74c3dfdf7b..440f6931bb 100644 --- a/src/db.c +++ b/src/db.c @@ -21,7 +21,7 @@ ** http://www.hwaci.com/drh/ ** ************************************************************************* -** $Id: db.c,v 1.3 2001/01/22 00:31:53 drh Exp $ +** $Id: db.c,v 1.4 2001/01/25 01:45:40 drh Exp $ */ #include "sqliteInt.h" #include "pg.h" @@ -52,6 +52,8 @@ struct DbIdxpt { int pgno; /* The page number */ u32 *aPage; /* The page data */ int idx; /* Index into pPage[] */ + int hashLB; /* Lower bound on hash at this level */ + int hashUB; /* Upper bound on hash at this level */ }; /* @@ -120,35 +122,84 @@ struct DbCursor { ** 4... root pages numbers of tables */ +/* +** The number of u32-sized objects that will fit on one page. +*/ #define U32_PER_PAGE (SQLITE_PAGE_SIZE/sizeof(u32)) -#deifne LOCAL_PAYLOAD (SQLITE_PAGE_SIZE - 18*sizeof(u32)) /* -** Byte swapping code. +** Number of direct overflow pages per database entry */ -#ifdef BIG_ENDIAN -# SWB(x) (x) -#else -# SWB(x) sqliteDbSwapBytes(x) -#endif - -static u32 sqliteDbSwapBytes(u32 x){ - unsigned char c, *s, *d; - s = (unsigned char*)&x; - d = (unsigned char*)&r; - d[0] = s[3]; - d[1] = s[2]; - d[2] = s[1]; - d[3] = s[0]; - return r; +#define N_DIRECT 10 + +/* +** The maximum amount of payload that will fit on on the same +** page as a leaf, assuming the leaf contains only a single +** database entry and the entry uses no overflow pages. +*/ +#define LOCAL_PAYLOAD (SQLITE_PAGE_SIZE - (8+N_DIRECT)*sizeof(u32)) + +/* +** Allocate a new page. Return both the page number and a pointer +** to the page data. The calling function is responsible for unref-ing +** the page when it is no longer needed. +*/ +int allocPage(Db *pDb, u32 *pPgno, u32 **ppPage){ + u32 pgno; + int rc; + + if( pDb->aContent==0 ) return SQLITE_NOMEM; + + /* Try to reuse a page from the freelist + */ + pgno = pDb->aContent[0]; + if( pgno!=0 ){ + rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage); + if( rc==SQLITE_OK ){ + pDb->aContent[0] = pFree[1]; + *pPgno = pgno; + memset(*ppPage, 0, SQLITE_PAGE_SIZE); + return SQLITE_OK; + } + } + + /* If the freelist is empty, or we cannot access it, + ** then allocate a new page from the end of the file. + */ + if( (rc = sqlitePgCount(pDb->pPgr, &pgno))==SQLITE_OK && + (rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage))==SQLITE_OK ){ + *pPgno = pgno; + memset(*ppPage, 0, SQLITE_PAGE_SIZE); + return SQLITE_OK; + } + return rc; } -#endif +/* +** Return a page to the freelist and dereference the page. +*/ +static void freePage(DB *pDb, u32 pgno, u32 *aPage){ + if( pDb->aContent==0 ) return; + if( pgno==0 ) return + if( aPage==0 ){ + int rc; + rc = sqlitePgGet(pDb->pPgr, pgno, &aPage); + if( rc!=SQLITE_OK ) return; + } + aPage[0] = BLOCK_MAGIC | BLOCK_FREE; + aPage[1] = pDb->aContent[0]; + memset(&aPage[2], 0, SQLITE_PAGE_SIZE - 2*sizeof(u32)); + pDb->aContent[0] = pgno; + sqlitePgTouch(aPage); + sqlitePgUnref(aPage); +} /* ** Return the number of bytes of payload storage required on the leaf -** node to hold the key and data given. Overflow pages do not count. -** The argument is the total size of the payload. +** node to hold the amount of payload specified by the argument. +** Overflow pages do not count, only memory on the leaf page. +** +** Return -1 if nTotal is more than sqlite is able to store. */ static int payloadLocalSize(int nTotal){ int nLocal, i; @@ -162,8 +213,8 @@ static int payloadLocalSize(int nTotal){ if( nTotal < 10*SQLITE_PAGE_SIZE ){ return nLocal + ((nTotal+SQLITE_PAGE_SIZE-1)/SQLITE_PAGE_SIZE)*sizeof(u32); } - nLocal += 10*sizeof(u32); - nTotal -= 10*SQLITE_PAGE_SIZE; + nLocal += N_DIRECT*sizeof(u32); + nTotal -= N_DIRECT*SQLITE_PAGE_SIZE; if( nTotal < U32_PER_PAGE*SQLITE_PAGE_SIZE ){ return nLocal + sizeof(u32); } @@ -184,116 +235,132 @@ static int payloadLocalSize(int nTotal){ */ static int payloadRead(Db *pDb, u32 *aPage, int offset, int amt, void *pBuf){ int rc; - int toread, more; + int tomove; + int i; + /* First read local data off of the leaf page itself. + ** This is all that ever happens in 99% of accesses. + */ assert( offset>=0 && amt>=0 ); if( offset < LOCAL_PAYLOAD ){ /* Data stored directly in the leaf block of the BTree */ if( amt+offset>LOCAL_PAYLOAD ){ - toread = LOCAL_PAYLOAD - offset; - more = 1; + tomove = LOCAL_PAYLOAD - offset; }else{ - toread = amt; - more = 0; + tomove = amt; } - memcpy(pBuf, &((char*)aPage)[offset], toread); - if( !more ) return SQLITE_OK; - pBuf = &((char*)pBuf)[toread]; - offset += toread; - amt -= toread; + memcpy(pBuf, &((char*)aPage)[offset], tomove); + pBuf = &((char*)pBuf)[tomove]; + offset += tomove; + amt -= tomove; + if( amt<=0 ) return SQLITE_OK; } offset -= LOCAL_PAYLOAD; aPage += LOCAL_PAYLOAD/sizeof(aPage[0]); - while( offset < 10*SQLITE_PAGE_SIZE ){ - /* Data stored in one of 10 direct pages */ - int iDir; - char *aData; - iDir = offset/SQLITE_PAGE_SIZE; - base = offset - iDir*SQLITE_PAGE_SIZE; - rc = sqlitePgGet(pDb->pPgr, aPage[iDir], &aData); - if( rc!=SQLITE_OK ) return rc; - if( amt+base > SQLITE_PAGE_SIZE ){ - toread = SQLITE_PAGE_SIZE - base; - more = 1; - }else{ - toread = amt; - more = 0; + + /* If not all of the data fits locally, read from the first + ** ten direct-access overflow pages. + */ + if( offset < N_DIRECT*SQLITE_PAGE_SIZE ){ + for(i=offset/SQLITE_PAGE_SIZE; i0; i++){ + char *aData; + base = offset - i*SQLITE_PAGE_SIZE; + rc = sqlitePgGet(pDb->pPgr, aPage[i], &aData); + if( rc!=SQLITE_OK ) return rc; + if( amt+base > SQLITE_PAGE_SIZE ){ + tomove = SQLITE_PAGE_SIZE - base; + }else{ + tomove = amt; + } + memcpy(pBuf, &aData[base], tomove); + sqlitePgUnref(aData); + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; } - memcpy(pBuf, &aData[base], toread); - sqlitePgUnref(aData); - if( !more ) return SQLITE_OK; - pBuf = &((char*)pBuf)[toread]; - amt -= toread; - offset += toread; - } - offset -= 10*SQLITE_PAGE_SIZE; - aPage += 10; + } + offset -= N_DIRECT*SQLITE_PAGE_SIZE; + aPage += N_DIRECT; + + /* If the first N_DIRECT overflow pages do not contain everything, then + ** read from an overflow page that is filled with pointer to + ** U32_PER_PAGE more overflow pages. + */ if( offset < U32_PER_PAGE*SQLITE_PAGE_SIZE ){ - /* Data stored in an indirect page */ u32 *indirPage; rc = sqlitePgGet(pDb->pPgr, aPage[0], &indirPage); if( rc!=SQLITE_OK ) return rc; - while( amt>0 && offset < U32_PER_PAGE*SQLITE_PAGE_SIZE ){ - int idx, base; + for(i=offset/SQLITE_PAGE_SIZE; i0; i++){ + int base; char *aData; - idx = offset/SQLITE_PAGE_SIZE; - base = offset - idx*SQLITE_PAGE_SIZE; + base = offset - i*SQLITE_PAGE_SIZE; rc = sqlitePgGet(pDb->pPgr, indirPage[idx], &aData); if( rc!=SQLITE_OK ) break; if( amt+base > SQLITE_PAGE_SIZE ){ - toread = SQLITE_PAGE_SIZE - base; + tomove = SQLITE_PAGE_SIZE - base; }else{ - toread = amt; + tomove = amt; } - memcpy(pBuf, &aData[base], toread); + memcpy(pBuf, &aData[base], tomove); sqlitePgUnref(aData); - pBuf = &((char*)pBuf)[toread]; - amt -= toread; - offset += toread; + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; } sqlitePgUnref(indirPage); if( rc!=SQLITE_OK ) return rc; + if( amt<=0 ) return SQLITE_OK; } offset -= U32_PER_PAGE*SQLITE_PAGE_SIZE; aPage++; + + /* If there is still more data, then read using a double-indirect + ** overflow. The overflow page points to U32_PER_PAGE additional + ** overflow pages, each of which pointer to U32_PER_PAGE more overflow + ** pages which contain data. + ** + ** This is hard to test. To exercise this code, you have to make + ** a database entry of more than 273336 bytes in side, assuming a + ** pagesize of 1024 bytes and 10 direct overflow pages. By the + ** time this code runs, you have already used 267 overflow pages. + */ if( offset < U32_PER_PAGE*U32_PER_PAGE*SQLITE_PAGE_SIZE ){ - /* Data stored in a double-indirect page */ u32 *dblIndirPage; rc = sqlitePgGet(pDb->pPgr, aPage[0], &dblIndirPage); if( rc!=SQLITE_OK ) return rc; - while( amt>0 && offset < U32_PER_PAGE*U32_PER_PAGE*SQLITE_PAGE_SIZE ){ - int dblidx; + i = offset/(U32_PER_PAGE*SQLITE_PAGE_SIZE); + for(; i0; i++){ u32 *indirPage; int basis; - dblidx = offset/(U32_PER_PAGE*SQLITE_PAGE_SIZE); - rc = sqlitePgGet(pDb->pPgr, dblIndirPage[dblidx], &indirPage); + int j; + rc = sqlitePgGet(pDb->pPgr, dblIndirPage[i], &indirPage); if( rc!=SQLITE_OK ) break; - basis = dblidx*U32_PER_PAGE*SQLITE_PAGE_SIZE; - while( amt>0 && offset < basis + U32_PER_PAGE*SQLITE_PAGE_SIZE ){ - int idx, base; + basis = i*U32_PER_PAGE*SQLITE_PAGE_SIZE; + j = (offset - basis)/SQLITE_PAGE_SIZE; + for(; j0; j++){ char *aData; - idx = (offset - basis)/SQLITE_PAGE_SIZE; - base = (offset - basis) - idx*SQLITE_PAGE_SIZE; - rc = sqlitePgGet(pDb->pPgr, indirPage[idx], &aData); + base = (offset - basis) - ij*SQLITE_PAGE_SIZE; + rc = sqlitePgGet(pDb->pPgr, indirPage[j], &aData); if( rc!=SQLITE_OK ) break; if( amt+base > SQLITE_PAGE_SIZE ){ - toread = SQLITE_PAGE_SIZE - base; + tomove = SQLITE_PAGE_SIZE - base; }else{ - toread = amt; + tomove = amt; } - memcpy(pBuf, &aData[base], toread); + memcpy(pBuf, &aData[base], tomove); sqlitePgUnref(aData); - pBuf = &((char*)pBuf)[toread]; - amt -= toread; - offset += toread; + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; } sqlitePgUnref(indirPage); if( rc!=SQLITE_OK ) break; } sqlitePgUnref(dblIndirPage); - return rc; } - memset(pBuf, 0, amt); + + /* Anything beyond the double-indirect pages, just fill in with + ** zeros. You have to write 67382200 bytes to go past the + ** double-indirect pages, assuming a 1024 byte page size. + */ + if( amt>0 ) memset(pBuf, 0, amt); return SQLITE_OK; } @@ -308,96 +375,241 @@ static int payloadRead(Db *pDb, u32 *aPage, int offset, int amt, void *pBuf){ */ static int payloadWrite(Db *pDb, u32 *aPage, int offset, int amt, void *pBuf){ assert( offset>=0 && amt>=0 ); + + /* Local data + */ if( offset < LOCAL_PAYLOAD ){ if( amt+offset>LOCAL_PAYLOAD ){ - towrite = LOCAL_PAYLOAD - offset; - more = 1; + tomove = LOCAL_PAYLOAD - offset; }else{ - towrite = amt; - more = 0; + tomove = amt; } - memcpy(&((char*)aPage)[offset], pBuf, towrite); - if( !more ) return SQLITE_OK; - pBuf = &((char*)pBuf)[towrite]; - offset += toread; - amt -= toread; + memcpy(&((char*)aPage)[offset], pBuf, tomove); + pBuf = &((char*)pBuf)[tomove]; + offset += tomove; + amt -= tomove; + if( amt<=0 ) return SQLITE_OK; } offset -= LOCAL_PAYLOAD; aPage += LOCAL_PAYLOAD/sizeof(aPage[0]); - while( offset < 10*SQLITE_PAGE_SIZE ){ - int iDir; - char *aData; - iDir = offset/SQLITE_PAGE_SIZE; - base = offset - iDir*SQLITE_PAGE_SIZE; - if( aPage[iDir] ){ - rc = sqliteGet(pDb->pPgr, aPage[iDir], &aData); + + /* Direct overflow pages + */ + if( offset < N_DIRECT*SQLITE_PAGE_SIZE ){ + for(i=offset/SQLITE_PAGE_SIZE; i0; i++){ + base = offset - i*SQLITE_PAGE_SIZE; + if( aPage[i] ){ + rc = sqlitePgGet(pDb->pPgr, aPage[i], &aData); + }else{ + rc = allocPage(pDb, &aPage[i], &aData); + } + if( rc!=SQLITE_OK ) return rc; + if( amt+base > SQLITE_PAGE_SIZE ){ + tomove = SQLITE_PAGE_SIZE - base; + }else{ + tomove = amt; + } + memcpy(&aData[base], pBuf, tomove); + sqlitePgTouch(aData); + sqlitePgUnref(aData); + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; + } + if( amt<=0 ) return SQLITE_OK; + } + offset -= N_DIRECT*SQLITE_PAGE_SIZE; + aPage += N_DIRECT; + + /* Indirect overflow pages + */ + if( offset < U32_PER_PAGE*SQLITE_PAGE_SIZE ){ + u32 *indirPage; + if( aPage[0] ){ + rc = sqlitePgGet(pDb->pPgr, aPage[0], &indirPage); }else{ - rc = sqliteDbAllocPage(pDb, &aPage[iDir], &aData); + rc = allocPage(pDb, &aPage[0], &indirPage); } if( rc!=SQLITE_OK ) return rc; - if( amt+base > SQLITE_PAGE_SIZE ){ - towrite = SQLITE_PAGE_SIZE - base; - more = 1; + for(i=offset/SQLITE_PAGE_SIZE; i0; i++){ + int base; + char *aData; + base = offset - i*SQLITE_PAGE_SIZE; + if( indirPage[i] ){ + rc = sqlitePgGet(pDb->pPgr, indirPage[i], &aData); + }else{ + rc = allocPage(pDb, &indirPage[i], &aData); + sqlitePgTouch(indirPage); + } + if( rc!=SQLITE_OK ) break; + if( amt+base > SQLITE_PAGE_SIZE ){ + tomove = SQLITE_PAGE_SIZE - base; + }else{ + tomove = amt; + } + memcpy(&aData[base], pBuf, tomove); + sqlitePgUnref(aData); + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; + } + sqlitePgUnref(indirPage); + if( rc!=SQLITE_OK ) return rc; + if( amt<=0 ) return SQLITE_OK; + } + offset -= U32_PER_PAGE*SQLITE_PAGE_SIZE; + aPage++; + + /* Double-indirect overflow pages + */ + if( offset < U32_PER_PAGE*U32_PER_PAGE*SQLITE_PAGE_SIZE ){ + u32 *dblIndirPage; + if( aPage[0] ){ + rc = sqlitePgGet(pDb->pPgr, aPage[0], &dblIndirPage); }else{ - towrite = amt; - more = 0; + rc = allocPage(pDb, &aPage[0], &dblIndirPage); } - memcpy(&aData[base], pBuf, towrite); - sqlitePgUnref(aData); - if( !more ) return SQLITE_OK; - pBuf = &((char*)pBuf)[towrite]; - amt -= towrite; - offset += towrite; - } - /* TBD.... */ + if( rc!=SQLITE_OK ) return rc; + i = offset/(U32_PER_PAGE*SQLITE_PAGE_SIZE); + for(; i0; i++){ + u32 *indirPage; + int basis; + int j; + if( aPage[0] ){ + rc = sqlitePgGet(pDb->pPgr, aPage[0], &dblIndirPage); + }else{ + rc = allocPage(pDb, &aPage[0], &dblIndirPage); + sqlitePgTouch(dblIndirPage); + } + rc = sqlitePgGet(pDb->pPgr, dblIndirPage[i], &indirPage); + if( rc!=SQLITE_OK ) break; + basis = i*U32_PER_PAGE*SQLITE_PAGE_SIZE; + j = (offset - basis)/SQLITE_PAGE_SIZE; + for(; j0; j++){ + char *aData; + base = (offset - basis) - ij*SQLITE_PAGE_SIZE; + if( indirPage[j] ){ + rc = sqlitePgGet(pDb->pPgr, indirPage[j], &aData); + }else{ + rc = allocPage(pDb, &indirPage[j], &aData); + sqlitePgTouch(indirPage); + } + if( rc!=SQLITE_OK ) break; + if( amt+base > SQLITE_PAGE_SIZE ){ + tomove = SQLITE_PAGE_SIZE - base; + }else{ + tomove = amt; + } + memcpy(&aData[base], pBuf, tomove); + sqlitePgTouch(aData); + sqlitePgUnref(aData); + pBuf = &((char*)pBuf)[tomove]; + amt -= tomove; + } + sqlitePgUnref(indirPage); + if( rc!=SQLITE_OK ) break; + } + sqlitePgUnref(dblIndirPage); + } + + return SQLITE_OK; } /* ** Release any and all overflow pages associated with data starting -** with byte "newSize" up to but not including "oldSize". +** with byte "newSize". oldSize is the amount of payload before doing +** the free operation. */ static int payloadFree(Db *pDb, u32 *aPage, int newSize, int oldSize){ - int i; + int i, j; /* Loop counters */ + int first, last; /* Indices of first and last pages to be freed */ + int rc; /* Return code from sqlitePgGet() */ - if( newSize>=oldSize ) return; + /* Skip over the local data. We do not need to free it. + */ + if( newSize>=oldSize ) return SQLITE_OK; oldSize -= LOCAL_PAYLOAD; if( oldSize<=0 ) return SQLITE_OK; newSize -= LOCAL_PAYLOAD; - if( newSize<0 ) newSize = 0; aPage += LOCAL_PAYLOAD/sizeof(u32); -************* - for(i=0; i<10; i++){ - sqliteDbFreePage(pDb, aPage[0], 0); - amt -= SQLITE_PAGE_SIZE; - if( amt<=0 ) return SQLITE_OK; - aPage++; + + /* Compute the indices of the first and last overflow pages to + ** be freed. + */ + first = (newSize - 1)/SQLITE_PAGE_SIZE + 1; + last = (oldSize - 1)/SQLITE_PAGE_SIZE; + + /* Free the direct overflow pages + */ + if( first < N_DIRECT ){ + for(i=first; ipPgr, aPage[0], &indirPage); + if( rc!=SQLITE_OK ) return rc; + for(i=first; ipPgr, aPage[0], &indirPage); - if( rc!=SQLITE_OK ) return rc; - for(i=0; ipPgr, aPage[0], &dblIndirPage); - if( rc!=SQLITE_OK ) return rc; - for(i=0; ipPgr, dblIndirPage[i], &indirPage); - if( rc!=SQLITE_OK ) break; - for(j=0; jpPgr, aPage[0], &dblIndirPage); + if( rc!=SQLITE_OK ) return rc; + for(i=first/U32_PER_PAGE; ipPgr, dblIndirPage[i], &indirPage); + if( rc!=SQLITE_OK ) return rc; + for(j=first>basis?first-basis:0 ; j last ) break; + freePage(pDb, indirPage[j], 0); + indirPage[j] = 0; + } + if( first<=basis ){ + freepage(pDb, dblIndirPage[i], 0); + dblIndirPage[i] = 0; + }else{ + sqlitePgTouch(indirPage); + sqlitePgUnref(indirPage); + } + } + if( first<=0 ){ + freepage(pDb, aPage[0], dblIndirPage); + aPage[0] = 0; + }else{ + sqlitePgTouch(dblIndirPage); + sqlitePgUnref(dblIndirPage); } - sqliteDbFreePage(pDb, dblIndirPage[i], indirPage); - sqlitePgUnder(indirPage); } - sqliteDbFreePage(pDb, aPage[0], dblIndirPage); - sqlitePgUnref(dblIndirPage); + return SQLITE_OK; } @@ -418,46 +630,6 @@ static int sqliteDbExpandContent(Db *pDb, int newSize){ return SQLITE_OK; } -/* -** Allocate a new page. Return both the page number and a pointer -** to the page data. The calling function is responsible for unref-ing -** the page when it is no longer needed. -*/ -int sqliteDbAllocPage(Db *pDb, u32 *pPgno, u32 **ppPage){ - u32 pgno; - int rc; - - if( pDb->aContent==0 ) return SQLITE_NOMEM; - pgno = SWB(pDb->aContent[0]); - if( pgno!=0 ){ - rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage); - if( rc==SQLITE_OK ){ - pDb->aContent[0] = pFree[1]; - *pPgno = pgno; - return SQLITE_OK; - } - } - if( (rc = sqlitePgCount(pDb->pPgr, &pgno))==SQLITE_OK && - (rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage))==SQLITE_OK ){ - *pPgno = pgno; - return SQLITE_OK; - } - return rc; -} - -/* -** Return a page to the freelist and dereference the page. -*/ -static void sqliteDbFreePage(DB *pDb, u32 pgno, u32 *aPage){ - if( pDb->aContent==0 ) return; - aPage[0] = SWB(BLOCK_MAGIC | BLOCK_FREE); - aPage[1] = pDb->aContent[0]; - memset(&aPage[2], 0, SQLITE_PAGE_SIZE - 2*sizeof(u32)); - pDb->aContent[0] = SWB(pgno); - sqlitePgTouch(aPage); - sqlitePgUnref(aPage); -} - /* ** Open a database. */ @@ -589,7 +761,7 @@ int sqliteDbCreateTable(Db *pDb, int *pTblno){ int swTblno; int i; - rc = sqliteDbAllocPage(pDb, &pgno, &pPage); + rc = allocPage(pDb, &pgno, &pPage); if( rc!=SQLITE_OK ){ return rc; } @@ -629,15 +801,15 @@ static int sqliteDbDropPage(Db *pDb, u32 pgno){ rc = sqlitePgGet(pDb->pPgr, pgno, (void**)&aPage); if( rc!=SQLITE_OK ) return rc; - switch( SWB(aPage[0]) ){ + switch( aPage[0] ){ case BLOCK_MAGIC | BLOCK_INDEX: { int n, i; - n = SWB(aPage[2]); + n = aPage[2]; for(i=0; ipPgr, pgno, &aPage); - } + freePage(pDb, pgno, aPage); break; } default: { @@ -675,21 +836,6 @@ static int sqliteDbDropPage(Db *pDb, u32 pgno){ ** this entry. */ static int sqliteDbClearEntry(Db *pDb, u32 *aEntry){ - int nByte; - int idx; - - idx = 4; - nByte = SWB(aEntry[2]); - if( nByte & 0x80000000 ){ - sqliteDbDropPage(pDb, SWB(aEntry[idx])); - idx++; - }else{ - idx += (nByte + 3)/4; - } - nByte = SWB(aEntry[3]); - if( nByte & 0x80000000 ){ - sqliteDbDropPage(pDb, SWB(aEntry[idx])); - } return SQLITE_OK; } @@ -1249,7 +1395,7 @@ int sqliteDbCursorInsert( }else{ u32 newPgno, *newPage; aPage[i+2] = SWB(nKey | 0x80000000); - rc = sqliteDbAllocPage(pCur->pDb, &newPgno, &newPage); + rc = allocPage(pCur->pDb, &newPgno, &newPage); if( rc!=SQLITE_OK ) goto write_err; aPage[i+4] = SWB(newPgno); newPage[0] = SWB(BLOCK_MAGIC | BLOCK_OVERFLOW); @@ -1266,7 +1412,7 @@ int sqliteDbCursorInsert( }else{ u32 newPgno, *newPage; aPage[i+3] = SWB(nData | 0x80000000); - rc = sqliteDbAllocPage(pCur->pDb, &newPgno, &newPage); + rc = allocPage(pCur->pDb, &newPgno, &newPage); if( rc!=SQLITE_OK ) goto write_err; aPage[j] = SWB(newPgno); newPage[0] = SWB(BLOCK_MAGIC | BLOCK_OVERFLOW); diff --git a/src/db.h b/src/db.h index ef7247a965..667d42ce9d 100644 --- a/src/db.h +++ b/src/db.h @@ -21,7 +21,7 @@ ** http://www.hwaci.com/drh/ ** ************************************************************************* -** $Id: db.h,v 1.2 2001/01/20 19:52:49 drh Exp $ +** $Id: db.h,v 1.3 2001/01/25 01:45:40 drh Exp $ */ typedef struct Db Db; @@ -43,10 +43,8 @@ int sqliteDbCursorFirst(DbCursor*); int sqliteDbCursorNext(DbCursor*); int sqliteDbCursorDatasize(DbCursor*); int sqliteDbCursorKeysize(DbCursor*); -int sqliteDbCursorRead(DbCursor*, int amt, int offset, char *buf); -int sqliteDbCursorReadKey(DbCursor*, int amt, int offset, char *buf); -int sqliteDbCursorMoveTo(DbCursor*, int nKey, void *pKey); -int sqliteDbCursorDelete(DbCursor*); -int sqliteDbCursorInsert(DbCursor*, int nKey, void *pKey, int nData, void *pD); - -int sqliteDbReorganize(Db*); +int sqliteDbCursorRead(DbCursor*, int amt, int offset, void *buf); +int sqliteDbCursorReadKey(DbCursor*, int amt, int offset, void *buf); +int sqliteDbCursorFind(DbCursor*, int nKey, const void *pKey, int createSize); +int sqliteDbCursorResize(DbCursor*, int nData); +int sqliteDbCursorWrite(DbCursor*, int amt, int offset, const void *buf); diff --git a/src/pg.c b/src/pg.c index 5dd8888542..f622a80d77 100644 --- a/src/pg.c +++ b/src/pg.c @@ -21,7 +21,7 @@ ** http://www.hwaci.com/drh/ ** ************************************************************************* -** $Id: pg.c,v 1.3 2001/01/21 00:58:08 drh Exp $ +** $Id: pg.c,v 1.4 2001/01/25 01:45:41 drh Exp $ */ #include #include @@ -256,7 +256,7 @@ static Pghdr *sqlitePgFindJidx(Pgr *p, u32 pgno){ static u32 sqlitePgJournalPageNumber(Pgr *p, u32 dbpgno){ u32 jpgno; - assert( dbpgno>0 ); + if( dbpgno==0 ) return 0; jpgno = p->aJHash[dbpgno % J_HASH_SIZE]; while( jpgno!=0 ){ int idx_num; /* Which journal index describes page jpgno */ @@ -638,9 +638,12 @@ int sqlitePgGet(Pgr *p, u32 pgno, void **ppData){ if( pPg->jpgno!=0 ){ TRACE(("PG: reading d-page %u content from j-page %u\n", pgno, pPg->jpgno)); sqlitePgRead(p->fdJournal, PG_TO_DATA(pPg), pPg->jpgno); - }else{ + }else if( pPg->dbpgno!=0 ){ TRACE(("PG: reading d-page %u from database\n", pgno)); sqlitePgRead(p->fdMain, PG_TO_DATA(pPg), pPg->dbpgno); + }else{ + TRACE(("PG: reading zero page\n"); + memset(PG_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); } pPg->isDirty = 0; pPg->nRef = 1; @@ -691,7 +694,7 @@ int sqlitePgTouch(void *pD){ ** Return the number of the first unused page at the end of the ** database file. */ -int sqlitePgAlloc(Pgr *p, u32 *pPgno){ +int sqlitePgCount(Pgr *p, u32 *pPgno){ *pPgno = p->nDbPg; return SQLITE_OK; } -- 2.47.3