]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimental change to the pcache interface to allow page buffers to be allocated...
authordan <dan@noemail.net>
Tue, 8 Nov 2011 20:08:44 +0000 (20:08 +0000)
committerdan <dan@noemail.net>
Tue, 8 Nov 2011 20:08:44 +0000 (20:08 +0000)
FossilOrigin-Name: c275c9d323cb1dccb031b199d413ac3a0b244fea

12 files changed:
manifest
manifest.uuid
src/global.c
src/main.c
src/pcache.c
src/pcache.h
src/pcache1.c
src/sqlite.h.in
src/sqliteInt.h
src/test_init.c
src/test_pcache.c
test/memsubsys1.test

index 4ac21d9d508dd4ad017c70d207dab7b6e0cad26b..e2c1f417592b008849ab8f68793fd4b02dfad867 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\sthe\sunix\sVFS\stolerant\sof\sread()\scalls\sthat\sreturn\sless\sthan\sthe\nrequested\snumber\sof\sbytes.
-D 2011-11-07T18:16:00.449
+C Experimental\schange\sto\sthe\spcache\sinterface\sto\sallow\spage\sbuffers\sto\sbe\sallocated\sseparately\sfrom\stheir\sassociated\scontainer\sstructures.
+D 2011-11-08T20:08:44.098
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -138,7 +138,7 @@ F src/expr.c fbf116f90cabc917ae50bba24a73a0b55519a0c8
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
 F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
-F src/global.c e230227de13601714b29f9363028514aada5ae2f
+F src/global.c 107ccaacb4b30895cf3a3a39decf417c804acfa1
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -147,7 +147,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
 F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f
-F src/main.c df06f5229b8046f85dde253dfd7fe35ae9e4902e
+F src/main.c 93d49bc6abf4ccea97721d016b9f45228cff7057
 F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
@@ -171,9 +171,9 @@ F src/os_win.c 49d418916428a59d773f39993db0ecde56ab4c37
 F src/pager.c db33d4bf1e3e019c34c220971cc6c3aa07c30f54
 F src/pager.h 9f81b08efb06db4ba8be69446e10b005c351373d
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
-F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce
-F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
-F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197
+F src/pcache.c fad8646667e074d06e29028029a0440d852497e5
+F src/pcache.h c770382f9fae4ca5025c5523bd0aa13cd6ddc6f8
+F src/pcache1.c 54fc4ed623157b6f706da961c1d3776a40aa131d
 F src/pragma.c da8ef96b3eec351e81e0061c39810e548bcc96d7
 F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
 F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869
@@ -182,9 +182,9 @@ F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
 F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
 F src/shell.c 6d2ad7f80adc9c8c3195412879af36eb3196c1b6
-F src/sqlite.h.in b7a4e8d428e467d820cbb4c1d275fdda88b4d7ab
+F src/sqlite.h.in c436f15dd27782e83d532651394c41fe4b96d1b0
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
-F src/sqliteInt.h b0b6df8f7fe739e3cd718debb60f58853666d13e
+F src/sqliteInt.h f87f241b9821a9d466c2711b7345d30ef3624249
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -208,7 +208,7 @@ F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
 F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
 F src/test_fuzzer.c f884f6f32e8513d34248d6e1ac8a32047fead254
 F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
-F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
+F src/test_init.c 1ff3a696ca45e3c4cd7639217ded5d9c41428fed
 F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
 F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
 F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
@@ -219,7 +219,7 @@ F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
 F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
 F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
-F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
+F src/test_pcache.c 708147942470815963efa7a58fe63470a1943a5e
 F src/test_quota.c a391c866217e92986c6f523f05b08aa6956c8419
 F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1
 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
@@ -592,7 +592,7 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
 F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
 F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6
 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
-F test/memsubsys1.test 16ce163ac1ace3d71bf0eaa6a821ed153addd91f
+F test/memsubsys1.test c0db8a1e99f4fa07cb858900c55bad9547899aa8
 F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
 F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
 F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
