xref: /sqlite-3.40.0/ext/lsm1/lsm_shared.c (revision ba334bb2)
1 /*
2 ** 2012-01-23
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** Utilities used to help multiple LSM clients to coexist within the
14 ** same process space.
15 */
16 #include "lsmInt.h"
17 
18 /*
19 ** Global data. All global variables used by code in this file are grouped
20 ** into the following structure instance.
21 **
22 ** pDatabase:
23 **   Linked list of all Database objects allocated within this process.
24 **   This list may not be traversed without holding the global mutex (see
25 **   functions enterGlobalMutex() and leaveGlobalMutex()).
26 */
27 static struct SharedData {
28   Database *pDatabase;            /* Linked list of all Database objects */
29 } gShared;
30 
31 /*
32 ** Database structure. There is one such structure for each distinct
33 ** database accessed by this process. They are stored in the singly linked
34 ** list starting at global variable gShared.pDatabase. Database objects are
35 ** reference counted. Once the number of connections to the associated
36 ** database drops to zero, they are removed from the linked list and deleted.
37 **
38 ** pFile:
39 **   In multi-process mode, this file descriptor is used to obtain locks
40 **   and to access shared-memory. In single process mode, its only job is
41 **   to hold the exclusive lock on the file.
42 **
43 */
44 struct Database {
45   /* Protected by the global mutex (enterGlobalMutex/leaveGlobalMutex): */
46   char *zName;                    /* Canonical path to database file */
47   int nName;                      /* strlen(zName) */
48   int nDbRef;                     /* Number of associated lsm_db handles */
49   Database *pDbNext;              /* Next Database structure in global list */
50 
51   /* Protected by the local mutex (pClientMutex) */
52   int bReadonly;                  /* True if Database.pFile is read-only */
53   int bMultiProc;                 /* True if running in multi-process mode */
54   lsm_file *pFile;                /* Used for locks/shm in multi-proc mode */
55   LsmFile *pLsmFile;              /* List of deferred closes */
56   lsm_mutex *pClientMutex;        /* Protects the apShmChunk[] and pConn */
57   int nShmChunk;                  /* Number of entries in apShmChunk[] array */
58   void **apShmChunk;              /* Array of "shared" memory regions */
59   lsm_db *pConn;                  /* List of connections to this db. */
60 };
61 
62 /*
63 ** Functions to enter and leave the global mutex. This mutex is used
64 ** to protect the global linked-list headed at gShared.pDatabase.
65 */
66 static int enterGlobalMutex(lsm_env *pEnv){
67   lsm_mutex *p;
68   int rc = lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
69   if( rc==LSM_OK ) lsmMutexEnter(pEnv, p);
70   return rc;
71 }
72 static void leaveGlobalMutex(lsm_env *pEnv){
73   lsm_mutex *p;
74   lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
75   lsmMutexLeave(pEnv, p);
76 }
77 
78 #ifdef LSM_DEBUG
79 static int holdingGlobalMutex(lsm_env *pEnv){
80   lsm_mutex *p;
81   lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
82   return lsmMutexHeld(pEnv, p);
83 }
84 #endif
85 
86 #if 0
87 static void assertNotInFreelist(Freelist *p, int iBlk){
88   int i;
89   for(i=0; i<p->nEntry; i++){
90     assert( p->aEntry[i].iBlk!=iBlk );
91   }
92 }
93 #else
94 # define assertNotInFreelist(x,y)
95 #endif
96 
97 /*
98 ** Append an entry to the free-list. If (iId==-1), this is a delete.
99 */
100 int freelistAppend(lsm_db *db, u32 iBlk, i64 iId){
101   lsm_env *pEnv = db->pEnv;
102   Freelist *p;
103   int i;
104 
105   assert( iId==-1 || iId>=0 );
106   p = db->bUseFreelist ? db->pFreelist : &db->pWorker->freelist;
107 
108   /* Extend the space allocated for the freelist, if required */
109   assert( p->nAlloc>=p->nEntry );
110   if( p->nAlloc==p->nEntry ){
111     int nNew;
112     int nByte;
113     FreelistEntry *aNew;
114 
115     nNew = (p->nAlloc==0 ? 4 : p->nAlloc*2);
116     nByte = sizeof(FreelistEntry) * nNew;
117     aNew = (FreelistEntry *)lsmRealloc(pEnv, p->aEntry, nByte);
118     if( !aNew ) return LSM_NOMEM_BKPT;
119     p->nAlloc = nNew;
120     p->aEntry = aNew;
121   }
122 
123   for(i=0; i<p->nEntry; i++){
124     assert( i==0 || p->aEntry[i].iBlk > p->aEntry[i-1].iBlk );
125     if( p->aEntry[i].iBlk>=iBlk ) break;
126   }
127 
128   if( i<p->nEntry && p->aEntry[i].iBlk==iBlk ){
129     /* Clobber an existing entry */
130     p->aEntry[i].iId = iId;
131   }else{
132     /* Insert a new entry into the list */
133     int nByte = sizeof(FreelistEntry)*(p->nEntry-i);
134     memmove(&p->aEntry[i+1], &p->aEntry[i], nByte);
135     p->aEntry[i].iBlk = iBlk;
136     p->aEntry[i].iId = iId;
137     p->nEntry++;
138   }
139 
140   return LSM_OK;
141 }
142 
143 /*
144 ** This function frees all resources held by the Database structure passed
145 ** as the only argument.
146 */
147 static void freeDatabase(lsm_env *pEnv, Database *p){
148   assert( holdingGlobalMutex(pEnv) );
149   if( p ){
150     /* Free the mutexes */
151     lsmMutexDel(pEnv, p->pClientMutex);
152 
153     if( p->pFile ){
154       lsmEnvClose(pEnv, p->pFile);
155     }
156 
157     /* Free the array of shm pointers */
158     lsmFree(pEnv, p->apShmChunk);
159 
160     /* Free the memory allocated for the Database struct itself */
161     lsmFree(pEnv, p);
162   }
163 }
164 
165 typedef struct DbTruncateCtx DbTruncateCtx;
166 struct DbTruncateCtx {
167   int nBlock;
168   i64 iInUse;
169 };
170 
171 static int dbTruncateCb(void *pCtx, int iBlk, i64 iSnapshot){
172   DbTruncateCtx *p = (DbTruncateCtx *)pCtx;
173   if( iBlk!=p->nBlock || (p->iInUse>=0 && iSnapshot>=p->iInUse) ) return 1;
174   p->nBlock--;
175   return 0;
176 }
177 
178 static int dbTruncate(lsm_db *pDb, i64 iInUse){
179   int rc = LSM_OK;
180 #if 0
181   int i;
182   DbTruncateCtx ctx;
183 
184   assert( pDb->pWorker );
185   ctx.nBlock = pDb->pWorker->nBlock;
186   ctx.iInUse = iInUse;
187 
188   rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);
189   for(i=ctx.nBlock+1; rc==LSM_OK && i<=pDb->pWorker->nBlock; i++){
190     rc = freelistAppend(pDb, i, -1);
191   }
192 
193   if( rc==LSM_OK ){
194 #ifdef LSM_LOG_FREELIST
195     if( ctx.nBlock!=pDb->pWorker->nBlock ){
196       lsmLogMessage(pDb, 0,
197           "dbTruncate(): truncated db to %d blocks",ctx.nBlock
198       );
199     }
200 #endif
201     pDb->pWorker->nBlock = ctx.nBlock;
202   }
203 #endif
204   return rc;
205 }
206 
207 
208 /*
209 ** This function is called during database shutdown (when the number of
210 ** connections drops from one to zero). It truncates the database file
211 ** to as small a size as possible without truncating away any blocks that
212 ** contain data.
213 */
214 static int dbTruncateFile(lsm_db *pDb){
215   int rc;
216 
217   assert( pDb->pWorker==0 );
218   assert( lsmShmAssertLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL) );
219   rc = lsmCheckpointLoadWorker(pDb);
220 
221   if( rc==LSM_OK ){
222     DbTruncateCtx ctx;
223 
224     /* Walk the database free-block-list in reverse order. Set ctx.nBlock
225     ** to the block number of the last block in the database that actually
226     ** contains data. */
227     ctx.nBlock = pDb->pWorker->nBlock;
228     ctx.iInUse = -1;
229     rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);
230 
231     /* If the last block that contains data is not already the last block in
232     ** the database file, truncate the database file so that it is. */
233     if( rc==LSM_OK && ctx.nBlock!=pDb->pWorker->nBlock ){
234       rc = lsmFsTruncateDb(
235           pDb->pFS, (i64)ctx.nBlock*lsmFsBlockSize(pDb->pFS)
236       );
237     }
238   }
239 
240   lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
241   pDb->pWorker = 0;
242   return rc;
243 }
244 
245 static void doDbDisconnect(lsm_db *pDb){
246   int rc;
247 
248   if( pDb->bReadonly ){
249     lsmShmLock(pDb, LSM_LOCK_DMS3, LSM_LOCK_UNLOCK, 0);
250   }else{
251     /* Block for an exclusive lock on DMS1. This lock serializes all calls
252     ** to doDbConnect() and doDbDisconnect() across all processes.  */
253     rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
254     if( rc==LSM_OK ){
255 
256       lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0);
257 
258       /* Try an exclusive lock on DMS2. If successful, this is the last
259       ** connection to the database. In this case flush the contents of the
260       ** in-memory tree to disk and write a checkpoint.  */
261       rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 1, LSM_LOCK_EXCL);
262       if( rc==LSM_OK ){
263         rc = lsmShmTestLock(pDb, LSM_LOCK_CHECKPOINTER, 1, LSM_LOCK_EXCL);
264       }
265       if( rc==LSM_OK ){
266         int bReadonly = 0;        /* True if there exist read-only conns. */
267 
268         /* Flush the in-memory tree, if required. If there is data to flush,
269         ** this will create a new client snapshot in Database.pClient. The
270         ** checkpoint (serialization) of this snapshot may be written to disk
271         ** by the following block.
272         **
273         ** There is no need to take a WRITER lock here. That there are no
274         ** other locks on DMS2 guarantees that there are no other read-write
275         ** connections at this time (and the lock on DMS1 guarantees that
276         ** no new ones may appear).
277         */
278         rc = lsmTreeLoadHeader(pDb, 0);
279         if( rc==LSM_OK && (lsmTreeHasOld(pDb) || lsmTreeSize(pDb)>0) ){
280           rc = lsmFlushTreeToDisk(pDb);
281         }
282 
283         /* Now check if there are any read-only connections. If there are,
284         ** then do not truncate the db file or unlink the shared-memory
285         ** region.  */
286         if( rc==LSM_OK ){
287           rc = lsmShmTestLock(pDb, LSM_LOCK_DMS3, 1, LSM_LOCK_EXCL);
288           if( rc==LSM_BUSY ){
289             bReadonly = 1;
290             rc = LSM_OK;
291           }
292         }
293 
294         /* Write a checkpoint to disk. */
295         if( rc==LSM_OK ){
296           rc = lsmCheckpointWrite(pDb, (bReadonly==0), 0);
297         }
298 
299         /* If the checkpoint was written successfully, delete the log file
300         ** and, if possible, truncate the database file.  */
301         if( rc==LSM_OK ){
302           int bRotrans = 0;
303           Database *p = pDb->pDatabase;
304 
305           /* The log file may only be deleted if there are no clients
306           ** read-only clients running rotrans transactions.  */
307           rc = lsmDetectRoTrans(pDb, &bRotrans);
308           if( rc==LSM_OK && bRotrans==0 ){
309             lsmFsCloseAndDeleteLog(pDb->pFS);
310           }
311 
312           /* The database may only be truncated if there exist no read-only
313           ** clients - either connected or running rotrans transactions. */
314           if( bReadonly==0 && bRotrans==0 ){
315             dbTruncateFile(pDb);
316             if( p->pFile && p->bMultiProc ){
317               lsmEnvShmUnmap(pDb->pEnv, p->pFile, 1);
318             }
319           }
320         }
321       }
322     }
323 
324     if( pDb->iRwclient>=0 ){
325       lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0);
326       pDb->iRwclient = -1;
327     }
328 
329     lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
330   }
331   pDb->pShmhdr = 0;
332 }
333 
334 static int doDbConnect(lsm_db *pDb){
335   const int nUsMax = 100000;      /* Max value for nUs */
336   int nUs = 1000;                 /* us to wait between DMS1 attempts */
337   int rc;
338 
339   /* Obtain a pointer to the shared-memory header */
340   assert( pDb->pShmhdr==0 );
341   assert( pDb->bReadonly==0 );
342   rc = lsmShmCacheChunks(pDb, 1);
343   if( rc!=LSM_OK ) return rc;
344   pDb->pShmhdr = (ShmHeader *)pDb->apShm[0];
345 
346   /* Block for an exclusive lock on DMS1. This lock serializes all calls
347   ** to doDbConnect() and doDbDisconnect() across all processes.  */
348   while( 1 ){
349     rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
350     if( rc!=LSM_BUSY ) break;
351     lsmEnvSleep(pDb->pEnv, nUs);
352     nUs = nUs * 2;
353     if( nUs>nUsMax ) nUs = nUsMax;
354   }
355   if( rc!=LSM_OK ){
356     pDb->pShmhdr = 0;
357     return rc;
358   }
359 
360   /* Try an exclusive lock on DMS2/DMS3. If successful, this is the first
361   ** and only connection to the database. In this case initialize the
362   ** shared-memory and run log file recovery.  */
363   assert( LSM_LOCK_DMS3==1+LSM_LOCK_DMS2 );
364   rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 2, LSM_LOCK_EXCL);
365   if( rc==LSM_OK ){
366     memset(pDb->pShmhdr, 0, sizeof(ShmHeader));
367     rc = lsmCheckpointRecover(pDb);
368     if( rc==LSM_OK ){
369       rc = lsmLogRecover(pDb);
370     }
371     if( rc==LSM_OK ){
372       ShmHeader *pShm = pDb->pShmhdr;
373       pShm->aReader[0].iLsmId = lsmCheckpointId(pShm->aSnap1, 0);
374       pShm->aReader[0].iTreeId = pDb->treehdr.iUsedShmid;
375     }
376   }else if( rc==LSM_BUSY ){
377     rc = LSM_OK;
378   }
379 
380   /* Take a shared lock on DMS2. In multi-process mode this lock "cannot"
381   ** fail, as connections may only hold an exclusive lock on DMS2 if they
382   ** first hold an exclusive lock on DMS1. And this connection is currently
383   ** holding the exclusive lock on DSM1.
384   **
385   ** However, if some other connection has the database open in single-process
386   ** mode, this operation will fail. In this case, return the error to the
387   ** caller - the attempt to connect to the db has failed.
388   */
389   if( rc==LSM_OK ){
390     rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_SHARED, 0);
391   }
392 
393   /* If anything went wrong, unlock DMS2. Otherwise, try to take an exclusive
394   ** lock on one of the LSM_LOCK_RWCLIENT() locks. Unlock DMS1 in any case. */
395   if( rc!=LSM_OK ){
396     pDb->pShmhdr = 0;
397   }else{
398     int i;
399     for(i=0; i<LSM_LOCK_NRWCLIENT; i++){
400       int rc2 = lsmShmLock(pDb, LSM_LOCK_RWCLIENT(i), LSM_LOCK_EXCL, 0);
401       if( rc2==LSM_OK ) pDb->iRwclient = i;
402       if( rc2!=LSM_BUSY ){
403         rc = rc2;
404         break;
405       }
406     }
407   }
408   lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
409 
410   return rc;
411 }
412 
413 static int dbOpenSharedFd(lsm_env *pEnv, Database *p, int bRoOk){
414   int rc;
415 
416   rc = lsmEnvOpen(pEnv, p->zName, 0, &p->pFile);
417   if( rc==LSM_IOERR && bRoOk ){
418     rc = lsmEnvOpen(pEnv, p->zName, LSM_OPEN_READONLY, &p->pFile);
419     p->bReadonly = 1;
420   }
421 
422   return rc;
423 }
424 
425 /*
426 ** Return a reference to the shared Database handle for the database
427 ** identified by canonical path zName. If this is the first connection to
428 ** the named database, a new Database object is allocated. Otherwise, a
429 ** pointer to an existing object is returned.
430 **
431 ** If successful, *ppDatabase is set to point to the shared Database
432 ** structure and LSM_OK returned. Otherwise, *ppDatabase is set to NULL
433 ** and and LSM error code returned.
434 **
435 ** Each successful call to this function should be (eventually) matched
436 ** by a call to lsmDbDatabaseRelease().
437 */
438 int lsmDbDatabaseConnect(
439   lsm_db *pDb,                    /* Database handle */
440   const char *zName               /* Full-path to db file */
441 ){
442   lsm_env *pEnv = pDb->pEnv;
443   int rc;                         /* Return code */
444   Database *p = 0;                /* Pointer returned via *ppDatabase */
445   int nName = lsmStrlen(zName);
446 
447   assert( pDb->pDatabase==0 );
448   rc = enterGlobalMutex(pEnv);
449   if( rc==LSM_OK ){
450 
451     /* Search the global list for an existing object. TODO: Need something
452     ** better than the memcmp() below to figure out if a given Database
453     ** object represents the requested file.  */
454     for(p=gShared.pDatabase; p; p=p->pDbNext){
455       if( nName==p->nName && 0==memcmp(zName, p->zName, nName) ) break;
456     }
457 
458     /* If no suitable Database object was found, allocate a new one. */
459     if( p==0 ){
460       p = (Database *)lsmMallocZeroRc(pEnv, sizeof(Database)+nName+1, &rc);
461 
462       /* If the allocation was successful, fill in other fields and
463       ** allocate the client mutex. */
464       if( rc==LSM_OK ){
465         p->bMultiProc = pDb->bMultiProc;
466         p->zName = (char *)&p[1];
467         p->nName = nName;
468         memcpy((void *)p->zName, zName, nName+1);
469         rc = lsmMutexNew(pEnv, &p->pClientMutex);
470       }
471 
472       /* If nothing has gone wrong so far, open the shared fd. And if that
473       ** succeeds and this connection requested single-process mode,
474       ** attempt to take the exclusive lock on DMS2.  */
475       if( rc==LSM_OK ){
476         int bReadonly = (pDb->bReadonly && pDb->bMultiProc);
477         rc = dbOpenSharedFd(pDb->pEnv, p, bReadonly);
478       }
479 
480       if( rc==LSM_OK && p->bMultiProc==0 ){
481         /* Hold an exclusive lock DMS1 while grabbing DMS2. This ensures
482         ** that any ongoing call to doDbDisconnect() (even one in another
483         ** process) is finished before proceeding.  */
484         assert( p->bReadonly==0 );
485         rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_EXCL);
486         if( rc==LSM_OK ){
487           rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS2, LSM_LOCK_EXCL);
488           lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK);
489         }
490       }
491 
492       if( rc==LSM_OK ){
493         p->pDbNext = gShared.pDatabase;
494         gShared.pDatabase = p;
495       }else{
496         freeDatabase(pEnv, p);
497         p = 0;
498       }
499     }
500 
501     if( p ){
502       p->nDbRef++;
503     }
504     leaveGlobalMutex(pEnv);
505 
506     if( p ){
507       lsmMutexEnter(pDb->pEnv, p->pClientMutex);
508       pDb->pNext = p->pConn;
509       p->pConn = pDb;
510       lsmMutexLeave(pDb->pEnv, p->pClientMutex);
511     }
512   }
513 
514   pDb->pDatabase = p;
515   if( rc==LSM_OK ){
516     assert( p );
517     rc = lsmFsOpen(pDb, zName, p->bReadonly);
518   }
519 
520   /* If the db handle is read-write, then connect to the system now. Run
521   ** recovery as necessary. Or, if this is a read-only database handle,
522   ** defer attempting to connect to the system until a read-transaction
523   ** is opened.  */
524   if( pDb->bReadonly==0 ){
525     if( rc==LSM_OK ){
526       rc = lsmFsConfigure(pDb);
527     }
528     if( rc==LSM_OK ){
529       rc = doDbConnect(pDb);
530     }
531   }
532 
533   return rc;
534 }
535 
536 static void dbDeferClose(lsm_db *pDb){
537   if( pDb->pFS ){
538     LsmFile *pLsmFile;
539     Database *p = pDb->pDatabase;
540     pLsmFile = lsmFsDeferClose(pDb->pFS);
541     pLsmFile->pNext = p->pLsmFile;
542     p->pLsmFile = pLsmFile;
543   }
544 }
545 
546 LsmFile *lsmDbRecycleFd(lsm_db *db){
547   LsmFile *pRet;
548   Database *p = db->pDatabase;
549   lsmMutexEnter(db->pEnv, p->pClientMutex);
550   if( (pRet = p->pLsmFile)!=0 ){
551     p->pLsmFile = pRet->pNext;
552   }
553   lsmMutexLeave(db->pEnv, p->pClientMutex);
554   return pRet;
555 }
556 
557 /*
558 ** Release a reference to a Database object obtained from
559 ** lsmDbDatabaseConnect(). There should be exactly one call to this function
560 ** for each successful call to Find().
561 */
562 void lsmDbDatabaseRelease(lsm_db *pDb){
563   Database *p = pDb->pDatabase;
564   if( p ){
565     lsm_db **ppDb;
566 
567     if( pDb->pShmhdr ){
568       doDbDisconnect(pDb);
569     }
570 
571     lsmMutexEnter(pDb->pEnv, p->pClientMutex);
572     for(ppDb=&p->pConn; *ppDb!=pDb; ppDb=&((*ppDb)->pNext));
573     *ppDb = pDb->pNext;
574     dbDeferClose(pDb);
575     lsmMutexLeave(pDb->pEnv, p->pClientMutex);
576 
577     enterGlobalMutex(pDb->pEnv);
578     p->nDbRef--;
579     if( p->nDbRef==0 ){
580       LsmFile *pIter;
581       LsmFile *pNext;
582       Database **pp;
583 
584       /* Remove the Database structure from the linked list. */
585       for(pp=&gShared.pDatabase; *pp!=p; pp=&((*pp)->pDbNext));
586       *pp = p->pDbNext;
587 
588       /* If they were allocated from the heap, free the shared memory chunks */
589       if( p->bMultiProc==0 ){
590         int i;
591         for(i=0; i<p->nShmChunk; i++){
592           lsmFree(pDb->pEnv, p->apShmChunk[i]);
593         }
594       }
595 
596       /* Close any outstanding file descriptors */
597       for(pIter=p->pLsmFile; pIter; pIter=pNext){
598         pNext = pIter->pNext;
599         lsmEnvClose(pDb->pEnv, pIter->pFile);
600         lsmFree(pDb->pEnv, pIter);
601       }
602       freeDatabase(pDb->pEnv, p);
603     }
604     leaveGlobalMutex(pDb->pEnv);
605   }
606 }
607 
608 Level *lsmDbSnapshotLevel(Snapshot *pSnapshot){
609   return pSnapshot->pLevel;
610 }
611 
612 void lsmDbSnapshotSetLevel(Snapshot *pSnap, Level *pLevel){
613   pSnap->pLevel = pLevel;
614 }
615 
616 /* TODO: Shuffle things around to get rid of this */
617 static int firstSnapshotInUse(lsm_db *, i64 *);
618 
619 /*
620 ** Context object used by the lsmWalkFreelist() utility.
621 */
622 typedef struct WalkFreelistCtx WalkFreelistCtx;
623 struct WalkFreelistCtx {
624   lsm_db *pDb;
625   int bReverse;
626   Freelist *pFreelist;
627   int iFree;
628   int (*xUsr)(void *, int, i64);  /* User callback function */
629   void *pUsrctx;                  /* User callback context */
630   int bDone;                      /* Set to true after xUsr() returns true */
631 };
632 
633 /*
634 ** Callback used by lsmWalkFreelist().
635 */
636 static int walkFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
637   WalkFreelistCtx *p = (WalkFreelistCtx *)pCtx;
638   const int iDir = (p->bReverse ? -1 : 1);
639   Freelist *pFree = p->pFreelist;
640 
641   assert( p->bDone==0 );
642   assert( iBlk>=0 );
643   if( pFree ){
644     while( (p->iFree < pFree->nEntry) && p->iFree>=0 ){
645       FreelistEntry *pEntry = &pFree->aEntry[p->iFree];
646       if( (p->bReverse==0 && pEntry->iBlk>(u32)iBlk)
647        || (p->bReverse!=0 && pEntry->iBlk<(u32)iBlk)
648       ){
649         break;
650       }else{
651         p->iFree += iDir;
652         if( pEntry->iId>=0
653             && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId)
654           ){
655           p->bDone = 1;
656           return 1;
657         }
658         if( pEntry->iBlk==(u32)iBlk ) return 0;
659       }
660     }
661   }
662 
663   if( p->xUsr(p->pUsrctx, iBlk, iSnapshot) ){
664     p->bDone = 1;
665     return 1;
666   }
667   return 0;
668 }
669 
670 /*
671 ** The database handle passed as the first argument must be the worker
672 ** connection. This function iterates through the contents of the current
673 ** free block list, invoking the supplied callback once for each list
674 ** element.
675 **
676 ** The difference between this function and lsmSortedWalkFreelist() is
677 ** that lsmSortedWalkFreelist() only considers those free-list elements
678 ** stored within the LSM. This function also merges in any in-memory
679 ** elements.
680 */
681 int lsmWalkFreelist(
682   lsm_db *pDb,                    /* Database handle (must be worker) */
683   int bReverse,                   /* True to iterate from largest to smallest */
684   int (*x)(void *, int, i64),     /* Callback function */
685   void *pCtx                      /* First argument to pass to callback */
686 ){
687   const int iDir = (bReverse ? -1 : 1);
688   int rc;
689   int iCtx;
690 
691   WalkFreelistCtx ctx[2];
692 
693   ctx[0].pDb = pDb;
694   ctx[0].bReverse = bReverse;
695   ctx[0].pFreelist = &pDb->pWorker->freelist;
696   if( ctx[0].pFreelist && bReverse ){
697     ctx[0].iFree = ctx[0].pFreelist->nEntry-1;
698   }else{
699     ctx[0].iFree = 0;
700   }
701   ctx[0].xUsr = walkFreelistCb;
702   ctx[0].pUsrctx = (void *)&ctx[1];
703   ctx[0].bDone = 0;
704 
705   ctx[1].pDb = pDb;
706   ctx[1].bReverse = bReverse;
707   ctx[1].pFreelist = pDb->pFreelist;
708   if( ctx[1].pFreelist && bReverse ){
709     ctx[1].iFree = ctx[1].pFreelist->nEntry-1;
710   }else{
711     ctx[1].iFree = 0;
712   }
713   ctx[1].xUsr = x;
714   ctx[1].pUsrctx = pCtx;
715   ctx[1].bDone = 0;
716 
717   rc = lsmSortedWalkFreelist(pDb, bReverse, walkFreelistCb, (void *)&ctx[0]);
718 
719   if( ctx[0].bDone==0 ){
720     for(iCtx=0; iCtx<2; iCtx++){
721       int i;
722       WalkFreelistCtx *p = &ctx[iCtx];
723       for(i=p->iFree;
724           p->pFreelist && rc==LSM_OK && i<p->pFreelist->nEntry && i>=0;
725           i += iDir
726          ){
727         FreelistEntry *pEntry = &p->pFreelist->aEntry[i];
728         if( pEntry->iId>=0 && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId) ){
729           return LSM_OK;
730         }
731       }
732     }
733   }
734 
735   return rc;
736 }
737 
738 
739 typedef struct FindFreeblockCtx FindFreeblockCtx;
740 struct FindFreeblockCtx {
741   i64 iInUse;
742   int iRet;
743   int bNotOne;
744 };
745 
746 static int findFreeblockCb(void *pCtx, int iBlk, i64 iSnapshot){
747   FindFreeblockCtx *p = (FindFreeblockCtx *)pCtx;
748   if( iSnapshot<p->iInUse && (iBlk!=1 || p->bNotOne==0) ){
749     p->iRet = iBlk;
750     return 1;
751   }
752   return 0;
753 }
754 
755 static int findFreeblock(lsm_db *pDb, i64 iInUse, int bNotOne, int *piRet){
756   int rc;                         /* Return code */
757   FindFreeblockCtx ctx;           /* Context object */
758 
759   ctx.iInUse = iInUse;
760   ctx.iRet = 0;
761   ctx.bNotOne = bNotOne;
762   rc = lsmWalkFreelist(pDb, 0, findFreeblockCb, (void *)&ctx);
763   *piRet = ctx.iRet;
764 
765   return rc;
766 }
767 
768 /*
769 ** Allocate a new database file block to write data to, either by extending
770 ** the database file or by recycling a free-list entry. The worker snapshot
771 ** must be held in order to call this function.
772 **
773 ** If successful, *piBlk is set to the block number allocated and LSM_OK is
774 ** returned. Otherwise, *piBlk is zeroed and an lsm error code returned.
775 */
776 int lsmBlockAllocate(lsm_db *pDb, int iBefore, int *piBlk){
777   Snapshot *p = pDb->pWorker;
778   int iRet = 0;                   /* Block number of allocated block */
779   int rc = LSM_OK;
780   i64 iInUse = 0;                 /* Snapshot id still in use */
781   i64 iSynced = 0;                /* Snapshot id synced to disk */
782 
783   assert( p );
784 
785 #ifdef LSM_LOG_FREELIST
786   {
787     static int nCall = 0;
788     char *zFree = 0;
789     nCall++;
790     rc = lsmInfoFreelist(pDb, &zFree);
791     if( rc!=LSM_OK ) return rc;
792     lsmLogMessage(pDb, 0, "lsmBlockAllocate(): %d freelist: %s", nCall, zFree);
793     lsmFree(pDb->pEnv, zFree);
794   }
795 #endif
796 
797   /* Set iInUse to the smallest snapshot id that is either:
798   **
799   **   * Currently in use by a database client,
800   **   * May be used by a database client in the future, or
801   **   * Is the most recently checkpointed snapshot (i.e. the one that will
802   **     be used following recovery if a failure occurs at this point).
803   */
804   rc = lsmCheckpointSynced(pDb, &iSynced, 0, 0);
805   if( rc==LSM_OK && iSynced==0 ) iSynced = p->iId;
806   iInUse = iSynced;
807   if( rc==LSM_OK && pDb->iReader>=0 ){
808     assert( pDb->pClient );
809     iInUse = LSM_MIN(iInUse, pDb->pClient->iId);
810   }
811   if( rc==LSM_OK ) rc = firstSnapshotInUse(pDb, &iInUse);
812 
813 #ifdef LSM_LOG_FREELIST
814   {
815     lsmLogMessage(pDb, 0, "lsmBlockAllocate(): "
816         "snapshot-in-use: %lld (iSynced=%lld) (client-id=%lld)",
817         iInUse, iSynced, (pDb->iReader>=0 ? pDb->pClient->iId : 0)
818     );
819   }
820 #endif
821 
822 
823   /* Unless there exists a read-only transaction (which prevents us from
824   ** recycling any blocks regardless, query the free block list for a
825   ** suitable block to reuse.
826   **
827   ** It might seem more natural to check for a read-only transaction at
828   ** the start of this function. However, it is better do wait until after
829   ** the call to lsmCheckpointSynced() to do so.
830   */
831   if( rc==LSM_OK ){
832     int bRotrans;
833     rc = lsmDetectRoTrans(pDb, &bRotrans);
834 
835     if( rc==LSM_OK && bRotrans==0 ){
836       rc = findFreeblock(pDb, iInUse, (iBefore>0), &iRet);
837     }
838   }
839 
840   if( iBefore>0 && (iRet<=0 || iRet>=iBefore) ){
841     iRet = 0;
842 
843   }else if( rc==LSM_OK ){
844     /* If a block was found in the free block list, use it and remove it from
845     ** the list. Otherwise, if no suitable block was found, allocate one from
846     ** the end of the file.  */
847     if( iRet>0 ){
848 #ifdef LSM_LOG_FREELIST
849       lsmLogMessage(pDb, 0,
850           "reusing block %d (snapshot-in-use=%lld)", iRet, iInUse);
851 #endif
852       rc = freelistAppend(pDb, iRet, -1);
853       if( rc==LSM_OK ){
854         rc = dbTruncate(pDb, iInUse);
855       }
856     }else{
857       iRet = ++(p->nBlock);
858 #ifdef LSM_LOG_FREELIST
859       lsmLogMessage(pDb, 0, "extending file to %d blocks", iRet);
860 #endif
861     }
862   }
863 
864   assert( iBefore>0 || iRet>0 || rc!=LSM_OK );
865   *piBlk = iRet;
866   return rc;
867 }
868 
869 /*
870 ** Free a database block. The worker snapshot must be held in order to call
871 ** this function.
872 **
873 ** If successful, LSM_OK is returned. Otherwise, an lsm error code (e.g.
874 ** LSM_NOMEM).
875 */
876 int lsmBlockFree(lsm_db *pDb, int iBlk){
877   Snapshot *p = pDb->pWorker;
878   assert( lsmShmAssertWorker(pDb) );
879 
880 #ifdef LSM_LOG_FREELIST
881   lsmLogMessage(pDb, LSM_OK, "lsmBlockFree(): Free block %d", iBlk);
882 #endif
883 
884   return freelistAppend(pDb, iBlk, p->iId);
885 }
886 
887 /*
888 ** Refree a database block. The worker snapshot must be held in order to call
889 ** this function.
890 **
891 ** Refreeing is required when a block is allocated using lsmBlockAllocate()
892 ** but then not used. This function is used to push the block back onto
893 ** the freelist. Refreeing a block is different from freeing is, as a refreed
894 ** block may be reused immediately. Whereas a freed block can not be reused
895 ** until (at least) after the next checkpoint.
896 */
897 int lsmBlockRefree(lsm_db *pDb, int iBlk){
898   int rc = LSM_OK;                /* Return code */
899 
900 #ifdef LSM_LOG_FREELIST
901   lsmLogMessage(pDb, LSM_OK, "lsmBlockRefree(): Refree block %d", iBlk);
902 #endif
903 
904   rc = freelistAppend(pDb, iBlk, 0);
905   return rc;
906 }
907 
908 /*
909 ** If required, copy a database checkpoint from shared memory into the
910 ** database itself.
911 **
912 ** The WORKER lock must not be held when this is called. This is because
913 ** this function may indirectly call fsync(). And the WORKER lock should
914 ** not be held that long (in case it is required by a client flushing an
915 ** in-memory tree to disk).
916 */
917 int lsmCheckpointWrite(lsm_db *pDb, int bTruncate, u32 *pnWrite){
918   int rc;                         /* Return Code */
919   u32 nWrite = 0;
920 
921   assert( pDb->pWorker==0 );
922   assert( 1 || pDb->pClient==0 );
923   assert( lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK) );
924 
925   rc = lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_EXCL, 0);
926   if( rc!=LSM_OK ) return rc;
927 
928   rc = lsmCheckpointLoad(pDb, 0);
929   if( rc==LSM_OK ){
930     int nBlock = lsmCheckpointNBlock(pDb->aSnapshot);
931     ShmHeader *pShm = pDb->pShmhdr;
932     int bDone = 0;                /* True if checkpoint is already stored */
933 
934     /* Check if this checkpoint has already been written to the database
935     ** file. If so, set variable bDone to true.  */
936     if( pShm->iMetaPage ){
937       MetaPage *pPg;              /* Meta page */
938       u8 *aData;                  /* Meta-page data buffer */
939       int nData;                  /* Size of aData[] in bytes */
940       i64 iCkpt;                  /* Id of checkpoint just loaded */
941       i64 iDisk = 0;              /* Id of checkpoint already stored in db */
942       iCkpt = lsmCheckpointId(pDb->aSnapshot, 0);
943       rc = lsmFsMetaPageGet(pDb->pFS, 0, pShm->iMetaPage, &pPg);
944       if( rc==LSM_OK ){
945         aData = lsmFsMetaPageData(pPg, &nData);
946         iDisk = lsmCheckpointId((u32 *)aData, 1);
947         nWrite = lsmCheckpointNWrite((u32 *)aData, 1);
948         lsmFsMetaPageRelease(pPg);
949       }
950       bDone = (iDisk>=iCkpt);
951     }
952 
953     if( rc==LSM_OK && bDone==0 ){
954       int iMeta = (pShm->iMetaPage % 2) + 1;
955       if( pDb->eSafety!=LSM_SAFETY_OFF ){
956         rc = lsmFsSyncDb(pDb->pFS, nBlock);
957       }
958       if( rc==LSM_OK ) rc = lsmCheckpointStore(pDb, iMeta);
959       if( rc==LSM_OK && pDb->eSafety!=LSM_SAFETY_OFF){
960         rc = lsmFsSyncDb(pDb->pFS, 0);
961       }
962       if( rc==LSM_OK ){
963         pShm->iMetaPage = iMeta;
964         nWrite = lsmCheckpointNWrite(pDb->aSnapshot, 0) - nWrite;
965       }
966 #ifdef LSM_LOG_WORK
967       lsmLogMessage(pDb, 0, "finish checkpoint %d",
968           (int)lsmCheckpointId(pDb->aSnapshot, 0)
969       );
970 #endif
971     }
972 
973     if( rc==LSM_OK && bTruncate && nBlock>0 ){
974       rc = lsmFsTruncateDb(pDb->pFS, (i64)nBlock*lsmFsBlockSize(pDb->pFS));
975     }
976   }
977 
978   lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_UNLOCK, 0);
979   if( pnWrite && rc==LSM_OK ) *pnWrite = nWrite;
980   return rc;
981 }
982 
983 int lsmBeginWork(lsm_db *pDb){
984   int rc;
985 
986   /* Attempt to take the WORKER lock */
987   rc = lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL, 0);
988 
989   /* Deserialize the current worker snapshot */
990   if( rc==LSM_OK ){
991     rc = lsmCheckpointLoadWorker(pDb);
992   }
993   return rc;
994 }
995 
996 void lsmFreeSnapshot(lsm_env *pEnv, Snapshot *p){
997   if( p ){
998     lsmSortedFreeLevel(pEnv, p->pLevel);
999     lsmFree(pEnv, p->freelist.aEntry);
1000     lsmFree(pEnv, p->redirect.a);
1001     lsmFree(pEnv, p);
1002   }
1003 }
1004 
1005 /*
1006 ** Attempt to populate one of the read-lock slots to contain lock values
1007 ** iLsm/iShm. Or, if such a slot exists already, this function is a no-op.
1008 **
1009 ** It is not an error if no slot can be populated because the write-lock
1010 ** cannot be obtained. If any other error occurs, return an LSM error code.
1011 ** Otherwise, LSM_OK.
1012 **
1013 ** This function is called at various points to try to ensure that there
1014 ** always exists at least one read-lock slot that can be used by a read-only
1015 ** client. And so that, in the usual case, there is an "exact match" available
1016 ** whenever a read transaction is opened by any client. At present this
1017 ** function is called when:
1018 **
1019 **    * A write transaction that called lsmTreeDiscardOld() is committed, and
1020 **    * Whenever the working snapshot is updated (i.e. lsmFinishWork()).
1021 */
1022 static int dbSetReadLock(lsm_db *db, i64 iLsm, u32 iShm){
1023   int rc = LSM_OK;
1024   ShmHeader *pShm = db->pShmhdr;
1025   int i;
1026 
1027   /* Check if there is already a slot containing the required values. */
1028   for(i=0; i<LSM_LOCK_NREADER; i++){
1029     ShmReader *p = &pShm->aReader[i];
1030     if( p->iLsmId==iLsm && p->iTreeId==iShm ) return LSM_OK;
1031   }
1032 
1033   /* Iterate through all read-lock slots, attempting to take a write-lock
1034   ** on each of them. If a write-lock succeeds, populate the locked slot
1035   ** with the required values and break out of the loop.  */
1036   for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
1037     rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
1038     if( rc==LSM_BUSY ){
1039       rc = LSM_OK;
1040     }else{
1041       ShmReader *p = &pShm->aReader[i];
1042       p->iLsmId = iLsm;
1043       p->iTreeId = iShm;
1044       lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
1045       break;
1046     }
1047   }
1048 
1049   return rc;
1050 }
1051 
1052 /*
1053 ** Release the read-lock currently held by connection db.
1054 */
1055 int dbReleaseReadlock(lsm_db *db){
1056   int rc = LSM_OK;
1057   if( db->iReader>=0 ){
1058     rc = lsmShmLock(db, LSM_LOCK_READER(db->iReader), LSM_LOCK_UNLOCK, 0);
1059     db->iReader = -1;
1060   }
1061   db->bRoTrans = 0;
1062   return rc;
1063 }
1064 
1065 
1066 /*
1067 ** Argument bFlush is true if the contents of the in-memory tree has just
1068 ** been flushed to disk. The significance of this is that once the snapshot
1069 ** created to hold the updated state of the database is synced to disk, log
1070 ** file space can be recycled.
1071 */
1072 void lsmFinishWork(lsm_db *pDb, int bFlush, int *pRc){
1073   int rc = *pRc;
1074   assert( rc!=0 || pDb->pWorker );
1075   if( pDb->pWorker ){
1076     /* If no error has occurred, serialize the worker snapshot and write
1077     ** it to shared memory.  */
1078     if( rc==LSM_OK ){
1079       rc = lsmSaveWorker(pDb, bFlush);
1080     }
1081 
1082     /* Assuming no error has occurred, update a read lock slot with the
1083     ** new snapshot id (see comments above function dbSetReadLock()).  */
1084     if( rc==LSM_OK ){
1085       if( pDb->iReader<0 ){
1086         rc = lsmTreeLoadHeader(pDb, 0);
1087       }
1088       if( rc==LSM_OK ){
1089         rc = dbSetReadLock(pDb, pDb->pWorker->iId, pDb->treehdr.iUsedShmid);
1090       }
1091     }
1092 
1093     /* Free the snapshot object. */
1094     lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
1095     pDb->pWorker = 0;
1096   }
1097 
1098   lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK, 0);
1099   *pRc = rc;
1100 }
1101 
1102 /*
1103 ** Called when recovery is finished.
1104 */
1105 int lsmFinishRecovery(lsm_db *pDb){
1106   lsmTreeEndTransaction(pDb, 1);
1107   return LSM_OK;
1108 }
1109 
1110 /*
1111 ** Check if the currently configured compression functions
1112 ** (LSM_CONFIG_SET_COMPRESSION) are compatible with a database that has its
1113 ** compression id set to iReq. Compression routines are compatible if iReq
1114 ** is zero (indicating the database is empty), or if it is equal to the
1115 ** compression id of the configured compression routines.
1116 **
1117 ** If the check shows that the current compression are incompatible and there
1118 ** is a compression factory registered, give it a chance to install new
1119 ** compression routines.
1120 **
1121 ** If, after any registered factory is invoked, the compression functions
1122 ** are still incompatible, return LSM_MISMATCH. Otherwise, LSM_OK.
1123 */
1124 int lsmCheckCompressionId(lsm_db *pDb, u32 iReq){
1125   if( iReq!=LSM_COMPRESSION_EMPTY && pDb->compress.iId!=iReq ){
1126     if( pDb->factory.xFactory ){
1127       pDb->bInFactory = 1;
1128       pDb->factory.xFactory(pDb->factory.pCtx, pDb, iReq);
1129       pDb->bInFactory = 0;
1130     }
1131     if( pDb->compress.iId!=iReq ){
1132       /* Incompatible */
1133       return LSM_MISMATCH;
1134     }
1135   }
1136   /* Compatible */
1137   return LSM_OK;
1138 }
1139 
1140 /*
1141 ** Begin a read transaction. This function is a no-op if the connection
1142 ** passed as the only argument already has an open read transaction.
1143 */
1144 int lsmBeginReadTrans(lsm_db *pDb){
1145   const int MAX_READLOCK_ATTEMPTS = 10;
1146   const int nMaxAttempt = (pDb->bRoTrans ? 1 : MAX_READLOCK_ATTEMPTS);
1147 
1148   int rc = LSM_OK;                /* Return code */
1149   int iAttempt = 0;
1150 
1151   assert( pDb->pWorker==0 );
1152 
1153   while( rc==LSM_OK && pDb->iReader<0 && (iAttempt++)<nMaxAttempt ){
1154     int iTreehdr = 0;
1155     int iSnap = 0;
1156     assert( pDb->pCsr==0 && pDb->nTransOpen==0 );
1157 
1158     /* Load the in-memory tree header. */
1159     rc = lsmTreeLoadHeader(pDb, &iTreehdr);
1160 
1161     /* Load the database snapshot */
1162     if( rc==LSM_OK ){
1163       if( lsmCheckpointClientCacheOk(pDb)==0 ){
1164         lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
1165         pDb->pClient = 0;
1166         lsmMCursorFreeCache(pDb);
1167         lsmFsPurgeCache(pDb->pFS);
1168         rc = lsmCheckpointLoad(pDb, &iSnap);
1169       }else{
1170         iSnap = 1;
1171       }
1172     }
1173 
1174     /* Take a read-lock on the tree and snapshot just loaded. Then check
1175     ** that the shared-memory still contains the same values. If so, proceed.
1176     ** Otherwise, relinquish the read-lock and retry the whole procedure
1177     ** (starting with loading the in-memory tree header).  */
1178     if( rc==LSM_OK ){
1179       u32 iShmMax = pDb->treehdr.iUsedShmid;
1180       u32 iShmMin = pDb->treehdr.iNextShmid+1-LSM_MAX_SHMCHUNKS;
1181       rc = lsmReadlock(
1182           pDb, lsmCheckpointId(pDb->aSnapshot, 0), iShmMin, iShmMax
1183       );
1184       if( rc==LSM_OK ){
1185         if( lsmTreeLoadHeaderOk(pDb, iTreehdr)
1186          && lsmCheckpointLoadOk(pDb, iSnap)
1187         ){
1188           /* Read lock has been successfully obtained. Deserialize the
1189           ** checkpoint just loaded. TODO: This will be removed after
1190           ** lsm_sorted.c is changed to work directly from the serialized
1191           ** version of the snapshot.  */
1192           if( pDb->pClient==0 ){
1193             rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot,&pDb->pClient);
1194           }
1195           assert( (rc==LSM_OK)==(pDb->pClient!=0) );
1196           assert( pDb->iReader>=0 );
1197 
1198           /* Check that the client has the right compression hooks loaded.
1199           ** If not, set rc to LSM_MISMATCH.  */
1200           if( rc==LSM_OK ){
1201             rc = lsmCheckCompressionId(pDb, pDb->pClient->iCmpId);
1202           }
1203         }else{
1204           rc = dbReleaseReadlock(pDb);
1205         }
1206       }
1207 
1208       if( rc==LSM_BUSY ){
1209         rc = LSM_OK;
1210       }
1211     }
1212 #if 0
1213 if( rc==LSM_OK && pDb->pClient ){
1214   fprintf(stderr,
1215       "reading %p: snapshot:%d used-shmid:%d trans-id:%d iOldShmid=%d\n",
1216       (void *)pDb,
1217       (int)pDb->pClient->iId, (int)pDb->treehdr.iUsedShmid,
1218       (int)pDb->treehdr.root.iTransId,
1219       (int)pDb->treehdr.iOldShmid
1220   );
1221 }
1222 #endif
1223   }
1224 
1225   if( rc==LSM_OK ){
1226     rc = lsmShmCacheChunks(pDb, pDb->treehdr.nChunk);
1227   }
1228   if( rc!=LSM_OK ){
1229     dbReleaseReadlock(pDb);
1230   }
1231   if( pDb->pClient==0 && rc==LSM_OK ) rc = LSM_BUSY;
1232   return rc;
1233 }
1234 
1235 /*
1236 ** This function is used by a read-write connection to determine if there
1237 ** are currently one or more read-only transactions open on the database
1238 ** (in this context a read-only transaction is one opened by a read-only
1239 ** connection on a non-live database).
1240 **
1241 ** If no error occurs, LSM_OK is returned and *pbExists is set to true if
1242 ** some other connection has a read-only transaction open, or false
1243 ** otherwise. If an error occurs an LSM error code is returned and the final
1244 ** value of *pbExist is undefined.
1245 */
1246 int lsmDetectRoTrans(lsm_db *db, int *pbExist){
1247   int rc;
1248 
1249   /* Only a read-write connection may use this function. */
1250   assert( db->bReadonly==0 );
1251 
1252   rc = lsmShmTestLock(db, LSM_LOCK_ROTRANS, 1, LSM_LOCK_EXCL);
1253   if( rc==LSM_BUSY ){
1254     *pbExist = 1;
1255     rc = LSM_OK;
1256   }else{
1257     *pbExist = 0;
1258   }
1259 
1260   return rc;
1261 }
1262 
1263 /*
1264 ** db is a read-only database handle in the disconnected state. This function
1265 ** attempts to open a read-transaction on the database. This may involve
1266 ** connecting to the database system (opening shared memory etc.).
1267 */
1268 int lsmBeginRoTrans(lsm_db *db){
1269   int rc = LSM_OK;
1270 
1271   assert( db->bReadonly && db->pShmhdr==0 );
1272   assert( db->iReader<0 );
1273 
1274   if( db->bRoTrans==0 ){
1275 
1276     /* Attempt a shared-lock on DMS1. */
1277     rc = lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_SHARED, 0);
1278     if( rc!=LSM_OK ) return rc;
1279 
1280     rc = lsmShmTestLock(
1281         db, LSM_LOCK_RWCLIENT(0), LSM_LOCK_NREADER, LSM_LOCK_SHARED
1282     );
1283     if( rc==LSM_OK ){
1284       /* System is not live. Take a SHARED lock on the ROTRANS byte and
1285       ** release DMS1. Locking ROTRANS tells all read-write clients that they
1286       ** may not recycle any disk space from within the database or log files,
1287       ** as a read-only client may be using it.  */
1288       rc = lsmShmLock(db, LSM_LOCK_ROTRANS, LSM_LOCK_SHARED, 0);
1289       lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
1290 
1291       if( rc==LSM_OK ){
1292         db->bRoTrans = 1;
1293         rc = lsmShmCacheChunks(db, 1);
1294         if( rc==LSM_OK ){
1295           db->pShmhdr = (ShmHeader *)db->apShm[0];
1296           memset(db->pShmhdr, 0, sizeof(ShmHeader));
1297           rc = lsmCheckpointRecover(db);
1298           if( rc==LSM_OK ){
1299             rc = lsmLogRecover(db);
1300           }
1301         }
1302       }
1303     }else if( rc==LSM_BUSY ){
1304       /* System is live! */
1305       rc = lsmShmLock(db, LSM_LOCK_DMS3, LSM_LOCK_SHARED, 0);
1306       lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
1307       if( rc==LSM_OK ){
1308         rc = lsmShmCacheChunks(db, 1);
1309         if( rc==LSM_OK ){
1310           db->pShmhdr = (ShmHeader *)db->apShm[0];
1311         }
1312       }
1313     }
1314 
1315     if( rc==LSM_OK ){
1316       rc = lsmBeginReadTrans(db);
1317     }
1318   }
1319 
1320   return rc;
1321 }
1322 
1323 /*
1324 ** Close the currently open read transaction.
1325 */
1326 void lsmFinishReadTrans(lsm_db *pDb){
1327 
1328   /* Worker connections should not be closing read transactions. And
1329   ** read transactions should only be closed after all cursors and write
1330   ** transactions have been closed. Finally pClient should be non-NULL
1331   ** only iff pDb->iReader>=0.  */
1332   assert( pDb->pWorker==0 );
1333   assert( pDb->pCsr==0 && pDb->nTransOpen==0 );
1334 
1335   if( pDb->bRoTrans ){
1336     int i;
1337     for(i=0; i<pDb->nShm; i++){
1338       lsmFree(pDb->pEnv, pDb->apShm[i]);
1339     }
1340     lsmFree(pDb->pEnv, pDb->apShm);
1341     pDb->apShm = 0;
1342     pDb->nShm = 0;
1343     pDb->pShmhdr = 0;
1344 
1345     lsmShmLock(pDb, LSM_LOCK_ROTRANS, LSM_LOCK_UNLOCK, 0);
1346   }
1347   dbReleaseReadlock(pDb);
1348 }
1349 
1350 /*
1351 ** Open a write transaction.
1352 */
1353 int lsmBeginWriteTrans(lsm_db *pDb){
1354   int rc = LSM_OK;                /* Return code */
1355   ShmHeader *pShm = pDb->pShmhdr; /* Shared memory header */
1356 
1357   assert( pDb->nTransOpen==0 );
1358   assert( pDb->bDiscardOld==0 );
1359   assert( pDb->bReadonly==0 );
1360 
1361   /* If there is no read-transaction open, open one now. */
1362   if( pDb->iReader<0 ){
1363     rc = lsmBeginReadTrans(pDb);
1364   }
1365 
1366   /* Attempt to take the WRITER lock */
1367   if( rc==LSM_OK ){
1368     rc = lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL, 0);
1369   }
1370 
1371   /* If the previous writer failed mid-transaction, run emergency rollback. */
1372   if( rc==LSM_OK && pShm->bWriter ){
1373     rc = lsmTreeRepair(pDb);
1374     if( rc==LSM_OK ) pShm->bWriter = 0;
1375   }
1376 
1377   /* Check that this connection is currently reading from the most recent
1378   ** version of the database. If not, return LSM_BUSY.  */
1379   if( rc==LSM_OK && memcmp(&pShm->hdr1, &pDb->treehdr, sizeof(TreeHeader)) ){
1380     rc = LSM_BUSY;
1381   }
1382 
1383   if( rc==LSM_OK ){
1384     rc = lsmLogBegin(pDb);
1385   }
1386 
1387   /* If everything was successful, set the "transaction-in-progress" flag
1388   ** and return LSM_OK. Otherwise, if some error occurred, relinquish the
1389   ** WRITER lock and return an error code.  */
1390   if( rc==LSM_OK ){
1391     TreeHeader *p = &pDb->treehdr;
1392     pShm->bWriter = 1;
1393     p->root.iTransId++;
1394     if( lsmTreeHasOld(pDb) && p->iOldLog==pDb->pClient->iLogOff ){
1395       lsmTreeDiscardOld(pDb);
1396       pDb->bDiscardOld = 1;
1397     }
1398   }else{
1399     lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);
1400     if( pDb->pCsr==0 ) lsmFinishReadTrans(pDb);
1401   }
1402   return rc;
1403 }
1404 
1405 /*
1406 ** End the current write transaction. The connection is left with an open
1407 ** read transaction. It is an error to call this if there is no open write
1408 ** transaction.
1409 **
1410 ** If the transaction was committed, then a commit record has already been
1411 ** written into the log file when this function is called. Or, if the
1412 ** transaction was rolled back, both the log file and in-memory tree
1413 ** structure have already been restored. In either case, this function
1414 ** merely releases locks and other resources held by the write-transaction.
1415 **
1416 ** LSM_OK is returned if successful, or an LSM error code otherwise.
1417 */
1418 int lsmFinishWriteTrans(lsm_db *pDb, int bCommit){
1419   int rc = LSM_OK;
1420   int bFlush = 0;
1421 
1422   lsmLogEnd(pDb, bCommit);
1423   if( rc==LSM_OK && bCommit && lsmTreeSize(pDb)>pDb->nTreeLimit ){
1424     bFlush = 1;
1425     lsmTreeMakeOld(pDb);
1426   }
1427   lsmTreeEndTransaction(pDb, bCommit);
1428 
1429   if( rc==LSM_OK ){
1430     if( bFlush && pDb->bAutowork ){
1431       rc = lsmSortedAutoWork(pDb, 1);
1432     }else if( bCommit && pDb->bDiscardOld ){
1433       rc = dbSetReadLock(pDb, pDb->pClient->iId, pDb->treehdr.iUsedShmid);
1434     }
1435   }
1436   pDb->bDiscardOld = 0;
1437   lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);
1438 
1439   if( bFlush && pDb->bAutowork==0 && pDb->xWork ){
1440     pDb->xWork(pDb, pDb->pWorkCtx);
1441   }
1442   return rc;
1443 }
1444 
1445 
1446 /*
1447 ** Return non-zero if the caller is holding the client mutex.
1448 */
1449 #ifdef LSM_DEBUG
1450 int lsmHoldingClientMutex(lsm_db *pDb){
1451   return lsmMutexHeld(pDb->pEnv, pDb->pDatabase->pClientMutex);
1452 }
1453 #endif
1454 
1455 static int slotIsUsable(ShmReader *p, i64 iLsm, u32 iShmMin, u32 iShmMax){
1456   return(
1457       p->iLsmId && p->iLsmId<=iLsm
1458       && shm_sequence_ge(iShmMax, p->iTreeId)
1459       && shm_sequence_ge(p->iTreeId, iShmMin)
1460   );
1461 }
1462 
1463 /*
1464 ** Obtain a read-lock on database version identified by the combination
1465 ** of snapshot iLsm and tree iTree. Return LSM_OK if successful, or
1466 ** an LSM error code otherwise.
1467 */
1468 int lsmReadlock(lsm_db *db, i64 iLsm, u32 iShmMin, u32 iShmMax){
1469   int rc = LSM_OK;
1470   ShmHeader *pShm = db->pShmhdr;
1471   int i;
1472 
1473   assert( db->iReader<0 );
1474   assert( shm_sequence_ge(iShmMax, iShmMin) );
1475 
1476   /* This is a no-op if the read-only transaction flag is set. */
1477   if( db->bRoTrans ){
1478     db->iReader = 0;
1479     return LSM_OK;
1480   }
1481 
1482   /* Search for an exact match. */
1483   for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
1484     ShmReader *p = &pShm->aReader[i];
1485     if( p->iLsmId==iLsm && p->iTreeId==iShmMax ){
1486       rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
1487       if( rc==LSM_OK && p->iLsmId==iLsm && p->iTreeId==iShmMax ){
1488         db->iReader = i;
1489       }else if( rc==LSM_BUSY ){
1490         rc = LSM_OK;
1491       }
1492     }
1493   }
1494 
1495   /* Try to obtain a write-lock on each slot, in order. If successful, set
1496   ** the slot values to iLsm/iTree.  */
1497   for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
1498     rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
1499     if( rc==LSM_BUSY ){
1500       rc = LSM_OK;
1501     }else{
1502       ShmReader *p = &pShm->aReader[i];
1503       p->iLsmId = iLsm;
1504       p->iTreeId = iShmMax;
1505       rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
1506       assert( rc!=LSM_BUSY );
1507       if( rc==LSM_OK ) db->iReader = i;
1508     }
1509   }
1510 
1511   /* Search for any usable slot */
1512   for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
1513     ShmReader *p = &pShm->aReader[i];
1514     if( slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
1515       rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
1516       if( rc==LSM_OK && slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
1517         db->iReader = i;
1518       }else if( rc==LSM_BUSY ){
1519         rc = LSM_OK;
1520       }
1521     }
1522   }
1523 
1524   if( rc==LSM_OK && db->iReader<0 ){
1525     rc = LSM_BUSY;
1526   }
1527   return rc;
1528 }
1529 
1530 /*
1531 ** This is used to check if there exists a read-lock locking a particular
1532 ** version of either the in-memory tree or database file.
1533 **
1534 ** If iLsmId is non-zero, then it is a snapshot id. If there exists a
1535 ** read-lock using this snapshot or newer, set *pbInUse to true. Or,
1536 ** if there is no such read-lock, set it to false.
1537 **
1538 ** Or, if iLsmId is zero, then iShmid is a shared-memory sequence id.
1539 ** Search for a read-lock using this sequence id or newer. etc.
1540 */
1541 static int isInUse(lsm_db *db, i64 iLsmId, u32 iShmid, int *pbInUse){
1542   ShmHeader *pShm = db->pShmhdr;
1543   int i;
1544   int rc = LSM_OK;
1545 
1546   for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
1547     ShmReader *p = &pShm->aReader[i];
1548     if( p->iLsmId ){
1549       if( (iLsmId!=0 && p->iLsmId!=0 && iLsmId>=p->iLsmId)
1550        || (iLsmId==0 && shm_sequence_ge(p->iTreeId, iShmid))
1551       ){
1552         rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
1553         if( rc==LSM_OK ){
1554           p->iLsmId = 0;
1555           lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
1556         }
1557       }
1558     }
1559   }
1560 
1561   if( rc==LSM_BUSY ){
1562     *pbInUse = 1;
1563     return LSM_OK;
1564   }
1565   *pbInUse = 0;
1566   return rc;
1567 }
1568 
1569 /*
1570 ** This function is called by worker connections to determine the smallest
1571 ** snapshot id that is currently in use by a database client. The worker
1572 ** connection uses this result to determine whether or not it is safe to
1573 ** recycle a database block.
1574 */
1575 static int firstSnapshotInUse(
1576   lsm_db *db,                     /* Database handle */
1577   i64 *piInUse                    /* IN/OUT: Smallest snapshot id in use */
1578 ){
1579   ShmHeader *pShm = db->pShmhdr;
1580   i64 iInUse = *piInUse;
1581   int i;
1582 
1583   assert( iInUse>0 );
1584   for(i=0; i<LSM_LOCK_NREADER; i++){
1585     ShmReader *p = &pShm->aReader[i];
1586     if( p->iLsmId ){
1587       i64 iThis = p->iLsmId;
1588       if( iThis!=0 && iInUse>iThis ){
1589         int rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
1590         if( rc==LSM_OK ){
1591           p->iLsmId = 0;
1592           lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
1593         }else if( rc==LSM_BUSY ){
1594           iInUse = iThis;
1595         }else{
1596           /* Some error other than LSM_BUSY. Return the error code to
1597           ** the caller in this case.  */
1598           return rc;
1599         }
1600       }
1601     }
1602   }
1603 
1604   *piInUse = iInUse;
1605   return LSM_OK;
1606 }
1607 
1608 int lsmTreeInUse(lsm_db *db, u32 iShmid, int *pbInUse){
1609   if( db->treehdr.iUsedShmid==iShmid ){
1610     *pbInUse = 1;
1611     return LSM_OK;
1612   }
1613   return isInUse(db, 0, iShmid, pbInUse);
1614 }
1615 
1616 int lsmLsmInUse(lsm_db *db, i64 iLsmId, int *pbInUse){
1617   if( db->pClient && db->pClient->iId<=iLsmId ){
1618     *pbInUse = 1;
1619     return LSM_OK;
1620   }
1621   return isInUse(db, iLsmId, 0, pbInUse);
1622 }
1623 
1624 /*
1625 ** This function may only be called after a successful call to
1626 ** lsmDbDatabaseConnect(). It returns true if the connection is in
1627 ** multi-process mode, or false otherwise.
1628 */
1629 int lsmDbMultiProc(lsm_db *pDb){
1630   return pDb->pDatabase && pDb->pDatabase->bMultiProc;
1631 }
1632 
1633 
1634 /*************************************************************************
1635 **************************************************************************
1636 **************************************************************************
1637 **************************************************************************
1638 **************************************************************************
1639 *************************************************************************/
1640 
1641 /*
1642 ** Ensure that database connection db has cached pointers to at least the
1643 ** first nChunk chunks of shared memory.
1644 */
1645 int lsmShmCacheChunks(lsm_db *db, int nChunk){
1646   int rc = LSM_OK;
1647   if( nChunk>db->nShm ){
1648     static const int NINCR = 16;
1649     Database *p = db->pDatabase;
1650     lsm_env *pEnv = db->pEnv;
1651     int nAlloc;
1652     int i;
1653 
1654     /* Ensure that the db->apShm[] array is large enough. If an attempt to
1655     ** allocate memory fails, return LSM_NOMEM immediately. The apShm[] array
1656     ** is always extended in multiples of 16 entries - so the actual allocated
1657     ** size can be inferred from nShm.  */
1658     nAlloc = ((db->nShm + NINCR - 1) / NINCR) * NINCR;
1659     while( nChunk>=nAlloc ){
1660       void **apShm;
1661       nAlloc += NINCR;
1662       apShm = lsmRealloc(pEnv, db->apShm, sizeof(void*)*nAlloc);
1663       if( !apShm ) return LSM_NOMEM_BKPT;
1664       db->apShm = apShm;
1665     }
1666 
1667     if( db->bRoTrans ){
1668       for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
1669         db->apShm[i] = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
1670         db->nShm++;
1671       }
1672 
1673     }else{
1674 
1675       /* Enter the client mutex */
1676       lsmMutexEnter(pEnv, p->pClientMutex);
1677 
1678       /* Extend the Database objects apShmChunk[] array if necessary. Using the
1679        ** same pattern as for the lsm_db.apShm[] array above.  */
1680       nAlloc = ((p->nShmChunk + NINCR - 1) / NINCR) * NINCR;
1681       while( nChunk>=nAlloc ){
1682         void **apShm;
1683         nAlloc +=  NINCR;
1684         apShm = lsmRealloc(pEnv, p->apShmChunk, sizeof(void*)*nAlloc);
1685         if( !apShm ){
1686           rc = LSM_NOMEM_BKPT;
1687           break;
1688         }
1689         p->apShmChunk = apShm;
1690       }
1691 
1692       for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
1693         if( i>=p->nShmChunk ){
1694           void *pChunk = 0;
1695           if( p->bMultiProc==0 ){
1696             /* Single process mode */
1697             pChunk = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
1698           }else{
1699             /* Multi-process mode */
1700             rc = lsmEnvShmMap(pEnv, p->pFile, i, LSM_SHM_CHUNK_SIZE, &pChunk);
1701           }
1702           if( rc==LSM_OK ){
1703             p->apShmChunk[i] = pChunk;
1704             p->nShmChunk++;
1705           }
1706         }
1707         if( rc==LSM_OK ){
1708           db->apShm[i] = p->apShmChunk[i];
1709           db->nShm++;
1710         }
1711       }
1712 
1713       /* Release the client mutex */
1714       lsmMutexLeave(pEnv, p->pClientMutex);
1715     }
1716   }
1717 
1718   return rc;
1719 }
1720 
1721 static int lockSharedFile(lsm_env *pEnv, Database *p, int iLock, int eOp){
1722   int rc = LSM_OK;
1723   if( p->bMultiProc ){
1724     rc = lsmEnvLock(pEnv, p->pFile, iLock, eOp);
1725   }
1726   return rc;
1727 }
1728 
1729 /*
1730 ** Test if it would be possible for connection db to obtain a lock of type
1731 ** eType on the nLock locks starting at iLock. If so, return LSM_OK. If it
1732 ** would not be possible to obtain the lock due to a lock held by another
1733 ** connection, return LSM_BUSY. If an IO or other error occurs (i.e. in the
1734 ** lsm_env.xTestLock function), return some other LSM error code.
1735 **
1736 ** Note that this function never actually locks the database - it merely
1737 ** queries the system to see if there exists a lock that would prevent
1738 ** it from doing so.
1739 */
1740 int lsmShmTestLock(
1741   lsm_db *db,
1742   int iLock,
1743   int nLock,
1744   int eOp
1745 ){
1746   int rc = LSM_OK;
1747   lsm_db *pIter;
1748   Database *p = db->pDatabase;
1749   int i;
1750   u64 mask = 0;
1751 
1752   for(i=iLock; i<(iLock+nLock); i++){
1753     mask |= ((u64)1 << (iLock-1));
1754     if( eOp==LSM_LOCK_EXCL ) mask |= ((u64)1 << (iLock+32-1));
1755   }
1756 
1757   lsmMutexEnter(db->pEnv, p->pClientMutex);
1758   for(pIter=p->pConn; pIter; pIter=pIter->pNext){
1759     if( pIter!=db && (pIter->mLock & mask) ){
1760       assert( pIter!=db );
1761       break;
1762     }
1763   }
1764 
1765   if( pIter ){
1766     rc = LSM_BUSY;
1767   }else if( p->bMultiProc ){
1768     rc = lsmEnvTestLock(db->pEnv, p->pFile, iLock, nLock, eOp);
1769   }
1770 
1771   lsmMutexLeave(db->pEnv, p->pClientMutex);
1772   return rc;
1773 }
1774 
1775 /*
1776 ** Attempt to obtain the lock identified by the iLock and bExcl parameters.
1777 ** If successful, return LSM_OK. If the lock cannot be obtained because
1778 ** there exists some other conflicting lock, return LSM_BUSY. If some other
1779 ** error occurs, return an LSM error code.
1780 **
1781 ** Parameter iLock must be one of LSM_LOCK_WRITER, WORKER or CHECKPOINTER,
1782 ** or else a value returned by the LSM_LOCK_READER macro.
1783 */
1784 int lsmShmLock(
1785   lsm_db *db,
1786   int iLock,
1787   int eOp,                        /* One of LSM_LOCK_UNLOCK, SHARED or EXCL */
1788   int bBlock                      /* True for a blocking lock */
1789 ){
1790   lsm_db *pIter;
1791   const u64 me = ((u64)1 << (iLock-1));
1792   const u64 ms = ((u64)1 << (iLock+32-1));
1793   int rc = LSM_OK;
1794   Database *p = db->pDatabase;
1795 
1796   assert( eOp!=LSM_LOCK_EXCL || p->bReadonly==0 );
1797   assert( iLock>=1 && iLock<=LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1) );
1798   assert( LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1)<=32 );
1799   assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );
1800 
1801   /* Check for a no-op. Proceed only if this is not one of those. */
1802   if( (eOp==LSM_LOCK_UNLOCK && (db->mLock & (me|ms))!=0)
1803    || (eOp==LSM_LOCK_SHARED && (db->mLock & (me|ms))!=ms)
1804    || (eOp==LSM_LOCK_EXCL   && (db->mLock & me)==0)
1805   ){
1806     int nExcl = 0;                /* Number of connections holding EXCLUSIVE */
1807     int nShared = 0;              /* Number of connections holding SHARED */
1808     lsmMutexEnter(db->pEnv, p->pClientMutex);
1809 
1810     /* Figure out the locks currently held by this process on iLock, not
1811     ** including any held by connection db.  */
1812     for(pIter=p->pConn; pIter; pIter=pIter->pNext){
1813       assert( (pIter->mLock & me)==0 || (pIter->mLock & ms)!=0 );
1814       if( pIter!=db ){
1815         if( pIter->mLock & me ){
1816           nExcl++;
1817         }else if( pIter->mLock & ms ){
1818           nShared++;
1819         }
1820       }
1821     }
1822     assert( nExcl==0 || nExcl==1 );
1823     assert( nExcl==0 || nShared==0 );
1824     assert( nExcl==0 || (db->mLock & (me|ms))==0 );
1825 
1826     switch( eOp ){
1827       case LSM_LOCK_UNLOCK:
1828         if( nShared==0 ){
1829           lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_UNLOCK);
1830         }
1831         db->mLock &= ~(me|ms);
1832         break;
1833 
1834       case LSM_LOCK_SHARED:
1835         if( nExcl ){
1836           rc = LSM_BUSY;
1837         }else{
1838           if( nShared==0 ){
1839             rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED);
1840           }
1841           if( rc==LSM_OK ){
1842             db->mLock |= ms;
1843             db->mLock &= ~me;
1844           }
1845         }
1846         break;
1847 
1848       default:
1849         assert( eOp==LSM_LOCK_EXCL );
1850         if( nExcl || nShared ){
1851           rc = LSM_BUSY;
1852         }else{
1853           rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL);
1854           if( rc==LSM_OK ){
1855             db->mLock |= (me|ms);
1856           }
1857         }
1858         break;
1859     }
1860 
1861     lsmMutexLeave(db->pEnv, p->pClientMutex);
1862   }
1863 
1864   return rc;
1865 }
1866 
1867 #ifdef LSM_DEBUG
1868 
1869 int shmLockType(lsm_db *db, int iLock){
1870   const u64 me = ((u64)1 << (iLock-1));
1871   const u64 ms = ((u64)1 << (iLock+32-1));
1872 
1873   if( db->mLock & me ) return LSM_LOCK_EXCL;
1874   if( db->mLock & ms ) return LSM_LOCK_SHARED;
1875   return LSM_LOCK_UNLOCK;
1876 }
1877 
1878 /*
1879 ** The arguments passed to this function are similar to those passed to
1880 ** the lsmShmLock() function. However, instead of obtaining a new lock
1881 ** this function returns true if the specified connection already holds
1882 ** (or does not hold) such a lock, depending on the value of eOp. As
1883 ** follows:
1884 **
1885 **   (eOp==LSM_LOCK_UNLOCK) -> true if db has no lock on iLock
1886 **   (eOp==LSM_LOCK_SHARED) -> true if db has at least a SHARED lock on iLock.
1887 **   (eOp==LSM_LOCK_EXCL)   -> true if db has an EXCLUSIVE lock on iLock.
1888 */
1889 int lsmShmAssertLock(lsm_db *db, int iLock, int eOp){
1890   int ret = 0;
1891   int eHave;
1892 
1893   assert( iLock>=1 && iLock<=LSM_LOCK_READER(LSM_LOCK_NREADER-1) );
1894   assert( iLock<=16 );
1895   assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );
1896 
1897   eHave = shmLockType(db, iLock);
1898 
1899   switch( eOp ){
1900     case LSM_LOCK_UNLOCK:
1901       ret = (eHave==LSM_LOCK_UNLOCK);
1902       break;
1903     case LSM_LOCK_SHARED:
1904       ret = (eHave!=LSM_LOCK_UNLOCK);
1905       break;
1906     case LSM_LOCK_EXCL:
1907       ret = (eHave==LSM_LOCK_EXCL);
1908       break;
1909     default:
1910       assert( !"bad eOp value passed to lsmShmAssertLock()" );
1911       break;
1912   }
1913 
1914   return ret;
1915 }
1916 
1917 int lsmShmAssertWorker(lsm_db *db){
1918   return lsmShmAssertLock(db, LSM_LOCK_WORKER, LSM_LOCK_EXCL) && db->pWorker;
1919 }
1920 
1921 /*
1922 ** This function does not contribute to library functionality, and is not
1923 ** included in release builds. It is intended to be called from within
1924 ** an interactive debugger.
1925 **
1926 ** When called, this function prints a single line of human readable output
1927 ** to stdout describing the locks currently held by the connection. For
1928 ** example:
1929 **
1930 **     (gdb) call print_db_locks(pDb)
1931 **     (shared on dms2) (exclusive on writer)
1932 */
1933 void print_db_locks(lsm_db *db){
1934   int iLock;
1935   for(iLock=0; iLock<16; iLock++){
1936     int bOne = 0;
1937     const char *azLock[] = {0, "shared", "exclusive"};
1938     const char *azName[] = {
1939       0, "dms1", "dms2", "writer", "worker", "checkpointer",
1940       "reader0", "reader1", "reader2", "reader3", "reader4", "reader5"
1941     };
1942     int eHave = shmLockType(db, iLock);
1943     if( azLock[eHave] ){
1944       printf("%s(%s on %s)", (bOne?" ":""), azLock[eHave], azName[iLock]);
1945       bOne = 1;
1946     }
1947   }
1948   printf("\n");
1949 }
1950 void print_all_db_locks(lsm_db *db){
1951   lsm_db *p;
1952   for(p=db->pDatabase->pConn; p; p=p->pNext){
1953     printf("%s connection %p ", ((p==db)?"*":""), p);
1954     print_db_locks(p);
1955   }
1956 }
1957 #endif
1958 
1959 void lsmShmBarrier(lsm_db *db){
1960   lsmEnvShmBarrier(db->pEnv);
1961 }
1962 
1963 int lsm_checkpoint(lsm_db *pDb, int *pnKB){
1964   int rc;                         /* Return code */
1965   u32 nWrite = 0;                 /* Number of pages checkpointed */
1966 
1967   /* Attempt the checkpoint. If successful, nWrite is set to the number of
1968   ** pages written between this and the previous checkpoint.  */
1969   rc = lsmCheckpointWrite(pDb, 0, &nWrite);
1970 
1971   /* If required, calculate the output variable (KB of data checkpointed).
1972   ** Set it to zero if an error occured.  */
1973   if( pnKB ){
1974     int nKB = 0;
1975     if( rc==LSM_OK && nWrite ){
1976       nKB = (((i64)nWrite * lsmFsPageSize(pDb->pFS)) + 1023) / 1024;
1977     }
1978     *pnKB = nKB;
1979   }
1980 
1981   return rc;
1982 }
1983