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