@@ -974,7 +974,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 4fe5b73115a8b44950767f1b528107261d7312c9
-R 235506ff1af96e54491bff797f85e25a
-U drh
-Z b43cdd5d2255740ef7ed4b6994dd0923
+P a210695abcfa5cb04279edfd04824d881b7c4ada
+R 753cd5b3a540b0935d5201e586350091
+T *branch * experimental-pcache
+T *sym-experimental-pcache *
+T -sym-trunk *
+U dan
+Z 65dd88e6b6c81cfeaddd0d87f1e89623
index 26a58694303178edfc4510fc692470f887d37a5f..9631c1e9b150c0326a31fbb805ae9f3ce69d3aba 100644 (file)
@@ -1 +1 @@
-a210695abcfa5cb04279edfd04824d881b7c4ada
\ No newline at end of file
+c275c9d323cb1dccb031b199d413ac3a0b244fea
\ No newline at end of file
index 1e691c44942353fac158a82c61a9c61ceaf036f4..b8a8a49d3df028c9b5fdb457b0c9984a9d5bba89 100644 (file)
@@ -147,7 +147,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    500,                       /* nLookaside */
    {0,0,0,0,0,0,0,0},         /* m */
    {0,0,0,0,0,0,0,0,0},       /* mutex */
-   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
+   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache2 */
    (void*)0,                  /* pHeap */
    0,                         /* nHeap */
    0, 0,                      /* mnHeap, mxHeap */
index 42bbba5d017736e196fb3b2982b582332ed5f840..6e6af78c7a46b47553bff821aa058c9281842b75 100644 (file)
@@ -365,16 +365,25 @@ int sqlite3_config(int op, ...){
     }
 
     case SQLITE_CONFIG_PCACHE: {
-      /* Specify an alternative page cache implementation */
-      sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*);
+      /* no-op */
       break;
     }
-
     case SQLITE_CONFIG_GETPCACHE: {
-      if( sqlite3GlobalConfig.pcache.xInit==0 ){
+      /* now an error */
+      rc = SQLITE_ERROR;
+      break;
+    }
+
+    case SQLITE_CONFIG_PCACHE2: {
+      /* Specify an alternative page cache implementation */
+      sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*);
+      break;
+    }
+    case SQLITE_CONFIG_GETPCACHE2: {
+      if( sqlite3GlobalConfig.pcache2.xInit==0 ){
         sqlite3PCacheSetDefault();
       }
-      *va_arg(ap, sqlite3_pcache_methods*) = sqlite3GlobalConfig.pcache;
+      *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2;
       break;
     }
 
index f37511e9e44247523e75161a96349bd602bd2064..f689aaa77f2df30a9a534818d2cb725f5472f257 100644 (file)
@@ -131,7 +131,7 @@ static void pcacheUnpin(PgHdr *p){
     if( p->pgno==1 ){
       pCache->pPage1 = 0;
     }
-    sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 0);
+    sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
   }
 }
 
