Add the (highly experimental) omit_readlock pragma that disables the use
of readlocks on read-only databases that are connected using ATTACH. (CVS 2317)

FossilOrigin-Name: 2155448d2128119f74241da0ea07d6713b71765c
diff --git a/src/btree.c b/src/btree.c
index 952e91a..4cb6bda 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.245 2005/02/04 04:07:17 danielk1977 Exp $
+** $Id: btree.c,v 1.246 2005/02/06 02:45:42 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -1223,8 +1223,7 @@
     *ppBtree = 0;
     return SQLITE_NOMEM;
   }
-  rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE,
-                        (flags & BTREE_OMIT_JOURNAL)==0);
+  rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
   if( rc!=SQLITE_OK ){
     if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
     sqliteFree(pBt);
diff --git a/src/btree.h b/src/btree.h
index 8d78f58..7426673 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -13,7 +13,7 @@
 ** subsystem.  See comments in the source code for a detailed description
 ** of what each interface routine does.
 **
-** @(#) $Id: btree.h,v 1.61 2005/01/12 07:15:05 danielk1977 Exp $
+** @(#) $Id: btree.h,v 1.62 2005/02/06 02:45:42 drh Exp $
 */
 #ifndef _BTREE_H_
 #define _BTREE_H_
@@ -46,9 +46,13 @@
 
 /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
 ** following values.
+**
+** NOTE:  These values must match the corresponding PAGER_ values in
+** pager.h.
 */
 #define BTREE_OMIT_JOURNAL  1  /* Do not use journal.  No argument */
-#define BTREE_MEMORY        2  /* In-memory DB.  No argument */
+#define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
+#define BTREE_MEMORY        4  /* In-memory DB.  No argument */
 
 int sqlite3BtreeClose(Btree*);
 int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
diff --git a/src/main.c b/src/main.c
index 51608cc..d36777d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.279 2005/02/05 07:33:34 danielk1977 Exp $
+** $Id: main.c,v 1.280 2005/02/06 02:45:42 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -858,6 +858,9 @@
   if( omitJournal ){
     btree_flags |= BTREE_OMIT_JOURNAL;
   }
+  if( db->flags & SQLITE_NoReadlock ){
+    btree_flags |= BTREE_NO_READLOCK;
+  }
   if( zFilename==0 ){
 #if TEMP_STORE==0
     /* Do nothing */
diff --git a/src/pager.c b/src/pager.c
index e8b5a14..53c2b84 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.187 2005/01/29 08:32:45 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.188 2005/02/06 02:45:42 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -250,6 +250,7 @@
   u8 journalOpen;             /* True if journal file descriptors is valid */
   u8 journalStarted;          /* True if header of journal is synced */
   u8 useJournal;              /* Use a rollback journal on this file */
+  u8 noReadlock;              /* Do not bother to obtain readlocks */
   u8 stmtOpen;                /* True if the statement subjournal is open */
   u8 stmtInUse;               /* True we are in a statement subtransaction */
   u8 stmtAutoopen;            /* Open stmt journal when main journal is opened*/
@@ -1483,7 +1484,7 @@
   Pager **ppPager,         /* Return the Pager structure here */
   const char *zFilename,   /* Name of the database file to open */
   int nExtra,              /* Extra bytes append to each in-memory page */
-  int useJournal           /* TRUE to use a rollback journal on this file */
+  int flags                /* flags controlling this file */
 ){
   Pager *pPager;
   char *zFullPathname = 0;
@@ -1494,6 +1495,8 @@
   int tempFile = 0;
   int memDb = 0;
   int readOnly = 0;
+  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
+  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
   char zTemp[SQLITE_TEMPNAME_SIZE];
 
   *ppPager = 0;
@@ -1556,6 +1559,7 @@
 #endif
   pPager->journalOpen = 0;
   pPager->useJournal = useJournal && !memDb;
+  pPager->noReadlock = noReadlock && readOnly;
   pPager->stmtOpen = 0;
   pPager->stmtInUse = 0;
   pPager->nRef = 0;
@@ -2144,7 +2148,7 @@
 */
 int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   PgHdr *pPg;
-  int rc;
+  int rc, n;
 
   /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
   ** number greater than this, or zero, is requested.
@@ -2165,9 +2169,11 @@
   ** on the database file.
   */
   if( pPager->nRef==0 && !MEMDB ){
-    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
-    if( rc!=SQLITE_OK ){
-      return rc;
+    if( !pPager->noReadlock ){
+      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
     }
 
     /* If a journal file exists, and there is no RESERVED lock on the
@@ -2354,13 +2360,13 @@
     if( pPager->nExtra>0 ){
       memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
     }
-    sqlite3pager_pagecount(pPager);
+    n = sqlite3pager_pagecount(pPager);
     if( pPager->errMask!=0 ){
       sqlite3pager_unref(PGHDR_TO_DATA(pPg));
       rc = pager_errcode(pPager);
       return rc;
     }
-    if( pPager->dbSize<(int)pgno ){
+    if( n<(int)pgno ){
       memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
     }else{
       int rc;
diff --git a/src/pager.h b/src/pager.h
index ef602d3..8e88c86 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -13,7 +13,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.40 2004/11/05 16:37:03 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.41 2005/02/06 02:45:42 drh Exp $
 */
 
 /*
@@ -50,13 +50,21 @@
 */
 typedef struct Pager Pager;
 
+/*
+** Allowed values for the flags parameter to sqlite3pager_open().
+**
+** NOTE: This values must match the corresponding BTREE_ values in btree.h.
+*/
+#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
+#define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
+
 
 /*
 ** See source code comments for a detailed description of the following
 ** routines:
 */
 int sqlite3pager_open(Pager **ppPager, const char *zFilename,
-                     int nExtra, int useJournal);
+                     int nExtra, int flags);
 void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
 void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
 void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
diff --git a/src/pragma.c b/src/pragma.c
index 10accbf..49a66c1 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.87 2005/02/04 04:07:17 danielk1977 Exp $
+** $Id: pragma.c,v 1.88 2005/02/06 02:45:42 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -148,6 +148,7 @@
     { "empty_result_callbacks",   SQLITE_NullCallback  },
     /* The following is VERY experimental */
     { "writable_schema",          SQLITE_WriteSchema   },
+    { "omit_readlock",            SQLITE_NoReadlock    },
   };
   int i;
   const struct sPragmaType *p;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index dc4369a..627aeae 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.367 2005/02/05 12:48:48 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.368 2005/02/06 02:45:43 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -469,6 +469,8 @@
 #define SQLITE_SqlTrace       0x00000200  /* Debug print SQL as it executes */
 #define SQLITE_VdbeListing    0x00000400  /* Debug listings of VDBE programs */
 #define SQLITE_WriteSchema    0x00000800  /* OK to update SQLITE_MASTER */
+#define SQLITE_NoReadlock     0x00001000  /* Readlocks are omitted when 
+                                          ** accessing read-only databases */
 
 /*
 ** Possible values for the sqlite.magic field.
diff --git a/src/test2.c b/src/test2.c
index b7c83cf..e77f2f2 100644
--- a/src/test2.c
+++ b/src/test2.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test2.c,v 1.28 2005/01/13 11:07:54 danielk1977 Exp $
+** $Id: test2.c,v 1.29 2005/02/06 02:45:43 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -81,7 +81,7 @@
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
-  rc = sqlite3pager_open(&pPager, argv[1], 0, 1);
+  rc = sqlite3pager_open(&pPager, argv[1], 0, 0);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;