/ Check-in [70661128]
Login

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

Overview
Comment:Untested implementation of the shared-memory dead-man-switch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: 706611283ea2575c2942543391026b36061cfc1c
User & Date: drh 2010-04-29 16:40:51
Context
2010-04-29
22:34
Refactor wal.c to use the VFS. This check-in compiles and links and works ok as long as you leave WAL turned off, but WAL does not work. check-in: 62db5fa3 user: drh tags: wal
16:40
Untested implementation of the shared-memory dead-man-switch. check-in: 70661128 user: drh tags: wal
15:17
Progress towards a VFS that will support WAL. Locking code is in place but is untested. Still no support for the DMS. check-in: 1bde41cf user: drh tags: wal
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  4694   4694   **
  4695   4695   ** lockMask might contain multiple bits but all bits are guaranteed
  4696   4696   ** to be contiguous.
  4697   4697   **
  4698   4698   ** Locks block if the UNIX_SHM_MUTEX bit is set and are non-blocking
  4699   4699   ** otherwise.
  4700   4700   */
  4701         -static int unixShmSystemLocks(
         4701  +static int unixShmSystemLock(
  4702   4702     unixShmFile *pFile,   /* Apply locks to this open shared-memory segment */
  4703   4703     int lockType,         /* F_UNLCK, F_RDLCK, or F_WRLCK */
  4704   4704     u8 lockMask           /* Which bytes to lock or unlock */
  4705   4705   ){
  4706   4706     struct flock f;       /* The posix advisory locking structure */
  4707   4707     int lockOp;           /* The opcode for fcntl() */
  4708   4708     int i;                /* Offset into the locking byte range */
  4709   4709     int rc;               /* Result code form fcntl() */
  4710   4710     u8 mask;              /* Mask of bits in lockMask */
         4711  +
         4712  +  /* Access to the unixShmFile object is serialized by the caller */
         4713  +  assert( sqlite3_mutex_held(pFile->mutex) );
  4711   4714   
  4712   4715     /* Initialize the locking parameters */
  4713   4716     memset(&f, 0, sizeof(f));
  4714   4717     f.l_type = lockType;
  4715   4718     f.l_whence = SEEK_SET;
  4716   4719     if( (lockMask & UNIX_SHM_MUTEX)!=0 && lockType!=F_UNLCK ){
  4717   4720       lockOp = F_SETLKW;
................................................................................
  4782   4785     unixShmFile *pFile,   /* The underlying shared-memory file */
  4783   4786     unixShm *p,           /* The connection to be unlocked */
  4784   4787     u8 unlockMask         /* Mask of locks to be unlocked */
  4785   4788   ){
  4786   4789     int rc;      /* Result code */
  4787   4790     unixShm *pX; /* For looping over all sibling connections */
  4788   4791     u8 allMask;  /* Union of locks held by connections other than "p" */
         4792  +
         4793  +  /* Access to the unixShmFile object is serialized by the caller */
         4794  +  assert( sqlite3_mutex_held(pFile->mutex) );
  4789   4795   
  4790   4796     /* We never try to unlock locks that we do not hold */
  4791   4797     assert( ((p->exclMask|p->sharedMask) & unlockMask)==unlockMask );
  4792   4798   
  4793   4799     /* Compute locks held by sibling connections */
  4794   4800     for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4795   4801       if( pX==p ) continue;
  4796   4802       assert( (pX->exclMask & unlockMask)==0 );
  4797   4803       allMask |= pX->sharedMask;
  4798   4804     }
  4799   4805   
  4800   4806     /* Unlock the system-level locks */
  4801   4807     if( (unlockMask & allMask)!=unlockMask ){
  4802         -    rc = unixShmSystemLocks(pFile, F_UNLCK, unlockMask & ~allMask);
         4808  +    rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask);
  4803   4809     }else{
  4804   4810       rc = SQLITE_OK;
  4805   4811     }
  4806   4812   
  4807   4813     /* Undo the local locks */
  4808   4814     if( rc==SQLITE_OK ){
  4809   4815       p->exclMask &= ~unlockMask;
................................................................................
  4819   4825     unixShmFile *pFile,   /* The underlying shared-memory file */
  4820   4826     unixShm *p,           /* The connection to get the shared locks */
  4821   4827     u8 readMask           /* Mask of shared locks to be acquired */
  4822   4828   ){
  4823   4829     int rc;        /* Result code */
  4824   4830     unixShm *pX;   /* For looping over all sibling connections */
  4825   4831     u8 allShared;  /* Union of locks held by connections other than "p" */
         4832  +
         4833  +  /* Access to the unixShmFile object is serialized by the caller */
         4834  +  assert( sqlite3_mutex_held(pFile->mutex) );
  4826   4835   
  4827   4836     /* Find out which shared locks are already held by sibling connections.
  4828   4837     ** If any sibling already holds an exclusive lock, go ahead and return
  4829   4838     ** SQLITE_BUSY.
  4830   4839     */
  4831   4840     for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4832   4841       if( pX==p ) continue;
  4833   4842       if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
  4834   4843       allShared |= pX->sharedMask;
  4835   4844     }
  4836   4845   
  4837   4846     /* Get shared locks at the system level, if necessary */
  4838   4847     if( (~allShared) & readMask ){
  4839         -    rc = unixShmSystemLocks(pFile, F_RDLCK, readMask);
         4848  +    rc = unixShmSystemLock(pFile, F_RDLCK, readMask);
  4840   4849     }else{
  4841   4850       rc = SQLITE_OK;
  4842   4851     }
  4843   4852   
  4844   4853     /* Get the local shared locks */
  4845   4854     if( rc==SQLITE_OK ){
  4846   4855       p->sharedMask |= readMask;
................................................................................
  4855   4864   static int unixShmExclusiveLock(
  4856   4865     unixShmFile *pFile,    /* The underlying shared-memory file */
  4857   4866     unixShm *p,            /* The connection to get the exclusive locks */
  4858   4867     u8 writeMask           /* Mask of exclusive locks to be acquired */
  4859   4868   ){
  4860   4869     int rc;        /* Result code */
  4861   4870     unixShm *pX;   /* For looping over all sibling connections */
         4871  +
         4872  +  /* Access to the unixShmFile object is serialized by the caller */
         4873  +  assert( sqlite3_mutex_held(pFile->mutex) );
  4862   4874   
  4863   4875     /* Make sure no sibling connections hold locks that will block this
  4864   4876     ** lock.  If any do, return SQLITE_BUSY right away.
  4865   4877     */
  4866   4878     for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4867   4879       if( pX==p ) continue;
  4868   4880       if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
  4869   4881       if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
  4870   4882     }
  4871   4883   
  4872   4884     /* Get the exclusive locks at the system level.  Then if successful
  4873   4885     ** also mark the local connection as being locked.
  4874   4886     */
  4875         -  rc = unixShmSystemLocks(pFile, F_WRLCK, writeMask);
         4887  +  rc = unixShmSystemLock(pFile, F_WRLCK, writeMask);
  4876   4888     if( rc==SQLITE_OK ){
  4877   4889       p->sharedMask &= ~writeMask;
  4878   4890       p->exclMask |= writeMask;
  4879   4891     }
  4880   4892     return rc;
  4881   4893   }
  4882   4894   
................................................................................
  4913   4925   ** the file must be truncated to zero length or have its header cleared.
  4914   4926   */
  4915   4927   static int unixShmOpen(
  4916   4928     sqlite3_vfs *pVfs,    /* The VFS */
  4917   4929     const char *zName,    /* Name of file to mmap */
  4918   4930     sqlite3_shm **pShm    /* Write the unixShm object created here */
  4919   4931   ){
  4920         -  struct unixShm *p = 0;
  4921         -  struct unixShmFile *pFile = 0;
  4922         -  int rc;
  4923         -  struct unixFileId fid;
  4924         -  struct stat sStat;
         4932  +  struct unixShm *p = 0;             /* The connection to be opened */
         4933  +  struct unixShmFile *pFile = 0;     /* The underlying mmapped file */
         4934  +  int rc;                            /* Result code */
         4935  +  struct unixFileId fid;             /* Unix file identifier */
         4936  +  struct stat sStat;                 /* Result from stat() an fstat() */
  4925   4937   
         4938  +  /* Allocate space for the new sqlite3_shm object */
  4926   4939     p = sqlite3_malloc( sizeof(*p) );
  4927   4940     if( p==0 ) return SQLITE_NOMEM;
  4928   4941     memset(p, 0, sizeof(*p));
  4929   4942   
         4943  +  /* Look to see if there is an existing unixShmFile that can be used.
         4944  +  ** If no matching unixShmFile currently exists, create a new one.
         4945  +  */
  4930   4946     unixEnterMutex();
  4931   4947     rc = stat(zName, &sStat);
  4932   4948     if( rc==0 ){
  4933   4949       memset(&fid, 0, sizeof(fid));
  4934   4950       fid.dev = sStat.st_dev;
  4935   4951       fid.ino = sStat.st_ino;
  4936   4952       for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){
................................................................................
  4978   4994         rc = SQLITE_CANTOPEN;
  4979   4995         goto shm_open_err;
  4980   4996       }
  4981   4997       pFile->fid.dev = sStat.st_dev;
  4982   4998       pFile->fid.ino = sStat.st_ino;
  4983   4999       pFile->size = (int)sStat.st_size;
  4984   5000       pFile->size = (pFile->size/SQLITE_UNIX_SHM_INCR)*SQLITE_UNIX_SHM_INCR;
  4985         -    if( pFile->size==0 ){
  4986         -      pFile->size = SQLITE_UNIX_SHM_INCR;
  4987         -      rc = ftruncate(pFile->h, pFile->size);
  4988         -      if( rc ){
  4989         -        rc = SQLITE_FULL;
         5001  +
         5002  +    /* Check to see if another process is holding the dead-man switch.
         5003  +    ** If not, truncate the file to zero length. 
         5004  +    */
         5005  +    if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_MUTEX) ){
         5006  +      rc = SQLITE_IOERR_LOCK;
         5007  +      goto shm_open_err;
         5008  +    }
         5009  +    if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
         5010  +      if( ftruncate(pFile->h, 0) ){
         5011  +        rc = SQLITE_IOERR;
  4990   5012           goto shm_open_err;
  4991   5013         }
         5014  +      pFile->size = 0;
  4992   5015       }
         5016  +    rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS);
         5017  +    if( rc ) goto shm_open_err;
         5018  +    unixShmSystemLock(pFile, F_UNLCK, UNIX_SHM_MUTEX);
  4993   5019     }
  4994   5020   
         5021  +  /* Make the new connection a child of the unixShmFile */
  4995   5022     p->pFile = pFile;
  4996   5023     p->pNext = pFile->pFirst;
  4997   5024   #ifdef SQLITE_DEBUG
  4998   5025     p->id = pFile->nextShmId++;
  4999   5026   #endif
  5000   5027     pFile->pFirst = p;
  5001   5028     pFile->nRef++;
  5002   5029     *pShm = (sqlite3_shm*)p;
  5003   5030     unixLeaveMutex();
  5004   5031     return SQLITE_OK;
  5005   5032   
         5033  +  /* Jump here on any error */
  5006   5034   shm_open_err:
  5007   5035     unixShmPurge();
  5008   5036     sqlite3_free(p);
  5009   5037     sqlite3_free(pFile);
  5010   5038     *pShm = 0;
  5011   5039     unixLeaveMutex();
  5012   5040     return rc;