]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the "getlock" utility for determining if a database file (on unix) is
authordrh <drh@noemail.net>
Fri, 22 Apr 2011 22:55:10 +0000 (22:55 +0000)
committerdrh <drh@noemail.net>
Fri, 22 Apr 2011 22:55:10 +0000 (22:55 +0000)
currently locked.

FossilOrigin-Name: 0ab24b133e332ad7f4517b8e113e9c241ee9af9f

manifest
manifest.uuid
tool/getlock.c [new file with mode: 0644]

index bcd5754bbe3fb033e11143bfad5a442049bce14f..65bc4f3b228b541508c3e731ecab3ec722fa5202 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sa\scomment\sin\se_createtable.test.
-D 2011-04-20T13:35:44.094
+C Add\sthe\s"getlock"\sutility\sfor\sdetermining\sif\sa\sdatabase\sfile\s(on\sunix)\sis\ncurrently\slocked.
+D 2011-04-22T22:55:10.113
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -899,6 +899,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
+F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027
 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
 F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
@@ -929,7 +930,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 0dd09fc034c127718366d3a3183e367d2f9fd82d
-R 056a0ea57c930302e35ea6c4f7c5b4b7
-U dan
-Z b72241c9e230cb141bfcaf5fbf022480
+P d8b149f5e465f7794739ed0210e1e5c53110ee9a
+R 46d4cc9c199137dd735f2ac252175f1e
+U drh
+Z 48df56ba9c3ee078a0d4702e2f08ce89
index fde4759710ba6e3d3977e656d8ab678131e6ec95..92d78b219dbf8c5036fe3e24976dab14f2cf9e80 100644 (file)
@@ -1 +1 @@
-d8b149f5e465f7794739ed0210e1e5c53110ee9a
\ No newline at end of file
+0ab24b133e332ad7f4517b8e113e9c241ee9af9f
\ No newline at end of file
diff --git a/tool/getlock.c b/tool/getlock.c
new file mode 100644 (file)
index 0000000..7eff04d
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+** This utility program looks at an SQLite database and determines whether
+** or not it is locked, the kind of lock, and who is holding this lock.
+**
+** This only works on unix when the posix advisory locking method is used
+** (which is the default on unix) and when the PENDING_BYTE is in its
+** usual place.
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static void usage(const char *argv0){
+  fprintf(stderr, "Usage: %s database\n", argv0);
+  exit(1);
+}
+
+/* Check for a conflicting lock.  If one is found, print an this
+** on standard output using the format string given and return 1.
+** If there are no conflicting locks, return 0.
+*/
+static int isLocked(
+  int h,                /* File descriptor to check */
+  int type,             /* F_RDLCK or F_WRLCK */
+  unsigned int iOfst,   /* First byte of the lock */
+  unsigned int iCnt,    /* Number of bytes in the lock range */
+  const char *zType     /* Type of lock */
+){
+  struct flock lk;
+
+  memset(&lk, 0, sizeof(lk));
+  lk.l_type = type;
+  lk.l_whence = SEEK_SET;
+  lk.l_start = iOfst;
+  lk.l_len = iCnt;
+  if( fcntl(h, F_GETLK, &lk)==(-1) ){
+    fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
+    exit(1);
+  }
+  if( lk.l_type==F_UNLCK ) return 0;
+  printf("%s lock held by %d\n", zType, (int)lk.l_pid);
+  return 1;
+}
+
+/*
+** Location of locking bytes in the database file
+*/
+#define PENDING_BYTE      (0x40000000)
+#define RESERVED_BYTE     (PENDING_BYTE+1)
+#define SHARED_FIRST      (PENDING_BYTE+2)
+#define SHARED_SIZE       510
+
+/*
+** Lock locations for shared-memory locks used by WAL mode.
+*/
+#define SHM_BASE          120
+#define SHM_WRITE         SHM_BASE
+#define SHM_CHECKPOINT    (SHM_BASE+1)
+#define SHM_RECOVER       (SHM_BASE+2)
+#define SHM_READ_FIRST    (SHM_BASE+3)
+#define SHM_READ_SIZE     5
+
+
+int main(int argc, char **argv){
+  int hDb;        /* File descriptor for the open database file */
+  int hShm;       /* File descriptor for WAL shared-memory file */
+  char *zShm;     /* Name of the shared-memory file for WAL mode */
+  ssize_t got;    /* Bytes read from header */
+  int isWal;                 /* True if in WAL mode */
+  int nName;                 /* Length of filename */
+  unsigned char aHdr[100];   /* Database header */
+  int nLock = 0;             /* Number of locks held */
+  int i;                     /* Loop counter */
+
+  if( argc!=2 ) usage(argv[0]);
+  hDb = open(argv[1], O_RDONLY, 0);
+  if( hDb<0 ){
+    fprintf(stderr, "cannot open %s\n", argv[1]);
+    return 1;
+  }
+
+  /* Make sure we are dealing with an database file */
+  got = read(hDb, aHdr, 100);
+  if( got!=100 || memcmp(aHdr, "SQLite format 3",16)!=0 ){
+    fprintf(stderr, "not an SQLite database: %s\n", argv[1]);
+    exit(1);
+  }
+
+  /* First check for an exclusive lock */
+  if( isLocked(hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE") ){
+    return 0;
+  }
+  isWal = aHdr[18]==2;
+  if( isWal==0 ){
+    /* Rollback mode */
+    if( isLocked(hDb, F_RDLCK, PENDING_BYTE, 1, "PENDING") ) return 0;
+    if( isLocked(hDb, F_RDLCK, RESERVED_BYTE, 1, "RESERVED") ) return 0;
+    if( isLocked(hDb, F_WRLCK, SHARED_FIRST, SHARED_SIZE, "SHARED") ){
+      return 0;
+    }
+  }else{
+    /* WAL mode */
+    nName = (int)strlen(argv[1]);
+    zShm = malloc( nName + 100 );
+    if( zShm==0 ){
+      fprintf(stderr, "out of memory\n");
+      exit(1);
+    }
+    memcpy(zShm, argv[1], nName);
+    memcpy(&zShm[nName], "-shm", 5);
+    hShm = open(zShm, O_RDONLY, 0);
+    if( hShm<0 ){
+      fprintf(stderr, "cannot open %s\n", zShm);
+      return 1;
+    }
+    if( isLocked(hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ){
+      return 0;
+    }
+    nLock += isLocked(hShm, F_RDLCK, SHM_CHECKPOINT, 1, "WAL-CHECKPOINT");
+    nLock += isLocked(hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE");
+    for(i=0; i<SHM_READ_SIZE; i++){
+      nLock += isLocked(hShm, F_WRLCK, SHM_READ_FIRST+i, 1, "WAL-READ");
+    }
+  }
+  if( nLock==0 ){
+    printf("file is not locked\n");
+  }
+  return 0;
+}