:-) (CVS 1712)

FossilOrigin-Name: edb01b1275c3de7c398522b5826c898917811247
This commit is contained in:
drh 2001-01-25 01:45:40 +00:00
parent acbcdc49c6
commit b5b452cb58
5 changed files with 391 additions and 244 deletions

View File

@ -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

View File

@ -1 +1 @@
98da825312fd4bb8a20ff33293131c02beb3ae63
edb01b1275c3de7c398522b5826c898917811247

592
src/db.c
View File

@ -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
#define N_DIRECT 10
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;
/*
** 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; i<N_DIRECT && amt>0; 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; i<U32_PER_PAGE && amt>0; 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(; i<U32_PER_PAGE && amt>0; 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(; j<U32_PER_PAGE && amt>0; 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; i<N_DIRECT && amt>0; 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;
}else{
towrite = amt;
more = 0;
for(i=offset/SQLITE_PAGE_SIZE; i<U32_PER_PAGE && amt>0; 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;
}
memcpy(&aData[base], pBuf, towrite);
sqlitePgUnref(aData);
if( !more ) return SQLITE_OK;
pBuf = &((char*)pBuf)[towrite];
amt -= towrite;
offset += towrite;
sqlitePgUnref(indirPage);
if( rc!=SQLITE_OK ) return rc;
if( amt<=0 ) return SQLITE_OK;
}
/* TBD.... */
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{
rc = allocPage(pDb, &aPage[0], &dblIndirPage);
}
if( rc!=SQLITE_OK ) return rc;
i = offset/(U32_PER_PAGE*SQLITE_PAGE_SIZE);
for(; i<U32_PER_PAGE && amt>0; 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(; j<U32_PER_PAGE && amt>0; 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++;
}
rc = sqlitePgGet(pDb->pPgr, aPage[0], &indirPage);
if( rc!=SQLITE_OK ) return rc;
for(i=0; i<U32_PER_PAGE; i++){
if( indirPage[i]==0 ) continue;
sqliteDbFreePage(pDb, indirPage[i], 0);
}
sqliteDbFreePage(pDb, aPage[0], indirPage);
sqlitePgUnref(indirPage);
amt -= U32_PER_PAGE*SQLITE_PAGE_SIZE;
if( amt<=0 ) return SQLITE_OK;
aPage++;
rc = sqlitePgGet(pDb->pPgr, aPage[0], &dblIndirPage);
if( rc!=SQLITE_OK ) return rc;
for(i=0; i<U32_PER_PAGE; i++){
if( dblIndirPage[i]==0 ) continue;
rc = sqlitePgGet(pDb->pPgr, dblIndirPage[i], &indirPage);
if( rc!=SQLITE_OK ) break;
for(j=0; j<U32_PER_PAGE; j++){
if( indirPage[j]==0 ) continue;
sqliteDbFreePage(pDb, dblIndirPage[i], 0);
/* 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; i<N_DIRECT && i<=last; i++){
freePage(pDb, aPage[i], 0);
aPage[i] = 0;
}
sqliteDbFreePage(pDb, dblIndirPage[i], indirPage);
sqlitePgUnder(indirPage);
}
sqliteDbFreePage(pDb, aPage[0], dblIndirPage);
sqlitePgUnref(dblIndirPage);
aPage += N_DIRECT;
first -= N_DIRECT;
last -= N_DIRECT;
if( last<0 ) return SQLITE_OK;
if( first<0 ) first = 0;
/* Free indirect overflow pages
*/
if( first < U32_PER_PAGE ){
u32 *indirPage;
rc = sqlitePgGet(pDb->pPgr, aPage[0], &indirPage);
if( rc!=SQLITE_OK ) return rc;
for(i=first; i<U32_PER_PAGE && i<=last; i++){
freePage(pDb, indirPage[i], 0);
indirPage[i] = 0;
touch = 1;
}
if( first<=0 ){
freepage(pDb, aPage[0], indirPage);
aPage[0] = 0;
}else{
sqlitePgTouch(indirPage);
sqlitePgUnref(indirPage);
}
}
aPage++;
first -= U32_PER_PAGE;
last -= U32_PER_PAGE;
if( last<0 ) return SQLITE_OK;
if( first<0 ) first = 0;
/* Free double-indirect overflow pages
*/
if( first < U32_PER_PAGE*U32_PER_PAGE ){
u32 *dblIndirPage;
rc = sqlitePgGet(pDb->pPgr, aPage[0], &dblIndirPage);
if( rc!=SQLITE_OK ) return rc;
for(i=first/U32_PER_PAGE; i<U32_PER_PAGE; i++){
u32 *indirPage;
basis = i*U32_PER_PAGE;
if( last < basis ) break;
rc = sqlitePgGet(pDb->pPgr, dblIndirPage[i], &indirPage);
if( rc!=SQLITE_OK ) return rc;
for(j=first>basis?first-basis:0 ; j<U32_PER_PAGE; j++){
if( j + basis > 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);
}
}
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; i<n; i++){
u32 subpgno = SWB(aPage[3+i*2]);
u32 subpgno = aPage[3+i*2];
sqliteDbDropPage(pDb, subpgno);
}
sqliteDbFreePage(pDb, pgno, aPage);
freePage(pDb, pgno, aPage);
break;
}
case BLOCK_MAGIC | BLOCK_LEAF: {
@ -648,18 +820,7 @@ static int sqliteDbDropPage(Db *pDb, u32 pgno){
sqliteDbClearEntry(pDb, &aPage[i]);
i += entrySize;
}
sqliteDbFreePage(pDb, pgno, aPage);
break;
}
case BLOCK_MAGIC | BLOCK_OVERFLOW: {
for(;;){
u32 nx = SWB(aPage[1]);
sqliteDbFreePage(pDb, pgno, aPage);
if( nx==0 ) break;
pgno = nx;
sqlitePgUnref(aPage);
sqlitePgGet(pDb->pPgr, 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);

View File

@ -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);

View File

@ -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 <assert.h>
#include <sys/types.h>
@ -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;
}