SQLite4
Check-in [69f33cfa12]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add definitions for the extra locks required for read-only clients to detect whether or not a database is live.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | read-only-clients
Files: files | file ages | folders
SHA1: 69f33cfa1257123be4e88410fb707de460f9f9cc
User & Date: dan 2013-02-09 19:42:47
Context
2013-02-17
14:19
Merge trunk changes into this branch. check-in: 29390891c5 user: dan tags: read-only-clients
2013-02-09
19:42
Add definitions for the extra locks required for read-only clients to detect whether or not a database is live. check-in: 69f33cfa12 user: dan tags: read-only-clients
16:55
Have worker clients and writers that discard an old in-memory tree update a read-lock slot before concluding their work or write transaction. This is required for read-only clients - which cannot set the value of their own read-lock slot. check-in: 798d9e23be user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/lsmInt.h.

   128    128   
   129    129   /* The number of bytes reserved at the start of each shm chunk for MM. */
   130    130   #define LSM_SHM_CHUNK_HDR  (sizeof(ShmChunk))
   131    131   
   132    132   /* The number of available read locks. */
   133    133   #define LSM_LOCK_NREADER   6
   134    134   
          135  +/* The number of available read-write client locks. */
          136  +#define LSM_LOCK_NRWCLIENT   16
          137  +
   135    138   /* Lock definitions */
   136    139   #define LSM_LOCK_DMS1         1
   137    140   #define LSM_LOCK_DMS2         2
   138         -#define LSM_LOCK_WRITER       3
   139         -#define LSM_LOCK_WORKER       4
   140         -#define LSM_LOCK_CHECKPOINTER 5
          141  +#define LSM_LOCK_DMS3         3
          142  +#define LSM_LOCK_WRITER       4
          143  +#define LSM_LOCK_WORKER       5
          144  +#define LSM_LOCK_CHECKPOINTER 6
   141    145   #define LSM_LOCK_READER(i)    ((i) + LSM_LOCK_CHECKPOINTER + 1)
          146  +#define LSM_LOCK_RWCLIENT(i)  ((i) + LSM_LOCK_READER(LSM_LOCK_NREADER))
   142    147   
   143    148   /*
   144    149   ** Hard limit on the number of free-list entries that may be stored in 
   145    150   ** a checkpoint (the remainder are stored as a system record in the LSM).
   146    151   ** See also LSM_CONFIG_MAX_FREELIST.
   147    152   */
   148    153   #define LSM_MAX_FREELIST_ENTRIES 24