@@ -141,18 +141,18 @@ static void pcacheUnpin(PgHdr *p){
 ** functions are threadsafe.
 */
 int sqlite3PcacheInitialize(void){
-  if( sqlite3GlobalConfig.pcache.xInit==0 ){
+  if( sqlite3GlobalConfig.pcache2.xInit==0 ){
     /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
     ** built-in default page cache is used instead of the application defined
     ** page cache. */
     sqlite3PCacheSetDefault();
   }
-  return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg);
+  return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
 }
 void sqlite3PcacheShutdown(void){
-  if( sqlite3GlobalConfig.pcache.xShutdown ){
+  if( sqlite3GlobalConfig.pcache2.xShutdown ){
     /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
-    sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg);
+    sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
   }
 }
 
@@ -191,7 +191,7 @@ void sqlite3PcacheOpen(
 void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
   assert( pCache->nRef==0 && pCache->pDirty==0 );
   if( pCache->pCache ){
-    sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
+    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
     pCache->pCache = 0;
     pCache->pPage1 = 0;
   }
@@ -207,7 +207,8 @@ int sqlite3PcacheFetch(
   int createFlag,       /* If true, create page if it does not exist already */
   PgHdr **ppPage        /* Write the page here */
 ){
-  PgHdr *pPage = 0;
+  sqlite3_pcache_page *pPage = 0;
+  PgHdr *pPgHdr = 0;
   int eCreate;
 
   assert( pCache!=0 );
@@ -219,19 +220,19 @@ int sqlite3PcacheFetch(
   */
   if( !pCache->pCache && createFlag ){
     sqlite3_pcache *p;
-    int nByte;
-    nByte = pCache->szPage + pCache->szExtra + sizeof(PgHdr);
-    p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache->bPurgeable);
+    p = sqlite3GlobalConfig.pcache2.xCreate(
+        pCache->szExtra + sizeof(PgHdr), pCache->szPage, pCache->bPurgeable
+    );
     if( !p ){
       return SQLITE_NOMEM;
     }
-    sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax);
+    sqlite3GlobalConfig.pcache2.xCachesize(p, pCache->nMax);
     pCache->pCache = p;
   }
 
   eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
   if( pCache->pCache ){
-    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate);
+    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
   }
 
   if( !pPage && eCreate==1 ){
@@ -266,33 +267,36 @@ int sqlite3PcacheFetch(
       }
     }
 
-    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
+    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
   }
 
   if( pPage ){
-    if( !pPage->pData ){
-      memset(pPage, 0, sizeof(PgHdr));
-      pPage->pData = (void *)&pPage[1];
-      pPage->pExtra = (void*)&((char *)pPage->pData)[pCache->szPage];
-      memset(pPage->pExtra, 0, pCache->szExtra);
-      pPage->pCache = pCache;
-      pPage->pgno = pgno;
+    pPgHdr = (PgHdr *)pPage->pExtra;
+
+    if( !pPgHdr->pPage ){
+      memset(pPgHdr, 0, sizeof(PgHdr));
+      pPgHdr->pPage = pPage;
+      pPgHdr->pData = pPage->pBuf;
+      pPgHdr->pExtra = (void *)&pPgHdr[1];
+      memset(pPgHdr->pExtra, 0, pCache->szExtra);
+      pPgHdr->pCache = pCache;
+      pPgHdr->pgno = pgno;
     }
-    assert( pPage->pCache==pCache );
-    assert( pPage->pgno==pgno );
-    assert( pPage->pData==(void *)&pPage[1] );
-    assert( pPage->pExtra==(void *)&((char *)&pPage[1])[pCache->szPage] );
+    assert( pPgHdr->pCache==pCache );
+    assert( pPgHdr->pgno==pgno );
+    assert( pPgHdr->pData==pPage->pBuf );
+    assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
 
-    if( 0==pPage->nRef ){
+    if( 0==pPgHdr->nRef ){
       pCache->nRef++;
     }
-    pPage->nRef++;
+    pPgHdr->nRef++;
     if( pgno==1 ){
-      pCache->pPage1 = pPage;
+      pCache->pPage1 = pPgHdr;
     }
   }
-  *ppPage = pPage;
-  return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
+  *ppPage = pPgHdr;
+  return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
 }
 
 /*
@@ -339,7 +343,7 @@ void sqlite3PcacheDrop(PgHdr *p){
   if( p->pgno==1 ){
     pCache->pPage1 = 0;
   }
-  sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 1);
+  sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
 }
 
 /*
@@ -397,7 +401,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
   PCache *pCache = p->pCache;
   assert( p->nRef>0 );
   assert( newPgno>0 );
-  sqlite3GlobalConfig.pcache.xRekey(pCache->pCache, p, p->pgno, newPgno);
+  sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
   p->pgno = newPgno;
   if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
     pcacheRemoveFromDirtyList(p);
@@ -434,7 +438,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
       memset(pCache->pPage1->pData, 0, pCache->szPage);
       pgno = 1;
     }
-    sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1);
+    sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
   }
 }
 
@@ -443,7 +447,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
 */
 void sqlite3PcacheClose(PCache *pCache){
   if( pCache->pCache ){
-    sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
+    sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
   }
 }
 
@@ -555,7 +559,7 @@ int sqlite3PcachePageRefcount(PgHdr *p){
 int sqlite3PcachePagecount(PCache *pCache){
   int nPage = 0;
   if( pCache->pCache ){
-    nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache);
+    nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
   }
   return nPage;
 }
@@ -575,7 +579,7 @@ int sqlite3PcacheGetCachesize(PCache *pCache){
 void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
   pCache->nMax = mxPage;
   if( pCache->pCache ){
-    sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage);
+    sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, mxPage);
   }
 }
 
