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