................................................................................
   280    285   
   281    286   /*
   282    287   ** Database handle structure.
   283    288   **
   284    289   ** mLock:
   285    290   **   A bitmask representing the locks currently held by the connection.
   286    291   **   An LSM database supports N distinct locks, where N is some number less
   287         -**   than or equal to 16. Locks are numbered starting from 1 (see the 
          292  +**   than or equal to 32. Locks are numbered starting from 1 (see the 
   288    293   **   definitions for LSM_LOCK_WRITER and co.).
   289    294   **
   290         -**   The least significant 16-bits in mLock represent EXCLUSIVE locks. The
          295  +**   The least significant 32-bits in mLock represent EXCLUSIVE locks. The
   291    296   **   most significant are SHARED locks. So, if a connection holds a SHARED
   292    297   **   lock on lock region iLock, then the following is true:
   293    298   **
   294         -**       (mLock & ((iLock+16-1) << 1))
          299  +**       (mLock & ((iLock+32-1) << 1))
   295    300   **
   296    301   **   Or for an EXCLUSIVE lock:
   297    302   **
   298    303   **       (mLock & ((iLock-1) << 1))
   299    304   */
   300    305   struct lsm_db {
   301    306   
................................................................................
   317    322     int bMultiProc;                 /* Configured by L_C_MULTIPLE_PROCESSES */
   318    323     lsm_compress compress;          /* Compression callbacks */
   319    324     lsm_compress_factory factory;   /* Compression callback factory */
   320    325   
   321    326     /* Sub-system handles */
   322    327     FileSystem *pFS;                /* On-disk portion of database */
   323    328     Database *pDatabase;            /* Database shared data */
          329  +  int iRwclient;                  /* Read-write client lock held (-1 == none) */
   324    330   
   325    331     /* Client transaction context */
   326    332     Snapshot *pClient;              /* Client snapshot */
   327    333     int iReader;                    /* Read lock held (-1 == unlocked) */
   328    334     MultiCursor *pCsr;              /* List of all open cursors */
   329    335     LogWriter *pLogWriter;          /* Context for writing to the log file */
   330    336     int nTransOpen;                 /* Number of opened write transactions */
................................................................................
   345    351     void (*xLog)(void *, int, const char *);
   346    352     void *pLogCtx;
   347    353   
   348    354     /* Work done notification callback */
   349    355     void (*xWork)(lsm_db *, void *);
   350    356     void *pWorkCtx;
   351    357   
   352         -  u32 mLock;                      /* Mask of current locks. See lsmShmLock(). */
          358  +  u64 mLock;                      /* Mask of current locks. See lsmShmLock(). */
   353    359     lsm_db *pNext;                  /* Next connection to same database */
   354    360   
   355    361     int nShm;                       /* Size of apShm[] array */
   356    362     void **apShm;                   /* Shared memory chunks */
   357    363     ShmHeader *pShmhdr;             /* Live shared-memory header */
   358    364     TreeHeader treehdr;             /* Local copy of tree-header */
   359    365     u32 aSnapshot[LSM_META_PAGE_SIZE / sizeof(u32)];

Changes to src/lsm_main.c.

    89     89     pDb->xCmp = xCmp;
    90     90     pDb->nDfltPgsz = LSM_DFLT_PAGE_SIZE;
    91     91     pDb->nDfltBlksz = LSM_DFLT_BLOCK_SIZE;
    92     92     pDb->nMerge = LSM_DFLT_AUTOMERGE;
    93     93     pDb->nMaxFreelist = LSM_MAX_FREELIST_ENTRIES;
    94     94     pDb->bUseLog = LSM_DFLT_USE_LOG;
    95     95     pDb->iReader = -1;
           96  +  pDb->iRwclient = -1;
    96     97     pDb->bMultiProc = LSM_DFLT_MULTIPLE_PROCESSES;
    97     98     pDb->bMmap = LSM_DFLT_MMAP;
    98     99     pDb->xLog = xLog;
    99    100     pDb->compress.iId = LSM_COMPRESSION_NONE;
   100    101     return LSM_OK;
   101    102   }
   102    103   