index 33735d2cbb2dc159ca988e91f90b8658f91e5394..c4a25b251f2fabdf016c6a3736f9249f29497470 100644 (file)
@@ -23,7 +23,8 @@ typedef struct PCache PCache;
 ** structure.
 */
 struct PgHdr {
-  void *pData;                   /* Content of this page */
+  sqlite3_pcache_page *pPage;    /* Pcache object page handle */
+  void *pData;                   /* Page data */
   void *pExtra;                  /* Extra content */
   PgHdr *pDirty;                 /* Transient list of dirty pages */
   Pgno pgno;                     /* Page number for this page */
index 077a7b2168079a6f054572b2a8b03a84ec0574f9..f94241f5ee262bb250cffe2a494f0dc25762c070 100644 (file)
@@ -72,6 +72,7 @@ struct PCache1 {
   */
   PGroup *pGroup;                     /* PGroup this cache belongs to */
   int szPage;                         /* Size of allocated pages in bytes */
+  int szExtra;                        /* Size of extra space in bytes */
   int bPurgeable;                     /* True if cache is purgeable */
   unsigned int nMin;                  /* Minimum number of pages reserved */
   unsigned int nMax;                  /* Configured "cache_size" value */
@@ -90,11 +91,12 @@ struct PCache1 {
 
 /*
 ** Each cache entry is represented by an instance of the following 
-** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated 
-** directly before this structure in memory (see the PGHDR1_TO_PAGE() 
-** macro below).
+** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
+** PgHdr1.pCache->szPage bytes is allocated directly before this structure 
+** in memory.
 */
 struct PgHdr1 {
+  sqlite3_pcache_page page;
   unsigned int iKey;             /* Key value (page number) */
   PgHdr1 *pNext;                 /* Next in hash table chain */
   PCache1 *pCache;               /* Cache that currently owns this page */
@@ -144,21 +146,6 @@ static SQLITE_WSD struct PCacheGlobal {
 */
 #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
 
-/*
-** When a PgHdr1 structure is allocated, the associated PCache1.szPage
-** bytes of data are located directly before it in memory (i.e. the total
-** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The
-** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as
-** an argument and returns a pointer to the associated block of szPage
-** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is
-** a pointer to a block of szPage bytes of data and the return value is
-** a pointer to the associated PgHdr1 structure.
-**
-**   assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
-*/
-#define PGHDR1_TO_PAGE(p)    (void*)(((char*)p) - p->pCache->szPage)
-#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
-
 /*
 ** Macros to enter and leave the PCache LRU mutex.
 */
@@ -288,7 +275,6 @@ static int pcache1MemSize(void *p){
 ** Allocate a new page object initially associated with cache pCache.
 */
 static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
-  int nByte = sizeof(PgHdr1) + pCache->szPage;
   PgHdr1 *p = 0;
   void *pPg;
 
@@ -297,16 +283,29 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
   ** this mutex is not held. */
   assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
   pcache1LeaveMutex(pCache->pGroup);
-  pPg = pcache1Alloc(nByte);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+  pPg = pcache1Alloc(pCache->szPage);
+  p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
+  if( !pPg || !p ){
+    pcache1Free(pPg);
+    sqlite3_free(p);
+    pPg = 0;
+  }
+#else
+  pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
+  p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+#endif
   pcache1EnterMutex(pCache->pGroup);
 
   if( pPg ){
-    p = PAGE_TO_PGHDR1(pCache, pPg);
+    p->page.pBuf = pPg;
+    p->page.pExtra = &p[1];
     if( pCache->bPurgeable ){
       pCache->pGroup->nCurrentPage++;
     }
+    return p;
   }
-  return p;
+  return 0;
 }
 
 /*
@@ -320,7 +319,10 @@ static void pcache1FreePage(PgHdr1 *p){
   if( ALWAYS(p) ){
     PCache1 *pCache = p->pCache;
     assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
-    pcache1Free(PGHDR1_TO_PAGE(p));
+    pcache1Free(p->page.pBuf);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+    sqlite3_free(p);
+#endif
     if( pCache->bPurgeable ){
       pCache->pGroup->nCurrentPage--;
     }
@@ -361,7 +363,7 @@ void sqlite3PageFree(void *p){
 ** the heap even further.
 */
 static int pcache1UnderMemoryPressure(PCache1 *pCache){
-  if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){
+  if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
     return pcache1.bUnderPressure;
   }else{
     return sqlite3HeapNearlyFull();
@@ -552,7 +554,7 @@ static void pcache1Shutdown(void *NotUsed){
 **
 ** Allocate a new cache.
 */
-static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
+static sqlite3_pcache *pcache1Create(int szExtra, int szPage, int bPurgeable){
   PCache1 *pCache;      /* The newly created page cache */
   PGroup *pGroup;       /* The group the new page cache will belong to */
   int sz;               /* Bytes of memory required to allocate the new cache */
@@ -587,6 +589,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
     }
     pCache->pGroup = pGroup;
     pCache->szPage = szPage;
+    pCache->szExtra = szExtra;
     pCache->bPurgeable = (bPurgeable ? 1 : 0);
     if( bPurgeable ){
       pCache->nMin = 10;
@@ -684,7 +687,11 @@ static int pcache1Pagecount(sqlite3_pcache *p){
 **
 **   5. Otherwise, allocate and return a new page buffer.
 */
-static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
+static sqlite3_pcache_page *pcache1Fetch(
+  sqlite3_pcache *p, 
+  unsigned int iKey, 
+  int createFlag
+){
   int nPinned;
   PCache1 *pCache = (PCache1 *)p;
   PGroup *pGroup;
@@ -719,7 +726,6 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
   pGroup = pCache->pGroup;
 #endif
 
-
   /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
   nPinned = pCache->nPage - pCache->nRecyclable;
   assert( nPinned>=0 );
@@ -747,12 +753,13 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
     pPage = pGroup->pLruTail;
     pcache1RemoveFromHash(pPage);
     pcache1PinPage(pPage);
-    if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage ){
+    if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage 
+     || pOtherCache->szExtra!=pCache->szExtra 
+    ){
       pcache1FreePage(pPage);
       pPage = 0;
     }else{
-      pGroup->nCurrentPage -= 
-               (pOtherCache->bPurgeable - pCache->bPurgeable);
+      pGroup->nCurrentPage -= (pOtherCache->bPurgeable - pCache->bPurgeable);
     }
   }
 
@@ -773,7 +780,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
     pPage->pCache = pCache;
     pPage->pLruPrev = 0;
     pPage->pLruNext = 0;
-    *(void **)(PGHDR1_TO_PAGE(pPage)) = 0;
+    *(void **)pPage->page.pExtra = 0;
     pCache->apHash[h] = pPage;
   }
 
@@ -782,7 +789,7 @@ fetch_out:
     pCache->iMaxKey = iKey;
   }
   pcache1LeaveMutex(pGroup);
-  return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);
+  return &pPage->page;
 }
 
 
@@ -791,9 +798,13 @@ fetch_out:
 **
 ** Mark a page as unpinned (eligible for asynchronous recycling).
 */
-static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
+static void pcache1Unpin(
+  sqlite3_pcache *p, 
+  sqlite3_pcache_page *pPg, 
+  int reuseUnlikely
+){
   PCache1 *pCache = (PCache1 *)p;
-  PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
+  PgHdr1 *pPage = (PgHdr1 *)pPg;
   PGroup *pGroup = pCache->pGroup;
  
   assert( pPage->pCache==pCache );
@@ -829,12 +840,12 @@ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
 */
 static void pcache1Rekey(
   sqlite3_pcache *p,
-  void *pPg,
+  sqlite3_pcache_page *pPg,
   unsigned int iOld,
   unsigned int iNew
 ){
   PCache1 *pCache = (PCache1 *)p;
-  PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
+  PgHdr1 *pPage = (PgHdr1 *)pPg;
   PgHdr1 **pp;
   unsigned int h; 
   assert( pPage->iKey==iOld );
@@ -903,7 +914,7 @@ static void pcache1Destroy(sqlite3_pcache *p){
 ** already provided an alternative.
 */
 void sqlite3PCacheSetDefault(void){
-  static const sqlite3_pcache_methods defaultMethods = {
+  static const sqlite3_pcache_methods2 defaultMethods = {
     0,                       /* pArg */
     pcache1Init,             /* xInit */
     pcache1Shutdown,         /* xShutdown */
@@ -916,7 +927,7 @@ void sqlite3PCacheSetDefault(void){
     pcache1Truncate,         /* xTruncate */
     pcache1Destroy           /* xDestroy */
   };
-  sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods);
+  sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
 }
 
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -937,7 +948,10 @@ int sqlite3PcacheReleaseMemory(int nReq){
     PgHdr1 *p;
     pcache1EnterMutex(&pcache1.grp);
     while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
-      nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));
+      nFree += pcache1MemSize(p->page.pBuf);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+      nFree += sqlite3MemSize(p);
+#endif
       pcache1PinPage(p);
       pcache1RemoveFromHash(p);
       pcache1FreePage(p);
index 9679965ce29362c7771f94b3e3c630eb78942343..d3dc86120b570d96d2ecbd761d7a6f7c131c3546 100644 (file)
@@ -1497,6 +1497,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
 #define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
 #define SQLITE_CONFIG_URI          17  /* int */
+#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -6097,6 +6099,27 @@ struct sqlite3_pcache_methods {
   void (*xDestroy)(sqlite3_pcache*);
 };
 
+typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
+typedef struct sqlite3_pcache_page sqlite3_pcache_page;
+struct sqlite3_pcache_page {
+  void *pBuf;
+  void *pExtra;
+};
+struct sqlite3_pcache_methods2 {
+  void *pArg;
+  int (*xInit)(void*);
+  void (*xShutdown)(void*);
+  sqlite3_pcache *(*xCreate)(int szExtra, int szPage, int bPurgeable);
+  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+  int (*xPagecount)(sqlite3_pcache*);
+  sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+  void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
+  void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, 
+      unsigned oldKey, unsigned newKey);
+  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+  void (*xDestroy)(sqlite3_pcache*);
+};
+
 /*
 ** CAPI3REF: Online Backup Object
 **
index 2171c15749693ad31fd42f9be316b3b0431b8436..46bec6a30936be9926e9b1946f58c7979a2bda02 100644 (file)
@@ -2459,7 +2459,7 @@ struct Sqlite3Config {
   int nLookaside;                   /* Default lookaside buffer count */
   sqlite3_mem_methods m;            /* Low-level memory allocation interface */
   sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
-  sqlite3_pcache_methods pcache;    /* Low-level page-cache interface */
+  sqlite3_pcache_methods2 pcache2;  /* Low-level page-cache interface */
   void *pHeap;                      /* Heap storage space */
   int nHeap;                        /* Size of pHeap[] */
   int mnReq, mxReq;                 /* Min and max heap requests sizes */
index a67b6788abf753c552a046294790156d8cefb532..7741cd19e7070c87cdd4f9f45043195a8a40d11e 100644 (file)
@@ -30,9 +30,9 @@
 #include <tcl.h>
 
 static struct Wrapped {
-  sqlite3_pcache_methods pcache;
-  sqlite3_mem_methods    mem;
-  sqlite3_mutex_methods  mutex;
+  sqlite3_pcache_methods2 pcache;
+  sqlite3_mem_methods     mem;
+  sqlite3_mutex_methods   mutex;
 
   int mem_init;                /* True if mem subsystem is initalized */
   int mem_fail;                /* True to fail mem subsystem inialization */
@@ -123,8 +123,8 @@ static void wrPCacheShutdown(void *pArg){
   wrapped.pcache_init = 0;
 }
 
-static sqlite3_pcache *wrPCacheCreate(int a, int b){
-  return wrapped.pcache.xCreate(a, b);
+static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){
+  return wrapped.pcache.xCreate(a, b, c);
 }  
 static void wrPCacheCachesize(sqlite3_pcache *p, int n){
   wrapped.pcache.xCachesize(p, n);
@@ -132,13 +132,18 @@ static void wrPCacheCachesize(sqlite3_pcache *p, int n){
 static int wrPCachePagecount(sqlite3_pcache *p){
   return wrapped.pcache.xPagecount(p);
 }  
-static void *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
+static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
   return wrapped.pcache.xFetch(p, a, b);
 }  
-static void wrPCacheUnpin(sqlite3_pcache *p, void *a, int b){
+static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
   wrapped.pcache.xUnpin(p, a, b);
 }  
-static void wrPCacheRekey(sqlite3_pcache *p, void *a, unsigned b, unsigned c){
+static void wrPCacheRekey(
+  sqlite3_pcache *p, 
+  sqlite3_pcache_page *a, 
+  unsigned b, 
+  unsigned c
+){
   wrapped.pcache.xRekey(p, a, b, c);
 }  
 static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
@@ -154,7 +159,7 @@ static void installInitWrappers(void){
     wrMutexFree,  wrMutexEnter, wrMutexTry,
     wrMutexLeave, wrMutexHeld,  wrMutexNotheld
   };
-  sqlite3_pcache_methods pcachemethods = {
+  sqlite3_pcache_methods2 pcachemethods = {
     0,
     wrPCacheInit,      wrPCacheShutdown,  wrPCacheCreate, 
     wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
@@ -173,10 +178,10 @@ static void installInitWrappers(void){
   sqlite3_shutdown();
   sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
   sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
-  sqlite3_config(SQLITE_CONFIG_GETPCACHE, &wrapped.pcache);
+  sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);
   sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
   sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
-  sqlite3_config(SQLITE_CONFIG_PCACHE, &pcachemethods);
+  sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);
 }
 
 static int init_wrapper_install(
@@ -218,7 +223,7 @@ static int init_wrapper_uninstall(
   sqlite3_shutdown();
   sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
   sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
-  sqlite3_config(SQLITE_CONFIG_PCACHE, &wrapped.pcache);
+  sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
   return TCL_OK;
 }
 
index 98aa1367aa19aa756ca315c449c4d598512f2b90..1b8424d10ff4a6e85c031b034d8e43e5ad89c097 100644 (file)
@@ -100,15 +100,16 @@ static void testpcacheShutdown(void *pArg){
 typedef struct testpcache testpcache;
 struct testpcache {
   int szPage;               /* Size of each page.  Multiple of 8. */
+  int szExtra;              /* Size of extra data that accompanies each page */
   int bPurgeable;           /* True if the page cache is purgeable */
   int nFree;                /* Number of unused slots in a[] */
   int nPinned;              /* Number of pinned slots in a[] */
   unsigned iRand;           /* State of the PRNG */
   unsigned iMagic;          /* Magic number for sanity checking */
   struct testpcachePage {
+    sqlite3_pcache_page page;  /* Base class */
     unsigned key;              /* The key for this page. 0 means unallocated */
     int isPinned;              /* True if the page is pinned */
-    void *pData;               /* Data for this page */
   } a[TESTPCACHE_NPAGE];    /* All pages in the cache */
 };
 
@@ -129,27 +130,33 @@ static unsigned testpcacheRandom(testpcache *p){
 /*
 ** Allocate a new page cache instance.
 */
-static sqlite3_pcache *testpcacheCreate(int szPage, int bPurgeable){
+static sqlite3_pcache *testpcacheCreate(
+  int szExtra, 
+  int szPage, 
+  int bPurgeable
+){
   int nMem;
   char *x;
   testpcache *p;
   int i;
   assert( testpcacheGlobal.pDummy!=0 );
   szPage = (szPage+7)&~7;
-  nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*szPage;
+  nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra);
   p = sqlite3_malloc( nMem );
   if( p==0 ) return 0;
   x = (char*)&p[1];
   p->szPage = szPage;
+  p->szExtra = szExtra;
   p->nFree = TESTPCACHE_NPAGE;
   p->nPinned = 0;
   p->iRand = testpcacheGlobal.prngSeed;
   p->bPurgeable = bPurgeable;
   p->iMagic = TESTPCACHE_VALID;
-  for(i=0; i<TESTPCACHE_NPAGE; i++, x += szPage){
+  for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){
     p->a[i].key = 0;
     p->a[i].isPinned = 0;
-    p->a[i].pData = (void*)x;
+    p->a[i].page.pBuf = (void*)x;
+    p->a[i].page.pExtra = (void*)&x[szPage];
   }
   testpcacheGlobal.nInstance++;
   return (sqlite3_pcache*)p;
@@ -181,7 +188,7 @@ static int testpcachePagecount(sqlite3_pcache *pCache){
 /*
 ** Fetch a page.
 */
-static void *testpcacheFetch(
+static sqlite3_pcache_page *testpcacheFetch(
   sqlite3_pcache *pCache,
   unsigned key,
   int createFlag
@@ -200,7 +207,7 @@ static void *testpcacheFetch(
         assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
         p->a[i].isPinned = 1;
       }
-      return p->a[i].pData;
+      return &p->a[i].page;
     }
   }
 
@@ -237,11 +244,12 @@ static void *testpcacheFetch(
       if( p->a[j].key==0 ){
         p->a[j].key = key;
         p->a[j].isPinned = 1;
-        memset(p->a[j].pData, 0, p->szPage);
+        memset(p->a[j].page.pBuf, 0, p->szPage);
+        memset(p->a[j].page.pExtra, 0, p->szExtra);
         p->nPinned++;
         p->nFree--;
         assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
-        return p->a[j].pData;
+        return &p->a[j].page;
       }
     }
 
@@ -263,10 +271,11 @@ static void *testpcacheFetch(
     if( p->a[j].key>0 && p->a[j].isPinned==0 ){
       p->a[j].key = key;
       p->a[j].isPinned = 1;
-      memset(p->a[j].pData, 0, p->szPage);
+      memset(p->a[j].page.pBuf, 0, p->szPage);
+      memset(p->a[j].page.pExtra, 0, p->szExtra);
       p->nPinned++;
       assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree );
-      return p->a[j].pData;
+      return &p->a[j].page;
     }
   }
 
@@ -280,7 +289,7 @@ static void *testpcacheFetch(
 */
 static void testpcacheUnpin(
   sqlite3_pcache *pCache,
-  void *pOldPage,
+  sqlite3_pcache_page *pOldPage,
   int discard
 ){
   testpcache *p = (testpcache*)pCache;
@@ -300,7 +309,7 @@ static void testpcacheUnpin(
   }
 
   for(i=0; i<TESTPCACHE_NPAGE; i++){
-    if( p->a[i].pData==pOldPage ){
+    if( &p->a[i].page==pOldPage ){
       /* The pOldPage pointer always points to a pinned page */
       assert( p->a[i].isPinned );
       p->a[i].isPinned = 0;
@@ -325,7 +334,7 @@ static void testpcacheUnpin(
 */
 static void testpcacheRekey(
   sqlite3_pcache *pCache,
-  void *pOldPage,
+  sqlite3_pcache_page *pOldPage,
   unsigned oldKey,
   unsigned newKey
 ){
@@ -354,7 +363,7 @@ static void testpcacheRekey(
   for(i=0; i<TESTPCACHE_NPAGE; i++){
     if( p->a[i].key==oldKey ){
       /* The oldKey and pOldPage parameters match */
-      assert( p->a[i].pData==pOldPage );
+      assert( &p->a[i].page==pOldPage );
       /* Page to be rekeyed must be pinned */
       assert( p->a[i].isPinned );
       p->a[i].key = newKey;
@@ -422,7 +431,7 @@ void installTestPCache(
   unsigned prngSeed,          /* Seed for the PRNG */
   unsigned highStress         /* Call xStress agressively */
 ){
-  static const sqlite3_pcache_methods testPcache = {
+  static const sqlite3_pcache_methods2 testPcache = {
     (void*)&testpcacheGlobal,
     testpcacheInit,
     testpcacheShutdown,
@@ -435,7 +444,7 @@ void installTestPCache(
     testpcacheTruncate,
     testpcacheDestroy,
   };
-  static sqlite3_pcache_methods defaultPcache;
+  static sqlite3_pcache_methods2 defaultPcache;
   static int isInstalled = 0;
 
   assert( testpcacheGlobal.nInstance==0 );
@@ -446,12 +455,12 @@ void installTestPCache(
   testpcacheGlobal.highStress = highStress;
   if( installFlag!=isInstalled ){
     if( installFlag ){
-      sqlite3_config(SQLITE_CONFIG_GETPCACHE, &defaultPcache);
+      sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache);
       assert( defaultPcache.xCreate!=testpcacheCreate );
-      sqlite3_config(SQLITE_CONFIG_PCACHE, &testPcache);
+      sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache);
     }else{
       assert( defaultPcache.xCreate!=0 );
-      sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultPcache);
+      sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache);
     }
     isInstalled = installFlag;
   }
index 7eecf083a77da3e190dbc2b7198ad2335779d213..894a554789cac725d20d24b7e253a8ad57369934 100644 (file)
@@ -68,7 +68,7 @@ proc reset_highwater_marks {} {
   sqlite3_status SQLITE_STATUS_PARSER_STACK 1
 }
 
-set xtra_size 256
+set xtra_size 272
 
 # Test 1:  Both PAGECACHE and SCRATCH are shut down.
 #