OLD | NEW |
1 /* | 1 /* |
2 ** 2008 November 05 | 2 ** 2008 November 05 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** | 12 ** |
13 ** This file implements the default page cache implementation (the | 13 ** This file implements the default page cache implementation (the |
14 ** sqlite3_pcache interface). It also contains part of the implementation | 14 ** sqlite3_pcache interface). It also contains part of the implementation |
15 ** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. | 15 ** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. |
16 ** If the default page cache implementation is overridden, then neither of | 16 ** If the default page cache implementation is overridden, then neither of |
17 ** these two features are available. | 17 ** these two features are available. |
| 18 ** |
| 19 ** A Page cache line looks like this: |
| 20 ** |
| 21 ** ------------------------------------------------------------- |
| 22 ** | database page content | PgHdr1 | MemPage | PgHdr | |
| 23 ** ------------------------------------------------------------- |
| 24 ** |
| 25 ** The database page content is up front (so that buffer overreads tend to |
| 26 ** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage |
| 27 ** is the extension added by the btree.c module containing information such |
| 28 ** as the database page number and how that database page is used. PgHdr |
| 29 ** is added by the pcache.c layer and contains information used to keep track |
| 30 ** of which pages are "dirty". PgHdr1 is an extension added by this |
| 31 ** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page. |
| 32 ** PgHdr1 contains information needed to look up a page by its page number. |
| 33 ** The superclass sqlite3_pcache_page.pBuf points to the start of the |
| 34 ** database page content and sqlite3_pcache_page.pExtra points to PgHdr. |
| 35 ** |
| 36 ** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at |
| 37 ** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The |
| 38 ** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this |
| 39 ** size can vary according to architecture, compile-time options, and |
| 40 ** SQLite library version number. |
| 41 ** |
| 42 ** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained |
| 43 ** using a separate memory allocation from the database page content. This |
| 44 ** seeks to overcome the "clownshoe" problem (also called "internal |
| 45 ** fragmentation" in academic literature) of allocating a few bytes more |
| 46 ** than a power of two with the memory allocator rounding up to the next |
| 47 ** power of two, and leaving the rounded-up space unused. |
| 48 ** |
| 49 ** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates |
| 50 ** with this module. Information is passed back and forth as PgHdr1 pointers. |
| 51 ** |
| 52 ** The pcache.c and pager.c modules deal pointers to PgHdr objects. |
| 53 ** The btree.c module deals with pointers to MemPage objects. |
| 54 ** |
| 55 ** SOURCE OF PAGE CACHE MEMORY: |
| 56 ** |
| 57 ** Memory for a page might come from any of three sources: |
| 58 ** |
| 59 ** (1) The general-purpose memory allocator - sqlite3Malloc() |
| 60 ** (2) Global page-cache memory provided using sqlite3_config() with |
| 61 ** SQLITE_CONFIG_PAGECACHE. |
| 62 ** (3) PCache-local bulk allocation. |
| 63 ** |
| 64 ** The third case is a chunk of heap memory (defaulting to 100 pages worth) |
| 65 ** that is allocated when the page cache is created. The size of the local |
| 66 ** bulk allocation can be adjusted using |
| 67 ** |
| 68 ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N). |
| 69 ** |
| 70 ** If N is positive, then N pages worth of memory are allocated using a single |
| 71 ** sqlite3Malloc() call and that memory is used for the first N pages allocated. |
| 72 ** Or if N is negative, then -1024*N bytes of memory are allocated and used |
| 73 ** for as many pages as can be accomodated. |
| 74 ** |
| 75 ** Only one of (2) or (3) can be used. Once the memory available to (2) or |
| 76 ** (3) is exhausted, subsequent allocations fail over to the general-purpose |
| 77 ** memory allocator (1). |
| 78 ** |
| 79 ** Earlier versions of SQLite used only methods (1) and (2). But experiments |
| 80 ** show that method (3) with N==100 provides about a 5% performance boost for |
| 81 ** common workloads. |
18 */ | 82 */ |
19 | |
20 #include "sqliteInt.h" | 83 #include "sqliteInt.h" |
21 | 84 |
22 typedef struct PCache1 PCache1; | 85 typedef struct PCache1 PCache1; |
23 typedef struct PgHdr1 PgHdr1; | 86 typedef struct PgHdr1 PgHdr1; |
24 typedef struct PgFreeslot PgFreeslot; | 87 typedef struct PgFreeslot PgFreeslot; |
25 typedef struct PGroup PGroup; | 88 typedef struct PGroup PGroup; |
26 | 89 |
| 90 /* |
| 91 ** Each cache entry is represented by an instance of the following |
| 92 ** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of |
| 93 ** PgHdr1.pCache->szPage bytes is allocated directly before this structure |
| 94 ** in memory. |
| 95 */ |
| 96 struct PgHdr1 { |
| 97 sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ |
| 98 unsigned int iKey; /* Key value (page number) */ |
| 99 u8 isPinned; /* Page in use, not on the LRU list */ |
| 100 u8 isBulkLocal; /* This page from bulk local storage */ |
| 101 u8 isAnchor; /* This is the PGroup.lru element */ |
| 102 PgHdr1 *pNext; /* Next in hash table chain */ |
| 103 PCache1 *pCache; /* Cache that currently owns this page */ |
| 104 PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ |
| 105 PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ |
| 106 }; |
| 107 |
27 /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set | 108 /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set |
28 ** of one or more PCaches that are able to recycle each other's unpinned | 109 ** of one or more PCaches that are able to recycle each other's unpinned |
29 ** pages when they are under memory pressure. A PGroup is an instance of | 110 ** pages when they are under memory pressure. A PGroup is an instance of |
30 ** the following object. | 111 ** the following object. |
31 ** | 112 ** |
32 ** This page cache implementation works in one of two modes: | 113 ** This page cache implementation works in one of two modes: |
33 ** | 114 ** |
34 ** (1) Every PCache is the sole member of its own PGroup. There is | 115 ** (1) Every PCache is the sole member of its own PGroup. There is |
35 ** one PGroup per PCache. | 116 ** one PGroup per PCache. |
36 ** | 117 ** |
37 ** (2) There is a single global PGroup that all PCaches are a member | 118 ** (2) There is a single global PGroup that all PCaches are a member |
38 ** of. | 119 ** of. |
39 ** | 120 ** |
40 ** Mode 1 uses more memory (since PCache instances are not able to rob | 121 ** Mode 1 uses more memory (since PCache instances are not able to rob |
41 ** unused pages from other PCaches) but it also operates without a mutex, | 122 ** unused pages from other PCaches) but it also operates without a mutex, |
42 ** and is therefore often faster. Mode 2 requires a mutex in order to be | 123 ** and is therefore often faster. Mode 2 requires a mutex in order to be |
43 ** threadsafe, but recycles pages more efficiently. | 124 ** threadsafe, but recycles pages more efficiently. |
44 ** | 125 ** |
45 ** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single | 126 ** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single |
46 ** PGroup which is the pcache1.grp global variable and its mutex is | 127 ** PGroup which is the pcache1.grp global variable and its mutex is |
47 ** SQLITE_MUTEX_STATIC_LRU. | 128 ** SQLITE_MUTEX_STATIC_LRU. |
48 */ | 129 */ |
49 struct PGroup { | 130 struct PGroup { |
50 sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ | 131 sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ |
51 unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ | 132 unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ |
52 unsigned int nMinPage; /* Sum of nMin for purgeable caches */ | 133 unsigned int nMinPage; /* Sum of nMin for purgeable caches */ |
53 unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ | 134 unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ |
54 unsigned int nCurrentPage; /* Number of purgeable pages allocated */ | 135 unsigned int nCurrentPage; /* Number of purgeable pages allocated */ |
55 PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ | 136 PgHdr1 lru; /* The beginning and end of the LRU list */ |
56 }; | 137 }; |
57 | 138 |
58 /* Each page cache is an instance of the following object. Every | 139 /* Each page cache is an instance of the following object. Every |
59 ** open database file (including each in-memory database and each | 140 ** open database file (including each in-memory database and each |
60 ** temporary or transient database) has a single page cache which | 141 ** temporary or transient database) has a single page cache which |
61 ** is an instance of this object. | 142 ** is an instance of this object. |
62 ** | 143 ** |
63 ** Pointers to structures of this type are cast and returned as | 144 ** Pointers to structures of this type are cast and returned as |
64 ** opaque sqlite3_pcache* handles. | 145 ** opaque sqlite3_pcache* handles. |
65 */ | 146 */ |
66 struct PCache1 { | 147 struct PCache1 { |
67 /* Cache configuration parameters. Page size (szPage) and the purgeable | 148 /* Cache configuration parameters. Page size (szPage) and the purgeable |
68 ** flag (bPurgeable) are set when the cache is created. nMax may be | 149 ** flag (bPurgeable) are set when the cache is created. nMax may be |
69 ** modified at any time by a call to the pcache1Cachesize() method. | 150 ** modified at any time by a call to the pcache1Cachesize() method. |
70 ** The PGroup mutex must be held when accessing nMax. | 151 ** The PGroup mutex must be held when accessing nMax. |
71 */ | 152 */ |
72 PGroup *pGroup; /* PGroup this cache belongs to */ | 153 PGroup *pGroup; /* PGroup this cache belongs to */ |
73 int szPage; /* Size of allocated pages in bytes */ | 154 int szPage; /* Size of database content section */ |
74 int szExtra; /* Size of extra space in bytes */ | 155 int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ |
| 156 int szAlloc; /* Total size of one pcache line */ |
75 int bPurgeable; /* True if cache is purgeable */ | 157 int bPurgeable; /* True if cache is purgeable */ |
76 unsigned int nMin; /* Minimum number of pages reserved */ | 158 unsigned int nMin; /* Minimum number of pages reserved */ |
77 unsigned int nMax; /* Configured "cache_size" value */ | 159 unsigned int nMax; /* Configured "cache_size" value */ |
78 unsigned int n90pct; /* nMax*9/10 */ | 160 unsigned int n90pct; /* nMax*9/10 */ |
79 unsigned int iMaxKey; /* Largest key seen since xTruncate() */ | 161 unsigned int iMaxKey; /* Largest key seen since xTruncate() */ |
80 | 162 |
81 /* Hash table of all pages. The following variables may only be accessed | 163 /* Hash table of all pages. The following variables may only be accessed |
82 ** when the accessor is holding the PGroup mutex. | 164 ** when the accessor is holding the PGroup mutex. |
83 */ | 165 */ |
84 unsigned int nRecyclable; /* Number of pages in the LRU list */ | 166 unsigned int nRecyclable; /* Number of pages in the LRU list */ |
85 unsigned int nPage; /* Total number of pages in apHash */ | 167 unsigned int nPage; /* Total number of pages in apHash */ |
86 unsigned int nHash; /* Number of slots in apHash[] */ | 168 unsigned int nHash; /* Number of slots in apHash[] */ |
87 PgHdr1 **apHash; /* Hash table for fast lookup by key */ | 169 PgHdr1 **apHash; /* Hash table for fast lookup by key */ |
| 170 PgHdr1 *pFree; /* List of unused pcache-local pages */ |
| 171 void *pBulk; /* Bulk memory used by pcache-local */ |
88 }; | 172 }; |
89 | 173 |
90 /* | 174 /* |
91 ** Each cache entry is represented by an instance of the following | 175 ** Free slots in the allocator used to divide up the global page cache |
92 ** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of | 176 ** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism. |
93 ** PgHdr1.pCache->szPage bytes is allocated directly before this structure | |
94 ** in memory. | |
95 */ | |
96 struct PgHdr1 { | |
97 sqlite3_pcache_page page; | |
98 unsigned int iKey; /* Key value (page number) */ | |
99 u8 isPinned; /* Page in use, not on the LRU list */ | |
100 PgHdr1 *pNext; /* Next in hash table chain */ | |
101 PCache1 *pCache; /* Cache that currently owns this page */ | |
102 PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ | |
103 PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ | |
104 }; | |
105 | |
106 /* | |
107 ** Free slots in the allocator used to divide up the buffer provided using | |
108 ** the SQLITE_CONFIG_PAGECACHE mechanism. | |
109 */ | 177 */ |
110 struct PgFreeslot { | 178 struct PgFreeslot { |
111 PgFreeslot *pNext; /* Next free slot */ | 179 PgFreeslot *pNext; /* Next free slot */ |
112 }; | 180 }; |
113 | 181 |
114 /* | 182 /* |
115 ** Global data used by this cache. | 183 ** Global data used by this cache. |
116 */ | 184 */ |
117 static SQLITE_WSD struct PCacheGlobal { | 185 static SQLITE_WSD struct PCacheGlobal { |
118 PGroup grp; /* The global PGroup for mode (2) */ | 186 PGroup grp; /* The global PGroup for mode (2) */ |
119 | 187 |
120 /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The | 188 /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The |
121 ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all | 189 ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all |
122 ** fixed at sqlite3_initialize() time and do not require mutex protection. | 190 ** fixed at sqlite3_initialize() time and do not require mutex protection. |
123 ** The nFreeSlot and pFree values do require mutex protection. | 191 ** The nFreeSlot and pFree values do require mutex protection. |
124 */ | 192 */ |
125 int isInit; /* True if initialized */ | 193 int isInit; /* True if initialized */ |
| 194 int separateCache; /* Use a new PGroup for each PCache */ |
| 195 int nInitPage; /* Initial bulk allocation size */ |
126 int szSlot; /* Size of each free slot */ | 196 int szSlot; /* Size of each free slot */ |
127 int nSlot; /* The number of pcache slots */ | 197 int nSlot; /* The number of pcache slots */ |
128 int nReserve; /* Try to keep nFreeSlot above this */ | 198 int nReserve; /* Try to keep nFreeSlot above this */ |
129 void *pStart, *pEnd; /* Bounds of pagecache malloc range */ | 199 void *pStart, *pEnd; /* Bounds of global page cache memory */ |
130 /* Above requires no mutex. Use mutex below for variable that follow. */ | 200 /* Above requires no mutex. Use mutex below for variable that follow. */ |
131 sqlite3_mutex *mutex; /* Mutex for accessing the following: */ | 201 sqlite3_mutex *mutex; /* Mutex for accessing the following: */ |
132 PgFreeslot *pFree; /* Free page blocks */ | 202 PgFreeslot *pFree; /* Free page blocks */ |
133 int nFreeSlot; /* Number of unused pcache slots */ | 203 int nFreeSlot; /* Number of unused pcache slots */ |
134 /* The following value requires a mutex to change. We skip the mutex on | 204 /* The following value requires a mutex to change. We skip the mutex on |
135 ** reading because (1) most platforms read a 32-bit integer atomically and | 205 ** reading because (1) most platforms read a 32-bit integer atomically and |
136 ** (2) even if an incorrect value is read, no great harm is done since this | 206 ** (2) even if an incorrect value is read, no great harm is done since this |
137 ** is really just an optimization. */ | 207 ** is really just an optimization. */ |
138 int bUnderPressure; /* True if low on PAGECACHE memory */ | 208 int bUnderPressure; /* True if low on PAGECACHE memory */ |
139 } pcache1_g; | 209 } pcache1_g; |
140 | 210 |
141 /* | 211 /* |
142 ** All code in this file should access the global structure above via the | 212 ** All code in this file should access the global structure above via the |
143 ** alias "pcache1". This ensures that the WSD emulation is used when | 213 ** alias "pcache1". This ensures that the WSD emulation is used when |
144 ** compiling for systems that do not support real WSD. | 214 ** compiling for systems that do not support real WSD. |
145 */ | 215 */ |
146 #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) | 216 #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) |
147 | 217 |
148 /* | 218 /* |
149 ** Macros to enter and leave the PCache LRU mutex. | 219 ** Macros to enter and leave the PCache LRU mutex. |
150 */ | 220 */ |
151 #define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) | 221 #if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 |
152 #define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) | 222 # define pcache1EnterMutex(X) assert((X)->mutex==0) |
| 223 # define pcache1LeaveMutex(X) assert((X)->mutex==0) |
| 224 # define PCACHE1_MIGHT_USE_GROUP_MUTEX 0 |
| 225 #else |
| 226 # define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) |
| 227 # define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) |
| 228 # define PCACHE1_MIGHT_USE_GROUP_MUTEX 1 |
| 229 #endif |
153 | 230 |
154 /******************************************************************************/ | 231 /******************************************************************************/ |
155 /******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ | 232 /******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ |
156 | 233 |
| 234 |
157 /* | 235 /* |
158 ** This function is called during initialization if a static buffer is | 236 ** This function is called during initialization if a static buffer is |
159 ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE | 237 ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE |
160 ** verb to sqlite3_config(). Parameter pBuf points to an allocation large | 238 ** verb to sqlite3_config(). Parameter pBuf points to an allocation large |
161 ** enough to contain 'n' buffers of 'sz' bytes each. | 239 ** enough to contain 'n' buffers of 'sz' bytes each. |
162 ** | 240 ** |
163 ** This routine is called from sqlite3_initialize() and so it is guaranteed | 241 ** This routine is called from sqlite3_initialize() and so it is guaranteed |
164 ** to be serialized already. There is no need for further mutexing. | 242 ** to be serialized already. There is no need for further mutexing. |
165 */ | 243 */ |
166 void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ | 244 void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ |
167 if( pcache1.isInit ){ | 245 if( pcache1.isInit ){ |
168 PgFreeslot *p; | 246 PgFreeslot *p; |
| 247 if( pBuf==0 ) sz = n = 0; |
169 sz = ROUNDDOWN8(sz); | 248 sz = ROUNDDOWN8(sz); |
170 pcache1.szSlot = sz; | 249 pcache1.szSlot = sz; |
171 pcache1.nSlot = pcache1.nFreeSlot = n; | 250 pcache1.nSlot = pcache1.nFreeSlot = n; |
172 pcache1.nReserve = n>90 ? 10 : (n/10 + 1); | 251 pcache1.nReserve = n>90 ? 10 : (n/10 + 1); |
173 pcache1.pStart = pBuf; | 252 pcache1.pStart = pBuf; |
174 pcache1.pFree = 0; | 253 pcache1.pFree = 0; |
175 pcache1.bUnderPressure = 0; | 254 pcache1.bUnderPressure = 0; |
176 while( n-- ){ | 255 while( n-- ){ |
177 p = (PgFreeslot*)pBuf; | 256 p = (PgFreeslot*)pBuf; |
178 p->pNext = pcache1.pFree; | 257 p->pNext = pcache1.pFree; |
179 pcache1.pFree = p; | 258 pcache1.pFree = p; |
180 pBuf = (void*)&((char*)pBuf)[sz]; | 259 pBuf = (void*)&((char*)pBuf)[sz]; |
181 } | 260 } |
182 pcache1.pEnd = pBuf; | 261 pcache1.pEnd = pBuf; |
183 } | 262 } |
184 } | 263 } |
185 | 264 |
186 /* | 265 /* |
| 266 ** Try to initialize the pCache->pFree and pCache->pBulk fields. Return |
| 267 ** true if pCache->pFree ends up containing one or more free pages. |
| 268 */ |
| 269 static int pcache1InitBulk(PCache1 *pCache){ |
| 270 i64 szBulk; |
| 271 char *zBulk; |
| 272 if( pcache1.nInitPage==0 ) return 0; |
| 273 /* Do not bother with a bulk allocation if the cache size very small */ |
| 274 if( pCache->nMax<3 ) return 0; |
| 275 sqlite3BeginBenignMalloc(); |
| 276 if( pcache1.nInitPage>0 ){ |
| 277 szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 278 }else{ |
| 279 szBulk = -1024 * (i64)pcache1.nInitPage; |
| 280 } |
| 281 if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 282 szBulk = pCache->szAlloc*pCache->nMax; |
| 283 } |
| 284 zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 285 sqlite3EndBenignMalloc(); |
| 286 if( zBulk ){ |
| 287 int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| 288 int i; |
| 289 for(i=0; i<nBulk; i++){ |
| 290 PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; |
| 291 pX->page.pBuf = zBulk; |
| 292 pX->page.pExtra = &pX[1]; |
| 293 pX->isBulkLocal = 1; |
| 294 pX->isAnchor = 0; |
| 295 pX->pNext = pCache->pFree; |
| 296 pCache->pFree = pX; |
| 297 zBulk += pCache->szAlloc; |
| 298 } |
| 299 } |
| 300 return pCache->pFree!=0; |
| 301 } |
| 302 |
| 303 /* |
187 ** Malloc function used within this file to allocate space from the buffer | 304 ** Malloc function used within this file to allocate space from the buffer |
188 ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no | 305 ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no |
189 ** such buffer exists or there is no space left in it, this function falls | 306 ** such buffer exists or there is no space left in it, this function falls |
190 ** back to sqlite3Malloc(). | 307 ** back to sqlite3Malloc(). |
191 ** | 308 ** |
192 ** Multiple threads can run this routine at the same time. Global variables | 309 ** Multiple threads can run this routine at the same time. Global variables |
193 ** in pcache1 need to be protected via mutex. | 310 ** in pcache1 need to be protected via mutex. |
194 */ | 311 */ |
195 static void *pcache1Alloc(int nByte){ | 312 static void *pcache1Alloc(int nByte){ |
196 void *p = 0; | 313 void *p = 0; |
197 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); | 314 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); |
198 sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); | |
199 if( nByte<=pcache1.szSlot ){ | 315 if( nByte<=pcache1.szSlot ){ |
200 sqlite3_mutex_enter(pcache1.mutex); | 316 sqlite3_mutex_enter(pcache1.mutex); |
201 p = (PgHdr1 *)pcache1.pFree; | 317 p = (PgHdr1 *)pcache1.pFree; |
202 if( p ){ | 318 if( p ){ |
203 pcache1.pFree = pcache1.pFree->pNext; | 319 pcache1.pFree = pcache1.pFree->pNext; |
204 pcache1.nFreeSlot--; | 320 pcache1.nFreeSlot--; |
205 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; | 321 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; |
206 assert( pcache1.nFreeSlot>=0 ); | 322 assert( pcache1.nFreeSlot>=0 ); |
207 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); | 323 sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); |
| 324 sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); |
208 } | 325 } |
209 sqlite3_mutex_leave(pcache1.mutex); | 326 sqlite3_mutex_leave(pcache1.mutex); |
210 } | 327 } |
211 if( p==0 ){ | 328 if( p==0 ){ |
212 /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get | 329 /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get |
213 ** it from sqlite3Malloc instead. | 330 ** it from sqlite3Malloc instead. |
214 */ | 331 */ |
215 p = sqlite3Malloc(nByte); | 332 p = sqlite3Malloc(nByte); |
216 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS | 333 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS |
217 if( p ){ | 334 if( p ){ |
218 int sz = sqlite3MallocSize(p); | 335 int sz = sqlite3MallocSize(p); |
219 sqlite3_mutex_enter(pcache1.mutex); | 336 sqlite3_mutex_enter(pcache1.mutex); |
220 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); | 337 sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); |
| 338 sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); |
221 sqlite3_mutex_leave(pcache1.mutex); | 339 sqlite3_mutex_leave(pcache1.mutex); |
222 } | 340 } |
223 #endif | 341 #endif |
224 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); | 342 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); |
225 } | 343 } |
226 return p; | 344 return p; |
227 } | 345 } |
228 | 346 |
229 /* | 347 /* |
230 ** Free an allocated buffer obtained from pcache1Alloc(). | 348 ** Free an allocated buffer obtained from pcache1Alloc(). |
231 */ | 349 */ |
232 static int pcache1Free(void *p){ | 350 static void pcache1Free(void *p){ |
233 int nFreed = 0; | 351 int nFreed = 0; |
234 if( p==0 ) return 0; | 352 if( p==0 ) return; |
235 if( p>=pcache1.pStart && p<pcache1.pEnd ){ | 353 if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ |
236 PgFreeslot *pSlot; | 354 PgFreeslot *pSlot; |
237 sqlite3_mutex_enter(pcache1.mutex); | 355 sqlite3_mutex_enter(pcache1.mutex); |
238 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1); | 356 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1); |
239 pSlot = (PgFreeslot*)p; | 357 pSlot = (PgFreeslot*)p; |
240 pSlot->pNext = pcache1.pFree; | 358 pSlot->pNext = pcache1.pFree; |
241 pcache1.pFree = pSlot; | 359 pcache1.pFree = pSlot; |
242 pcache1.nFreeSlot++; | 360 pcache1.nFreeSlot++; |
243 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; | 361 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve; |
244 assert( pcache1.nFreeSlot<=pcache1.nSlot ); | 362 assert( pcache1.nFreeSlot<=pcache1.nSlot ); |
245 sqlite3_mutex_leave(pcache1.mutex); | 363 sqlite3_mutex_leave(pcache1.mutex); |
246 }else{ | 364 }else{ |
247 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); | 365 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); |
248 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); | 366 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 367 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS |
249 nFreed = sqlite3MallocSize(p); | 368 nFreed = sqlite3MallocSize(p); |
250 #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS | |
251 sqlite3_mutex_enter(pcache1.mutex); | 369 sqlite3_mutex_enter(pcache1.mutex); |
252 sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed); | 370 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); |
253 sqlite3_mutex_leave(pcache1.mutex); | 371 sqlite3_mutex_leave(pcache1.mutex); |
254 #endif | 372 #endif |
255 sqlite3_free(p); | 373 sqlite3_free(p); |
256 } | 374 } |
257 return nFreed; | |
258 } | 375 } |
259 | 376 |
260 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | 377 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
261 /* | 378 /* |
262 ** Return the size of a pcache allocation | 379 ** Return the size of a pcache allocation |
263 */ | 380 */ |
264 static int pcache1MemSize(void *p){ | 381 static int pcache1MemSize(void *p){ |
265 if( p>=pcache1.pStart && p<pcache1.pEnd ){ | 382 if( p>=pcache1.pStart && p<pcache1.pEnd ){ |
266 return pcache1.szSlot; | 383 return pcache1.szSlot; |
267 }else{ | 384 }else{ |
268 int iSize; | 385 int iSize; |
269 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); | 386 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); |
270 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); | 387 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
271 iSize = sqlite3MallocSize(p); | 388 iSize = sqlite3MallocSize(p); |
272 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); | 389 sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); |
273 return iSize; | 390 return iSize; |
274 } | 391 } |
275 } | 392 } |
276 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ | 393 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ |
277 | 394 |
278 /* | 395 /* |
279 ** Allocate a new page object initially associated with cache pCache. | 396 ** Allocate a new page object initially associated with cache pCache. |
280 */ | 397 */ |
281 static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ | 398 static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){ |
282 PgHdr1 *p = 0; | 399 PgHdr1 *p = 0; |
283 void *pPg; | 400 void *pPg; |
284 | 401 |
285 /* The group mutex must be released before pcache1Alloc() is called. This | |
286 ** is because it may call sqlite3_release_memory(), which assumes that | |
287 ** this mutex is not held. */ | |
288 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); | 402 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); |
289 pcache1LeaveMutex(pCache->pGroup); | 403 if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ |
| 404 p = pCache->pFree; |
| 405 pCache->pFree = p->pNext; |
| 406 p->pNext = 0; |
| 407 }else{ |
| 408 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 409 /* The group mutex must be released before pcache1Alloc() is called. This |
| 410 ** is because it might call sqlite3_release_memory(), which assumes that |
| 411 ** this mutex is not held. */ |
| 412 assert( pcache1.separateCache==0 ); |
| 413 assert( pCache->pGroup==&pcache1.grp ); |
| 414 pcache1LeaveMutex(pCache->pGroup); |
| 415 #endif |
| 416 if( benignMalloc ){ sqlite3BeginBenignMalloc(); } |
290 #ifdef SQLITE_PCACHE_SEPARATE_HEADER | 417 #ifdef SQLITE_PCACHE_SEPARATE_HEADER |
291 pPg = pcache1Alloc(pCache->szPage); | 418 pPg = pcache1Alloc(pCache->szPage); |
292 p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); | 419 p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); |
293 if( !pPg || !p ){ | 420 if( !pPg || !p ){ |
294 pcache1Free(pPg); | 421 pcache1Free(pPg); |
295 sqlite3_free(p); | 422 sqlite3_free(p); |
296 pPg = 0; | 423 pPg = 0; |
297 } | 424 } |
298 #else | 425 #else |
299 pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); | 426 pPg = pcache1Alloc(pCache->szAlloc); |
300 p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; | 427 p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
301 #endif | 428 #endif |
302 pcache1EnterMutex(pCache->pGroup); | 429 if( benignMalloc ){ sqlite3EndBenignMalloc(); } |
303 | 430 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
304 if( pPg ){ | 431 pcache1EnterMutex(pCache->pGroup); |
| 432 #endif |
| 433 if( pPg==0 ) return 0; |
305 p->page.pBuf = pPg; | 434 p->page.pBuf = pPg; |
306 p->page.pExtra = &p[1]; | 435 p->page.pExtra = &p[1]; |
307 if( pCache->bPurgeable ){ | 436 p->isBulkLocal = 0; |
308 pCache->pGroup->nCurrentPage++; | 437 p->isAnchor = 0; |
309 } | |
310 return p; | |
311 } | 438 } |
312 return 0; | 439 if( pCache->bPurgeable ){ |
| 440 pCache->pGroup->nCurrentPage++; |
| 441 } |
| 442 return p; |
313 } | 443 } |
314 | 444 |
315 /* | 445 /* |
316 ** Free a page object allocated by pcache1AllocPage(). | 446 ** Free a page object allocated by pcache1AllocPage(). |
317 ** | |
318 ** The pointer is allowed to be NULL, which is prudent. But it turns out | |
319 ** that the current implementation happens to never call this routine | |
320 ** with a NULL pointer, so we mark the NULL test with ALWAYS(). | |
321 */ | 447 */ |
322 static void pcache1FreePage(PgHdr1 *p){ | 448 static void pcache1FreePage(PgHdr1 *p){ |
323 if( ALWAYS(p) ){ | 449 PCache1 *pCache; |
324 PCache1 *pCache = p->pCache; | 450 assert( p!=0 ); |
325 assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); | 451 pCache = p->pCache; |
| 452 assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); |
| 453 if( p->isBulkLocal ){ |
| 454 p->pNext = pCache->pFree; |
| 455 pCache->pFree = p; |
| 456 }else{ |
326 pcache1Free(p->page.pBuf); | 457 pcache1Free(p->page.pBuf); |
327 #ifdef SQLITE_PCACHE_SEPARATE_HEADER | 458 #ifdef SQLITE_PCACHE_SEPARATE_HEADER |
328 sqlite3_free(p); | 459 sqlite3_free(p); |
329 #endif | 460 #endif |
330 if( pCache->bPurgeable ){ | 461 } |
331 pCache->pGroup->nCurrentPage--; | 462 if( pCache->bPurgeable ){ |
332 } | 463 pCache->pGroup->nCurrentPage--; |
333 } | 464 } |
334 } | 465 } |
335 | 466 |
336 /* | 467 /* |
337 ** Malloc function used by SQLite to obtain space from the buffer configured | 468 ** Malloc function used by SQLite to obtain space from the buffer configured |
338 ** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer | 469 ** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer |
339 ** exists, this function falls back to sqlite3Malloc(). | 470 ** exists, this function falls back to sqlite3Malloc(). |
340 */ | 471 */ |
341 void *sqlite3PageMalloc(int sz){ | 472 void *sqlite3PageMalloc(int sz){ |
342 return pcache1Alloc(sz); | 473 return pcache1Alloc(sz); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 548 } |
418 } | 549 } |
419 | 550 |
420 /* | 551 /* |
421 ** This function is used internally to remove the page pPage from the | 552 ** This function is used internally to remove the page pPage from the |
422 ** PGroup LRU list, if is part of it. If pPage is not part of the PGroup | 553 ** PGroup LRU list, if is part of it. If pPage is not part of the PGroup |
423 ** LRU list, then this function is a no-op. | 554 ** LRU list, then this function is a no-op. |
424 ** | 555 ** |
425 ** The PGroup mutex must be held when this function is called. | 556 ** The PGroup mutex must be held when this function is called. |
426 */ | 557 */ |
427 static void pcache1PinPage(PgHdr1 *pPage){ | 558 static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ |
428 PCache1 *pCache; | 559 PCache1 *pCache; |
429 PGroup *pGroup; | |
430 | 560 |
431 assert( pPage!=0 ); | 561 assert( pPage!=0 ); |
432 assert( pPage->isPinned==0 ); | 562 assert( pPage->isPinned==0 ); |
433 pCache = pPage->pCache; | 563 pCache = pPage->pCache; |
434 pGroup = pCache->pGroup; | 564 assert( pPage->pLruNext ); |
435 assert( pPage->pLruNext || pPage==pGroup->pLruTail ); | 565 assert( pPage->pLruPrev ); |
436 assert( pPage->pLruPrev || pPage==pGroup->pLruHead ); | 566 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); |
437 assert( sqlite3_mutex_held(pGroup->mutex) ); | 567 pPage->pLruPrev->pLruNext = pPage->pLruNext; |
438 if( pPage->pLruPrev ){ | 568 pPage->pLruNext->pLruPrev = pPage->pLruPrev; |
439 pPage->pLruPrev->pLruNext = pPage->pLruNext; | |
440 }else{ | |
441 pGroup->pLruHead = pPage->pLruNext; | |
442 } | |
443 if( pPage->pLruNext ){ | |
444 pPage->pLruNext->pLruPrev = pPage->pLruPrev; | |
445 }else{ | |
446 pGroup->pLruTail = pPage->pLruPrev; | |
447 } | |
448 pPage->pLruNext = 0; | 569 pPage->pLruNext = 0; |
449 pPage->pLruPrev = 0; | 570 pPage->pLruPrev = 0; |
450 pPage->isPinned = 1; | 571 pPage->isPinned = 1; |
| 572 assert( pPage->isAnchor==0 ); |
| 573 assert( pCache->pGroup->lru.isAnchor==1 ); |
451 pCache->nRecyclable--; | 574 pCache->nRecyclable--; |
| 575 return pPage; |
452 } | 576 } |
453 | 577 |
454 | 578 |
455 /* | 579 /* |
456 ** Remove the page supplied as an argument from the hash table | 580 ** Remove the page supplied as an argument from the hash table |
457 ** (PCache1.apHash structure) that it is currently stored in. | 581 ** (PCache1.apHash structure) that it is currently stored in. |
| 582 ** Also free the page if freePage is true. |
458 ** | 583 ** |
459 ** The PGroup mutex must be held when this function is called. | 584 ** The PGroup mutex must be held when this function is called. |
460 */ | 585 */ |
461 static void pcache1RemoveFromHash(PgHdr1 *pPage){ | 586 static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){ |
462 unsigned int h; | 587 unsigned int h; |
463 PCache1 *pCache = pPage->pCache; | 588 PCache1 *pCache = pPage->pCache; |
464 PgHdr1 **pp; | 589 PgHdr1 **pp; |
465 | 590 |
466 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); | 591 assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); |
467 h = pPage->iKey % pCache->nHash; | 592 h = pPage->iKey % pCache->nHash; |
468 for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext); | 593 for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext); |
469 *pp = (*pp)->pNext; | 594 *pp = (*pp)->pNext; |
470 | 595 |
471 pCache->nPage--; | 596 pCache->nPage--; |
| 597 if( freeFlag ) pcache1FreePage(pPage); |
472 } | 598 } |
473 | 599 |
474 /* | 600 /* |
475 ** If there are currently more than nMaxPage pages allocated, try | 601 ** If there are currently more than nMaxPage pages allocated, try |
476 ** to recycle pages to reduce the number allocated to nMaxPage. | 602 ** to recycle pages to reduce the number allocated to nMaxPage. |
477 */ | 603 */ |
478 static void pcache1EnforceMaxPage(PGroup *pGroup){ | 604 static void pcache1EnforceMaxPage(PCache1 *pCache){ |
| 605 PGroup *pGroup = pCache->pGroup; |
| 606 PgHdr1 *p; |
479 assert( sqlite3_mutex_held(pGroup->mutex) ); | 607 assert( sqlite3_mutex_held(pGroup->mutex) ); |
480 while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ | 608 while( pGroup->nCurrentPage>pGroup->nMaxPage |
481 PgHdr1 *p = pGroup->pLruTail; | 609 && (p=pGroup->lru.pLruPrev)->isAnchor==0 |
| 610 ){ |
482 assert( p->pCache->pGroup==pGroup ); | 611 assert( p->pCache->pGroup==pGroup ); |
483 assert( p->isPinned==0 ); | 612 assert( p->isPinned==0 ); |
484 pcache1PinPage(p); | 613 pcache1PinPage(p); |
485 pcache1RemoveFromHash(p); | 614 pcache1RemoveFromHash(p, 1); |
486 pcache1FreePage(p); | 615 } |
| 616 if( pCache->nPage==0 && pCache->pBulk ){ |
| 617 sqlite3_free(pCache->pBulk); |
| 618 pCache->pBulk = pCache->pFree = 0; |
487 } | 619 } |
488 } | 620 } |
489 | 621 |
490 /* | 622 /* |
491 ** Discard all pages from cache pCache with a page number (key value) | 623 ** Discard all pages from cache pCache with a page number (key value) |
492 ** greater than or equal to iLimit. Any pinned pages that meet this | 624 ** greater than or equal to iLimit. Any pinned pages that meet this |
493 ** criteria are unpinned before they are discarded. | 625 ** criteria are unpinned before they are discarded. |
494 ** | 626 ** |
495 ** The PCache mutex must be held when this function is called. | 627 ** The PCache mutex must be held when this function is called. |
496 */ | 628 */ |
(...skipping 25 matching lines...) Expand all Loading... |
522 /******************************************************************************/ | 654 /******************************************************************************/ |
523 /******** sqlite3_pcache Methods **********************************************/ | 655 /******** sqlite3_pcache Methods **********************************************/ |
524 | 656 |
525 /* | 657 /* |
526 ** Implementation of the sqlite3_pcache.xInit method. | 658 ** Implementation of the sqlite3_pcache.xInit method. |
527 */ | 659 */ |
528 static int pcache1Init(void *NotUsed){ | 660 static int pcache1Init(void *NotUsed){ |
529 UNUSED_PARAMETER(NotUsed); | 661 UNUSED_PARAMETER(NotUsed); |
530 assert( pcache1.isInit==0 ); | 662 assert( pcache1.isInit==0 ); |
531 memset(&pcache1, 0, sizeof(pcache1)); | 663 memset(&pcache1, 0, sizeof(pcache1)); |
| 664 |
| 665 |
| 666 /* |
| 667 ** The pcache1.separateCache variable is true if each PCache has its own |
| 668 ** private PGroup (mode-1). pcache1.separateCache is false if the single |
| 669 ** PGroup in pcache1.grp is used for all page caches (mode-2). |
| 670 ** |
| 671 ** * Always use separate caches (mode-1) if SQLITE_SEPARATE_CACHE_POOLS |
| 672 ** |
| 673 ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT |
| 674 ** |
| 675 ** * Use a unified cache in single-threaded applications that have |
| 676 ** configured a start-time buffer for use as page-cache memory using |
| 677 ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL |
| 678 ** pBuf argument. |
| 679 ** |
| 680 ** * Otherwise use separate caches (mode-1) |
| 681 */ |
| 682 #ifdef SQLITE_SEPARATE_CACHE_POOLS |
| 683 const int separateCache = 1; |
| 684 #elif defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) |
| 685 pcache1.separateCache = 0; |
| 686 #elif SQLITE_THREADSAFE |
| 687 pcache1.separateCache = sqlite3GlobalConfig.pPage==0 |
| 688 || sqlite3GlobalConfig.bCoreMutex>0; |
| 689 #else |
| 690 pcache1.separateCache = sqlite3GlobalConfig.pPage==0; |
| 691 #endif |
| 692 |
| 693 #if SQLITE_THREADSAFE |
532 if( sqlite3GlobalConfig.bCoreMutex ){ | 694 if( sqlite3GlobalConfig.bCoreMutex ){ |
533 pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); | 695 pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); |
534 pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); | 696 pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); |
535 } | 697 } |
| 698 #endif |
| 699 if( pcache1.separateCache |
| 700 && sqlite3GlobalConfig.nPage!=0 |
| 701 && sqlite3GlobalConfig.pPage==0 |
| 702 ){ |
| 703 pcache1.nInitPage = sqlite3GlobalConfig.nPage; |
| 704 }else{ |
| 705 pcache1.nInitPage = 0; |
| 706 } |
536 pcache1.grp.mxPinned = 10; | 707 pcache1.grp.mxPinned = 10; |
537 pcache1.isInit = 1; | 708 pcache1.isInit = 1; |
538 return SQLITE_OK; | 709 return SQLITE_OK; |
539 } | 710 } |
540 | 711 |
541 /* | 712 /* |
542 ** Implementation of the sqlite3_pcache.xShutdown method. | 713 ** Implementation of the sqlite3_pcache.xShutdown method. |
543 ** Note that the static mutex allocated in xInit does | 714 ** Note that the static mutex allocated in xInit does |
544 ** not need to be freed. | 715 ** not need to be freed. |
545 */ | 716 */ |
546 static void pcache1Shutdown(void *NotUsed){ | 717 static void pcache1Shutdown(void *NotUsed){ |
547 UNUSED_PARAMETER(NotUsed); | 718 UNUSED_PARAMETER(NotUsed); |
548 assert( pcache1.isInit!=0 ); | 719 assert( pcache1.isInit!=0 ); |
549 memset(&pcache1, 0, sizeof(pcache1)); | 720 memset(&pcache1, 0, sizeof(pcache1)); |
550 } | 721 } |
551 | 722 |
552 /* forward declaration */ | 723 /* forward declaration */ |
553 static void pcache1Destroy(sqlite3_pcache *p); | 724 static void pcache1Destroy(sqlite3_pcache *p); |
554 | 725 |
555 /* | 726 /* |
556 ** Implementation of the sqlite3_pcache.xCreate method. | 727 ** Implementation of the sqlite3_pcache.xCreate method. |
557 ** | 728 ** |
558 ** Allocate a new cache. | 729 ** Allocate a new cache. |
559 */ | 730 */ |
560 static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ | 731 static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ |
561 PCache1 *pCache; /* The newly created page cache */ | 732 PCache1 *pCache; /* The newly created page cache */ |
562 PGroup *pGroup; /* The group the new page cache will belong to */ | 733 PGroup *pGroup; /* The group the new page cache will belong to */ |
563 int sz; /* Bytes of memory required to allocate the new cache */ | 734 int sz; /* Bytes of memory required to allocate the new cache */ |
564 | 735 |
565 /* | |
566 ** The separateCache variable is true if each PCache has its own private | |
567 ** PGroup. In other words, separateCache is true for mode (1) where no | |
568 ** mutexing is required. | |
569 ** | |
570 ** * Always use separate caches (mode-1) if SQLITE_SEPARATE_CACHE_POOLS | |
571 ** | |
572 ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT | |
573 ** | |
574 ** * Always use a unified cache in single-threaded applications | |
575 ** | |
576 ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off) | |
577 ** use separate caches (mode-1) | |
578 */ | |
579 #ifdef SQLITE_SEPARATE_CACHE_POOLS | |
580 const int separateCache = 1; | |
581 #elif defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 | |
582 const int separateCache = 0; | |
583 #else | |
584 int separateCache = sqlite3GlobalConfig.bCoreMutex>0; | |
585 #endif | |
586 | |
587 assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); | 736 assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); |
588 assert( szExtra < 300 ); | 737 assert( szExtra < 300 ); |
589 | 738 |
590 sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; | 739 sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache; |
591 pCache = (PCache1 *)sqlite3MallocZero(sz); | 740 pCache = (PCache1 *)sqlite3MallocZero(sz); |
592 if( pCache ){ | 741 if( pCache ){ |
593 if( separateCache ){ | 742 if( pcache1.separateCache ){ |
594 pGroup = (PGroup*)&pCache[1]; | 743 pGroup = (PGroup*)&pCache[1]; |
595 pGroup->mxPinned = 10; | 744 pGroup->mxPinned = 10; |
596 }else{ | 745 }else{ |
597 pGroup = &pcache1.grp; | 746 pGroup = &pcache1.grp; |
598 } | 747 } |
| 748 if( pGroup->lru.isAnchor==0 ){ |
| 749 pGroup->lru.isAnchor = 1; |
| 750 pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru; |
| 751 } |
599 pCache->pGroup = pGroup; | 752 pCache->pGroup = pGroup; |
600 pCache->szPage = szPage; | 753 pCache->szPage = szPage; |
601 pCache->szExtra = szExtra; | 754 pCache->szExtra = szExtra; |
| 755 pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); |
602 pCache->bPurgeable = (bPurgeable ? 1 : 0); | 756 pCache->bPurgeable = (bPurgeable ? 1 : 0); |
603 pcache1EnterMutex(pGroup); | 757 pcache1EnterMutex(pGroup); |
604 pcache1ResizeHash(pCache); | 758 pcache1ResizeHash(pCache); |
605 if( bPurgeable ){ | 759 if( bPurgeable ){ |
606 pCache->nMin = 10; | 760 pCache->nMin = 10; |
607 pGroup->nMinPage += pCache->nMin; | 761 pGroup->nMinPage += pCache->nMin; |
608 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; | 762 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; |
609 } | 763 } |
610 pcache1LeaveMutex(pGroup); | 764 pcache1LeaveMutex(pGroup); |
611 if( pCache->nHash==0 ){ | 765 if( pCache->nHash==0 ){ |
(...skipping 11 matching lines...) Expand all Loading... |
623 */ | 777 */ |
624 static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ | 778 static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ |
625 PCache1 *pCache = (PCache1 *)p; | 779 PCache1 *pCache = (PCache1 *)p; |
626 if( pCache->bPurgeable ){ | 780 if( pCache->bPurgeable ){ |
627 PGroup *pGroup = pCache->pGroup; | 781 PGroup *pGroup = pCache->pGroup; |
628 pcache1EnterMutex(pGroup); | 782 pcache1EnterMutex(pGroup); |
629 pGroup->nMaxPage += (nMax - pCache->nMax); | 783 pGroup->nMaxPage += (nMax - pCache->nMax); |
630 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; | 784 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; |
631 pCache->nMax = nMax; | 785 pCache->nMax = nMax; |
632 pCache->n90pct = pCache->nMax*9/10; | 786 pCache->n90pct = pCache->nMax*9/10; |
633 pcache1EnforceMaxPage(pGroup); | 787 pcache1EnforceMaxPage(pCache); |
634 pcache1LeaveMutex(pGroup); | 788 pcache1LeaveMutex(pGroup); |
635 } | 789 } |
636 } | 790 } |
637 | 791 |
638 /* | 792 /* |
639 ** Implementation of the sqlite3_pcache.xShrink method. | 793 ** Implementation of the sqlite3_pcache.xShrink method. |
640 ** | 794 ** |
641 ** Free up as much memory as possible. | 795 ** Free up as much memory as possible. |
642 */ | 796 */ |
643 static void pcache1Shrink(sqlite3_pcache *p){ | 797 static void pcache1Shrink(sqlite3_pcache *p){ |
644 PCache1 *pCache = (PCache1*)p; | 798 PCache1 *pCache = (PCache1*)p; |
645 if( pCache->bPurgeable ){ | 799 if( pCache->bPurgeable ){ |
646 PGroup *pGroup = pCache->pGroup; | 800 PGroup *pGroup = pCache->pGroup; |
647 int savedMaxPage; | 801 int savedMaxPage; |
648 pcache1EnterMutex(pGroup); | 802 pcache1EnterMutex(pGroup); |
649 savedMaxPage = pGroup->nMaxPage; | 803 savedMaxPage = pGroup->nMaxPage; |
650 pGroup->nMaxPage = 0; | 804 pGroup->nMaxPage = 0; |
651 pcache1EnforceMaxPage(pGroup); | 805 pcache1EnforceMaxPage(pCache); |
652 pGroup->nMaxPage = savedMaxPage; | 806 pGroup->nMaxPage = savedMaxPage; |
653 pcache1LeaveMutex(pGroup); | 807 pcache1LeaveMutex(pGroup); |
654 } | 808 } |
655 } | 809 } |
656 | 810 |
657 /* | 811 /* |
658 ** Implementation of the sqlite3_pcache.xPagecount method. | 812 ** Implementation of the sqlite3_pcache.xPagecount method. |
659 */ | 813 */ |
660 static int pcache1Pagecount(sqlite3_pcache *p){ | 814 static int pcache1Pagecount(sqlite3_pcache *p){ |
661 int n; | 815 int n; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 || nPinned>=pCache->n90pct | 848 || nPinned>=pCache->n90pct |
695 || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned) | 849 || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned) |
696 )){ | 850 )){ |
697 return 0; | 851 return 0; |
698 } | 852 } |
699 | 853 |
700 if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache); | 854 if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache); |
701 assert( pCache->nHash>0 && pCache->apHash ); | 855 assert( pCache->nHash>0 && pCache->apHash ); |
702 | 856 |
703 /* Step 4. Try to recycle a page. */ | 857 /* Step 4. Try to recycle a page. */ |
704 if( pCache->bPurgeable && pGroup->pLruTail && ( | 858 if( pCache->bPurgeable |
705 (pCache->nPage+1>=pCache->nMax) | 859 && !pGroup->lru.pLruPrev->isAnchor |
706 || pGroup->nCurrentPage>=pGroup->nMaxPage | 860 && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache)) |
707 || pcache1UnderMemoryPressure(pCache) | 861 ){ |
708 )){ | |
709 PCache1 *pOther; | 862 PCache1 *pOther; |
710 pPage = pGroup->pLruTail; | 863 pPage = pGroup->lru.pLruPrev; |
711 assert( pPage->isPinned==0 ); | 864 assert( pPage->isPinned==0 ); |
712 pcache1RemoveFromHash(pPage); | 865 pcache1RemoveFromHash(pPage, 0); |
713 pcache1PinPage(pPage); | 866 pcache1PinPage(pPage); |
714 pOther = pPage->pCache; | 867 pOther = pPage->pCache; |
715 | 868 if( pOther->szAlloc != pCache->szAlloc ){ |
716 /* We want to verify that szPage and szExtra are the same for pOther | |
717 ** and pCache. Assert that we can verify this by comparing sums. */ | |
718 assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); | |
719 assert( pCache->szExtra<512 ); | |
720 assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); | |
721 assert( pOther->szExtra<512 ); | |
722 | |
723 if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ | |
724 pcache1FreePage(pPage); | 869 pcache1FreePage(pPage); |
725 pPage = 0; | 870 pPage = 0; |
726 }else{ | 871 }else{ |
727 pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); | 872 pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); |
728 } | 873 } |
729 } | 874 } |
730 | 875 |
731 /* Step 5. If a usable page buffer has still not been found, | 876 /* Step 5. If a usable page buffer has still not been found, |
732 ** attempt to allocate a new one. | 877 ** attempt to allocate a new one. |
733 */ | 878 */ |
734 if( !pPage ){ | 879 if( !pPage ){ |
735 if( createFlag==1 ) sqlite3BeginBenignMalloc(); | 880 pPage = pcache1AllocPage(pCache, createFlag==1); |
736 pPage = pcache1AllocPage(pCache); | |
737 if( createFlag==1 ) sqlite3EndBenignMalloc(); | |
738 } | 881 } |
739 | 882 |
740 if( pPage ){ | 883 if( pPage ){ |
741 unsigned int h = iKey % pCache->nHash; | 884 unsigned int h = iKey % pCache->nHash; |
742 pCache->nPage++; | 885 pCache->nPage++; |
743 pPage->iKey = iKey; | 886 pPage->iKey = iKey; |
744 pPage->pNext = pCache->apHash[h]; | 887 pPage->pNext = pCache->apHash[h]; |
745 pPage->pCache = pCache; | 888 pPage->pCache = pCache; |
746 pPage->pLruPrev = 0; | 889 pPage->pLruPrev = 0; |
747 pPage->pLruNext = 0; | 890 pPage->pLruNext = 0; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 ** purgeable caches, | 944 ** purgeable caches, |
802 ** | 945 ** |
803 ** (c) The system is under memory pressure and wants to avoid | 946 ** (c) The system is under memory pressure and wants to avoid |
804 ** unnecessary pages cache entry allocations | 947 ** unnecessary pages cache entry allocations |
805 ** | 948 ** |
806 ** then attempt to recycle a page from the LRU list. If it is the right | 949 ** then attempt to recycle a page from the LRU list. If it is the right |
807 ** size, return the recycled buffer. Otherwise, free the buffer and | 950 ** size, return the recycled buffer. Otherwise, free the buffer and |
808 ** proceed to step 5. | 951 ** proceed to step 5. |
809 ** | 952 ** |
810 ** 5. Otherwise, allocate and return a new page buffer. | 953 ** 5. Otherwise, allocate and return a new page buffer. |
| 954 ** |
| 955 ** There are two versions of this routine. pcache1FetchWithMutex() is |
| 956 ** the general case. pcache1FetchNoMutex() is a faster implementation for |
| 957 ** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper |
| 958 ** invokes the appropriate routine. |
811 */ | 959 */ |
812 static sqlite3_pcache_page *pcache1Fetch( | 960 static PgHdr1 *pcache1FetchNoMutex( |
813 sqlite3_pcache *p, | 961 sqlite3_pcache *p, |
814 unsigned int iKey, | 962 unsigned int iKey, |
815 int createFlag | 963 int createFlag |
816 ){ | 964 ){ |
817 PCache1 *pCache = (PCache1 *)p; | 965 PCache1 *pCache = (PCache1 *)p; |
818 PgHdr1 *pPage = 0; | 966 PgHdr1 *pPage = 0; |
819 | 967 |
| 968 /* Step 1: Search the hash table for an existing entry. */ |
| 969 pPage = pCache->apHash[iKey % pCache->nHash]; |
| 970 while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } |
| 971 |
| 972 /* Step 2: If the page was found in the hash table, then return it. |
| 973 ** If the page was not in the hash table and createFlag is 0, abort. |
| 974 ** Otherwise (page not in hash and createFlag!=0) continue with |
| 975 ** subsequent steps to try to create the page. */ |
| 976 if( pPage ){ |
| 977 if( !pPage->isPinned ){ |
| 978 return pcache1PinPage(pPage); |
| 979 }else{ |
| 980 return pPage; |
| 981 } |
| 982 }else if( createFlag ){ |
| 983 /* Steps 3, 4, and 5 implemented by this subroutine */ |
| 984 return pcache1FetchStage2(pCache, iKey, createFlag); |
| 985 }else{ |
| 986 return 0; |
| 987 } |
| 988 } |
| 989 #if PCACHE1_MIGHT_USE_GROUP_MUTEX |
| 990 static PgHdr1 *pcache1FetchWithMutex( |
| 991 sqlite3_pcache *p, |
| 992 unsigned int iKey, |
| 993 int createFlag |
| 994 ){ |
| 995 PCache1 *pCache = (PCache1 *)p; |
| 996 PgHdr1 *pPage; |
| 997 |
| 998 pcache1EnterMutex(pCache->pGroup); |
| 999 pPage = pcache1FetchNoMutex(p, iKey, createFlag); |
| 1000 assert( pPage==0 || pCache->iMaxKey>=iKey ); |
| 1001 pcache1LeaveMutex(pCache->pGroup); |
| 1002 return pPage; |
| 1003 } |
| 1004 #endif |
| 1005 static sqlite3_pcache_page *pcache1Fetch( |
| 1006 sqlite3_pcache *p, |
| 1007 unsigned int iKey, |
| 1008 int createFlag |
| 1009 ){ |
| 1010 #if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG) |
| 1011 PCache1 *pCache = (PCache1 *)p; |
| 1012 #endif |
| 1013 |
820 assert( offsetof(PgHdr1,page)==0 ); | 1014 assert( offsetof(PgHdr1,page)==0 ); |
821 assert( pCache->bPurgeable || createFlag!=1 ); | 1015 assert( pCache->bPurgeable || createFlag!=1 ); |
822 assert( pCache->bPurgeable || pCache->nMin==0 ); | 1016 assert( pCache->bPurgeable || pCache->nMin==0 ); |
823 assert( pCache->bPurgeable==0 || pCache->nMin==10 ); | 1017 assert( pCache->bPurgeable==0 || pCache->nMin==10 ); |
824 assert( pCache->nMin==0 || pCache->bPurgeable ); | 1018 assert( pCache->nMin==0 || pCache->bPurgeable ); |
825 assert( pCache->nHash>0 ); | 1019 assert( pCache->nHash>0 ); |
826 pcache1EnterMutex(pCache->pGroup); | 1020 #if PCACHE1_MIGHT_USE_GROUP_MUTEX |
827 | 1021 if( pCache->pGroup->mutex ){ |
828 /* Step 1: Search the hash table for an existing entry. */ | 1022 return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag); |
829 pPage = pCache->apHash[iKey % pCache->nHash]; | 1023 }else |
830 while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } | 1024 #endif |
831 | 1025 { |
832 /* Step 2: Abort if no existing page is found and createFlag is 0 */ | 1026 return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag); |
833 if( pPage ){ | |
834 if( !pPage->isPinned ) pcache1PinPage(pPage); | |
835 }else if( createFlag ){ | |
836 /* Steps 3, 4, and 5 implemented by this subroutine */ | |
837 pPage = pcache1FetchStage2(pCache, iKey, createFlag); | |
838 } | 1027 } |
839 assert( pPage==0 || pCache->iMaxKey>=iKey ); | |
840 pcache1LeaveMutex(pCache->pGroup); | |
841 return (sqlite3_pcache_page*)pPage; | |
842 } | 1028 } |
843 | 1029 |
844 | 1030 |
845 /* | 1031 /* |
846 ** Implementation of the sqlite3_pcache.xUnpin method. | 1032 ** Implementation of the sqlite3_pcache.xUnpin method. |
847 ** | 1033 ** |
848 ** Mark a page as unpinned (eligible for asynchronous recycling). | 1034 ** Mark a page as unpinned (eligible for asynchronous recycling). |
849 */ | 1035 */ |
850 static void pcache1Unpin( | 1036 static void pcache1Unpin( |
851 sqlite3_pcache *p, | 1037 sqlite3_pcache *p, |
852 sqlite3_pcache_page *pPg, | 1038 sqlite3_pcache_page *pPg, |
853 int reuseUnlikely | 1039 int reuseUnlikely |
854 ){ | 1040 ){ |
855 PCache1 *pCache = (PCache1 *)p; | 1041 PCache1 *pCache = (PCache1 *)p; |
856 PgHdr1 *pPage = (PgHdr1 *)pPg; | 1042 PgHdr1 *pPage = (PgHdr1 *)pPg; |
857 PGroup *pGroup = pCache->pGroup; | 1043 PGroup *pGroup = pCache->pGroup; |
858 | 1044 |
859 assert( pPage->pCache==pCache ); | 1045 assert( pPage->pCache==pCache ); |
860 pcache1EnterMutex(pGroup); | 1046 pcache1EnterMutex(pGroup); |
861 | 1047 |
862 /* It is an error to call this function if the page is already | 1048 /* It is an error to call this function if the page is already |
863 ** part of the PGroup LRU list. | 1049 ** part of the PGroup LRU list. |
864 */ | 1050 */ |
865 assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); | 1051 assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); |
866 assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); | |
867 assert( pPage->isPinned==1 ); | 1052 assert( pPage->isPinned==1 ); |
868 | 1053 |
869 if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ | 1054 if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ |
870 pcache1RemoveFromHash(pPage); | 1055 pcache1RemoveFromHash(pPage, 1); |
871 pcache1FreePage(pPage); | |
872 }else{ | 1056 }else{ |
873 /* Add the page to the PGroup LRU list. */ | 1057 /* Add the page to the PGroup LRU list. */ |
874 if( pGroup->pLruHead ){ | 1058 PgHdr1 **ppFirst = &pGroup->lru.pLruNext; |
875 pGroup->pLruHead->pLruPrev = pPage; | 1059 pPage->pLruPrev = &pGroup->lru; |
876 pPage->pLruNext = pGroup->pLruHead; | 1060 (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; |
877 pGroup->pLruHead = pPage; | 1061 *ppFirst = pPage; |
878 }else{ | |
879 pGroup->pLruTail = pPage; | |
880 pGroup->pLruHead = pPage; | |
881 } | |
882 pCache->nRecyclable++; | 1062 pCache->nRecyclable++; |
883 pPage->isPinned = 0; | 1063 pPage->isPinned = 0; |
884 } | 1064 } |
885 | 1065 |
886 pcache1LeaveMutex(pCache->pGroup); | 1066 pcache1LeaveMutex(pCache->pGroup); |
887 } | 1067 } |
888 | 1068 |
889 /* | 1069 /* |
890 ** Implementation of the sqlite3_pcache.xRekey method. | 1070 ** Implementation of the sqlite3_pcache.xRekey method. |
891 */ | 1071 */ |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
948 PCache1 *pCache = (PCache1 *)p; | 1128 PCache1 *pCache = (PCache1 *)p; |
949 PGroup *pGroup = pCache->pGroup; | 1129 PGroup *pGroup = pCache->pGroup; |
950 assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); | 1130 assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); |
951 pcache1EnterMutex(pGroup); | 1131 pcache1EnterMutex(pGroup); |
952 pcache1TruncateUnsafe(pCache, 0); | 1132 pcache1TruncateUnsafe(pCache, 0); |
953 assert( pGroup->nMaxPage >= pCache->nMax ); | 1133 assert( pGroup->nMaxPage >= pCache->nMax ); |
954 pGroup->nMaxPage -= pCache->nMax; | 1134 pGroup->nMaxPage -= pCache->nMax; |
955 assert( pGroup->nMinPage >= pCache->nMin ); | 1135 assert( pGroup->nMinPage >= pCache->nMin ); |
956 pGroup->nMinPage -= pCache->nMin; | 1136 pGroup->nMinPage -= pCache->nMin; |
957 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; | 1137 pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; |
958 pcache1EnforceMaxPage(pGroup); | 1138 pcache1EnforceMaxPage(pCache); |
959 pcache1LeaveMutex(pGroup); | 1139 pcache1LeaveMutex(pGroup); |
| 1140 sqlite3_free(pCache->pBulk); |
960 sqlite3_free(pCache->apHash); | 1141 sqlite3_free(pCache->apHash); |
961 sqlite3_free(pCache); | 1142 sqlite3_free(pCache); |
962 } | 1143 } |
963 | 1144 |
964 /* | 1145 /* |
965 ** This function is called during initialization (sqlite3_initialize()) to | 1146 ** This function is called during initialization (sqlite3_initialize()) to |
966 ** install the default pluggable cache module, assuming the user has not | 1147 ** install the default pluggable cache module, assuming the user has not |
967 ** already provided an alternative. | 1148 ** already provided an alternative. |
968 */ | 1149 */ |
969 void sqlite3PCacheSetDefault(void){ | 1150 void sqlite3PCacheSetDefault(void){ |
970 static const sqlite3_pcache_methods2 defaultMethods = { | 1151 static const sqlite3_pcache_methods2 defaultMethods = { |
971 1, /* iVersion */ | 1152 1, /* iVersion */ |
972 0, /* pArg */ | 1153 0, /* pArg */ |
973 pcache1Init, /* xInit */ | 1154 pcache1Init, /* xInit */ |
974 pcache1Shutdown, /* xShutdown */ | 1155 pcache1Shutdown, /* xShutdown */ |
975 pcache1Create, /* xCreate */ | 1156 pcache1Create, /* xCreate */ |
976 pcache1Cachesize, /* xCachesize */ | 1157 pcache1Cachesize, /* xCachesize */ |
977 pcache1Pagecount, /* xPagecount */ | 1158 pcache1Pagecount, /* xPagecount */ |
978 pcache1Fetch, /* xFetch */ | 1159 pcache1Fetch, /* xFetch */ |
979 pcache1Unpin, /* xUnpin */ | 1160 pcache1Unpin, /* xUnpin */ |
980 pcache1Rekey, /* xRekey */ | 1161 pcache1Rekey, /* xRekey */ |
981 pcache1Truncate, /* xTruncate */ | 1162 pcache1Truncate, /* xTruncate */ |
982 pcache1Destroy, /* xDestroy */ | 1163 pcache1Destroy, /* xDestroy */ |
983 pcache1Shrink /* xShrink */ | 1164 pcache1Shrink /* xShrink */ |
984 }; | 1165 }; |
985 sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); | 1166 sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); |
986 } | 1167 } |
987 | 1168 |
| 1169 /* |
| 1170 ** Return the size of the header on each page of this PCACHE implementation. |
| 1171 */ |
| 1172 int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } |
| 1173 |
| 1174 /* |
| 1175 ** Return the global mutex used by this PCACHE implementation. The |
| 1176 ** sqlite3_status() routine needs access to this mutex. |
| 1177 */ |
| 1178 sqlite3_mutex *sqlite3Pcache1Mutex(void){ |
| 1179 return pcache1.mutex; |
| 1180 } |
| 1181 |
988 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | 1182 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
989 /* | 1183 /* |
990 ** This function is called to free superfluous dynamically allocated memory | 1184 ** This function is called to free superfluous dynamically allocated memory |
991 ** held by the pager system. Memory in use by any SQLite pager allocated | 1185 ** held by the pager system. Memory in use by any SQLite pager allocated |
992 ** by the current thread may be sqlite3_free()ed. | 1186 ** by the current thread may be sqlite3_free()ed. |
993 ** | 1187 ** |
994 ** nReq is the number of bytes of memory required. Once this much has | 1188 ** nReq is the number of bytes of memory required. Once this much has |
995 ** been released, the function returns. The return value is the total number | 1189 ** been released, the function returns. The return value is the total number |
996 ** of bytes of memory released. | 1190 ** of bytes of memory released. |
997 */ | 1191 */ |
998 int sqlite3PcacheReleaseMemory(int nReq){ | 1192 int sqlite3PcacheReleaseMemory(int nReq){ |
999 int nFree = 0; | 1193 int nFree = 0; |
1000 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); | 1194 assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); |
1001 assert( sqlite3_mutex_notheld(pcache1.mutex) ); | 1195 assert( sqlite3_mutex_notheld(pcache1.mutex) ); |
1002 if( pcache1.pStart==0 ){ | 1196 if( sqlite3GlobalConfig.nPage==0 ){ |
1003 PgHdr1 *p; | 1197 PgHdr1 *p; |
1004 pcache1EnterMutex(&pcache1.grp); | 1198 pcache1EnterMutex(&pcache1.grp); |
1005 while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){ | 1199 while( (nReq<0 || nFree<nReq) |
| 1200 && (p=pcache1.grp.lru.pLruPrev)!=0 |
| 1201 && p->isAnchor==0 |
| 1202 ){ |
1006 nFree += pcache1MemSize(p->page.pBuf); | 1203 nFree += pcache1MemSize(p->page.pBuf); |
1007 #ifdef SQLITE_PCACHE_SEPARATE_HEADER | 1204 #ifdef SQLITE_PCACHE_SEPARATE_HEADER |
1008 nFree += sqlite3MemSize(p); | 1205 nFree += sqlite3MemSize(p); |
1009 #endif | 1206 #endif |
1010 assert( p->isPinned==0 ); | 1207 assert( p->isPinned==0 ); |
1011 pcache1PinPage(p); | 1208 pcache1PinPage(p); |
1012 pcache1RemoveFromHash(p); | 1209 pcache1RemoveFromHash(p, 1); |
1013 pcache1FreePage(p); | |
1014 } | 1210 } |
1015 pcache1LeaveMutex(&pcache1.grp); | 1211 pcache1LeaveMutex(&pcache1.grp); |
1016 } | 1212 } |
1017 return nFree; | 1213 return nFree; |
1018 } | 1214 } |
1019 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ | 1215 #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ |
1020 | 1216 |
1021 #ifdef SQLITE_TEST | 1217 #ifdef SQLITE_TEST |
1022 /* | 1218 /* |
1023 ** This function is used by test procedures to inspect the internal state | 1219 ** This function is used by test procedures to inspect the internal state |
1024 ** of the global cache. | 1220 ** of the global cache. |
1025 */ | 1221 */ |
1026 void sqlite3PcacheStats( | 1222 void sqlite3PcacheStats( |
1027 int *pnCurrent, /* OUT: Total number of pages cached */ | 1223 int *pnCurrent, /* OUT: Total number of pages cached */ |
1028 int *pnMax, /* OUT: Global maximum cache size */ | 1224 int *pnMax, /* OUT: Global maximum cache size */ |
1029 int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */ | 1225 int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */ |
1030 int *pnRecyclable /* OUT: Total number of pages available for recycling */ | 1226 int *pnRecyclable /* OUT: Total number of pages available for recycling */ |
1031 ){ | 1227 ){ |
1032 PgHdr1 *p; | 1228 PgHdr1 *p; |
1033 int nRecyclable = 0; | 1229 int nRecyclable = 0; |
1034 for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ | 1230 for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ |
1035 assert( p->isPinned==0 ); | 1231 assert( p->isPinned==0 ); |
1036 nRecyclable++; | 1232 nRecyclable++; |
1037 } | 1233 } |
1038 *pnCurrent = pcache1.grp.nCurrentPage; | 1234 *pnCurrent = pcache1.grp.nCurrentPage; |
1039 *pnMax = (int)pcache1.grp.nMaxPage; | 1235 *pnMax = (int)pcache1.grp.nMaxPage; |
1040 *pnMin = (int)pcache1.grp.nMinPage; | 1236 *pnMin = (int)pcache1.grp.nMinPage; |
1041 *pnRecyclable = nRecyclable; | 1237 *pnRecyclable = nRecyclable; |
1042 } | 1238 } |
1043 #endif | 1239 #endif |
OLD | NEW |