................................................................................
   188    189     if( pDb ){
   189    190       assert_db_state(pDb);
   190    191       if( pDb->pCsr || pDb->nTransOpen ){
   191    192         rc = LSM_MISUSE_BKPT;
   192    193       }else{
   193    194         lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
   194    195         pDb->pClient = 0;
          196  +
   195    197         lsmDbDatabaseRelease(pDb);
   196    198         lsmLogClose(pDb);
   197    199         lsmFsClose(pDb->pFS);
          200  +      assert( pDb->mLock==0 );
   198    201         
   199    202         /* Invoke any destructors registered for the compression or 
   200    203         ** compression factory callbacks.  */
   201    204         if( pDb->factory.xFree ) pDb->factory.xFree(pDb->factory.pCtx);
   202    205         if( pDb->compress.xFree ) pDb->compress.xFree(pDb->compress.pCtx);
   203    206   
   204    207         lsmFree(pDb->pEnv, pDb->rollback.aArray);

Changes to src/lsm_shared.c.

   276    276           Database *p = pDb->pDatabase;
   277    277           dbTruncateFile(pDb);
   278    278           lsmFsCloseAndDeleteLog(pDb->pFS);
   279    279           if( p->pFile && p->bMultiProc ) lsmEnvShmUnmap(pDb->pEnv, p->pFile, 1);
   280    280         }
   281    281       }
   282    282     }
          283  +
          284  +  if( pDb->iRwclient>=0 ){
          285  +    lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0);
          286  +  }
   283    287   
   284    288     lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0);
   285    289     lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
   286    290     pDb->pShmhdr = 0;
   287    291   }
   288    292   
   289    293   static int doDbConnect(lsm_db *pDb){
................................................................................
   334    338     ** mode, this operation will fail. In this case, return the error to the
   335    339     ** caller - the attempt to connect to the db has failed.
   336    340     */
   337    341     if( rc==LSM_OK ){
   338    342       rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_SHARED, 0);
   339    343     }
   340    344   
   341         -  /* If anything went wrong, unlock DMS2. Unlock DMS1 in any case. */
          345  +  /* If anything went wrong, unlock DMS2. Otherwise, try to take an exclusive
          346  +  ** lock on one of the LSM_LOCK_RWCLIENT() locks. Unlock DMS1 in any case. */
   342    347     if( rc!=LSM_OK ){
   343    348       lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0);
   344    349       pDb->pShmhdr = 0;
          350  +  }else{
          351  +    int i;
          352  +    for(i=0; i<LSM_LOCK_NRWCLIENT; i++){
          353  +      int rc2 = lsmShmLock(pDb, LSM_LOCK_RWCLIENT(i), LSM_LOCK_EXCL, 0);
          354  +      if( rc2==LSM_OK ) pDb->iRwclient = i;
          355  +      if( rc2!=LSM_BUSY ){
          356  +        rc = rc2;
          357  +        break;
          358  +      }
          359  +    }
   345    360     }
   346    361     lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
   347    362     return rc;
   348    363   }
   349    364   
   350    365   /*
   351    366   ** Return a reference to the shared Database handle for the database 
................................................................................
  1520   1535   int lsmShmLock(
  1521   1536     lsm_db *db, 
  1522   1537     int iLock,
  1523   1538     int eOp,                        /* One of LSM_LOCK_UNLOCK, SHARED or EXCL */
  1524   1539     int bBlock                      /* True for a blocking lock */
  1525   1540   ){
  1526   1541     lsm_db *pIter;
  1527         -  const u32 me = (1 << (iLock-1));
  1528         -  const u32 ms = (1 << (iLock+16-1));
         1542  +  const u64 me = ((u64)1 << (iLock-1));
         1543  +  const u64 ms = ((u64)1 << (iLock+32-1));
  1529   1544     int rc = LSM_OK;
  1530   1545     Database *p = db->pDatabase;
  1531   1546   
  1532         -  assert( iLock>=1 && iLock<=LSM_LOCK_READER(LSM_LOCK_NREADER-1) );
  1533         -  assert( iLock<=16 );
         1547  +  assert( iLock>=1 && iLock<=LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1) );
         1548  +  assert( LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1)<=32 );
  1534   1549     assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );
  1535   1550   
  1536   1551     /* Check for a no-op. Proceed only if this is not one of those. */
  1537   1552     if( (eOp==LSM_LOCK_UNLOCK && (db->mLock & (me|ms))!=0)
  1538   1553      || (eOp==LSM_LOCK_SHARED && (db->mLock & (me|ms))!=ms)
  1539   1554      || (eOp==LSM_LOCK_EXCL   && (db->mLock & me)==0)
  1540   1555     ){
................................................................................
  1594   1609   
  1595   1610     return rc;
  1596   1611   }
  1597   1612   
  1598   1613   #ifdef LSM_DEBUG
  1599   1614   
  1600   1615   int shmLockType(lsm_db *db, int iLock){
  1601         -  const u32 me = (1 << (iLock-1));
  1602         -  const u32 ms = (1 << (iLock+16-1));
         1616  +  const u64 me = ((u64)1 << (iLock-1));
         1617  +  const u64 ms = ((u64)1 << (iLock+32-1));
  1603   1618   
  1604   1619     if( db->mLock & me ) return LSM_LOCK_EXCL;
  1605   1620     if( db->mLock & ms ) return LSM_LOCK_SHARED;
  1606   1621     return LSM_LOCK_UNLOCK;
  1607   1622   }
  1608   1623   
  1609   1624   /*

Changes to src/lsm_unix.c.

   302    302     static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
   303    303     struct flock lock;
   304    304   
   305    305     assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
   306    306     assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
   307    307     assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
   308    308     assert( eType>=0 && eType<array_size(aType) );
   309         -  assert( iLock>0 && iLock<=16 );
          309  +  assert( iLock>0 && iLock<=32 );
   310    310   
   311    311     memset(&lock, 0, sizeof(lock));
   312    312     lock.l_whence = SEEK_SET;
   313    313     lock.l_len = 1;
   314    314     lock.l_type = aType[eType];
   315    315     lock.l_start = (4096-iLock);
   316    316