diff --git a/manifest b/manifest index 46adc64d72..18db763866 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reinsert\scode\sdeleted\sby\s(1998)\sthat\swe\sthought\swas\sunused\sbut\swas\sin\sfact\r\nneeded.\s\sFix\sfor\sticket\s#966.\s(CVS\s2025) -D 2004-10-19T16:40:59 +C Fix\salignment\sproblems\sin\sbtree\sand\spager\sand\sallow\spage\ssizes\sthat\sare\nnot\sa\smultiple\sof\s8.\s(CVS\s2026) +D 2004-10-22T16:22:58 F Makefile.in 52c1cc106cad9148d4b7cb387b458e82dc86b339 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -30,7 +30,7 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea -F src/btree.c bb3f8cadf65cc0752d07e219733a496c1aebe020 +F src/btree.c d8426846c0db61c97a0e3e11531781be7a96f1bc F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029 F src/build.c cb0232e0f239d7cea8598d982039b99259074f64 F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad @@ -53,7 +53,7 @@ F src/os_unix.c 5824b22ba41fe9d514ef9169aac1b5fde73af229 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c dc0ffab9941393b072e0b1f1f3de54830727cec9 +F src/pager.c cc2e7fb3d7913862d7b1170f923d2dcfdbac3bed F src/pager.h 774d1973acbda341827d21b0da0150575d69f7d9 F src/parse.y 8d97a91cba7e35b5eaac064c9f6e597dc6442b29 F src/pragma.c 3134201e4d47be04b9fcd437e01eab682ad3a096 @@ -154,7 +154,7 @@ F test/null.test 642428b6a5408cc5b954b49e1b6e5025e4458b2b F test/pager.test 394455707a079804e8a4e431d12edce831a065f0 F test/pager2.test c7e731ac56a2984a605b032ffd19b9deee820377 F test/pager3.test 16f546293bb751b8151dc17df613fca938bbec8b -F test/pagesize.test f8b46ec46b9fe9f708a8d757dda232588dfb7217 +F test/pagesize.test 56d11f4d6df9949d646bf87da1d6d995ed37cd78 F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57 F test/progress.test 5ddba78cb6011fba36093973cfb3ac473b8fb96a x @@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P 55b03c560d2f66c55d64c3e9f9577e33f8c63195 -R 462557c854f7b30b37ca39ec9dc0db3d +P 370ca539506a431dbe77dcb644215886760f34e9 +R 3144c4632ba02236b46866a5c5939839 U drh -Z e8f25bd39be0085dd77f02f0608ae8de +Z fbdbb4c36ca4011ce6bdf20082c190a3 diff --git a/manifest.uuid b/manifest.uuid index b23f520787..c4c24c6d99 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -370ca539506a431dbe77dcb644215886760f34e9 \ No newline at end of file +0539c2d2b8e16efcbe4db3afeae9c7b426e11b05 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a5bd886139..677e48c61f 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.192 2004/10/05 02:41:42 drh Exp $ +** $Id: btree.c,v 1.193 2004/10/22 16:22:58 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -211,6 +211,11 @@ #include "os.h" #include +/* +** This macro rounds values up so that if the value is an address it +** is guaranteed to be an address that is aligned to an 8-byte boundary. +*/ +#define FORCE_ALIGNMENT(X) (((X)+7)&~7) /* The following value is the maximum cell size assuming a maximum page ** size give above. @@ -300,6 +305,7 @@ struct Btree { u8 minLeafFrac; /* Minimum leaf payload as % of total page size */ u8 pageSizeFixed; /* True if the page size can no longer be changed */ u16 pageSize; /* Total number of bytes on a page */ + u16 psAligned; /* pageSize rounded up to a multiple of 8 */ u16 usableSize; /* Number of usable bytes on each page */ int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ int minLocal; /* Minimum local payload in non-LEAFDATA tables */ @@ -533,7 +539,7 @@ static void _pageIntegrity(MemPage *pPage){ used = sqliteMallocRaw( pPage->pBt->pageSize ); if( used==0 ) return; usableSize = pPage->pBt->usableSize; - assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] ); + assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->psAligned] ); hdr = pPage->hdrOffset; assert( hdr==(pPage->pgno==1 ? 100 : 0) ); assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); @@ -837,7 +843,7 @@ static int initPage( assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); - assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); + assert( pPage->aData == &((unsigned char*)pPage)[-pBt->psAligned] ); if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ /* The parent page should never change unless the file is corrupt */ return SQLITE_CORRUPT; /* bkpt-CORRUPT */ @@ -910,7 +916,7 @@ static void zeroPage(MemPage *pPage, int flags){ int first; assert( sqlite3pager_pagenumber(data)==pPage->pgno ); - assert( &data[pBt->pageSize] == (unsigned char*)pPage ); + assert( &data[pBt->psAligned] == (unsigned char*)pPage ); assert( sqlite3pager_iswriteable(data) ); memset(&data[hdr], 0, pBt->usableSize - hdr); data[hdr] = flags; @@ -939,7 +945,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ MemPage *pPage; rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData); if( rc ) return rc; - pPage = (MemPage*)&aData[pBt->pageSize]; + pPage = (MemPage*)&aData[pBt->psAligned]; pPage->aData = aData; pPage->pBt = pBt; pPage->pgno = pgno; @@ -978,7 +984,7 @@ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); - assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); + assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage ); sqlite3pager_unref(pPage->aData); } } @@ -989,7 +995,7 @@ static void releasePage(MemPage *pPage){ ** happens. */ static void pageDestructor(void *pData, int pageSize){ - MemPage *pPage = (MemPage*)&((char*)pData)[pageSize]; + MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)]; if( pPage->pParent ){ MemPage *pParent = pPage->pParent; pPage->pParent = 0; @@ -1007,7 +1013,7 @@ static void pageDestructor(void *pData, int pageSize){ ** page to agree with the restored data. */ static void pageReinit(void *pData, int pageSize){ - MemPage *pPage = (MemPage*)&((char*)pData)[pageSize]; + MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)]; if( pPage->isInit ){ pPage->isInit = 0; initPage(pPage, pPage->pParent); @@ -1078,6 +1084,7 @@ int sqlite3BtreeOpen( pBt->pageSizeFixed = 1; } pBt->usableSize = pBt->pageSize - nReserve; + pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize); sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); *ppBtree = pBt; return SQLITE_OK; @@ -1148,6 +1155,7 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ } if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ){ pBt->pageSize = pageSize; + pBt->psAligned = FORCE_ALIGNMENT(pageSize); sqlite3pager_set_pagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; @@ -1199,6 +1207,7 @@ static int lockBtree(Btree *pBt){ if( pBt->usableSize<500 ){ goto page1_init_failed; } + pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize); pBt->maxEmbedFrac = page1[21]; pBt->minEmbedFrac = page1[22]; pBt->minLeafFrac = page1[23]; @@ -1248,7 +1257,7 @@ static void unlockBtreeIfUnused(Btree *pBt){ if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ if( pBt->pPage1->aData==0 ){ MemPage *pPage = pBt->pPage1; - pPage->aData = &((char*)pPage)[-pBt->pageSize]; + pPage->aData = &((char*)pPage)[-pBt->psAligned]; pPage->pBt = pBt; pPage->pgno = 1; } @@ -2673,7 +2682,7 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ assert( pBt->pPager!=0 ); aData = sqlite3pager_lookup(pBt->pPager, pgno); if( aData ){ - pThis = (MemPage*)&aData[pBt->pageSize]; + pThis = (MemPage*)&aData[pBt->psAligned]; assert( pThis->aData==aData ); if( pThis->isInit ){ if( pThis->pParent!=pNewParent ){ @@ -2960,7 +2969,7 @@ static int balance_nonroot(MemPage *pPage){ apCell = sqliteMallocRaw( (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int)) + sizeof(MemPage)*NB - + pBt->pageSize*(5+NB) + + pBt->psAligned*(5+NB) ); if( apCell==0 ){ return SQLITE_NOMEM; @@ -2968,9 +2977,9 @@ static int balance_nonroot(MemPage *pPage){ szCell = (int*)&apCell[(mxCellPerPage+2)*NB]; aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB]; for(i=1; ipageSize+sizeof(MemPage)]; + aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)]; } - aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)]; + aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)]; /* ** Find the cell in the parent page whose left child points back @@ -3041,10 +3050,10 @@ static int balance_nonroot(MemPage *pPage){ ** process of being overwritten. */ for(i=0; ipageSize]; - p->aData = &((u8*)p)[-pBt->pageSize]; - memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage)); - p->aData = &((u8*)p)[-pBt->pageSize]; + MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->psAligned]; + p->aData = &((u8*)p)[-pBt->psAligned]; + memcpy(p->aData, apOld[i]->aData, pBt->psAligned + sizeof(MemPage)); + p->aData = &((u8*)p)[-pBt->psAligned]; } /* @@ -3088,7 +3097,7 @@ static int balance_nonroot(MemPage *pPage){ szCell[nCell] = sz; pTemp = &aSpace[iSpace]; iSpace += sz; - assert( iSpace<=pBt->pageSize*5 ); + assert( iSpace<=pBt->psAligned*5 ); memcpy(pTemp, apDiv[i], sz); apCell[nCell] = pTemp+leafCorrection; dropCell(pParent, nxDiv, sz); @@ -3272,13 +3281,13 @@ static int balance_nonroot(MemPage *pPage){ pCell = &aSpace[iSpace]; fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz); iSpace += sz; - assert( iSpace<=pBt->pageSize*5 ); + assert( iSpace<=pBt->psAligned*5 ); pTemp = 0; }else{ pCell -= 4; pTemp = &aSpace[iSpace]; iSpace += sz; - assert( iSpace<=pBt->pageSize*5 ); + assert( iSpace<=pBt->psAligned*5 ); } insertCell(pParent, nxDiv, pCell, sz, pTemp); put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); diff --git a/src/pager.c b/src/pager.c index cf0da5200d..fe06e2a4b3 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.167 2004/10/05 02:41:43 drh Exp $ +** @(#) $Id: pager.c,v 1.168 2004/10/22 16:22:59 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -110,6 +110,12 @@ # define SQLITE_BUSY_RESERVED_LOCK 0 #endif +/* +** This macro rounds values up so that if the value is an address it +** is guaranteed to be an address that is aligned to an 8-byte boundary. +*/ +#define FORCE_ALIGNMENT(X) (((X)+7)&~7) + /* ** Each in-memory image of a page begins with the following header. ** This header is only visible to this pager module. The client @@ -143,7 +149,7 @@ struct PgHdr { u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ - /* pPager->pageSize bytes of page data follow this header */ + /* pPager->psAligned bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; @@ -179,9 +185,9 @@ struct PgHistory { */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) -#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned]) #define PGHDR_TO_HIST(P,PGR) \ - ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) + ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra]) /* ** How big to make the hash table used for locating in-memory pages @@ -214,6 +220,7 @@ struct Pager { void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ int pageSize; /* Number of bytes in a page */ + int psAligned; /* pageSize rounded up to a multiple of 8 */ 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 */ @@ -1503,6 +1510,7 @@ int sqlite3pager_open( pPager->nRef = 0; pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; + pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize); pPager->stmtSize = 0; pPager->stmtJSize = 0; pPager->nPage = 0; @@ -1518,7 +1526,7 @@ int sqlite3pager_open( pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; - pPager->nExtra = nExtra; + pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; pPager->pBusyHandler = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); @@ -1564,6 +1572,7 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); pPager->pageSize = pageSize; + pPager->psAligned = FORCE_ALIGNMENT(pageSize); } /* @@ -2133,7 +2142,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPager->nMiss++; if( pPager->nPagemxPage || pPager->pFirst==0 || pPager->memDb ){ /* Create a new page */ - pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned + sizeof(u32) + pPager->nExtra + pPager->memDb*sizeof(PgHistory) ); if( pPg==0 ){ diff --git a/test/pagesize.test b/test/pagesize.test index f794a8f45b..7fe6b8b509 100644 --- a/test/pagesize.test +++ b/test/pagesize.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. # This file implements tests for the page_size PRAGMA. # -# $Id: pagesize.test,v 1.3 2004/09/05 00:33:44 drh Exp $ +# $Id: pagesize.test,v 1.4 2004/10/22 16:22:59 drh Exp $ set testdir [file dirname $argv0] @@ -61,7 +61,7 @@ do_test pagesize-1.7 { -foreach PGSZ {512 2000 2048 3000 4096} { +foreach PGSZ {512 515 516 751 2000 2001 2002 2003 2004 2048 3000 4096} { do_test pagesize-2.$PGSZ.1 { db close file delete -force test.db