/ Check-in [941a01eb]
Login

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

Overview
Comment:Customizations for OSX contributed by Apple.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1:941a01eb868815f566539e9ab21f807d9e798e40
User & Date: adam 2009-11-03 22:34:36
Original Comment: Merging in OSX customizations:

A ext/sqlrr/sqlrr.[ch] -- add sql recording/replay support (very experimental extension -- pre alpha)

M ext/rtree/rtree.c -- fix cast compiler warning

M src/func.c -- substring backward compatiblity <rdar://problem/6778339>

M src/legacy.c -- replay recorder calls

M src/main.c -- if SQLITE_ENABLE_AUTO_PROFILE, call sqlite3_profile when env(SQLITE_AUTO_PROFILE) -- replay recorder calls

M src/mem1.c -- use custom malloc zone on single core systems

M src/os_unix.c -- hostid via gethostuuid -- read-only file system support for proxy locking -- improved handling of simulated shared lock on AFP/SMB on 64 bit systems -- disable whole-file-lock NFS file locking -- fix for downgrading from exclusive to shared lock on NFS -- proxy lock breaking & recreating local lock files -- support SQLITE_OPEN_AUTOPROXY flag -- only write 1st byte into new zero-length files if fs is DOS -- cache fs type info in unixFile struct -- force use of fsync() even if fdatasync() is available -- remove flock locking style support for SMB -- replace strcpy with strlcpy

M src/prepare.c -- replay recorder calls

M src/sqlite.h.in -- added SQLITE_OPEN_AUTOPROXY

M src/sqliteInt.h -- include replay recorder header

M src/vdbeapi.c -- checking for NULL statement for <rdar://6646331> -- replay recorder calls

Context
2009-11-05
18:31
Fix an undefined variable on non-Mac builds. check-in: 9552de8f user: drh tags: apple-osx
2009-11-03
22:34
Customizations for OSX contributed by Apple. check-in: 941a01eb user: adam tags: apple-osx
19:42
Fix compiler warnings on MSVC build. check-in: 01c4b5b8 user: shane tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to Makefile.in.

   322    322     $(TOP)/ext/fts3/fts3_tokenizer1.c
   323    323   SRC += \
   324    324     $(TOP)/ext/icu/sqliteicu.h \
   325    325     $(TOP)/ext/icu/icu.c
   326    326   SRC += \
   327    327     $(TOP)/ext/rtree/rtree.h \
   328    328     $(TOP)/ext/rtree/rtree.c
          329  +SRC += \
          330  +  $(TOP)/ext/sqlrr/sqlrr.h \
          331  +  $(TOP)/ext/sqlrr/sqlrr.c
   329    332   
   330    333   # Source code to the library files needed by the test fixture
   331    334   #
   332    335   TESTSRC2 = \
   333    336     $(TOP)/src/attach.c \
   334    337     $(TOP)/src/backup.c \
   335    338     $(TOP)/src/bitvec.c \
................................................................................
   430    433     $(TOP)/ext/fts3/fts3_expr.h \
   431    434     $(TOP)/ext/fts3/fts3_hash.h \
   432    435     $(TOP)/ext/fts3/fts3_tokenizer.h
   433    436   HDR += \
   434    437     $(TOP)/ext/rtree/rtree.h
   435    438   HDR += \
   436    439     $(TOP)/ext/icu/sqliteicu.h
          440  +HDR += \
          441  +  $(TOP)/ext/sqlrr/sqlrr.h
   437    442   
   438    443   # If using the amalgamation, use sqlite3.c directly to build the test
   439    444   # fixture.  Otherwise link against libsqlite3.la.  (This distinction is
   440    445   # necessary because the test fixture requires non-API symbols which are
   441    446   # hidden when the library is built via the amalgamation).
   442    447   #
   443    448   TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la

Changes to ext/rtree/rtree.c.

    61     61     SQLITE_EXTENSION_INIT1
    62     62   #else
    63     63     #include "sqlite3.h"
    64     64   #endif
    65     65   
    66     66   #include <string.h>
    67     67   #include <assert.h>
           68  +#include <stdint.h>
    68     69   
    69     70   #ifndef SQLITE_AMALGAMATION
    70     71   typedef sqlite3_int64 i64;
    71     72   typedef unsigned char u8;
    72     73   typedef unsigned int u32;
    73     74   #endif
    74     75   
................................................................................
  2666   2667     int isCreate                        /* True for xCreate, false for xConnect */
  2667   2668   ){
  2668   2669     int rc = SQLITE_OK;
  2669   2670     int iPageSize = 0;
  2670   2671     Rtree *pRtree;
  2671   2672     int nDb;              /* Length of string argv[1] */
  2672   2673     int nName;            /* Length of string argv[2] */
  2673         -  int eCoordType = (int)pAux;
         2674  +  int eCoordType = (int)(intptr_t)pAux;
  2674   2675   
  2675   2676     const char *aErrMsg[] = {
  2676   2677       0,                                                    /* 0 */
  2677   2678       "Wrong number of columns for an rtree table",         /* 1 */
  2678   2679       "Too few columns for an rtree table",                 /* 2 */
  2679   2680       "Too many columns for an rtree table"                 /* 3 */
  2680   2681     };

Added ext/sqlrr/README.txt.

            1  +
            2  +sqlrr - 10/19/2009
            3  +
            4  +SQL Replay Recording
            5  +
            6  +SUMMARY
            7  +-------------------------------------------------------
            8  +This extension enables recording sqlite API calls that access the database so that they can be replayed or examined.
            9  +
           10  +USAGE
           11  +------------------------------------------------------
           12  +Recording is enabled by compiling sqlite with symbolic constant SQLITE_ENABLE_SQLRR defined.  
           13  +By default logs are written to /tmp/<databasename>_<pid>_<connection_number>.sqlrr, to choose another directory, set the environment variable SQLITE_REPLAY_RECORD_DIR to that path.
           14  +
           15  +FILE FORMAT
           16  +-----------------------------------------------------
           17  + file:			<header>[<sql-command>]*
           18  + 
           19  + header:			<signature><format-version>
           20  +   signature: 		SQLRR (5 bytes)
           21  +   format-version:	n (1 byte)
           22  + 
           23  + sql-command:		<timestamp><type><arg-data>
           24  +   timestamp:       n (16 bytes)
           25  +   type:			n (1 byte)
           26  +        open		0
           27  +        close		1
           28  +        exec		8
           29  +        bind-text	16
           30  +        bind-double	17
           31  +        bind-int	18
           32  +        bind-null	19
           33  +        bind-value	20
           34  +        bind-clear	21
           35  +        prep		32
           36  +        step		33
           37  +        reset		34
           38  +        finalize	35
           39  +
           40  +  open-arg-data:		<connection><path><flags>
           41  +  close-arg-data:		<connection>
           42  +  exec-arg-data:		<connection><len><statement-text>
           43  +  bind-text-arg-data:	<statement-ref><index><len><data>
           44  +  bind-double-arg-data:	<statement-ref><index><data>
           45  +  bind-int-arg-data:	<statement-ref><index><data>
           46  +  bind-null-arg-data:	<statement-ref><index>
           47  +  bind-value-arg-data:	<statement-ref><index><len><data> ???
           48  +  bind-clear-arg-data:	<statement-ref>
           49  +  prep-arg-data:		<connection><len><statement-text>
           50  +  step-arg-data:		<statement-ref>
           51  +  reset-arg-data:		<statement-ref>
           52  +  finalize-arg-data:	<statement-ref>
           53  +
           54  +NOTES

Added ext/sqlrr/sqlrr.c.

            1  +/*
            2  + *  sqlrr.c
            3  + */
            4  +
            5  +#include "sqlrr.h"
            6  +
            7  +#if defined(SQLITE_ENABLE_SQLRR)
            8  +
            9  +#include <unistd.h>
           10  +#include <string.h>
           11  +#include <stdio.h>
           12  +#include <sys/param.h>
           13  +#include <errno.h>
           14  +#include <pthread.h>
           15  +#include <libkern/OSAtomic.h>
           16  +
           17  +#include "sqliteInt.h"
           18  +#include "vdbeInt.h"
           19  +
           20  +#define LOGSUFFIXLEN 48
           21  +
           22  +/* 
           23  + * Data types 
           24  + */
           25  +typedef struct SRRLogRef SRRLogRef;
           26  +struct SRRLogRef {
           27  +    int fd;
           28  +    sqlite3 *db;
           29  +    const char *dbPath;
           30  +    char *logPath;
           31  +    int connection;
           32  +    int depth;
           33  +    SRRLogRef *nextRef;
           34  +};
           35  +
           36  +/* 
           37  + * Globals 
           38  + */
           39  +SRRLogRef *logRefHead = NULL;
           40  +int dbLogCount = 0;
           41  +static int srr_enabled = 1;
           42  +pthread_mutex_t srr_log_mutex;
           43  +static volatile int32_t srr_initialized = 0;
           44  +
           45  +/* 
           46  + * Log management 
           47  + */
           48  +extern void SRRecInitialize() {
           49  +    int go = OSAtomicCompareAndSwap32Barrier(0, 1, &srr_initialized); 
           50  +    if( go ){
           51  +        pthread_mutex_init(&srr_log_mutex, NULL);
           52  +    }
           53  +}
           54  +
           55  +static SRRLogRef *createLog(sqlite3 *db, const char *dbPath) {
           56  +    SRRLogRef *ref = NULL;
           57  +    char *baseDir = getenv("SQLITE_REPLAY_RECORD_DIR");
           58  +    char logPath[MAXPATHLEN] = "";
           59  +    char suffix[LOGSUFFIXLEN] = "";
           60  +    const char *dbName = dbPath;
           61  +    int len = 0;
           62  +    int index = 0;
           63  +    int fd = -1;
           64  +    size_t out;
           65  +    unsigned char version = SRR_FILE_VERSION;
           66  +    
           67  +    SRRecInitialize();
           68  +
           69  +    /* construct the path for the log file 
           70  +     * ${SQLITE_REPLAY_DIR}/<dbname>_<pid>_<connection_number>.sqlrr
           71  +     */
           72  +    if (baseDir == NULL) {
           73  +        baseDir = "/tmp"; /* getenv(TMPDIR) */
           74  +    }
           75  +    len = strlen(baseDir);
           76  +    strlcat(logPath, baseDir, MAXPATHLEN);
           77  +    if ((len>0) && (baseDir[len-1] != '/')) {
           78  +        strlcat(logPath, "/", MAXPATHLEN);
           79  +    }
           80  +    len = strlen(dbPath);
           81  +    for (index = len-2; index >= 0; index --){
           82  +        if (dbPath[index] == '/') {
           83  +            dbName = &dbPath[index+1];
           84  +            break;
           85  +        }
           86  +    }
           87  +    strlcat(logPath, dbName, MAXPATHLEN);
           88  +    int cNum = ++dbLogCount;
           89  +    snprintf(suffix, sizeof(suffix), "_%d_%d_XXXX.sqlrr", getpid(), cNum);
           90  +    len = strlcat(logPath, suffix, MAXPATHLEN);
           91  +    /* make it unique if we have the space */
           92  +    if ((len + 1) < MAXPATHLEN) {
           93  +        fd = mkstemps(logPath, 6);
           94  +    } else {
           95  +        fprintf(stderr, "Failed to create sqlite replay log path for %s [%s]\n", dbPath, logPath);
           96  +        return NULL;
           97  +    }
           98  +    if (fd == -1) {
           99  +        fprintf(stderr, "Failed to create sqlite replay log file for %s with path %s [%s]\n", dbPath, logPath, strerror(errno));
          100  +        return NULL;
          101  +    }
          102  +    fprintf(stdout, "Writing sqlite replay log file %s\n", logPath);
          103  +    out = write(fd, SRR_FILE_SIGNATURE, SRR_FILE_SIGNATURE_LEN);
          104  +    if (out!=-1) {
          105  +        out = write(fd, &version, 1);
          106  +    }
          107  +    if (out == -1){
          108  +        fprintf(stderr, "Write failure on log [%s]: %s\n", logPath, strerror(errno));
          109  +        close(fd);
          110  +        return NULL;
          111  +    }
          112  +
          113  +    len = strlen(logPath) + 1;
          114  +    ref = (SRRLogRef *)malloc(sizeof(SRRLogRef));
          115  +
          116  +    ref->db = db;
          117  +    ref->dbPath = dbPath;
          118  +    ref->logPath = (char *)malloc(len * sizeof(char));
          119  +    strlcpy(ref->logPath, logPath, len);
          120  +    ref->fd = fd;
          121  +    ref->connection = cNum;
          122  +    ref->depth = 0;
          123  +    
          124  +    pthread_mutex_lock(&srr_log_mutex);
          125  +    ref->nextRef = logRefHead;
          126  +    logRefHead = ref;
          127  +    pthread_mutex_unlock(&srr_log_mutex);
          128  +    return ref;
          129  +}
          130  +
          131  +static void closeLog(sqlite3 *db) {
          132  +    SRRLogRef *ref = NULL;
          133  +    SRRLogRef *lastRef = NULL;
          134  +
          135  +    pthread_mutex_lock(&srr_log_mutex);
          136  +    for (ref = logRefHead; ref != NULL; ref = ref->nextRef) {
          137  +        if (ref->db == db) {
          138  +            if (lastRef == NULL) {
          139  +                logRefHead = ref->nextRef;
          140  +            } else {
          141  +                lastRef->nextRef = ref->nextRef;
          142  +            }
          143  +        }
          144  +    }
          145  +    pthread_mutex_unlock(&srr_log_mutex);
          146  +
          147  +    if (ref != NULL) {
          148  +        fprintf(stdout, "Closing sqlite replay log file %s\n", ref->logPath);
          149  +        close(ref->fd);
          150  +        free(ref->logPath);
          151  +        free(ref);
          152  +    }
          153  +}
          154  +
          155  +static SRRLogRef *getLog(sqlite3 *db) {
          156  +    pthread_mutex_lock(&srr_log_mutex);
          157  +    SRRLogRef *ref = logRefHead;
          158  +    for (ref = logRefHead; ref != NULL; ref = ref->nextRef) {
          159  +        if (ref->db == db) {
          160  +            pthread_mutex_unlock(&srr_log_mutex);
          161  +            return ref;
          162  +        }
          163  +    }
          164  +    pthread_mutex_unlock(&srr_log_mutex);
          165  +    return NULL;
          166  +}
          167  +
          168  +
          169  +/*
          170  + * SQLite recording API
          171  + */
          172  +void SQLiteReplayRecorder(int flag) {
          173  +    srr_enabled = flag;
          174  +}
          175  +
          176  +// open-arg-data:		<connection><len><path><flags>
          177  +void _SRRecOpen(sqlite3 *db, const char *path, int flags) {
          178  +    if (!srr_enabled) return;
          179  +    if (db) {
          180  +        SRRLogRef *ref = createLog(db, path);
          181  +        if (ref) {
          182  +            SRRCommand code = SRROpen;
          183  +            int len = strlen(path);
          184  +            struct timeval tv;
          185  +            size_t out;
          186  +            
          187  +            gettimeofday(&tv, NULL);
          188  +            out = write(ref->fd, &tv, sizeof(tv));
          189  +            if (out!=-1) { out=write(ref->fd, &code, sizeof(SRRCommand)); }
          190  +            if (out!=-1) { out=write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
          191  +            if (out!=-1) { out=write(ref->fd, &len, sizeof(len)); }
          192  +            if (out!=-1) { out=write(ref->fd, path, len); }
          193  +            if (out!=-1) { out=write(ref->fd, &flags, sizeof(flags)); }
          194  +            if (out==-1) {
          195  +                fprintf(stderr, "Error writing open to log file [%s]: %s\n", ref->logPath, strerror(errno));
          196  +                closeLog(db);
          197  +            }
          198  +        }
          199  +    }
          200  +}
          201  +
          202  +//close-arg-data:		<connection>
          203  +void SRRecClose(sqlite3 *db) {
          204  +    if (!srr_enabled) return;
          205  +    if (db) {
          206  +        SRRLogRef *ref = getLog(db);
          207  +        if (ref) {
          208  +            SRRCommand code = SRRClose;
          209  +            struct timeval tv;
          210  +            size_t out;
          211  +            
          212  +            gettimeofday(&tv, NULL);
          213  +            out = write(ref->fd, &tv, sizeof(tv));
          214  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          215  +            if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
          216  +            if (out==-1) {
          217  +                fprintf(stderr, "Error writing close to log file [%s]: %s\n", ref->logPath, strerror(errno));
          218  +            }
          219  +            closeLog(db);
          220  +        }
          221  +    }
          222  +}
          223  +
          224  +// exec-arg-data:		<connection><len><statement-text>
          225  +void SRRecExec(sqlite3 *db, const char *sql) {
          226  +    if (!srr_enabled) return;
          227  +    if (db) {
          228  +        SRRLogRef *ref = getLog(db);
          229  +        if (ref) {
          230  +            if (ref->depth == 0) {
          231  +                SRRCommand code = SRRExec;
          232  +                int len = strlen(sql);
          233  +                struct timeval tv;
          234  +                size_t out;
          235  +                
          236  +                ref->depth = 1;
          237  +                gettimeofday(&tv, NULL);
          238  +                out = write(ref->fd, &tv, sizeof(tv));
          239  +                if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          240  +                if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
          241  +                if (out!=-1) { out = write(ref->fd, &len, sizeof(len)); }
          242  +                if (out!=-1) { out = write(ref->fd, sql, len); }
          243  +                if (out==-1) {
          244  +                    fprintf(stderr, "Error writing exec to log file [%s]: %s\n", ref->logPath, strerror(errno));
          245  +                    closeLog(db);
          246  +                }
          247  +            } else {
          248  +                ref->depth ++;
          249  +            }
          250  +        }
          251  +    }
          252  +}
          253  +
          254  +void SRRecExecEnd(sqlite3 *db) {
          255  +    if (!srr_enabled) return;
          256  +    if (db) {
          257  +        SRRLogRef *ref = getLog(db);
          258  +        if (ref) {
          259  +            ref->depth --;
          260  +        }
          261  +    }
          262  +}
          263  +            
          264  +// prep-arg-data:		<connection><len><statement-text><savesql><statement-ref>
          265  +void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *pStmt) {
          266  +    if (!srr_enabled) return;
          267  +    if ((db!=NULL)&&(pStmt!=NULL)) {
          268  +        SRRLogRef *ref = getLog(db);
          269  +        if (ref && (ref->depth == 0)) {
          270  +            SRRCommand code = SRRPrepare;
          271  +            struct timeval tv;
          272  +            size_t out;
          273  +            int sqlLen = nBytes;
          274  +
          275  +            if (sqlLen == -1) {
          276  +                sqlLen = strlen(sql);
          277  +            }
          278  +            
          279  +            gettimeofday(&tv, NULL);
          280  +            out = write(ref->fd, &tv, sizeof(tv));
          281  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          282  +            if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); }
          283  +            if (out!=-1) { out = write(ref->fd, &sqlLen, sizeof(sqlLen)); }
          284  +            if (out!=-1) { out = write(ref->fd, sql, sqlLen); }
          285  +            if (out!=-1) { out = write(ref->fd, &saveSql, sizeof(saveSql)); }
          286  +            if (out!=-1) { 
          287  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          288  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          289  +            }
          290  +            if (out==-1) {
          291  +                fprintf(stderr, "Error writing prepare to log file [%s]: %s\n", ref->logPath, strerror(errno));
          292  +                closeLog(db);
          293  +            }
          294  +        }
          295  +    }
          296  +}
          297  +
          298  +//step-arg-data:		<statement-ref>
          299  +void SRRecStep(sqlite3_stmt *pStmt) {
          300  +    if (!srr_enabled) return;
          301  +    if(pStmt!=NULL) {
          302  +        Vdbe *v = (Vdbe *)pStmt;
          303  +        SRRLogRef *ref = getLog(v->db);
          304  +        if (ref) {
          305  +            if (ref->depth == 0) {
          306  +                SRRCommand code = SRRStep;
          307  +                struct timeval tv;
          308  +                size_t out;
          309  +                
          310  +                ref->depth = 1;
          311  +                gettimeofday(&tv, NULL);
          312  +                out = write(ref->fd, &tv, sizeof(tv));
          313  +                if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          314  +                if (out!=-1) { 
          315  +                    int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          316  +                    out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          317  +                }
          318  +                if (out==-1) {
          319  +                    fprintf(stderr, "Error writing step to log file [%s]: %s\n", ref->logPath, strerror(errno));
          320  +                    closeLog(ref->db);
          321  +                }
          322  +            } else {
          323  +                ref->depth ++;
          324  +            }            
          325  +        }
          326  +    }
          327  +}
          328  +
          329  +void SRRecStepEnd(sqlite3_stmt *pStmt) {
          330  +    if (!srr_enabled) return;
          331  +    if(pStmt!=NULL) {
          332  +        Vdbe *v = (Vdbe *)pStmt;
          333  +        SRRLogRef *ref = getLog(v->db);
          334  +        if (ref) {
          335  +            ref->depth --;
          336  +        }
          337  +    }
          338  +}
          339  +
          340  +// reset-arg-data:		<statement-ref>
          341  +void SRRecReset(sqlite3_stmt *pStmt) {
          342  +    if (!srr_enabled) return;
          343  +    if(pStmt!=NULL) {
          344  +        Vdbe *v = (Vdbe *)pStmt;
          345  +        SRRLogRef *ref = getLog(v->db);
          346  +        if (ref && (ref->depth == 0)) {
          347  +            SRRCommand code = SRRReset;
          348  +            struct timeval tv;
          349  +            size_t out;
          350  +            
          351  +            gettimeofday(&tv, NULL);
          352  +            out = write(ref->fd, &tv, sizeof(tv));
          353  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          354  +            if (out!=-1) { 
          355  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          356  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          357  +            }
          358  +            if (out==-1) {
          359  +                fprintf(stderr, "Error writing reset to log file [%s]: %s\n", ref->logPath, strerror(errno));
          360  +                closeLog(ref->db);
          361  +            }
          362  +        }
          363  +    }
          364  +}
          365  +
          366  +// finalize-arg-data:	<statement-ref>
          367  +void SRRecFinalize(sqlite3_stmt *pStmt) {
          368  +    if (!srr_enabled) return;
          369  +    if(pStmt!=NULL) {
          370  +        Vdbe *v = (Vdbe *)pStmt;
          371  +        SRRLogRef *ref = getLog(v->db);
          372  +        if (ref && (ref->depth == 0)) {
          373  +            SRRCommand code = SRRFinalize;
          374  +            struct timeval tv;
          375  +            size_t out;
          376  +            
          377  +            gettimeofday(&tv, NULL);
          378  +            out = write(ref->fd, &tv, sizeof(tv));
          379  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          380  +            if (out!=-1) { 
          381  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          382  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          383  +            }
          384  +            if (out==-1) {
          385  +                fprintf(stderr, "Error writing finalize to log file [%s]: %s\n", ref->logPath, strerror(errno));
          386  +                closeLog(ref->db);
          387  +            }
          388  +        }
          389  +    }
          390  +}
          391  +
          392  +// bind-text-arg-data:	<statement-ref><index><len><data>
          393  +void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) {
          394  +    if (!srr_enabled) return;
          395  +    if(pStmt!=NULL) {
          396  +        Vdbe *v = (Vdbe *)pStmt;
          397  +        SRRLogRef *ref = getLog(v->db);
          398  +        if (ref && (ref->depth == 0)) {
          399  +            SRRCommand code = SRRBindText;
          400  +            struct timeval tv;
          401  +            size_t out;
          402  +            int64_t textLen = nData;
          403  +            if (textLen == -1) {
          404  +                textLen = strlen(zData);
          405  +            }
          406  +            
          407  +            gettimeofday(&tv, NULL);
          408  +            out = write(ref->fd, &tv, sizeof(tv));
          409  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          410  +            if (out!=-1) { 
          411  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          412  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          413  +            }
          414  +            if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
          415  +            if (out!=-1) { out = write(ref->fd, &textLen, sizeof(textLen)); }
          416  +            if (out!=-1) { out = write(ref->fd, zData, textLen); }
          417  +            if (out==-1) {
          418  +                fprintf(stderr, "Error writing bind text to log file [%s]: %s\n", ref->logPath, strerror(errno));
          419  +                closeLog(ref->db);
          420  +            }
          421  +        }
          422  +    }
          423  +}
          424  +
          425  +// bind-blob-arg-data:	<statement-ref><index><len>[<data>]
          426  +void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) {
          427  +    if (!srr_enabled) return;
          428  +    if(pStmt!=NULL) {
          429  +        Vdbe *v = (Vdbe *)pStmt;
          430  +        SRRLogRef *ref = getLog(v->db);
          431  +        if (ref && (ref->depth == 0)) {
          432  +            SRRCommand code = SRRBindBlob;
          433  +            struct timeval tv;
          434  +            size_t out;
          435  +            
          436  +            gettimeofday(&tv, NULL);
          437  +            out = write(ref->fd, &tv, sizeof(tv));
          438  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          439  +            if (out!=-1) { 
          440  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          441  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          442  +            }
          443  +            if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
          444  +            if (zData == NULL) {
          445  +                int64_t negNData = -nData;
          446  +                if (out!=-1) { out = write(ref->fd, &negNData, sizeof(negNData)); }
          447  +            } else {
          448  +                if (out!=-1) { out = write(ref->fd, &nData, sizeof(nData)); }
          449  +                if (out!=-1) { out = write(ref->fd, zData, nData); }
          450  +            }
          451  +            if (out==-1) {
          452  +                fprintf(stderr, "Error writing bind blob to log file [%s]: %s\n", ref->logPath, strerror(errno));
          453  +                closeLog(ref->db);
          454  +            }
          455  +        }
          456  +    }
          457  +}
          458  +
          459  +// bind-double-arg-data:	<statement-ref><index><data>
          460  +void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value) {
          461  +    if (!srr_enabled) return;
          462  +    if(pStmt!=NULL) {
          463  +        Vdbe *v = (Vdbe *)pStmt;
          464  +        SRRLogRef *ref = getLog(v->db);
          465  +        if (ref && (ref->depth == 0)) {
          466  +            SRRCommand code = SRRBindDouble;
          467  +            struct timeval tv;
          468  +            size_t out;
          469  +            
          470  +            gettimeofday(&tv, NULL);
          471  +            out = write(ref->fd, &tv, sizeof(tv));
          472  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          473  +            if (out!=-1) { 
          474  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          475  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          476  +            }
          477  +            if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
          478  +            if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); }
          479  +            if (out==-1) {
          480  +                fprintf(stderr, "Error writing bind double to log file [%s]: %s\n", ref->logPath, strerror(errno));
          481  +                closeLog(ref->db);
          482  +            }
          483  +        }
          484  +    }
          485  +}
          486  +
          487  +// bind-int-arg-data:	<statement-ref><index><data>
          488  +void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value) {
          489  +    if (!srr_enabled) return;
          490  +    if(pStmt!=NULL) {
          491  +        Vdbe *v = (Vdbe *)pStmt;
          492  +        SRRLogRef *ref = getLog(v->db);
          493  +        if (ref && (ref->depth == 0)) {
          494  +            SRRCommand code = SRRBindInt;
          495  +            struct timeval tv;
          496  +            size_t out;
          497  +            
          498  +            gettimeofday(&tv, NULL);
          499  +            out = write(ref->fd, &tv, sizeof(tv));
          500  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          501  +            if (out!=-1) { 
          502  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          503  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          504  +            }
          505  +            if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
          506  +            if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); }
          507  +            if (out==-1) {
          508  +                fprintf(stderr, "Error writing bind int to log file [%s]: %s\n", ref->logPath, strerror(errno));
          509  +                closeLog(ref->db);
          510  +            }
          511  +        }
          512  +    }
          513  +}
          514  +
          515  +// bind-null-arg-data:	<statement-ref><index>
          516  +void SRRecBindNull(sqlite3_stmt *pStmt, int i) {
          517  +    if (!srr_enabled) return;
          518  +    if(pStmt!=NULL) {
          519  +        Vdbe *v = (Vdbe *)pStmt;
          520  +        SRRLogRef *ref = getLog(v->db);
          521  +        if (ref && (ref->depth == 0)) {
          522  +            SRRCommand code = SRRBindNull;
          523  +            struct timeval tv;
          524  +            size_t out;
          525  +            
          526  +            gettimeofday(&tv, NULL);
          527  +            out = write(ref->fd, &tv, sizeof(tv));
          528  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          529  +            if (out!=-1) { 
          530  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          531  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          532  +            }
          533  +            if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); }
          534  +            if (out==-1) {
          535  +                fprintf(stderr, "Error writing bind null to log file [%s]: %s\n", ref->logPath, strerror(errno));
          536  +                closeLog(ref->db);
          537  +            }
          538  +        }
          539  +    }
          540  +}
          541  +
          542  +// bind-value-arg-data:	<statement-ref><index><len><data> ???
          543  +void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value) {
          544  +    if (!srr_enabled) return;
          545  +    if(pStmt!=NULL) {
          546  +        Vdbe *v = (Vdbe *)pStmt;
          547  +        SRRLogRef *ref = getLog(v->db);
          548  +        if (ref && (ref->depth == 0)) {
          549  +            fprintf(stderr, "SRRecBindValue(sqlite3_bind_value) is not yet supported, closing [%s]: %s\n", ref->logPath, strerror(errno));
          550  +            closeLog(ref->db);
          551  +        }
          552  +    }
          553  +}
          554  +
          555  +// bind-clear-arg-data:	<statement-ref>
          556  +void SRRecClearBindings(sqlite3_stmt *pStmt) {
          557  +    if (!srr_enabled) return;
          558  +    if(pStmt!=NULL) {
          559  +        Vdbe *v = (Vdbe *)pStmt;
          560  +        SRRLogRef *ref = getLog(v->db);
          561  +        if (ref && (ref->depth == 0)) {
          562  +            SRRCommand code = SRRBindClear;
          563  +            struct timeval tv;
          564  +            size_t out;
          565  +            
          566  +            gettimeofday(&tv, NULL);
          567  +            out = write(ref->fd, &tv, sizeof(tv));
          568  +            if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); }
          569  +            if (out!=-1) { 
          570  +                int64_t stmtInt = (int64_t)((intptr_t)(pStmt));
          571  +                out = write(ref->fd, &stmtInt, sizeof(int64_t)); 
          572  +            }
          573  +            if (out==-1) {
          574  +                fprintf(stderr, "Error writing clear bindings to log file [%s]: %s\n", ref->logPath, strerror(errno));
          575  +                closeLog(ref->db);
          576  +            }
          577  +        }
          578  +    }
          579  +}
          580  +
          581  +#endif /* SQLITE_ENABLE_SQLRR */

Added ext/sqlrr/sqlrr.h.

            1  +/*
            2  + *  sqlrr.h
            3  + */
            4  +
            5  +#ifndef _SQLRR_H_
            6  +#define _SQLRR_H_
            7  +
            8  +/*
            9  +** Header constants
           10  +*/
           11  +#define SRR_FILE_SIGNATURE       "SQLRR"
           12  +#define SRR_FILE_SIGNATURE_LEN   5
           13  +#define SRR_FILE_VERSION         0x1 
           14  +#define SRR_FILE_VERSION_LEN     1
           15  +
           16  +#if defined(SQLITE_ENABLE_SQLRR)
           17  +
           18  +#include "sqlite3.h"
           19  +#include <sys/types.h>
           20  +
           21  +#define SRRecOpen(A,B,C)        if(!rc){_SRRecOpen(A,B,C);}
           22  +#define SRRecPrepare(A,B,C,D,E) if(!rc){_SRRecPrepare(A,B,C,D,E);}
           23  +
           24  +typedef enum {
           25  +    SRROpen = 0,
           26  +    SRRClose = 1,
           27  +    SRRExec = 8,
           28  +    SRRBindText = 16,
           29  +    SRRBindBlob = 17,
           30  +    SRRBindDouble = 18,
           31  +    SRRBindInt = 19,
           32  +    SRRBindNull = 20,
           33  +    SRRBindValue = 21,
           34  +    SRRBindClear = 22,
           35  +    SRRPrepare = 32,
           36  +    SRRStep = 33,
           37  +    SRRReset = 34,
           38  +    SRRFinalize = 35
           39  +} SRRCommand;
           40  +
           41  +extern void SQLiteReplayRecorder(int flag);
           42  +extern void _SRRecOpen(sqlite3 *db, const char *path, int flags);
           43  +extern void SRRecClose(sqlite3 *db);
           44  +extern void SRRecExec(sqlite3 *db, const char *sql);
           45  +extern void SRRecExecEnd(sqlite3 *db);
           46  +extern void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *stmt);
           47  +extern void SRRecStep(sqlite3_stmt *pStmt);
           48  +extern void SRRecStepEnd(sqlite3_stmt *pStmt);
           49  +extern void SRRecReset(sqlite3_stmt *pStmt);
           50  +extern void SRRecFinalize(sqlite3_stmt *pStmt);
           51  +extern void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData);
           52  +extern void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData);
           53  +extern void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value);
           54  +extern void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value);
           55  +extern void SRRecBindNull(sqlite3_stmt *pStmt, int i);
           56  +extern void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value);
           57  +extern void SRRecClearBindings(sqlite3_stmt *pStmt);
           58  +
           59  +#endif /* defined(SQLITE_ENABLE_SQLRR) */
           60  +
           61  +#endif /* _SQLRR_H_ */

Changes to src/func.c.

   187    187       if( z==0 ) return;
   188    188       len = 0;
   189    189       for(z2=z; *z2; len++){
   190    190         SQLITE_SKIP_UTF8(z2);
   191    191       }
   192    192     }
   193    193     p1 = sqlite3_value_int(argv[1]);
          194  +#ifdef SQLITE_SUBSTR_COMPATIBILITY
          195  +  if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
          196  +#endif
   194    197     if( argc==3 ){
   195    198       p2 = sqlite3_value_int(argv[2]);
   196    199       if( p2<0 ){
   197    200         p2 = -p2;
   198    201         negP2 = 1;
   199    202       }
   200    203     }else{

Changes to src/legacy.c.

    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17     17   ** $Id: legacy.c,v 1.35 2009/08/07 16:56:00 danielk1977 Exp $
    18     18   */
    19     19   
    20     20   #include "sqliteInt.h"
           21  +#ifdef SQLITE_ENABLE_SQLRR
           22  +# include "sqlrr.h"
           23  +#endif
    21     24   
    22     25   /*
    23     26   ** Execute SQL code.  Return one of the SQLITE_ success/failure
    24     27   ** codes.  Also write an error message into memory obtained from
    25     28   ** malloc() and make *pzErrMsg point to that message.
    26     29   **
    27     30   ** If the SQL is a query, then for each row in the query result
................................................................................
    40     43     const char *zLeftover;      /* Tail of unprocessed SQL */
    41     44     sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
    42     45     char **azCols = 0;          /* Names of result columns */
    43     46     int nRetry = 0;             /* Number of retry attempts */
    44     47     int callbackIsInit;         /* True if callback data is initialized */
    45     48   
    46     49     if( zSql==0 ) zSql = "";
    47         -
           50  +#ifdef SQLITE_ENABLE_SQLRR
           51  +  SRRecExec(db, zSql);
           52  +#endif  
    48     53     sqlite3_mutex_enter(db->mutex);
    49     54     sqlite3Error(db, SQLITE_OK, 0);
    50     55     while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    51     56       int nCol;
    52     57       char **azVals = 0;
    53     58   
    54     59       pStmt = 0;
................................................................................
   121    126       sqlite3DbFree(db, azCols);
   122    127       azCols = 0;
   123    128     }
   124    129   
   125    130   exec_out:
   126    131     if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
   127    132     sqlite3DbFree(db, azCols);
          133  +#ifdef SQLITE_ENABLE_SQLRR
          134  +  SRRecExecEnd(db);
          135  +#endif
   128    136   
   129    137     rc = sqlite3ApiExit(db, rc);
   130    138     if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
   131    139       int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
   132    140       *pzErrMsg = sqlite3Malloc(nErrMsg);
   133    141       if( *pzErrMsg ){
   134    142         memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);

Changes to src/main.c.

    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
           19  +#ifdef SQLITE_ENABLE_SQLRR
           20  +# include "sqlrr.h"
           21  +#endif 
    19     22   #ifdef SQLITE_ENABLE_FTS3
    20     23   # include "fts3.h"
    21     24   #endif
    22     25   #ifdef SQLITE_ENABLE_RTREE
    23     26   # include "rtree.h"
    24     27   #endif
    25     28   #ifdef SQLITE_ENABLE_ICU
................................................................................
   698    701     sqlite3_mutex_leave(db->mutex);
   699    702     db->magic = SQLITE_MAGIC_CLOSED;
   700    703     sqlite3_mutex_free(db->mutex);
   701    704     assert( db->lookaside.nOut==0 );  /* Fails on a lookaside memory leak */
   702    705     if( db->lookaside.bMalloced ){
   703    706       sqlite3_free(db->lookaside.pStart);
   704    707     }
          708  +#ifdef SQLITE_ENABLE_SQLRR
          709  +  SRRecClose(db);
          710  +#endif
          711  +  
   705    712     sqlite3_free(db);
   706    713     return SQLITE_OK;
   707    714   }
   708    715   
   709    716   /*
   710    717   ** Rollback all database files.
   711    718   */
................................................................................
  1509   1516       if( newLimit>aHardLimit[limitId] ){
  1510   1517         newLimit = aHardLimit[limitId];
  1511   1518       }
  1512   1519       db->aLimit[limitId] = newLimit;
  1513   1520     }
  1514   1521     return oldLimit;
  1515   1522   }
         1523  +#if defined(SQLITE_ENABLE_AUTO_PROFILE)
         1524  +static void profile_sql(void *aux, const char *sql, uint64_t ns) {
         1525  +#pragma unused(aux)
         1526  +	fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
         1527  +}
         1528  +#endif
  1516   1529   
  1517   1530   /*
  1518   1531   ** This routine does the work of opening a database on behalf of
  1519   1532   ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
  1520   1533   ** is UTF-8 encoded.
  1521   1534   */
  1522   1535   static int openDatabase(
................................................................................
  1739   1752     rc = sqlite3_errcode(db);
  1740   1753     if( rc==SQLITE_NOMEM ){
  1741   1754       sqlite3_close(db);
  1742   1755       db = 0;
  1743   1756     }else if( rc!=SQLITE_OK ){
  1744   1757       db->magic = SQLITE_MAGIC_SICK;
  1745   1758     }
         1759  +#if defined(SQLITE_ENABLE_AUTO_PROFILE)
         1760  +  if( db && !rc ){
         1761  +    char *envprofile = getenv("SQLITE_AUTO_PROFILE");
         1762  +    
         1763  +    if( envprofile!=NULL ){
         1764  +      sqlite3_profile(db, profile_sql, NULL);
         1765  +    }
         1766  +  }
         1767  +#endif
  1746   1768     *ppDb = db;
         1769  +#ifdef SQLITE_ENABLE_SQLRR
         1770  +  SRRecOpen(db, zFilename, flags);
         1771  +#endif
  1747   1772     return sqlite3ApiExit(0, rc);
  1748   1773   }
  1749   1774   
  1750   1775   /*
  1751   1776   ** Open a new database handle.
  1752   1777   */
  1753   1778   int sqlite3_open(

Changes to src/mem1.c.

    24     24   /*
    25     25   ** This version of the memory allocator is the default.  It is
    26     26   ** used when no other memory allocator is specified using compile-time
    27     27   ** macros.
    28     28   */
    29     29   #ifdef SQLITE_SYSTEM_MALLOC
    30     30   
           31  +#if (!defined(__APPLE__))
           32  +
           33  +#define SQLITE_MALLOC(x) malloc(x)
           34  +#define SQLITE_FREE(x) free(x)
           35  +#define SQLITE_REALLOC(x,y) realloc((x),(y))
           36  +
           37  +
           38  +#else
           39  +
           40  +
           41  +#include <sys/sysctl.h>
           42  +#include <malloc/malloc.h>
           43  +#include <libkern/OSAtomic.h>
           44  +
           45  +static malloc_zone_t* _sqliteZone_;
           46  +
           47  +#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
           48  +#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
           49  +#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
           50  +
           51  +#endif
           52  +
    31     53   /*
    32     54   ** Like malloc(), but remember the size of the allocation
    33     55   ** so that we can find it later using sqlite3MemSize().
    34     56   **
    35     57   ** For this low-level routine, we are guaranteed that nByte>0 because
    36     58   ** cases of nByte<=0 will be intercepted and dealt with by higher level
    37     59   ** routines.
    38     60   */
    39     61   static void *sqlite3MemMalloc(int nByte){
    40     62     sqlite3_int64 *p;
    41     63     assert( nByte>0 );
    42     64     nByte = ROUND8(nByte);
    43         -  p = malloc( nByte+8 );
           65  +  p = SQLITE_MALLOC( nByte+8 );
    44     66     if( p ){
    45     67       p[0] = nByte;
    46     68       p++;
    47     69     }
    48     70     return (void *)p;
    49     71   }
    50     72   
................................................................................
    56     78   ** cases where pPrior==0 will have been intecepted and dealt with
    57     79   ** by higher-level routines.
    58     80   */
    59     81   static void sqlite3MemFree(void *pPrior){
    60     82     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    61     83     assert( pPrior!=0 );
    62     84     p--;
    63         -  free(p);
           85  +  SQLITE_FREE(p);
    64     86   }
    65     87   
    66     88   /*
    67     89   ** Like realloc().  Resize an allocation previously obtained from
    68     90   ** sqlite3MemMalloc().
    69     91   **
    70     92   ** For this low-level interface, we know that pPrior!=0.  Cases where
................................................................................
    75     97   */
    76     98   static void *sqlite3MemRealloc(void *pPrior, int nByte){
    77     99     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    78    100     assert( pPrior!=0 && nByte>0 );
    79    101     nByte = ROUND8(nByte);
    80    102     p = (sqlite3_int64*)pPrior;
    81    103     p--;
    82         -  p = realloc(p, nByte+8 );
          104  +  p = SQLITE_REALLOC(p, nByte+8 );
    83    105     if( p ){
    84    106       p[0] = nByte;
    85    107       p++;
    86    108     }
    87    109     return (void*)p;
    88    110   }
    89    111   
................................................................................
   106    128     return ROUND8(n);
   107    129   }
   108    130   
   109    131   /*
   110    132   ** Initialize this module.
   111    133   */
   112    134   static int sqlite3MemInit(void *NotUsed){
          135  +#if defined(__APPLE__)
          136  +	if (_sqliteZone_) {
          137  +		return SQLITE_OK;
          138  +	}
          139  +	int cpuCount;
          140  +    size_t len;
          141  +    
          142  +    len = sizeof(cpuCount);
          143  +    sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);  //  one almost always wants to use "hw.activecpu" for MT decisions, but not here.
          144  +	
          145  +	if (cpuCount > 1) {
          146  +		// defer MT decisions to system malloc
          147  +		_sqliteZone_ = malloc_default_zone();
          148  +	} else {
          149  +		// only 1 core, use our own zone to contention over global locks, 
          150  +		// e.g. we have our own dedicated locks
          151  +		malloc_zone_t* newzone = malloc_create_zone(4096, 0);
          152  +		malloc_set_zone_name(newzone, "Sqlite_Heap");
          153  +
          154  +		bool success;		
          155  +		do {
          156  +			success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, (void * volatile *)&_sqliteZone_);
          157  +		} while (!_sqliteZone_);
          158  +		
          159  +		if (!success) {
          160  +			// somebody registered a zone first
          161  +			malloc_destroy_zone(newzone);
          162  +		}
          163  +	}
          164  +#endif
          165  +
   113    166     UNUSED_PARAMETER(NotUsed);
   114    167     return SQLITE_OK;
   115    168   }
   116    169   
   117    170   /*
   118    171   ** Deinitialize this module.
   119    172   */
   120    173   static void sqlite3MemShutdown(void *NotUsed){
          174  +#if (0 && defined(__APPLE__))
          175  +	if (_sqliteZone_ && (_sqliteZone_ != malloc_default_zone())) {
          176  +		malloc_zone_t* oldzone = _sqliteZone_;
          177  +
          178  +		bool success = OSAtomicCompareAndSwapPtrBarrier(oldzone, NULL, (void * volatile *)&_sqliteZone_);
          179  +		if (success) {
          180  +			malloc_destroy_zone(oldzone);
          181  +		}
          182  +	}
          183  +#endif
          184  +	
   121    185     UNUSED_PARAMETER(NotUsed);
   122    186     return;
   123    187   }
   124    188   
   125    189   /*
   126    190   ** This routine is the only routine in this file with external linkage.
   127    191   **
................................................................................
   138    202        sqlite3MemInit,
   139    203        sqlite3MemShutdown,
   140    204        0
   141    205     };
   142    206     sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
   143    207   }
   144    208   
          209  +#undef SQLITE_MALLOC
          210  +#undef SQLITE_FREE
          211  +#undef SQLITE_REALLOC
          212  +
   145    213   #endif /* SQLITE_SYSTEM_MALLOC */

Changes to src/os_unix.c.

   127    127   #  include <limits.h>
   128    128   # else
   129    129   #  include <sys/file.h>
   130    130   #  include <sys/param.h>
   131    131   #  include <sys/mount.h>
   132    132   # endif
   133    133   #endif /* SQLITE_ENABLE_LOCKING_STYLE */
          134  +
          135  +#define SQLITE_FSFLAGS_IS_READONLY  0x1
          136  +#define SQLITE_FSFLAGS_IS_LOCAL     0x2
          137  +#define SQLITE_FSFLAGS_IS_HFSPLUS   0x4
          138  +#define SQLITE_FSFLAGS_IS_MSDOS     0x8
          139  +#define SQLITE_FSFLAGS_INITIALIZED     0x10000
          140  +
   134    141   
   135    142   /*
   136    143   ** If we are to be thread-safe, include the pthreads header and define
   137    144   ** the SQLITE_UNIX_THREADS macro.
   138    145   */
   139    146   #if SQLITE_THREADSAFE
   140    147   # include <pthread.h>
................................................................................
   195    202     int lastErrno;                   /* The unix errno from the last I/O error */
   196    203     void *lockingContext;            /* Locking style specific state */
   197    204     UnixUnusedFd *pUnused;           /* Pre-allocated UnixUnusedFd */
   198    205     int fileFlags;                   /* Miscellanous flags */
   199    206   #if SQLITE_ENABLE_LOCKING_STYLE
   200    207     int openFlags;                   /* The flags specified at open() */
   201    208   #endif
          209  +#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
          210  +  unsigned fsFlags;                 /* cached details from statfs() */
          211  +#endif
   202    212   #if SQLITE_THREADSAFE && defined(__linux__)
   203    213     pthread_t tid;                   /* The thread that "owns" this unixFile */
   204    214   #endif
   205    215   #if OS_VXWORKS
   206    216     int isDelete;                    /* Delete on close if true */
   207    217     struct vxworksFileId *pId;       /* Unique file ID */
   208    218   #endif
................................................................................
   986    996     ** we always increase the file size to 1 by writing a single byte
   987    997     ** prior to accessing the inode number.  The one byte written is
   988    998     ** an ASCII 'S' character which also happens to be the first byte
   989    999     ** in the header of every SQLite database.  In this way, if there
   990   1000     ** is a race condition such that another thread has already populated
   991   1001     ** the first page of the database, no damage is done.
   992   1002     */
   993         -  if( statbuf.st_size==0 ){
         1003  +  if (( statbuf.st_size==0 ) && (0 != (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS))) {
   994   1004       rc = write(fd, "S", 1);
   995   1005       if( rc!=1 ){
         1006  +        pFile->lastErrno = errno;
   996   1007         return SQLITE_IOERR;
   997   1008       }
   998   1009       rc = fstat(fd, &statbuf);
   999   1010       if( rc!=0 ){
  1000   1011         pFile->lastErrno = errno;
  1001   1012         return SQLITE_IOERR;
  1002   1013       }
................................................................................
  1161   1172     unixLeaveMutex();
  1162   1173     OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
  1163   1174   
  1164   1175     *pResOut = reserved;
  1165   1176     return rc;
  1166   1177   }
  1167   1178   
         1179  +#ifdef SQLITE_ENABLE_NFS_RANGELOCK
  1168   1180   /*
  1169   1181   ** Perform a file locking operation on a range of bytes in a file.
  1170   1182   ** The "op" parameter should be one of F_RDLCK, F_WRLCK, or F_UNLCK.
  1171   1183   ** Return 0 on success or -1 for failure.  On failure, write the error
  1172   1184   ** code into *pErrcode.
  1173   1185   **
  1174   1186   ** If the SQLITE_WHOLE_FILE_LOCKING bit is clear, then only lock
................................................................................
  1217   1229           fcntl(pFile->h, F_SETLK, &lock);
  1218   1230         }
  1219   1231       }
  1220   1232     }
  1221   1233     return rc;
  1222   1234   }
  1223   1235   
         1236  +#endif /* SQLITE_ENABLE_NFS_RANGELOCK */
  1224   1237   /*
  1225   1238   ** Lock the file with the lock specified by parameter locktype - one
  1226   1239   ** of the following:
  1227   1240   **
  1228   1241   **     (1) SHARED_LOCK
  1229   1242   **     (2) RESERVED_LOCK
  1230   1243   **     (3) PENDING_LOCK
................................................................................
  1381   1394     ** operating system calls for the specified lock.
  1382   1395     */
  1383   1396     if( locktype==SHARED_LOCK ){
  1384   1397       assert( pLock->cnt==0 );
  1385   1398       assert( pLock->locktype==0 );
  1386   1399   
  1387   1400       /* Now get the read-lock */
  1388         -    s = rangeLock(pFile, F_RDLCK, &tErrno);
  1389         -
         1401  +    lock.l_start = SHARED_FIRST;
         1402  +    lock.l_len = SHARED_SIZE;
         1403  +    if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
         1404  +      tErrno = errno;
         1405  +    }
  1390   1406       /* Drop the temporary PENDING lock */
  1391   1407       lock.l_start = PENDING_BYTE;
  1392   1408       lock.l_len = 1L;
  1393   1409       lock.l_type = F_UNLCK;
  1394   1410       if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
  1395   1411         if( s != -1 ){
  1396   1412           /* This could happen with a network mount */
................................................................................
  1422   1438       ** already.
  1423   1439       */
  1424   1440       assert( 0!=pFile->locktype );
  1425   1441       lock.l_type = F_WRLCK;
  1426   1442       switch( locktype ){
  1427   1443         case RESERVED_LOCK:
  1428   1444           lock.l_start = RESERVED_BYTE;
  1429         -        s = fcntl(pFile->h, F_SETLK, &lock);
  1430         -        tErrno = errno;
  1431   1445           break;
  1432   1446         case EXCLUSIVE_LOCK:
  1433         -        s = rangeLock(pFile, F_WRLCK, &tErrno);
         1447  +        lock.l_start = SHARED_FIRST;
         1448  +        lock.l_len = SHARED_SIZE;
  1434   1449           break;
  1435   1450         default:
  1436   1451           assert(0);
  1437   1452       }
         1453  +    s = fcntl(pFile->h, F_SETLK, &lock);
  1438   1454       if( s==(-1) ){
         1455  +      tErrno = errno;
  1439   1456         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1440   1457         if( IS_LOCK_ERROR(rc) ){
  1441   1458           pFile->lastErrno = tErrno;
  1442   1459         }
  1443   1460       }
  1444   1461     }
  1445   1462     
................................................................................
  1521   1538   
  1522   1539   /*
  1523   1540   ** Lower the locking level on file descriptor pFile to locktype.  locktype
  1524   1541   ** must be either NO_LOCK or SHARED_LOCK.
  1525   1542   **
  1526   1543   ** If the locking level of the file descriptor is already at or below
  1527   1544   ** the requested locking level, this routine is a no-op.
         1545  +** 
         1546  +** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
         1547  +** the byte range is divided into 2 parts and the first part is unlocked then
         1548  +** set to a read lock, then the other part is simply unlocked.  This works 
         1549  +** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to 
         1550  +** remove the write lock on a region when a read lock is set.
  1528   1551   */
  1529         -static int unixUnlock(sqlite3_file *id, int locktype){
  1530         -  unixFile *pFile = (unixFile*)id; /* The open file */
  1531         -  struct unixLockInfo *pLock;      /* Structure describing current lock state */
  1532         -  struct flock lock;               /* Information passed into fcntl() */
  1533         -  int rc = SQLITE_OK;              /* Return code from this interface */
  1534         -  int h;                           /* The underlying file descriptor */
         1552  +static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){
         1553  +  unixFile *pFile = (unixFile*)id;
         1554  +  struct unixLockInfo *pLock;
         1555  +  struct flock lock;
         1556  +  int rc = SQLITE_OK;
         1557  +  int h;
  1535   1558     int tErrno;                      /* Error code from system call errors */
  1536   1559   
  1537   1560     assert( pFile );
  1538   1561     OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
  1539   1562         pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
  1540   1563   
  1541   1564     assert( locktype<=SHARED_LOCK );
................................................................................
  1566   1589       */
  1567   1590       assert( pFile->inNormalWrite==0
  1568   1591            || pFile->dbUpdate==0
  1569   1592            || pFile->transCntrChng==1 );
  1570   1593       pFile->inNormalWrite = 0;
  1571   1594   #endif
  1572   1595   
  1573         -
         1596  +    /* downgrading to a shared lock on NFS involves clearing the write lock
         1597  +     ** before establishing the readlock - to avoid a race condition we downgrade
         1598  +     ** the lock in 2 blocks, so that part of the range will be covered by a 
         1599  +     ** write lock until the rest is covered by a read lock:
         1600  +     **  1:   [WWWWW]
         1601  +     **  2:   [....W]
         1602  +     **  3:   [RRRRW]
         1603  +     **  4:   [RRRR.]
         1604  +     */
  1574   1605       if( locktype==SHARED_LOCK ){
  1575         -      if( rangeLock(pFile, F_RDLCK, &tErrno)==(-1) ){
         1606  +      if( handleNFSUnlock ){
         1607  +        off_t divSize = SHARED_SIZE - 1;
         1608  +        
         1609  +        lock.l_type = F_UNLCK;
         1610  +        lock.l_whence = SEEK_SET;
         1611  +        lock.l_start = SHARED_FIRST;
         1612  +        lock.l_len = divSize;
         1613  +        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1614  +          int tErrno = errno;
         1615  +          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
         1616  +          if( IS_LOCK_ERROR(rc) ){
         1617  +            pFile->lastErrno = tErrno;
         1618  +          }
         1619  +          goto end_unlock;
         1620  +        }
         1621  +        lock.l_type = F_RDLCK;
         1622  +        lock.l_whence = SEEK_SET;
         1623  +        lock.l_start = SHARED_FIRST;
         1624  +        lock.l_len = divSize;
         1625  +        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1626  +          int tErrno = errno;
         1627  +          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
         1628  +          if( IS_LOCK_ERROR(rc) ){
         1629  +            pFile->lastErrno = tErrno;
         1630  +          }
         1631  +          goto end_unlock;
         1632  +        }
         1633  +        lock.l_type = F_UNLCK;
         1634  +        lock.l_whence = SEEK_SET;
         1635  +        lock.l_start = SHARED_FIRST+divSize;
         1636  +        lock.l_len = SHARED_SIZE-divSize;
         1637  +        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1638  +          int tErrno = errno;
         1639  +          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
         1640  +          if( IS_LOCK_ERROR(rc) ){
         1641  +            pFile->lastErrno = tErrno;
         1642  +          }
         1643  +          goto end_unlock;
         1644  +        }
         1645  +      }else{
         1646  +        lock.l_type = F_RDLCK;
         1647  +        lock.l_whence = SEEK_SET;
         1648  +        lock.l_start = SHARED_FIRST;
         1649  +        lock.l_len = SHARED_SIZE;
         1650  +        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1651  +          int tErrno = errno;
  1576   1652           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1577   1653           if( IS_LOCK_ERROR(rc) ){
  1578   1654             pFile->lastErrno = tErrno;
  1579   1655           }
  1580   1656           goto end_unlock;
  1581   1657         }
  1582   1658       }
         1659  +    }
  1583   1660       lock.l_type = F_UNLCK;
  1584   1661       lock.l_whence = SEEK_SET;
  1585   1662       lock.l_start = PENDING_BYTE;
  1586   1663       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  1587   1664       if( fcntl(h, F_SETLK, &lock)!=(-1) ){
  1588   1665         pLock->locktype = SHARED_LOCK;
  1589   1666       }else{
................................................................................
  1639   1716     }
  1640   1717   	
  1641   1718   end_unlock:
  1642   1719     unixLeaveMutex();
  1643   1720     if( rc==SQLITE_OK ) pFile->locktype = locktype;
  1644   1721     return rc;
  1645   1722   }
         1723  +
         1724  +/*
         1725  +** Lower the locking level on file descriptor pFile to locktype.  locktype
         1726  +** must be either NO_LOCK or SHARED_LOCK.
         1727  +**
         1728  +** If the locking level of the file descriptor is already at or below
         1729  +** the requested locking level, this routine is a no-op.
         1730  +*/
         1731  +static int unixUnlock(sqlite3_file *id, int locktype){
         1732  +  return _posixUnlock(id, locktype, 0);
         1733  +}
  1646   1734   
  1647   1735   /*
  1648   1736   ** This function performs the parts of the "close file" operation 
  1649   1737   ** common to all locking schemes. It closes the directory and file
  1650   1738   ** handles, if they are valid, and sets all fields of the unixFile
  1651   1739   ** structure to 0.
  1652   1740   **
................................................................................
  2352   2440   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  2353   2441   /*
  2354   2442   ** The afpLockingContext structure contains all afp lock specific state
  2355   2443   */
  2356   2444   typedef struct afpLockingContext afpLockingContext;
  2357   2445   struct afpLockingContext {
  2358   2446     unsigned long long sharedByte;
         2447  +  int reserved;
  2359   2448     const char *dbPath;             /* Name of the open file */
  2360   2449   };
  2361   2450   
  2362   2451   struct ByteRangeLockPB2
  2363   2452   {
  2364   2453     unsigned long long offset;        /* offset to first byte to lock */
  2365   2454     unsigned long long length;        /* nbr of bytes to lock */
................................................................................
  2428   2517     int reserved = 0;
  2429   2518     unixFile *pFile = (unixFile*)id;
  2430   2519     
  2431   2520     SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  2432   2521     
  2433   2522     assert( pFile );
  2434   2523     afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
         2524  +  if( context->reserved ){
         2525  +    *pResOut = 1;
         2526  +    return SQLITE_OK;
         2527  +  }
         2528  +  unixEnterMutex(); /* Because pFile->pLock is shared across threads */
  2435   2529     
  2436   2530     /* Check if a thread in this process holds such a lock */
  2437         -  if( pFile->locktype>SHARED_LOCK ){
         2531  +  if( pFile->pLock->locktype>SHARED_LOCK ){
  2438   2532       reserved = 1;
  2439   2533     }
  2440   2534     
  2441   2535     /* Otherwise see if some other process holds it.
  2442   2536      */
  2443   2537     if( !reserved ){
  2444   2538       /* lock the RESERVED byte */
................................................................................
  2452   2546         reserved = 1;
  2453   2547       }
  2454   2548       if( IS_LOCK_ERROR(lrc) ){
  2455   2549         rc=lrc;
  2456   2550       }
  2457   2551     }
  2458   2552     
         2553  +  unixLeaveMutex();
  2459   2554     OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
  2460   2555     
  2461   2556     *pResOut = reserved;
  2462   2557     return rc;
  2463   2558   }
  2464   2559   
  2465   2560   /*
................................................................................
  2485   2580   **
  2486   2581   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  2487   2582   ** routine to lower a locking level.
  2488   2583   */
  2489   2584   static int afpLock(sqlite3_file *id, int locktype){
  2490   2585     int rc = SQLITE_OK;
  2491   2586     unixFile *pFile = (unixFile*)id;
         2587  +  struct unixLockInfo *pLock = pFile->pLock;
  2492   2588     afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
  2493   2589     
  2494   2590     assert( pFile );
  2495         -  OSTRACE5("LOCK    %d %s was %s pid=%d\n", pFile->h,
  2496         -         locktypeName(locktype), locktypeName(pFile->locktype), getpid());
         2591  +  OSTRACE7("LOCK    %d %s was %s(%s,%d) pid=%d\n", pFile->h,
         2592  +           locktypeName(locktype), locktypeName(pFile->locktype),
         2593  +           locktypeName(pLock->locktype), pLock->cnt , getpid());
  2497   2594   
  2498   2595     /* If there is already a lock of this type or more restrictive on the
  2499   2596     ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
  2500   2597     ** unixEnterMutex() hasn't been called yet.
  2501   2598     */
  2502   2599     if( pFile->locktype>=locktype ){
  2503   2600       OSTRACE3("LOCK    %d %s ok (already held)\n", pFile->h,
  2504   2601              locktypeName(locktype));
  2505   2602       return SQLITE_OK;
  2506   2603     }
  2507   2604   
  2508   2605     /* Make sure the locking sequence is correct
         2606  +  **  (1) We never move from unlocked to anything higher than shared lock.
         2607  +  **  (2) SQLite never explicitly requests a pendig lock.
         2608  +  **  (3) A shared lock is always held when a reserve lock is requested.
  2509   2609     */
  2510   2610     assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  2511   2611     assert( locktype!=PENDING_LOCK );
  2512   2612     assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
  2513   2613     
  2514   2614     /* This mutex is needed because pFile->pLock is shared across threads
  2515   2615     */
................................................................................
  2517   2617   
  2518   2618     /* Make sure the current thread owns the pFile.
  2519   2619     */
  2520   2620     rc = transferOwnership(pFile);
  2521   2621     if( rc!=SQLITE_OK ){
  2522   2622       unixLeaveMutex();
  2523   2623       return rc;
         2624  +  }
         2625  +  pLock = pFile->pLock;
         2626  +
         2627  +  /* If some thread using this PID has a lock via a different unixFile*
         2628  +  ** handle that precludes the requested lock, return BUSY.
         2629  +  */
         2630  +  if( (pFile->locktype!=pLock->locktype && 
         2631  +       (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
         2632  +     ){
         2633  +    rc = SQLITE_BUSY;
         2634  +    goto afp_end_lock;
         2635  +  }
         2636  +  
         2637  +  /* If a SHARED lock is requested, and some thread using this PID already
         2638  +  ** has a SHARED or RESERVED lock, then increment reference counts and
         2639  +  ** return SQLITE_OK.
         2640  +  */
         2641  +  if( locktype==SHARED_LOCK && 
         2642  +     (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
         2643  +    assert( locktype==SHARED_LOCK );
         2644  +    assert( pFile->locktype==0 );
         2645  +    assert( pLock->cnt>0 );
         2646  +    pFile->locktype = SHARED_LOCK;
         2647  +    pLock->cnt++;
         2648  +    pFile->pOpen->nLock++;
         2649  +    goto afp_end_lock;
  2524   2650     }
  2525   2651       
  2526   2652     /* A PENDING lock is needed before acquiring a SHARED lock and before
  2527   2653     ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  2528   2654     ** be released.
  2529   2655     */
  2530   2656     if( locktype==SHARED_LOCK 
................................................................................
  2538   2664       }
  2539   2665     }
  2540   2666     
  2541   2667     /* If control gets to this point, then actually go ahead and make
  2542   2668     ** operating system calls for the specified lock.
  2543   2669     */
  2544   2670     if( locktype==SHARED_LOCK ){
  2545         -    int lk, lrc1, lrc2;
  2546         -    int lrc1Errno = 0;
         2671  +    int lrc1, lrc2, lrc1Errno;
         2672  +    long lk, mask;
  2547   2673       
         2674  +    assert( pLock->cnt==0 );
         2675  +    assert( pLock->locktype==0 );
         2676  +        
         2677  +    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
  2548   2678       /* Now get the read-lock SHARED_LOCK */
  2549   2679       /* note that the quality of the randomness doesn't matter that much */
  2550   2680       lk = random(); 
  2551         -    context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
         2681  +    context->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
  2552   2682       lrc1 = afpSetLock(context->dbPath, pFile, 
  2553   2683             SHARED_FIRST+context->sharedByte, 1, 1);
  2554   2684       if( IS_LOCK_ERROR(lrc1) ){
  2555   2685         lrc1Errno = pFile->lastErrno;
  2556   2686       }
  2557   2687       /* Drop the temporary PENDING lock */
  2558   2688       lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
................................................................................
  2565   2695         rc = lrc2;
  2566   2696         goto afp_end_lock;
  2567   2697       } else if( lrc1 != SQLITE_OK ) {
  2568   2698         rc = lrc1;
  2569   2699       } else {
  2570   2700         pFile->locktype = SHARED_LOCK;
  2571   2701         pFile->pOpen->nLock++;
         2702  +      pLock->cnt = 1;
  2572   2703       }
         2704  +  }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){
         2705  +    /* We are trying for an exclusive lock but another thread in this
         2706  +     ** same process is still holding a shared lock. */
         2707  +    rc = SQLITE_BUSY;
  2573   2708     }else{
  2574   2709       /* The request was for a RESERVED or EXCLUSIVE lock.  It is
  2575   2710       ** assumed that there is a SHARED or greater lock on the file
  2576   2711       ** already.
  2577   2712       */
  2578   2713       int failed = 0;
  2579   2714       assert( 0!=pFile->locktype );
  2580   2715       if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
  2581   2716           /* Acquire a RESERVED lock */
  2582   2717           failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
         2718  +      if( !failed ){
         2719  +        context->reserved = 1;
         2720  +      }
  2583   2721       }
  2584   2722       if (!failed && locktype == EXCLUSIVE_LOCK) {
  2585   2723         /* Acquire an EXCLUSIVE lock */
  2586   2724           
  2587   2725         /* Remove the shared lock before trying the range.  we'll need to 
  2588   2726         ** reestablish the shared lock if we can't get the  afpUnlock
  2589   2727         */
................................................................................
  2609   2747       if( failed ){
  2610   2748         rc = failed;
  2611   2749       }
  2612   2750     }
  2613   2751     
  2614   2752     if( rc==SQLITE_OK ){
  2615   2753       pFile->locktype = locktype;
         2754  +    pLock->locktype = locktype;
  2616   2755     }else if( locktype==EXCLUSIVE_LOCK ){
  2617   2756       pFile->locktype = PENDING_LOCK;
         2757  +    pLock->locktype = PENDING_LOCK;
  2618   2758     }
  2619   2759     
  2620   2760   afp_end_lock:
  2621   2761     unixLeaveMutex();
  2622   2762     OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
  2623   2763            rc==SQLITE_OK ? "ok" : "failed");
  2624   2764     return rc;
................................................................................
  2630   2770   **
  2631   2771   ** If the locking level of the file descriptor is already at or below
  2632   2772   ** the requested locking level, this routine is a no-op.
  2633   2773   */
  2634   2774   static int afpUnlock(sqlite3_file *id, int locktype) {
  2635   2775     int rc = SQLITE_OK;
  2636   2776     unixFile *pFile = (unixFile*)id;
  2637         -  afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext;
         2777  +  struct unixLockInfo *pLock;
         2778  +  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
         2779  +#ifdef SQLITE_TEST
         2780  +  int h = pFile->h;
         2781  +#endif
  2638   2782   
  2639   2783     assert( pFile );
  2640         -  OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,
  2641         -         pFile->locktype, getpid());
         2784  +  OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
         2785  +           pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
  2642   2786   
  2643   2787     assert( locktype<=SHARED_LOCK );
  2644   2788     if( pFile->locktype<=locktype ){
  2645   2789       return SQLITE_OK;
  2646   2790     }
  2647   2791     if( CHECK_THREADID(pFile) ){
  2648   2792       return SQLITE_MISUSE;
  2649   2793     }
  2650   2794     unixEnterMutex();
         2795  +  pLock = pFile->pLock;
         2796  +  assert( pLock->cnt!=0 );
  2651   2797     if( pFile->locktype>SHARED_LOCK ){
         2798  +    assert( pLock->locktype==pFile->locktype );
         2799  +    SimulateIOErrorBenign(1);
         2800  +    SimulateIOError( h=(-1) )
         2801  +    SimulateIOErrorBenign(0);
         2802  +    
         2803  +#ifndef NDEBUG
         2804  +    /* When reducing a lock such that other processes can start
         2805  +     ** reading the database file again, make sure that the
         2806  +     ** transaction counter was updated if any part of the database
         2807  +     ** file changed.  If the transaction counter is not updated,
         2808  +     ** other connections to the same file might not realize that
         2809  +     ** the file has changed and hence might not know to flush their
         2810  +     ** cache.  The use of a stale cache can lead to database corruption.
         2811  +     */
         2812  +    assert( pFile->inNormalWrite==0
         2813  +           || pFile->dbUpdate==0
         2814  +           || pFile->transCntrChng==1 );
         2815  +    pFile->inNormalWrite = 0;
         2816  +#endif
  2652   2817       
  2653   2818       if( pFile->locktype==EXCLUSIVE_LOCK ){
  2654         -      rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
         2819  +      rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
  2655   2820         if( rc==SQLITE_OK && locktype==SHARED_LOCK ){
  2656   2821           /* only re-establish the shared lock if necessary */
  2657         -        int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
  2658         -        rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1);
         2822  +        int sharedLockByte = SHARED_FIRST+context->sharedByte;
         2823  +        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
  2659   2824         }
  2660   2825       }
  2661   2826       if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){
  2662         -      rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0);
         2827  +      rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
  2663   2828       } 
  2664         -    if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){
  2665         -      rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0);
         2829  +    if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){
         2830  +      rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
         2831  +      if( !rc ){ 
         2832  +        context->reserved = 0; 
         2833  +      }
         2834  +    }
         2835  +    if( rc==SQLITE_OK && locktype==SHARED_LOCK){
         2836  +      pLock->locktype = SHARED_LOCK;
  2666   2837       }
  2667   2838     }else if( locktype==NO_LOCK ){
  2668         -    /* clear the shared lock */
  2669         -    int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
  2670         -    rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0);
         2839  +
         2840  +    /* Decrement the shared lock counter.  Release the lock using an
         2841  +     ** OS call only when all threads in this same process have released
         2842  +     ** the lock.
         2843  +     */
         2844  +    int sharedLockByte = SHARED_FIRST+context->sharedByte;
         2845  +    pLock->cnt--;
         2846  +    if( pLock->cnt==0 ){
         2847  +      SimulateIOErrorBenign(1);
         2848  +      SimulateIOError( h=(-1) )
         2849  +      SimulateIOErrorBenign(0);
         2850  +      rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
         2851  +      pLock->locktype = NO_LOCK;
         2852  +      if( !rc ){
         2853  +        pFile->locktype = NO_LOCK;
         2854  +      }
         2855  +    }
  2671   2856     }
  2672   2857   
  2673   2858     if( rc==SQLITE_OK ){
  2674   2859       if( locktype==NO_LOCK ){
  2675   2860         struct unixOpenCnt *pOpen = pFile->pOpen;
         2861  +        
  2676   2862         pOpen->nLock--;
  2677   2863         assert( pOpen->nLock>=0 );
  2678   2864         if( pOpen->nLock==0 ){
  2679   2865           rc = closePendingFds(pFile);
  2680   2866         }
  2681   2867       }
  2682   2868     }
         2869  +  
  2683   2870     unixLeaveMutex();
  2684         -  if( rc==SQLITE_OK ){
  2685         -    pFile->locktype = locktype;
  2686         -  }
         2871  +  if( rc==SQLITE_OK ) pFile->locktype = locktype;
  2687   2872     return rc;
  2688   2873   }
  2689   2874   
  2690   2875   /*
  2691   2876   ** Close a file & cleanup AFP specific locking context 
  2692   2877   */
  2693   2878   static int afpClose(sqlite3_file *id) {
         2879  +  int rc = SQLITE_OK;
  2694   2880     if( id ){
  2695   2881       unixFile *pFile = (unixFile*)id;
  2696   2882       afpUnlock(id, NO_LOCK);
  2697   2883       unixEnterMutex();
  2698   2884       if( pFile->pOpen && pFile->pOpen->nLock ){
  2699   2885         /* If there are outstanding locks, do not actually close the file just
  2700   2886         ** yet because that would clear those locks.  Instead, add the file
  2701   2887         ** descriptor to pOpen->aPending.  It will be automatically closed when
  2702   2888         ** the last lock is cleared.
  2703   2889         */
  2704   2890         setPendingFd(pFile);
  2705   2891       }
         2892  +    releaseLockInfo(pFile->pLock);
  2706   2893       releaseOpenCnt(pFile->pOpen);
  2707   2894       sqlite3_free(pFile->lockingContext);
  2708         -    closeUnixFile(id);
         2895  +    rc = closeUnixFile(id);
  2709   2896       unixLeaveMutex();
  2710   2897     }
  2711         -  return SQLITE_OK;
         2898  +  return rc;
  2712   2899   }
  2713   2900   
  2714   2901   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  2715   2902   /*
  2716   2903   ** The code above is the AFP lock implementation.  The code is specific
  2717   2904   ** to MacOSX and does not work on other unix platforms.  No alternative
  2718   2905   ** is available.  If you don't compile for a mac, then the "unix-afp"
  2719   2906   ** VFS is not available.
  2720   2907   **
  2721   2908   ********************* End of the AFP lock implementation **********************
  2722   2909   ******************************************************************************/
  2723   2910   
         2911  +/******************************************************************************
         2912  +*************************** Begin NFS Locking ********************************/
         2913  +
         2914  +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
         2915  +/*
         2916  + ** Lower the locking level on file descriptor pFile to locktype.  locktype
         2917  + ** must be either NO_LOCK or SHARED_LOCK.
         2918  + **
         2919  + ** If the locking level of the file descriptor is already at or below
         2920  + ** the requested locking level, this routine is a no-op.
         2921  + */
         2922  +static int nfsUnlock(sqlite3_file *id, int locktype){
         2923  +  return _posixUnlock(id, locktype, 1);
         2924  +}
         2925  +
         2926  +#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
         2927  +/*
         2928  +** The code above is the NFS lock implementation.  The code is specific
         2929  +** to MacOSX and does not work on other unix platforms.  No alternative
         2930  +** is available.  
         2931  +**
         2932  +********************* End of the NFS lock implementation **********************
         2933  +******************************************************************************/
  2724   2934   
  2725   2935   /******************************************************************************
  2726   2936   **************** Non-locking sqlite3_file methods *****************************
  2727   2937   **
  2728   2938   ** The next division contains implementations for all methods of the 
  2729   2939   ** sqlite3_file object other than the locking methods.  The locking
  2730   2940   ** methods were defined in divisions above (one locking method per
................................................................................
  2743   2953   ** See tickets #2741 and #2681.
  2744   2954   **
  2745   2955   ** To avoid stomping the errno value on a failed read the lastErrno value
  2746   2956   ** is set before returning.
  2747   2957   */
  2748   2958   static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
  2749   2959     int got;
         2960  +#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  2750   2961     i64 newOffset;
         2962  +#endif
  2751   2963     TIMER_START;
  2752   2964   #if defined(USE_PREAD)
  2753   2965     got = pread(id->h, pBuf, cnt, offset);
  2754   2966     SimulateIOError( got = -1 );
  2755   2967   #elif defined(USE_PREAD64)
  2756   2968     got = pread64(id->h, pBuf, cnt, offset);
  2757   2969     SimulateIOError( got = -1 );
................................................................................
  2817   3029   ** Return the number of bytes actually read.  Update the offset.
  2818   3030   **
  2819   3031   ** To avoid stomping the errno value on a failed write the lastErrno value
  2820   3032   ** is set before returning.
  2821   3033   */
  2822   3034   static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
  2823   3035     int got;
         3036  +#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  2824   3037     i64 newOffset;
         3038  +#endif
  2825   3039     TIMER_START;
  2826   3040   #if defined(USE_PREAD)
  2827   3041     got = pwrite(id->h, pBuf, cnt, offset);
  2828   3042   #elif defined(USE_PREAD64)
  2829   3043     got = pwrite64(id->h, pBuf, cnt, offset);
  2830   3044   #else
  2831   3045     newOffset = lseek(id->h, offset, SEEK_SET);
................................................................................
  3011   3225     ** isn't supported for this file system. So, attempt an fsync 
  3012   3226     ** and (for now) ignore the overhead of a superfluous fcntl call.  
  3013   3227     ** It'd be better to detect fullfsync support once and avoid 
  3014   3228     ** the fcntl call every time sync is called.
  3015   3229     */
  3016   3230     if( rc ) rc = fsync(fd);
  3017   3231   
         3232  +#elif defined(__APPLE__)
         3233  +  // fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
         3234  +	// so currently we default to the macro that redefines fdatasync to fsync
         3235  +  rc = fsync(fd);
  3018   3236   #else 
  3019   3237     rc = fdatasync(fd);
  3020   3238   #if OS_VXWORKS
  3021   3239     if( rc==-1 && errno==ENOTSUP ){
  3022   3240       rc = fsync(fd);
  3023   3241     }
  3024   3242   #endif /* OS_VXWORKS */
................................................................................
  3332   3550     afpClose,                 /* xClose method */
  3333   3551     afpLock,                  /* xLock method */
  3334   3552     afpUnlock,                /* xUnlock method */
  3335   3553     afpCheckReservedLock      /* xCheckReservedLock method */
  3336   3554   )
  3337   3555   #endif
  3338   3556   
  3339         -/*
  3340         -** The "Whole File Locking" finder returns the same set of methods as
  3341         -** the posix locking finder.  But it also sets the SQLITE_WHOLE_FILE_LOCKING
  3342         -** flag to force the posix advisory locks to cover the whole file instead
  3343         -** of just a small span of bytes near the 1GiB boundary.  Whole File Locking
  3344         -** is useful on NFS-mounted files since it helps NFS to maintain cache
  3345         -** coherency.  But it is a detriment to other filesystems since it runs
  3346         -** slower.
  3347         -*/
  3348         -static const sqlite3_io_methods *posixWflIoFinderImpl(const char*z, unixFile*p){
  3349         -  UNUSED_PARAMETER(z);
  3350         -  p->fileFlags = SQLITE_WHOLE_FILE_LOCKING;
  3351         -  return &posixIoMethods;
  3352         -}
  3353         -static const sqlite3_io_methods 
  3354         -  *(*const posixWflIoFinder)(const char*,unixFile *p) = posixWflIoFinderImpl;
  3355         -
  3356   3557   /*
  3357   3558   ** The proxy locking method is a "super-method" in the sense that it
  3358   3559   ** opens secondary file descriptors for the conch and lock files and
  3359   3560   ** it uses proxy, dot-file, AFP, and flock() locking methods on those
  3360   3561   ** secondary files.  For this reason, the division that implements
  3361   3562   ** proxy locking is located much further down in the file.  But we need
  3362   3563   ** to go ahead and define the sqlite3_io_methods and finder function
................................................................................
  3373   3574     proxyClose,               /* xClose method */
  3374   3575     proxyLock,                /* xLock method */
  3375   3576     proxyUnlock,              /* xUnlock method */
  3376   3577     proxyCheckReservedLock    /* xCheckReservedLock method */
  3377   3578   )
  3378   3579   #endif
  3379   3580   
         3581  +/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
         3582  +#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
         3583  +IOMETHODS(
         3584  +  nfsIoFinder,               /* Finder function name */
         3585  +  nfsIoMethods,              /* sqlite3_io_methods object name */
         3586  +  unixClose,                 /* xClose method */
         3587  +  unixLock,                  /* xLock method */
         3588  +  nfsUnlock,                 /* xUnlock method */
         3589  +  unixCheckReservedLock      /* xCheckReservedLock method */
         3590  +)
         3591  +#endif
  3380   3592   
  3381   3593   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3382   3594   /* 
  3383   3595   ** This "finder" function attempts to determine the best locking strategy 
  3384   3596   ** for the database file "filePath".  It then returns the sqlite3_io_methods
  3385   3597   ** object that implements that strategy.
  3386   3598   **
................................................................................
  3393   3605     static const struct Mapping {
  3394   3606       const char *zFilesystem;              /* Filesystem type name */
  3395   3607       const sqlite3_io_methods *pMethods;   /* Appropriate locking method */
  3396   3608     } aMap[] = {
  3397   3609       { "hfs",    &posixIoMethods },
  3398   3610       { "ufs",    &posixIoMethods },
  3399   3611       { "afpfs",  &afpIoMethods },
  3400         -#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
  3401   3612       { "smbfs",  &afpIoMethods },
  3402         -#else
  3403         -    { "smbfs",  &flockIoMethods },
  3404         -#endif
  3405   3613       { "webdav", &nolockIoMethods },
  3406   3614       { 0, 0 }
  3407   3615     };
  3408   3616     int i;
  3409   3617     struct statfs fsInfo;
  3410   3618     struct flock lockInfo;
  3411   3619   
................................................................................
  3430   3638     ** assume that the file-system supports POSIX style locks. 
  3431   3639     */
  3432   3640     lockInfo.l_len = 1;
  3433   3641     lockInfo.l_start = 0;
  3434   3642     lockInfo.l_whence = SEEK_SET;
  3435   3643     lockInfo.l_type = F_RDLCK;
  3436   3644     if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
  3437         -    pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING;
         3645  +    if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
         3646  +      return &nfsIoMethods;
         3647  +    } else {
  3438   3648       return &posixIoMethods;
         3649  +    }
  3439   3650     }else{
  3440   3651       return &dotlockIoMethods;
  3441   3652     }
  3442   3653   }
  3443   3654   static const sqlite3_io_methods 
  3444   3655     *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
  3445   3656   
................................................................................
  3542   3753       /* Cache zFilename in the locking context (AFP and dotlock override) for
  3543   3754       ** proxyLock activation is possible (remote proxy is based on db name)
  3544   3755       ** zFilename remains valid until file is closed, to support */
  3545   3756       pNew->lockingContext = (void*)zFilename;
  3546   3757   #endif
  3547   3758     }
  3548   3759   
  3549         -  if( pLockingStyle == &posixIoMethods ){
         3760  +  if( pLockingStyle == &posixIoMethods || pLockingStyle == &nfsIoMethods ){
  3550   3761       unixEnterMutex();
  3551   3762       rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
  3552   3763       if( rc!=SQLITE_OK ){
  3553   3764         /* If an error occured in findLockInfo(), close the file descriptor
  3554   3765         ** immediately, before releasing the mutex. findLockInfo() may fail
  3555   3766         ** in two scenarios:
  3556   3767         **
................................................................................
  3584   3795       if( pCtx==0 ){
  3585   3796         rc = SQLITE_NOMEM;
  3586   3797       }else{
  3587   3798         /* NB: zFilename exists and remains valid until the file is closed
  3588   3799         ** according to requirement F11141.  So we do not need to make a
  3589   3800         ** copy of the filename. */
  3590   3801         pCtx->dbPath = zFilename;
         3802  +      pCtx->reserved = 0;
  3591   3803         srandomdev();
  3592   3804         unixEnterMutex();
  3593         -      rc = findLockInfo(pNew, NULL, &pNew->pOpen);
         3805  +      rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
         3806  +      if( rc!=SQLITE_OK ){
         3807  +        sqlite3_free(pNew->lockingContext);
         3808  +        close(h);
         3809  +        h = -1;
         3810  +      }
  3594   3811         unixLeaveMutex();        
  3595   3812       }
  3596   3813     }
  3597   3814   #endif
  3598   3815   
  3599   3816     else if( pLockingStyle == &dotlockIoMethods ){
  3600   3817       /* Dotfile locking uses the file path so it needs to be included in
................................................................................
  3850   4067     int rc = SQLITE_OK;            /* Function Return Code */
  3851   4068   
  3852   4069     int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  3853   4070     int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  3854   4071     int isCreate     = (flags & SQLITE_OPEN_CREATE);
  3855   4072     int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  3856   4073     int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
         4074  +  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
  3857   4075   
  3858   4076     /* If creating a master or main-file journal, this function will open
  3859   4077     ** a file-descriptor on the directory too. The first time unixSync()
  3860   4078     ** is called the directory file descriptor will be fsync()ed and close()d.
  3861   4079     */
  3862   4080     int isOpenDirectory = (isCreate && 
  3863   4081         (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
................................................................................
  3984   4202   #ifdef FD_CLOEXEC
  3985   4203     fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
  3986   4204   #endif
  3987   4205   
  3988   4206     noLock = eType!=SQLITE_OPEN_MAIN_DB;
  3989   4207   
  3990   4208   #if SQLITE_PREFER_PROXY_LOCKING
  3991         -  if( zPath!=NULL && !noLock && pVfs->xOpen ){
         4209  +  isAutoProxy = 1;
         4210  +#endif
         4211  +  
         4212  +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
         4213  +
         4214  +  struct statfs fsInfo;
         4215  +  if( fstatfs(fd, &fsInfo) == -1 ){
         4216  +    ((unixFile*)pFile)->lastErrno = errno;
         4217  +    if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
         4218  +    close(fd); /* silently leak if fail, in error */
         4219  +    return SQLITE_IOERR_ACCESS;
         4220  +  }
         4221  +  
         4222  +  ((unixFile*)pFile)->fsFlags = SQLITE_FSFLAGS_INITIALIZED;
         4223  +  
         4224  +  if (fsInfo.f_flags & MNT_RDONLY) {
         4225  +    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_READONLY;
         4226  +  }
         4227  +  if (fsInfo.f_flags & MNT_LOCAL) {
         4228  +    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_LOCAL;
         4229  +  }
         4230  +  if (0 == strncmp("hfs", fsInfo.f_fstypename, 3)) {
         4231  +    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_HFSPLUS;
         4232  +  } else if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
         4233  +    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
         4234  +  }
         4235  +#endif
         4236  +  
         4237  +#if SQLITE_ENABLE_LOCKING_STYLE
         4238  +  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
  3992   4239       char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
  3993   4240       int useProxy = 0;
  3994   4241   
  3995   4242       /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means 
  3996   4243       ** never use proxy, NULL means use proxy for non-local files only.  */
  3997   4244       if( envforce!=NULL ){
  3998   4245         useProxy = atoi(envforce)>0;
................................................................................
  4016   4263         }
  4017   4264         useProxy = !(fsInfo.f_flags&MNT_LOCAL);
  4018   4265       }
  4019   4266       if( useProxy ){
  4020   4267         rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
  4021   4268         if( rc==SQLITE_OK ){
  4022   4269           rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
         4270  +        if( rc!=SQLITE_OK ){
         4271  +          /* Use unixClose to clean up the resources added in fillInUnixFile 
         4272  +          ** and clear all the structure's references.  Specifically, 
         4273  +          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
         4274  +          */
         4275  +          unixClose(pFile);
         4276  +          return rc;
         4277  +        }
  4023   4278         }
  4024   4279         goto open_finished;
  4025   4280       }
  4026   4281     }
  4027   4282   #endif
  4028   4283     
  4029   4284     rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
................................................................................
  4443   4698   ** will fail and SQLITE_BUSY is returned.
  4444   4699   **
  4445   4700   ** The proxy file - a single-byte file used for all advisory file locks
  4446   4701   ** normally taken on the database file.   This allows for safe sharing
  4447   4702   ** of the database file for multiple readers and writers on the same
  4448   4703   ** host (the conch ensures that they all use the same local lock file).
  4449   4704   **
  4450         -** There is a third file - the host ID file - used as a persistent record
  4451         -** of a unique identifier for the host, a 128-byte unique host id file
  4452         -** in the path defined by the HOSTIDPATH macro (default value is
  4453         -** /Library/Caches/.com.apple.sqliteConchHostId).
  4454         -**
  4455   4705   ** Requesting the lock proxy does not immediately take the conch, it is
  4456   4706   ** only taken when the first request to lock database file is made.  
  4457   4707   ** This matches the semantics of the traditional locking behavior, where
  4458   4708   ** opening a connection to a database file does not take a lock on it.
  4459   4709   ** The shared lock and an open file descriptor are maintained until 
  4460   4710   ** the connection to the database is closed. 
  4461   4711   **
................................................................................
  4473   4723   **       PRAGMA lock_proxy_file=":auto:"
  4474   4724   **    
  4475   4725   **  SQLITE_PROXY_DEBUG
  4476   4726   **
  4477   4727   **       Enables the logging of error messages during host id file
  4478   4728   **       retrieval and creation
  4479   4729   **
  4480         -**  HOSTIDPATH
  4481         -**
  4482         -**       Overrides the default host ID file path location
  4483         -**
  4484   4730   **  LOCKPROXYDIR
  4485   4731   **
  4486   4732   **       Overrides the default directory used for lock proxy files that
  4487   4733   **       are named automatically via the ":auto:" setting
  4488   4734   **
  4489   4735   **  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
  4490   4736   **
................................................................................
  4501   4747   */
  4502   4748   
  4503   4749   /*
  4504   4750   ** Proxy locking is only available on MacOSX 
  4505   4751   */
  4506   4752   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4507   4753   
  4508         -#ifdef SQLITE_TEST
  4509         -/* simulate multiple hosts by creating unique hostid file paths */
  4510         -int sqlite3_hostid_num = 0;
  4511         -#endif
  4512         -
  4513   4754   /*
  4514   4755   ** The proxyLockingContext has the path and file structures for the remote 
  4515   4756   ** and local proxy files in it
  4516   4757   */
  4517   4758   typedef struct proxyLockingContext proxyLockingContext;
  4518   4759   struct proxyLockingContext {
  4519   4760     unixFile *conchFile;         /* Open conch file */
  4520   4761     char *conchFilePath;         /* Name of the conch file */
  4521   4762     unixFile *lockProxy;         /* Open proxy lock file */
  4522   4763     char *lockProxyPath;         /* Name of the proxy lock file */
  4523   4764     char *dbPath;                /* Name of the open file */
  4524         -  int conchHeld;               /* True if the conch is currently held */
         4765  +  int conchHeld;               /* 1 if the conch is held, -1 if lockless */
  4525   4766     void *oldLockingContext;     /* Original lockingcontext to restore on close */
  4526   4767     sqlite3_io_methods const *pOldMethod;     /* Original I/O methods for close */
  4527   4768   };
  4528   4769   
  4529         -/* HOSTIDLEN and CONCHLEN both include space for the string 
  4530         -** terminating nul 
  4531         -*/
  4532         -#define HOSTIDLEN         128
  4533         -#define CONCHLEN          (MAXPATHLEN+HOSTIDLEN+1)
  4534         -#ifndef HOSTIDPATH
  4535         -# define HOSTIDPATH       "/Library/Caches/.com.apple.sqliteConchHostId"
  4536         -#endif
  4537         -
  4538         -/* basically a copy of unixRandomness with different
  4539         -** test behavior built in */
  4540         -static int proxyGenerateHostID(char *pHostID){
  4541         -  int pid, fd, len;
  4542         -  unsigned char *key = (unsigned char *)pHostID;
  4543         -  
  4544         -  memset(key, 0, HOSTIDLEN);
  4545         -  len = 0;
  4546         -  fd = open("/dev/urandom", O_RDONLY);
  4547         -  if( fd>=0 ){
  4548         -    len = read(fd, key, HOSTIDLEN);
  4549         -    close(fd); /* silently leak the fd if it fails */
  4550         -  }
  4551         -  if( len < HOSTIDLEN ){
  4552         -    time_t t;
  4553         -    time(&t);
  4554         -    memcpy(key, &t, sizeof(t));
  4555         -    pid = getpid();
  4556         -    memcpy(&key[sizeof(t)], &pid, sizeof(pid));
  4557         -  }
  4558         -  
  4559         -#ifdef MAKE_PRETTY_HOSTID
  4560         -  {
  4561         -    int i;
  4562         -    /* filter the bytes into printable ascii characters and NUL terminate */
  4563         -    key[(HOSTIDLEN-1)] = 0x00;
  4564         -    for( i=0; i<(HOSTIDLEN-1); i++ ){
  4565         -      unsigned char pa = key[i]&0x7F;
  4566         -      if( pa<0x20 ){
  4567         -        key[i] = (key[i]&0x80 == 0x80) ? pa+0x40 : pa+0x20;
  4568         -      }else if( pa==0x7F ){
  4569         -        key[i] = (key[i]&0x80 == 0x80) ? pa=0x20 : pa+0x7E;
  4570         -      }
  4571         -    }
  4572         -  }
  4573         -#endif
  4574         -  return SQLITE_OK;
  4575         -}
  4576         -
  4577         -/* writes the host id path to path, path should be an pre-allocated buffer
  4578         -** with enough space for a path 
  4579         -*/
  4580         -static void proxyGetHostIDPath(char *path, size_t len){
  4581         -  strlcpy(path, HOSTIDPATH, len);
  4582         -#ifdef SQLITE_TEST
  4583         -  if( sqlite3_hostid_num>0 ){
  4584         -    char suffix[2] = "1";
  4585         -    suffix[0] = suffix[0] + sqlite3_hostid_num;
  4586         -    strlcat(path, suffix, len);
  4587         -  }
  4588         -#endif
  4589         -  OSTRACE3("GETHOSTIDPATH  %s pid=%d\n", path, getpid());
  4590         -}
  4591         -
  4592         -/* get the host ID from a sqlite hostid file stored in the 
  4593         -** user-specific tmp directory, create the ID if it's not there already 
  4594         -*/
  4595         -static int proxyGetHostID(char *pHostID, int *pError){
  4596         -  int fd;
  4597         -  char path[MAXPATHLEN]; 
  4598         -  size_t len;
  4599         -  int rc=SQLITE_OK;
  4600         -
  4601         -  proxyGetHostIDPath(path, MAXPATHLEN);
  4602         -  /* try to create the host ID file, if it already exists read the contents */
  4603         -  fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644);
  4604         -  if( fd<0 ){
  4605         -    int err=errno;
  4606         -		
  4607         -    if( err!=EEXIST ){
  4608         -#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
  4609         -      fprintf(stderr, "sqlite error creating host ID file %s: %s\n",
  4610         -              path, strerror(err));
  4611         -#endif
  4612         -      return SQLITE_PERM;
  4613         -    }
  4614         -    /* couldn't create the file, read it instead */
  4615         -    fd = open(path, O_RDONLY|O_EXCL);
  4616         -    if( fd<0 ){
  4617         -#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
  4618         -      int err = errno;
  4619         -      fprintf(stderr, "sqlite error opening host ID file %s: %s\n",
  4620         -              path, strerror(err));
  4621         -#endif
  4622         -      return SQLITE_PERM;
  4623         -    }
  4624         -    len = pread(fd, pHostID, HOSTIDLEN, 0);
  4625         -    if( len<0 ){
  4626         -      *pError = errno;
  4627         -      rc = SQLITE_IOERR_READ;
  4628         -    }else if( len<HOSTIDLEN ){
  4629         -      *pError = 0;
  4630         -      rc = SQLITE_IOERR_SHORT_READ;
  4631         -    }
  4632         -    close(fd); /* silently leak the fd if it fails */
  4633         -    OSTRACE3("GETHOSTID  read %s pid=%d\n", pHostID, getpid());
  4634         -    return rc;
  4635         -  }else{
  4636         -    /* we're creating the host ID file (use a random string of bytes) */
  4637         -    proxyGenerateHostID(pHostID);
  4638         -    len = pwrite(fd, pHostID, HOSTIDLEN, 0);
  4639         -    if( len<0 ){
  4640         -      *pError = errno;
  4641         -      rc = SQLITE_IOERR_WRITE;
  4642         -    }else if( len<HOSTIDLEN ){
  4643         -      *pError = 0;
  4644         -      rc = SQLITE_IOERR_WRITE;
  4645         -    }
  4646         -    close(fd); /* silently leak the fd if it fails */
  4647         -    OSTRACE3("GETHOSTID  wrote %s pid=%d\n", pHostID, getpid());
  4648         -    return rc;
  4649         -  }
  4650         -}
  4651         -
         4770  +/* 
         4771  +** The proxy lock file path for the database at dbPath is written into lPath, 
         4772  +** which must point to valid, writable memory large enough for a maxLen length
         4773  +** file path. 
         4774  +*/
  4652   4775   static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
  4653   4776     int len;
  4654   4777     int dbLen;
  4655   4778     int i;
  4656   4779   
  4657   4780   #ifdef LOCKPROXYDIR
  4658   4781     len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
  4659   4782   #else
  4660   4783   # ifdef _CS_DARWIN_USER_TEMP_DIR
  4661   4784     {
  4662         -    confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen);
         4785  +    if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
         4786  +      OSTRACE4("GETLOCKPATH  failed %s errno=%d pid=%d\n", lPath, errno, getpid());
         4787  +      return SQLITE_IOERR_LOCK;
         4788  +    }
  4663   4789       len = strlcat(lPath, "sqliteplocks", maxLen);
  4664         -    if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
  4665         -      /* if mkdir fails, handle as lock file creation failure */
  4666         -#  ifdef SQLITE_DEBUG
  4667         -      int err = errno;
  4668         -      if( err!=EEXIST ){
  4669         -        fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath,
  4670         -                SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err));
  4671         -      }
  4672         -#  endif
  4673         -    }else{
  4674         -      OSTRACE3("GETLOCKPATH  mkdir %s pid=%d\n", lPath, getpid());
  4675         -    }
  4676         -    
  4677   4790     }
  4678   4791   # else
  4679   4792     len = strlcpy(lPath, "/tmp/", maxLen);
  4680   4793   # endif
  4681   4794   #endif
  4682   4795   
  4683   4796     if( lPath[len-1]!='/' ){
................................................................................
  4688   4801     dbLen = (int)strlen(dbPath);
  4689   4802     for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
  4690   4803       char c = dbPath[i];
  4691   4804       lPath[i+len] = (c=='/')?'_':c;
  4692   4805     }
  4693   4806     lPath[i+len]='\0';
  4694   4807     strlcat(lPath, ":auto:", maxLen);
         4808  +  OSTRACE3("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid());
  4695   4809     return SQLITE_OK;
  4696   4810   }
         4811  +
         4812  +/* 
         4813  + ** Creates the lock file and any missing directories in lockPath
         4814  + */
         4815  +static int proxyCreateLockPath(const char *lockPath){
         4816  +  int i, len;
         4817  +  char buf[MAXPATHLEN];
         4818  +  int start = 0;
         4819  +  
         4820  +  assert(lockPath!=NULL);
         4821  +  /* try to create all the intermediate directories */
         4822  +  len = (int)strlen(lockPath);
         4823  +  buf[0] = lockPath[0];
         4824  +  for( i=1; i<len; i++ ){
         4825  +    if( lockPath[i] == '/' && (i - start > 0) ){
         4826  +      /* only mkdir if leaf dir != "." or "/" or ".." */
         4827  +      if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') 
         4828  +         || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
         4829  +        buf[i]='\0';
         4830  +        if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
         4831  +          int err=errno;
         4832  +          if( err!=EEXIST ) {
         4833  +            OSTRACE5("CREATELOCKPATH  FAILED creating %s, '%s' proxy lock path=%s pid=%d\n", buf, strerror(err), lockPath, getpid());
         4834  +            return err;
         4835  +          }
         4836  +        }
         4837  +      }
         4838  +      start=i+1;
         4839  +    }
         4840  +    buf[i] = lockPath[i];
         4841  +  }
         4842  +  OSTRACE3("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid());
         4843  +  return 0;
         4844  +}
  4697   4845   
  4698   4846   /*
  4699   4847   ** Create a new VFS file descriptor (stored in memory obtained from
  4700   4848   ** sqlite3_malloc) and open the file named "path" in the file descriptor.
  4701   4849   **
  4702   4850   ** The caller is responsible not only for closing the file descriptor
  4703   4851   ** but also for freeing the memory associated with the file descriptor.
  4704   4852   */
  4705         -static int proxyCreateUnixFile(const char *path, unixFile **ppFile) {
         4853  +static int proxyCreateUnixFile(
         4854  +    const char *path,        /* path for the new unixFile */
         4855  +    unixFile **ppFile,       /* unixFile created and returned by ref */
         4856  +    int islockfile           /* if non zero missing dirs will be created */
         4857  +) {
         4858  +  int fd = -1;
         4859  +  int dirfd = -1;
  4706   4860     unixFile *pNew;
  4707         -  int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
  4708   4861     int rc = SQLITE_OK;
         4862  +  int openFlags = O_RDWR | O_CREAT;
  4709   4863     sqlite3_vfs dummyVfs;
         4864  +  int terrno = 0;
         4865  +  UnixUnusedFd *pUnused = NULL;
  4710   4866   
  4711         -  pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile));
  4712         -  if( !pNew ){
         4867  +  /* 1. first try to open/create the file
         4868  +  ** 2. if that fails, and this is a lock file (not-conch), try creating
         4869  +  ** the parent directories and then try again.
         4870  +  ** 3. if that fails, try to open the file read-only
         4871  +  ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
         4872  +  */
         4873  +  pUnused = findReusableFd(path, openFlags);
         4874  +  if( pUnused ){
         4875  +    fd = pUnused->fd;
         4876  +  }else{
         4877  +    pUnused = sqlite3_malloc(sizeof(*pUnused));
         4878  +    if( !pUnused ){
  4713   4879       return SQLITE_NOMEM;
  4714   4880     }
         4881  +  }
         4882  +  if( fd<0 ){
         4883  +    fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         4884  +    terrno = errno;
         4885  +    if( fd<0 && errno==ENOENT && islockfile ){
         4886  +      if( proxyCreateLockPath(path) == SQLITE_OK ){
         4887  +        fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         4888  +      }
         4889  +    }
         4890  +  }
         4891  +  if( fd<0 ){
         4892  +    openFlags = O_RDONLY;
         4893  +    fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         4894  +    terrno = errno;
         4895  +  }
         4896  +  if( fd<0 ){
         4897  +    if( islockfile ){
         4898  +      return SQLITE_BUSY;
         4899  +    }
         4900  +    switch (terrno) {
         4901  +      case EACCES:
         4902  +        return SQLITE_PERM;
         4903  +      case EIO: 
         4904  +        return SQLITE_IOERR_LOCK; /* even though it is the conch */
         4905  +      default:
         4906  +        return SQLITE_CANTOPEN;
         4907  +    }
         4908  +  }
         4909  +  
         4910  +  pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
         4911  +  if( pNew==NULL ){
         4912  +    rc = SQLITE_NOMEM;
         4913  +    goto end_create_proxy;
         4914  +  }
  4715   4915     memset(pNew, 0, sizeof(unixFile));
  4716         -
  4717         -  /* Call unixOpen() to open the proxy file. The flags passed to unixOpen()
  4718         -  ** suggest that the file being opened is a "main database". This is
  4719         -  ** necessary as other file types do not necessarily support locking. It
  4720         -  ** is better to use unixOpen() instead of opening the file directly with
  4721         -  ** open(), as unixOpen() sets up the various mechanisms required to
  4722         -  ** make sure a call to close() does not cause the system to discard
  4723         -  ** POSIX locks prematurely.
  4724         -  **
  4725         -  ** It is important that the xOpen member of the VFS object passed to 
  4726         -  ** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file 
  4727         -  ** for the proxy-file (creating a potential infinite loop).
  4728         -  */
         4916  +  pNew->openFlags = openFlags;
  4729   4917     dummyVfs.pAppData = (void*)&autolockIoFinder;
  4730         -  dummyVfs.xOpen = 0;
  4731         -  rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags);
  4732         -  if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){
  4733         -    pNew->pMethod->xClose((sqlite3_file *)pNew);
  4734         -    rc = SQLITE_CANTOPEN;
         4918  +  pUnused->fd = fd;
         4919  +  pUnused->flags = openFlags;
         4920  +  pNew->pUnused = pUnused;
         4921  +  
         4922  +  rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0);
         4923  +  if( rc==SQLITE_OK ){
         4924  +    *ppFile = pNew;
         4925  +    return SQLITE_OK;
  4735   4926     }
  4736         -
  4737         -  if( rc!=SQLITE_OK ){
         4927  +end_create_proxy:    
         4928  +  close(fd); /* silently leak fd if error, we're already in error */
  4738   4929       sqlite3_free(pNew);
  4739         -    pNew = 0;
  4740         -  }
  4741         -
  4742         -  *ppFile = pNew;
         4930  +  sqlite3_free(pUnused);
         4931  +  return rc;
         4932  +}
         4933  +
         4934  +#ifdef SQLITE_TEST
         4935  +/* simulate multiple hosts by creating unique hostid file paths */
         4936  +int sqlite3_hostid_num = 0;
         4937  +#endif
         4938  +
         4939  +#define PROXY_HOSTIDLEN    16  /* conch file host id length */
         4940  +
         4941  +/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN 
         4942  +** bytes of writable memory.
         4943  +*/
         4944  +static int proxyGetHostID(unsigned char *pHostID, int *pError){
         4945  +  struct timespec timeout = {1, 0}; /* 1 sec timeout */
         4946  +  
         4947  +  assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
         4948  +  memset(pHostID, 0, PROXY_HOSTIDLEN);
         4949  +  if( gethostuuid(pHostID, &timeout) ){
         4950  +    int err = errno;
         4951  +    if( pError ){
         4952  +      *pError = err;
         4953  +    }
         4954  +    return SQLITE_IOERR;
         4955  +  }
         4956  +#ifdef SQLITE_TEST
         4957  +  /* simulate multiple hosts by creating unique hostid file paths */
         4958  +  if( sqlite3_hostid_num != 0){
         4959  +    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
         4960  +  }
         4961  +#endif
         4962  +  
         4963  +  return SQLITE_OK;
         4964  +}
         4965  +
         4966  +/* The conch file contains the header, host id and lock file path
         4967  + */
         4968  +#define PROXY_CONCHVERSION 2   /* 1-byte header, 16-byte host id, path */
         4969  +#define PROXY_HEADERLEN    1   /* conch file header length */
         4970  +#define PROXY_PATHINDEX    (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
         4971  +#define PROXY_MAXCONCHLEN  (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
         4972  +
         4973  +/* 
         4974  +** Takes an open conch file, copies the contents to a new path and then moves 
         4975  +** it back.  The newly created file's file descriptor is assigned to the
         4976  +** conch file structure and finally the original conch file descriptor is 
         4977  +** closed.  Returns zero if successful.
         4978  +*/
         4979  +static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
         4980  +  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
         4981  +  unixFile *conchFile = pCtx->conchFile;
         4982  +  char tPath[MAXPATHLEN];
         4983  +  char buf[PROXY_MAXCONCHLEN];
         4984  +  char *cPath = pCtx->conchFilePath;
         4985  +  size_t readLen = 0;
         4986  +  size_t pathLen = 0;
         4987  +  char errmsg[64] = "";
         4988  +  int fd = -1;
         4989  +  int rc = -1;
         4990  +
         4991  +  /* create a new path by replace the trailing '-conch' with '-break' */
         4992  +  pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
         4993  +  if( pathLen>MAXPATHLEN || pathLen<6 || 
         4994  +     (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
         4995  +    sprintf(errmsg, "path error (len %d)", (int)pathLen);
         4996  +    goto end_breaklock;
         4997  +  }
         4998  +  /* read the conch content */
         4999  +  readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
         5000  +  if( readLen<PROXY_PATHINDEX ){
         5001  +    sprintf(errmsg, "read error (len %d)", (int)readLen);
         5002  +    goto end_breaklock;
         5003  +  }
         5004  +  /* write it out to the temporary break file */
         5005  +  fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS);
         5006  +  if( fd<0 ){
         5007  +    sprintf(errmsg, "create failed (%d)", errno);
         5008  +    goto end_breaklock;
         5009  +  }
         5010  +  if( pwrite(fd, buf, readLen, 0) != readLen ){
         5011  +    sprintf(errmsg, "write failed (%d)", errno);
         5012  +    goto end_breaklock;
         5013  +  }
         5014  +  if( rename(tPath, cPath) ){
         5015  +    sprintf(errmsg, "rename failed (%d)", errno);
         5016  +    goto end_breaklock;
         5017  +  }
         5018  +  rc = 0;
         5019  +  fprintf(stderr, "broke stale lock on %s\n", cPath);
         5020  +  close(conchFile->h);
         5021  +  conchFile->h = fd;
         5022  +  conchFile->openFlags = O_RDWR | O_CREAT;
         5023  +
         5024  +end_breaklock:
         5025  +  if( rc ){
         5026  +    if( fd>=0 ){
         5027  +      unlink(tPath);
         5028  +      close(fd);
         5029  +    }
         5030  +    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
         5031  +  }
         5032  +  return rc;
         5033  +}
         5034  +
         5035  +/* Take the requested lock on the conch file and break a stale lock if the 
         5036  +** host id matches.
         5037  +*/
         5038  +static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
         5039  +  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
         5040  +  unixFile *conchFile = pCtx->conchFile;
         5041  +  int rc = SQLITE_OK;
         5042  +  int nTries = 0;
         5043  +  struct timespec conchModTime;
         5044  +  
         5045  +  do {
         5046  +    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
         5047  +    nTries ++;
         5048  +    if( rc==SQLITE_BUSY ){
         5049  +      /* If the lock failed (busy):
         5050  +       * 1st try: get the mod time of the conch, wait 0.5s and try again. 
         5051  +       * 2nd try: fail if the mod time changed or host id is different, wait 
         5052  +       *           10 sec and try again
         5053  +       * 3rd try: break the lock unless the mod time has changed.
         5054  +       */
         5055  +      struct stat buf;
         5056  +      if( fstat(conchFile->h, &buf) ){
         5057  +        pFile->lastErrno = errno;
         5058  +        return SQLITE_IOERR_LOCK;
         5059  +      }
         5060  +      
         5061  +      if( nTries==1 ){
         5062  +        conchModTime = buf.st_mtimespec;
         5063  +        usleep(500000); /* wait 0.5 sec and try the lock again*/
         5064  +        continue;  
         5065  +      }
         5066  +
         5067  +      assert( nTries>1 );
         5068  +      if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || 
         5069  +         conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
         5070  +        return SQLITE_BUSY;
         5071  +      }
         5072  +      
         5073  +      if( nTries==2 ){  
         5074  +        char tBuf[PROXY_MAXCONCHLEN];
         5075  +        int len = pread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
         5076  +        if( len<0 ){
         5077  +          pFile->lastErrno = errno;
         5078  +          return SQLITE_IOERR_LOCK;
         5079  +        }
         5080  +        if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
         5081  +          /* don't break the lock if the host id doesn't match */
         5082  +          if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
         5083  +            return SQLITE_BUSY;
         5084  +          }
         5085  +        }else{
         5086  +          /* don't break the lock on short read or a version mismatch */
         5087  +          return SQLITE_BUSY;
         5088  +        }
         5089  +        usleep(10000000); /* wait 10 sec and try the lock again */
         5090  +        continue; 
         5091  +      }
         5092  +      
         5093  +      assert( nTries==3 );
         5094  +      if( 0==proxyBreakConchLock(pFile, myHostID) ){
         5095  +        rc = SQLITE_OK;
         5096  +        if( lockType==EXCLUSIVE_LOCK ){
         5097  +          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);          
         5098  +        }
         5099  +        if( !rc ){
         5100  +          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
         5101  +        }
         5102  +      }
         5103  +    }
         5104  +  } while( rc==SQLITE_BUSY && nTries<3 );
         5105  +  
  4743   5106     return rc;
  4744   5107   }
  4745   5108   
  4746         -/* takes the conch by taking a shared lock and read the contents conch, if 
         5109  +/* Takes the conch by taking a shared lock and read the contents conch, if 
  4747   5110   ** lockPath is non-NULL, the host ID and lock file path must match.  A NULL 
  4748   5111   ** lockPath means that the lockPath in the conch file will be used if the 
  4749   5112   ** host IDs match, or a new lock path will be generated automatically 
  4750   5113   ** and written to the conch file.
  4751   5114   */
  4752   5115   static int proxyTakeConch(unixFile *pFile){
  4753   5116     proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; 
  4754   5117     
  4755         -  if( pCtx->conchHeld>0 ){
         5118  +  if( pCtx->conchHeld!=0 ){
  4756   5119       return SQLITE_OK;
  4757   5120     }else{
  4758   5121       unixFile *conchFile = pCtx->conchFile;
  4759         -    char testValue[CONCHLEN];
  4760         -    char conchValue[CONCHLEN];
         5122  +    uuid_t myHostID;
         5123  +    int pError = 0;
         5124  +    char readBuf[PROXY_MAXCONCHLEN];
  4761   5125       char lockPath[MAXPATHLEN];
  4762         -    char *tLockPath = NULL;
         5126  +    char *tempLockPath = NULL;
  4763   5127       int rc = SQLITE_OK;
  4764         -    int readRc = SQLITE_OK;
  4765         -    int syncPerms = 0;
         5128  +    int createConch = 0;
         5129  +    int hostIdMatch = 0;
         5130  +    int readLen = 0;
         5131  +    int tryOldLockPath = 0;
         5132  +    int forceNewLockPath = 0;
  4766   5133   
  4767   5134       OSTRACE4("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
  4768   5135                (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid());
  4769   5136   
  4770         -    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
  4771         -    if( rc==SQLITE_OK ){
  4772         -      int pError = 0;
  4773         -      memset(testValue, 0, CONCHLEN); /* conch is fixed size */
  4774         -      rc = proxyGetHostID(testValue, &pError);
         5137  +    rc = proxyGetHostID(myHostID, &pError);
  4775   5138         if( (rc&0xff)==SQLITE_IOERR ){
  4776   5139           pFile->lastErrno = pError;
         5140  +      goto end_takeconch;
  4777   5141         }
  4778         -      if( pCtx->lockProxyPath ){
  4779         -        strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN);
  4780         -      }
  4781         -    }
         5142  +    rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
  4782   5143       if( rc!=SQLITE_OK ){
  4783   5144         goto end_takeconch;
  4784   5145       }
  4785         -    
  4786         -    readRc = unixRead((sqlite3_file *)conchFile, conchValue, CONCHLEN, 0);
  4787         -    if( readRc!=SQLITE_IOERR_SHORT_READ ){
  4788         -      if( readRc!=SQLITE_OK ){
  4789         -        if( (rc&0xff)==SQLITE_IOERR ){
         5146  +    /* read the existing conch file */
         5147  +    readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
         5148  +    if( readLen<0 ){
         5149  +      /* I/O error: lastErrno set by seekAndRead */
  4790   5150             pFile->lastErrno = conchFile->lastErrno;
  4791         -        }
  4792         -        rc = readRc;
         5151  +      rc = SQLITE_IOERR_READ;
  4793   5152           goto end_takeconch;
         5153  +    }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || 
         5154  +             readBuf[0]!=(char)PROXY_CONCHVERSION ){
         5155  +      /* a short read or version format mismatch means we need to create a new 
         5156  +      ** conch file. 
         5157  +      */
         5158  +      createConch = 1;
  4794   5159         }
         5160  +    /* if the host id matches and the lock path already exists in the conch
         5161  +    ** we'll try to use the path there, if we can't open that path, we'll 
         5162  +    ** retry with a new auto-generated path 
         5163  +    */
         5164  +    do { /* in case we need to try again for an :auto: named lock file */
         5165  +
         5166  +      if( !createConch && !forceNewLockPath ){
         5167  +        hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, 
         5168  +                                  PROXY_HOSTIDLEN);
  4795   5169         /* if the conch has data compare the contents */
  4796   5170         if( !pCtx->lockProxyPath ){
  4797   5171           /* for auto-named local lock file, just check the host ID and we'll
  4798         -         ** use the local lock file path that's already in there */
  4799         -        if( !memcmp(testValue, conchValue, HOSTIDLEN) ){
  4800         -          tLockPath = (char *)&conchValue[HOSTIDLEN];
         5172  +           ** use the local lock file path that's already in there
         5173  +           */
         5174  +          if( hostIdMatch ){
         5175  +            size_t pathLen = (readLen - PROXY_PATHINDEX);
         5176  +            
         5177  +            if( pathLen>=MAXPATHLEN ){
         5178  +              pathLen=MAXPATHLEN-1;
         5179  +            }
         5180  +            memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
         5181  +            lockPath[pathLen] = 0;
         5182  +            tempLockPath = lockPath;
         5183  +            tryOldLockPath = 1;
         5184  +            /* create a copy of the lock path if the conch is taken */
         5185  +            goto end_takeconch;
         5186  +          }
         5187  +        }else if( hostIdMatch && !strncmp(pCtx->lockProxyPath, 
         5188  +                                          &readBuf[PROXY_PATHINDEX], readLen-PROXY_PATHINDEX) ){
         5189  +          /* conch host and lock path match */
  4801   5190             goto end_takeconch;
  4802   5191           }
  4803         -      }else{
  4804         -        /* we've got the conch if conchValue matches our path and host ID */
  4805         -        if( !memcmp(testValue, conchValue, CONCHLEN) ){
         5192  +      }
         5193  +      
         5194  +      /* if the conch isn't writable and doesn't match, we can't take it */
         5195  +      if( (conchFile->openFlags&O_RDWR) == 0 ){
         5196  +        rc = SQLITE_BUSY;
  4806   5197             goto end_takeconch;
  4807   5198           }
  4808         -      }
  4809         -    }else{
  4810         -      /* a short read means we're "creating" the conch (even though it could 
  4811         -      ** have been user-intervention), if we acquire the exclusive lock,
  4812         -      ** we'll try to match the current on-disk permissions of the database
  4813         -      */
  4814         -      syncPerms = 1;
  4815         -    }
  4816   5199       
  4817         -    /* either conch was emtpy or didn't match */
         5200  +      /* either the conch didn't match or we need to create a new one */
  4818   5201       if( !pCtx->lockProxyPath ){
  4819   5202         proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
  4820         -      tLockPath = lockPath;
  4821         -      strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN);
         5203  +        tempLockPath = lockPath;
         5204  +        /* create a copy of the lock path _only_ if the conch is taken */
  4822   5205       }
  4823   5206       
  4824   5207       /* update conch with host and path (this will fail if other process
  4825         -     ** has a shared lock already) */
         5208  +      ** has a shared lock already), if the host id matches, use the big
         5209  +      ** stick.
         5210  +      */
         5211  +      futimes(conchFile->h, NULL);
         5212  +      if( hostIdMatch && !createConch ){
         5213  +        if( conchFile->pLock && conchFile->pLock->cnt>1 ){
         5214  +          /* We are trying for an exclusive lock but another thread in this
         5215  +           ** same process is still holding a shared lock. */
         5216  +          rc = SQLITE_BUSY;
         5217  +        } else {          
         5218  +          rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
         5219  +        }
         5220  +      }else{
  4826   5221       rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
         5222  +      }
  4827   5223       if( rc==SQLITE_OK ){
  4828         -      rc = unixWrite((sqlite3_file *)conchFile, testValue, CONCHLEN, 0);
  4829         -      if( rc==SQLITE_OK && syncPerms ){
         5224  +        char writeBuffer[PROXY_MAXCONCHLEN];
         5225  +        int writeSize = 0;
         5226  +        
         5227  +        writeBuffer[0] = (char)PROXY_CONCHVERSION;
         5228  +        memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
         5229  +        if( pCtx->lockProxyPath!=NULL ){
         5230  +          strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
         5231  +        }else{
         5232  +          strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
         5233  +        }
         5234  +        writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
         5235  +        ftruncate(conchFile->h, writeSize);
         5236  +        rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
         5237  +        fsync(conchFile->h);
         5238  +        /* If we created a new conch file (not just updated the contents of a 
         5239  +         ** valid conch file), try to match the permissions of the database 
         5240  +         */
         5241  +        if( rc==SQLITE_OK && createConch ){
  4830   5242           struct stat buf;
  4831   5243           int err = fstat(pFile->h, &buf);
  4832   5244           if( err==0 ){
  4833         -          /* try to match the database file permissions, ignore failure */
         5245  +            mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
         5246  +                                        S_IROTH|S_IWOTH);
         5247  +            /* try to match the database file R/W permissions, ignore failure */
  4834   5248   #ifndef SQLITE_PROXY_DEBUG
  4835         -          fchmod(conchFile->h, buf.st_mode);
         5249  +            fchmod(conchFile->h, cmode);
  4836   5250   #else
  4837         -          if( fchmod(conchFile->h, buf.st_mode)!=0 ){
         5251  +            if( fchmod(conchFile->h, cmode)!=0 ){
  4838   5252               int code = errno;
  4839   5253               fprintf(stderr, "fchmod %o FAILED with %d %s\n",
  4840         -                             buf.st_mode, code, strerror(code));
         5254  +                      cmode, code, strerror(code));
  4841   5255             } else {
  4842         -            fprintf(stderr, "fchmod %o SUCCEDED\n",buf.st_mode);
         5256  +              fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
  4843   5257             }
  4844   5258           }else{
  4845   5259             int code = errno;
  4846   5260             fprintf(stderr, "STAT FAILED[%d] with %d %s\n", 
  4847   5261                             err, code, strerror(code));
  4848   5262   #endif
  4849   5263           }
................................................................................
  4872   5286           pFile->h = fd;
  4873   5287         }else{
  4874   5288           rc=SQLITE_CANTOPEN; /* SQLITE_BUSY? proxyTakeConch called
  4875   5289                                  during locking */
  4876   5290         }
  4877   5291       }
  4878   5292       if( rc==SQLITE_OK && !pCtx->lockProxy ){
  4879         -      char *path = tLockPath ? tLockPath : pCtx->lockProxyPath;
  4880         -      /* ACS: Need to make a copy of path sometimes */
  4881         -      rc = proxyCreateUnixFile(path, &pCtx->lockProxy);
         5293  +        char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
         5294  +        rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
         5295  +        if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
         5296  +          /* we couldn't create the proxy lock file with the old lock file path
         5297  +           ** so try again via auto-naming 
         5298  +           */
         5299  +          forceNewLockPath = 1;
         5300  +          tryOldLockPath = 0;
         5301  +          continue; // go back to the do {} while start point, try again
         5302  +        }
         5303  +      }
         5304  +      if( rc==SQLITE_OK ){
         5305  +        /* Need to make a copy of path if we extracted the value
         5306  +         ** from the conch file or the path was allocated on the stack
         5307  +         */
         5308  +        if( tempLockPath ){
         5309  +          pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
         5310  +          if( !pCtx->lockProxyPath ){
         5311  +            rc = SQLITE_NOMEM;
         5312  +          }
         5313  +        }
  4882   5314       }
  4883   5315       if( rc==SQLITE_OK ){
  4884   5316         pCtx->conchHeld = 1;
  4885   5317   
  4886         -      if( tLockPath ){
  4887         -        pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath);
  4888   5318           if( pCtx->lockProxy->pMethod == &afpIoMethods ){
  4889         -          ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath =
  4890         -                     pCtx->lockProxyPath;
  4891         -        }
         5319  +          afpLockingContext *afpCtx;
         5320  +          afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
         5321  +          afpCtx->dbPath = pCtx->lockProxyPath;
  4892   5322         }
  4893   5323       } else {
  4894   5324         conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
  4895   5325       }
  4896   5326       OSTRACE3("TAKECONCH  %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
  4897   5327       return rc;
         5328  +    } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */
  4898   5329     }
  4899   5330   }
  4900   5331   
  4901   5332   /*
  4902   5333   ** If pFile holds a lock on a conch file, then release that lock.
  4903   5334   */
  4904   5335   static int proxyReleaseConch(unixFile *pFile){
................................................................................
  4907   5338     unixFile *conchFile;        /* Name of the conch file */
  4908   5339   
  4909   5340     pCtx = (proxyLockingContext *)pFile->lockingContext;
  4910   5341     conchFile = pCtx->conchFile;
  4911   5342     OSTRACE4("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
  4912   5343              (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), 
  4913   5344              getpid());
  4914         -  pCtx->conchHeld = 0;
         5345  +  if( pCtx->conchHeld>0 ){
  4915   5346     rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
         5347  +  }
         5348  +  pCtx->conchHeld = 0;
  4916   5349     OSTRACE3("RELEASECONCH  %d %s\n", conchFile->h,
  4917   5350              (rc==SQLITE_OK ? "ok" : "failed"));
  4918   5351     return rc;
  4919   5352   }
  4920   5353   
  4921   5354   /*
  4922   5355   ** Given the name of a database file, compute the name of its conch file.
................................................................................
  5004   5437   */
  5005   5438   static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
  5006   5439   #if defined(__APPLE__)
  5007   5440     if( pFile->pMethod == &afpIoMethods ){
  5008   5441       /* afp style keeps a reference to the db path in the filePath field 
  5009   5442       ** of the struct */
  5010   5443       assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
  5011         -    strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath);
         5444  +    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
  5012   5445     }else
  5013   5446   #endif
  5014   5447     if( pFile->pMethod == &dotlockIoMethods ){
  5015   5448       /* dot lock style uses the locking context to store the dot lock
  5016   5449       ** file path */
  5017   5450       int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
  5018   5451       memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
  5019   5452     }else{
  5020   5453       /* all other styles use the locking context to store the db file path */
  5021   5454       assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
  5022         -    strcpy(dbPath, (char *)pFile->lockingContext);
         5455  +    strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
  5023   5456     }
  5024   5457     return SQLITE_OK;
  5025   5458   }
  5026   5459   
  5027   5460   /*
  5028   5461   ** Takes an already filled in unix file and alters it so all file locking 
  5029   5462   ** will be performed on the local proxy lock file.  The following fields
................................................................................
  5055   5488     if( pCtx==0 ){
  5056   5489       return SQLITE_NOMEM;
  5057   5490     }
  5058   5491     memset(pCtx, 0, sizeof(*pCtx));
  5059   5492   
  5060   5493     rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
  5061   5494     if( rc==SQLITE_OK ){
  5062         -    rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile);
         5495  +    rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
         5496  +    if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
         5497  +      /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
         5498  +      ** (c) the file system is read-only, then enable no-locking access.
         5499  +      ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
         5500  +      ** that openFlags will have only one of O_RDONLY or O_RDWR.
         5501  +      */
         5502  +      struct statfs fsInfo;
         5503  +      struct stat conchInfo;
         5504  +      int goLockless = 0;
         5505  +
         5506  +      if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) {
         5507  +        int err = errno;
         5508  +        if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
         5509  +          goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
         5510  +        }
         5511  +      }
         5512  +      if( goLockless ){
         5513  +        pCtx->conchHeld = -1; /* read only FS/ lockless */
         5514  +        rc = SQLITE_OK;
         5515  +      }
         5516  +    }
  5063   5517     }  
  5064   5518     if( rc==SQLITE_OK && lockPath ){
  5065   5519       pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
  5066   5520     }
  5067   5521   
         5522  +  if( rc==SQLITE_OK ){
         5523  +    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
         5524  +    if( pCtx->dbPath==NULL ){
         5525  +      rc = SQLITE_NOMEM;
         5526  +    }
         5527  +  }
  5068   5528     if( rc==SQLITE_OK ){
  5069   5529       /* all memory is allocated, proxys are created and assigned, 
  5070   5530       ** switch the locking context and pMethod then return.
  5071   5531       */
  5072         -    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
  5073   5532       pCtx->oldLockingContext = pFile->lockingContext;
  5074   5533       pFile->lockingContext = pCtx;
  5075   5534       pCtx->pOldMethod = pFile->pMethod;
  5076   5535       pFile->pMethod = &proxyIoMethods;
  5077   5536     }else{
  5078   5537       if( pCtx->conchFile ){ 
  5079         -      rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
  5080         -      if( rc ) return rc;
         5538  +      pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
  5081   5539         sqlite3_free(pCtx->conchFile);
  5082   5540       }
         5541  +    sqlite3_free(pCtx->lockProxyPath);
  5083   5542       sqlite3_free(pCtx->conchFilePath); 
  5084   5543       sqlite3_free(pCtx);
  5085   5544     }
  5086   5545     OSTRACE3("TRANSPROXY  %d %s\n", pFile->h,
  5087   5546              (rc==SQLITE_OK ? "ok" : "failed"));
  5088   5547     return rc;
  5089   5548   }
................................................................................
  5164   5623   ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
  5165   5624   */
  5166   5625   static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
  5167   5626     unixFile *pFile = (unixFile*)id;
  5168   5627     int rc = proxyTakeConch(pFile);
  5169   5628     if( rc==SQLITE_OK ){
  5170   5629       proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
         5630  +    if( pCtx->conchHeld>0 ){
  5171   5631       unixFile *proxy = pCtx->lockProxy;
  5172   5632       return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
         5633  +    }else{ /* conchHeld < 0 is lockless */
         5634  +      pResOut=0;
         5635  +    }
  5173   5636     }
  5174   5637     return rc;
  5175   5638   }
  5176   5639   
  5177   5640   /*
  5178   5641   ** Lock the file with the lock specified by parameter locktype - one
  5179   5642   ** of the following:
................................................................................
  5199   5662   ** routine to lower a locking level.
  5200   5663   */
  5201   5664   static int proxyLock(sqlite3_file *id, int locktype) {
  5202   5665     unixFile *pFile = (unixFile*)id;
  5203   5666     int rc = proxyTakeConch(pFile);
  5204   5667     if( rc==SQLITE_OK ){
  5205   5668       proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
         5669  +    if( pCtx->conchHeld>0 ){
  5206   5670       unixFile *proxy = pCtx->lockProxy;
  5207   5671       rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype);
  5208   5672       pFile->locktype = proxy->locktype;
         5673  +    }else{
         5674  +      /* conchHeld < 0 is lockless */
         5675  +    }
  5209   5676     }
  5210   5677     return rc;
  5211   5678   }
  5212   5679   
  5213   5680   
  5214   5681   /*
  5215   5682   ** Lower the locking level on file descriptor pFile to locktype.  locktype
................................................................................
  5219   5686   ** the requested locking level, this routine is a no-op.
  5220   5687   */
  5221   5688   static int proxyUnlock(sqlite3_file *id, int locktype) {
  5222   5689     unixFile *pFile = (unixFile*)id;
  5223   5690     int rc = proxyTakeConch(pFile);
  5224   5691     if( rc==SQLITE_OK ){
  5225   5692       proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
         5693  +    if( pCtx->conchHeld>0 ){
  5226   5694       unixFile *proxy = pCtx->lockProxy;
  5227   5695       rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype);
  5228   5696       pFile->locktype = proxy->locktype;
         5697  +    }else{
         5698  +      /* conchHeld < 0 is lockless */
         5699  +    }
  5229   5700     }
  5230   5701     return rc;
  5231   5702   }
  5232   5703   
  5233   5704   /*
  5234   5705   ** Close a file that uses proxy locks.
  5235   5706   */
................................................................................
  5348   5819   #if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
  5349   5820       UNIXVFS("unix",          autolockIoFinder ),
  5350   5821   #else
  5351   5822       UNIXVFS("unix",          posixIoFinder ),
  5352   5823   #endif
  5353   5824       UNIXVFS("unix-none",     nolockIoFinder ),
  5354   5825       UNIXVFS("unix-dotfile",  dotlockIoFinder ),
  5355         -    UNIXVFS("unix-wfl",      posixWflIoFinder ),
  5356   5826   #if OS_VXWORKS
  5357   5827       UNIXVFS("unix-namedsem", semIoFinder ),
  5358   5828   #endif
  5359   5829   #if SQLITE_ENABLE_LOCKING_STYLE
  5360   5830       UNIXVFS("unix-posix",    posixIoFinder ),
  5361   5831   #if !OS_VXWORKS
  5362   5832       UNIXVFS("unix-flock",    flockIoFinder ),
  5363   5833   #endif
  5364   5834   #endif
  5365   5835   #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  5366   5836       UNIXVFS("unix-afp",      afpIoFinder ),
         5837  +    UNIXVFS("unix-nfs",      nfsIoFinder ),
  5367   5838       UNIXVFS("unix-proxy",    proxyIoFinder ),
  5368   5839   #endif
  5369   5840     };
  5370   5841     unsigned int i;          /* Loop counter */
  5371   5842   
  5372   5843     /* Register all VFSes defined in the aVfs[] array */
  5373   5844     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){

Changes to src/pragma.c.

   140    140     return SQLITE_OK;
   141    141   }
   142    142   #endif /* SQLITE_PAGER_PRAGMAS */
   143    143   
   144    144   /*
   145    145   ** Generate code to return a single integer value.
   146    146   */
   147         -static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
          147  +static void returnSingleInt(Parse *pParse, const char *zLabel, i64 *pValue){
   148    148     Vdbe *v = sqlite3GetVdbe(pParse);
   149    149     int mem = ++pParse->nMem;
   150         -  i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
          150  +  i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(*pValue));
   151    151     if( pI64 ){
   152         -    memcpy(pI64, &value, sizeof(value));
          152  +    memcpy(pI64, pValue, sizeof(*pValue));
   153    153     }
   154    154     sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
   155    155     sqlite3VdbeSetNumCols(v, 1);
   156    156     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
   157    157     sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
   158    158   }
   159    159   
................................................................................
   204    204       if( sqlite3StrICmp(zLeft, p->zName)==0 ){
   205    205         sqlite3 *db = pParse->db;
   206    206         Vdbe *v;
   207    207         v = sqlite3GetVdbe(pParse);
   208    208         assert( v!=0 );  /* Already allocated by sqlite3Pragma() */
   209    209         if( ALWAYS(v) ){
   210    210           if( zRight==0 ){
   211         -          returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
          211  +          i64 value = ((db->flags & p->mask)!=0 ? 1 : 0);
          212  +          returnSingleInt(pParse, p->zName, &value);
   212    213           }else{
   213    214             int mask = p->mask;          /* Mask of bits to set or clear. */
   214    215             if( db->autoCommit==0 ){
   215    216               /* Foreign key support may not be enabled or disabled while not
   216    217               ** in auto-commit mode.  */
   217    218               mask &= ~(SQLITE_ForeignKeys);
   218    219             }
................................................................................
   379    380     ** database page size value.  The value can only be set if
   380    381     ** the database has not yet been created.
   381    382     */
   382    383     if( sqlite3StrICmp(zLeft,"page_size")==0 ){
   383    384       Btree *pBt = pDb->pBt;
   384    385       assert( pBt!=0 );
   385    386       if( !zRight ){
   386         -      int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
   387         -      returnSingleInt(pParse, "page_size", size);
          387  +      i64 size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
          388  +      returnSingleInt(pParse, "page_size", &size);
   388    389       }else{
   389    390         /* Malloc may fail when setting the page-size, as there is an internal
   390    391         ** buffer that the pager module resizes using sqlite3_realloc().
   391    392         */
   392    393         db->nextPagesize = atoi(zRight);
   393    394         if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
   394    395           db->mallocFailed = 1;
................................................................................
   403    404     ** The first form reports the current setting for the
   404    405     ** maximum number of pages in the database file.  The 
   405    406     ** second form attempts to change this setting.  Both
   406    407     ** forms return the current setting.
   407    408     */
   408    409     if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){
   409    410       Btree *pBt = pDb->pBt;
   410         -    int newMax = 0;
          411  +    i64 newMax = 0;
   411    412       assert( pBt!=0 );
   412    413       if( zRight ){
   413    414         newMax = atoi(zRight);
   414    415       }
   415    416       if( ALWAYS(pBt) ){
   416    417         newMax = sqlite3BtreeMaxPageCount(pBt, newMax);
   417    418       }
   418         -    returnSingleInt(pParse, "max_page_count", newMax);
          419  +    returnSingleInt(pParse, "max_page_count", &newMax);
   419    420     }else
   420    421   
   421    422     /*
   422    423     **  PRAGMA [database.]page_count
   423    424     **
   424    425     ** Return the number of pages in the specified database.
   425    426     */
................................................................................
   552    553       Pager *pPager = sqlite3BtreePager(pDb->pBt);
   553    554       i64 iLimit = -2;
   554    555       if( zRight ){
   555    556         sqlite3Atoi64(zRight, &iLimit);
   556    557         if( iLimit<-1 ) iLimit = -1;
   557    558       }
   558    559       iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
   559         -    returnSingleInt(pParse, "journal_size_limit", iLimit);
          560  +    returnSingleInt(pParse, "journal_size_limit", &iLimit);
   560    561     }else
   561    562   
   562    563   #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
   563    564   
   564    565     /*
   565    566     **  PRAGMA [database.]auto_vacuum
   566    567     **  PRAGMA [database.]auto_vacuum=N
................................................................................
   572    573     if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
   573    574       Btree *pBt = pDb->pBt;
   574    575       assert( pBt!=0 );
   575    576       if( sqlite3ReadSchema(pParse) ){
   576    577         goto pragma_out;
   577    578       }
   578    579       if( !zRight ){
   579         -      int auto_vacuum;
          580  +      i64 auto_vacuum;
   580    581         if( ALWAYS(pBt) ){
   581    582            auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
   582    583         }else{
   583    584            auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
   584    585         }
   585         -      returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
          586  +      returnSingleInt(pParse, "auto_vacuum", &auto_vacuum);
   586    587       }else{
   587    588         int eAuto = getAutoVacuum(zRight);
   588    589         assert( eAuto>=0 && eAuto<=2 );
   589    590         db->nextAutovac = (u8)eAuto;
   590    591         if( ALWAYS(eAuto>=0) ){
   591    592           /* Call SetAutoVacuum() to set initialize the internal auto and
   592    593           ** incr-vacuum flags. This is required in case this connection
................................................................................
   660    661     ** cache size stored on the disk so the cache size will revert
   661    662     ** to its default value when the database is closed and reopened.
   662    663     ** N should be a positive integer.
   663    664     */
   664    665     if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
   665    666       if( sqlite3ReadSchema(pParse) ) goto pragma_out;
   666    667       if( !zRight ){
   667         -      returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
          668  +      i64 cacheSize = pDb->pSchema->cache_size;
          669  +      returnSingleInt(pParse, "cache_size", &cacheSize);
   668    670       }else{
   669    671         int size = atoi(zRight);
   670    672         if( size<0 ) size = -size;
   671    673         pDb->pSchema->cache_size = size;
   672    674         sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
   673    675       }
   674    676     }else
................................................................................
   682    684     ** value will be restored the next time the database is opened.
   683    685     **
   684    686     ** Note that it is possible for the library compile-time options to
   685    687     ** override this setting
   686    688     */
   687    689     if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
   688    690       if( !zRight ){
   689         -      returnSingleInt(pParse, "temp_store", db->temp_store);
          691  +      i64 tempStore = db->temp_store;
          692  +      returnSingleInt(pParse, "temp_store", &tempStore);
   690    693       }else{
   691    694         changeTempStorage(pParse, zRight);
   692    695       }
   693    696     }else
   694    697   
   695    698     /*
   696    699     **   PRAGMA temp_store_directory
................................................................................
   796    799     ** the local value does not make changes to the disk file and the
   797    800     ** default value will be restored the next time the database is
   798    801     ** opened.
   799    802     */
   800    803     if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
   801    804       if( sqlite3ReadSchema(pParse) ) goto pragma_out;
   802    805       if( !zRight ){
   803         -      returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
          806  +      i64 safetyLevel = pDb->safety_level-1;
          807  +      returnSingleInt(pParse, "synchronous", &safetyLevel);
   804    808       }else{
   805    809         if( !db->autoCommit ){
   806    810           sqlite3ErrorMsg(pParse, 
   807    811               "Safety level may not be changed inside a transaction");
   808    812         }else{
   809    813           pDb->safety_level = getSafetyLevel(zRight)+1;
   810    814         }

Changes to src/prepare.c.

    12     12   ** This file contains the implementation of the sqlite3_prepare()
    13     13   ** interface, and routines that contribute to loading the database schema
    14     14   ** from disk.
    15     15   **
    16     16   ** $Id: prepare.c,v 1.131 2009/08/06 17:43:31 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
           19  +#ifdef SQLITE_ENABLE_SQLRR
           20  +# include "sqlrr.h"
           21  +#endif
    19     22   
    20     23   /*
    21     24   ** Fill the InitData structure with an error message that indicates
    22     25   ** that the database is corrupt.
    23     26   */
    24     27   static void corruptSchema(
    25     28     InitData *pData,     /* Initialization context */
................................................................................
   770    773     const char *zSql,         /* UTF-8 encoded SQL statement. */
   771    774     int nBytes,               /* Length of zSql in bytes. */
   772    775     sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   773    776     const char **pzTail       /* OUT: End of parsed string */
   774    777   ){
   775    778     int rc;
   776    779     rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail);
          780  +#ifdef SQLITE_ENABLE_SQLRR
          781  +  SRRecPrepare(db, zSql, nBytes, 0, *ppStmt);
          782  +#endif
   777    783     assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );  /* VERIFY: F13021 */
   778    784     return rc;
   779    785   }
   780    786   int sqlite3_prepare_v2(
   781    787     sqlite3 *db,              /* Database handle. */
   782    788     const char *zSql,         /* UTF-8 encoded SQL statement. */
   783    789     int nBytes,               /* Length of zSql in bytes. */
   784    790     sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   785    791     const char **pzTail       /* OUT: End of parsed string */
   786    792   ){
   787    793     int rc;
   788    794     rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail);
          795  +#ifdef SQLITE_ENABLE_SQLRR
          796  +  SRRecPrepare(db, zSql, nBytes, 1, *ppStmt);
          797  +#endif
   789    798     assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );  /* VERIFY: F13021 */
   790    799     return rc;
   791    800   }
   792    801   
   793    802   
   794    803   #ifndef SQLITE_OMIT_UTF16
   795    804   /*
................................................................................
   817    826       return SQLITE_MISUSE;
   818    827     }
   819    828     sqlite3_mutex_enter(db->mutex);
   820    829     zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
   821    830     if( zSql8 ){
   822    831       rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
   823    832     }
   824         -
          833  +#ifdef SQLITE_ENABLE_SQLRR
          834  +  SRRecPrepare(db, zSql8, -1, 1, *ppStmt);
          835  +#endif
   825    836     if( zTail8 && pzTail ){
   826    837       /* If sqlite3_prepare returns a tail pointer, we calculate the
   827    838       ** equivalent pointer into the UTF-16 string by counting the unicode
   828    839       ** characters between zSql8 and zTail8, and then returning a pointer
   829    840       ** the same number of characters into the UTF-16 string.
   830    841       */
   831    842       int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));

Changes to src/sqlite.h.in.

   411    411   ** [sqlite3_vfs] object.
   412    412   */
   413    413   #define SQLITE_OPEN_READONLY         0x00000001  /* Ok for sqlite3_open_v2() */
   414    414   #define SQLITE_OPEN_READWRITE        0x00000002  /* Ok for sqlite3_open_v2() */
   415    415   #define SQLITE_OPEN_CREATE           0x00000004  /* Ok for sqlite3_open_v2() */
   416    416   #define SQLITE_OPEN_DELETEONCLOSE    0x00000008  /* VFS only */
   417    417   #define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
          418  +#define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
   418    419   #define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
   419    420   #define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
   420    421   #define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
   421    422   #define SQLITE_OPEN_MAIN_JOURNAL     0x00000800  /* VFS only */
   422    423   #define SQLITE_OPEN_TEMP_JOURNAL     0x00001000  /* VFS only */
   423    424   #define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
   424    425   #define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */

Changes to src/test1.c.

  3124   3124     sqlite3_stmt *pStmt;
  3125   3125   
  3126   3126     if( objc!=2 ){
  3127   3127       Tcl_WrongNumArgs(interp, 1, objv, "STMT");
  3128   3128       return TCL_ERROR;
  3129   3129     }
  3130   3130     if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
         3131  +  sqlite3_clear_bindings(0); /* test for handling NULL <rdar://problem/6646331> */
  3131   3132     Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
  3132   3133     return TCL_OK;
  3133   3134   }
  3134   3135   
  3135   3136   /*
  3136   3137   ** Usage:   sqlite3_sleep MILLISECONDS
  3137   3138   */

Changes to src/test_backup.c.

    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** $Id: test_backup.c,v 1.3 2009/03/30 12:56:52 drh Exp $
    14     14   */
    15     15   
    16     16   #include "tcl.h"
    17         -#include <sqlite3.h>
           17  +#include "sqlite3.h"
    18     18   #include <assert.h>
    19     19   
    20     20   /* These functions are implemented in test1.c. */
    21     21   int getDbPointer(Tcl_Interp *, const char *, sqlite3 **);
    22     22   const char *sqlite3TestErrorName(int);
    23     23   
    24     24   static int backupTestCmd(

Changes to src/vdbeapi.c.

    13     13   ** This file contains code use to implement APIs that are part of the
    14     14   ** VDBE.
    15     15   **
    16     16   ** $Id: vdbeapi.c,v 1.167 2009/06/25 01:47:12 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "vdbeInt.h"
           20  +#ifdef SQLITE_ENABLE_SQLRR
           21  +# include "sqlrr.h"
           22  +#endif 
    20     23   
    21     24   #ifndef SQLITE_OMIT_DEPRECATED
    22     25   /*
    23     26   ** Return TRUE (non-zero) of the statement supplied as an argument needs
    24     27   ** to be recompiled.  A statement needs to be recompiled whenever the
    25     28   ** execution environment changes in a way that would alter the program
    26     29   ** that sqlite3_prepare() generates.  For example, if new functions or
................................................................................
    44     47   */
    45     48   int sqlite3_finalize(sqlite3_stmt *pStmt){
    46     49     int rc;
    47     50     if( pStmt==0 ){
    48     51       rc = SQLITE_OK;
    49     52     }else{
    50     53       Vdbe *v = (Vdbe*)pStmt;
           54  +#ifdef SQLITE_ENABLE_SQLRR
           55  +    SRRecFinalize(pStmt);
           56  +#endif
    51     57       sqlite3 *db = v->db;
    52     58   #if SQLITE_THREADSAFE
    53     59       sqlite3_mutex *mutex = v->db->mutex;
    54     60   #endif
    55     61       sqlite3_mutex_enter(mutex);
    56     62       rc = sqlite3VdbeFinalize(v);
    57     63       rc = sqlite3ApiExit(db, rc);
................................................................................
    70     76   */
    71     77   int sqlite3_reset(sqlite3_stmt *pStmt){
    72     78     int rc;
    73     79     if( pStmt==0 ){
    74     80       rc = SQLITE_OK;
    75     81     }else{
    76     82       Vdbe *v = (Vdbe*)pStmt;
           83  +#ifdef SQLITE_ENABLE_SQLRR
           84  +    SRRecReset(pStmt);
           85  +#endif
    77     86       sqlite3_mutex_enter(v->db->mutex);
    78     87       rc = sqlite3VdbeReset(v);
    79     88       sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
    80     89       assert( (rc & (v->db->errMask))==rc );
    81     90       rc = sqlite3ApiExit(v->db, rc);
    82     91       sqlite3_mutex_leave(v->db->mutex);
    83     92     }
................................................................................
    88     97   ** Set all the parameters in the compiled SQL statement to NULL.
    89     98   */
    90     99   int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
    91    100     int i;
    92    101     int rc = SQLITE_OK;
    93    102     Vdbe *p = (Vdbe*)pStmt;
    94    103   #if SQLITE_THREADSAFE
    95         -  sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
          104  +  sqlite3_mutex *mutex=NULL;
          105  +#endif
          106  +  if( NULL==pStmt ){ return SQLITE_OK; } /* <rdar://problem/6646331> */
          107  +#ifdef SQLITE_ENABLE_SQLRR
          108  +  SRRecClearBindings(pStmt);  
          109  +#endif
          110  +#if SQLITE_THREADSAFE
          111  +  mutex = ((Vdbe*)pStmt)->db->mutex;
    96    112   #endif
    97    113     sqlite3_mutex_enter(mutex);
    98    114     for(i=0; i<p->nVar; i++){
    99    115       sqlite3VdbeMemRelease(&p->aVar[i]);
   100    116       p->aVar[i].flags = MEM_Null;
   101    117     }
   102    118     if( p->isPrepareV2 && p->expmask ){
................................................................................
   400    416   */
   401    417   int sqlite3_step(sqlite3_stmt *pStmt){
   402    418     int rc = SQLITE_MISUSE;
   403    419     if( pStmt ){
   404    420       int cnt = 0;
   405    421       Vdbe *v = (Vdbe*)pStmt;
   406    422       sqlite3 *db = v->db;
          423  +#ifdef SQLITE_ENABLE_SQLRR
          424  +    SRRecStep(pStmt);
          425  +#endif
          426  +    
   407    427       sqlite3_mutex_enter(db->mutex);
   408    428       while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
   409    429              && cnt++ < 5
   410    430              && (rc = sqlite3Reprepare(v))==SQLITE_OK ){
   411    431         sqlite3_reset(pStmt);
   412    432         v->expired = 0;
   413    433       }
................................................................................
   427    447         } else {
   428    448           v->zErrMsg = 0;
   429    449           v->rc = SQLITE_NOMEM;
   430    450         }
   431    451       }
   432    452       rc = sqlite3ApiExit(db, rc);
   433    453       sqlite3_mutex_leave(db->mutex);
          454  +#ifdef SQLITE_ENABLE_SQLRR
          455  +    SRRecStepEnd(pStmt);
          456  +#endif
   434    457     }
   435    458     return rc;
   436    459   }
   437    460   
   438    461   /*
   439    462   ** Extract the user data from a sqlite3_context structure and return a
   440    463   ** pointer to it.
................................................................................
   967    990   int sqlite3_bind_blob(
   968    991     sqlite3_stmt *pStmt, 
   969    992     int i, 
   970    993     const void *zData, 
   971    994     int nData, 
   972    995     void (*xDel)(void*)
   973    996   ){
          997  +#ifdef SQLITE_ENABLE_SQLRR
          998  +  SRRecBindBlob(pStmt, i, zData, nData);
          999  +#endif
   974   1000     return bindText(pStmt, i, zData, nData, xDel, 0);
   975   1001   }
   976   1002   int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
   977   1003     int rc;
   978   1004     Vdbe *p = (Vdbe *)pStmt;
         1005  +#ifdef SQLITE_ENABLE_SQLRR
         1006  +  SRRecBindDouble(pStmt, i, rValue);
         1007  +#endif
   979   1008     rc = vdbeUnbind(p, i);
   980   1009     if( rc==SQLITE_OK ){
   981   1010       sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
   982   1011       sqlite3_mutex_leave(p->db->mutex);
   983   1012     }
   984   1013     return rc;
   985   1014   }
   986   1015   int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
         1016  +#ifdef SQLITE_ENABLE_SQLRR
         1017  +  SRRecBindInt64(p, i, (i64)iValue);
         1018  +#endif
   987   1019     return sqlite3_bind_int64(p, i, (i64)iValue);
   988   1020   }
   989   1021   int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
   990   1022     int rc;
   991   1023     Vdbe *p = (Vdbe *)pStmt;
         1024  +#ifdef SQLITE_ENABLE_SQLRR
         1025  +  SRRecBindInt64(pStmt, i, iValue);
         1026  +#endif
   992   1027     rc = vdbeUnbind(p, i);
   993   1028     if( rc==SQLITE_OK ){
   994   1029       sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
   995   1030       sqlite3_mutex_leave(p->db->mutex);
   996   1031     }
   997   1032     return rc;
   998   1033   }
   999   1034   int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  1000   1035     int rc;
  1001   1036     Vdbe *p = (Vdbe*)pStmt;
         1037  +#ifdef SQLITE_ENABLE_SQLRR
         1038  +  SRRecBindNull(pStmt, i);
         1039  +#endif
  1002   1040     rc = vdbeUnbind(p, i);
  1003   1041     if( rc==SQLITE_OK ){
  1004   1042       sqlite3_mutex_leave(p->db->mutex);
  1005   1043     }
  1006   1044     return rc;
  1007   1045   }
  1008   1046   int sqlite3_bind_text( 
  1009   1047     sqlite3_stmt *pStmt, 
  1010   1048     int i, 
  1011   1049     const char *zData, 
  1012   1050     int nData, 
  1013   1051     void (*xDel)(void*)
  1014   1052   ){
         1053  +#ifdef SQLITE_ENABLE_SQLRR
         1054  +  SRRecBindText(pStmt, i, zData, nData);
         1055  +#endif
  1015   1056     return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
  1016   1057   }
  1017   1058   #ifndef SQLITE_OMIT_UTF16
  1018   1059   int sqlite3_bind_text16(
  1019   1060     sqlite3_stmt *pStmt, 
  1020   1061     int i, 
  1021   1062     const void *zData, 
  1022   1063     int nData, 
  1023   1064     void (*xDel)(void*)
  1024   1065   ){
         1066  +#ifdef SQLITE_ENABLE_SQLRR
         1067  +  SRRecBindText(pStmt, i, zData, nData);
         1068  +#endif
  1025   1069     return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
  1026   1070   }
  1027   1071   #endif /* SQLITE_OMIT_UTF16 */
  1028   1072   int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
  1029   1073     int rc;
  1030   1074     switch( pValue->type ){
  1031   1075       case SQLITE_INTEGER: {
................................................................................
  1041   1085           rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
  1042   1086         }else{
  1043   1087           rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
  1044   1088         }
  1045   1089         break;
  1046   1090       }
  1047   1091       case SQLITE_TEXT: {
         1092  +#ifdef SQLITE_ENABLE_SQLRR
         1093  +      SRRecBindText(pStmt, i, zData, nData);
         1094  +#endif
  1048   1095         rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE_TRANSIENT,
  1049   1096                                 pValue->enc);
  1050   1097         break;
  1051   1098       }
  1052   1099       default: {
  1053   1100         rc = sqlite3_bind_null(pStmt, i);
  1054   1101         break;
................................................................................
  1055   1102       }
  1056   1103     }
  1057   1104     return rc;
  1058   1105   }
  1059   1106   int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  1060   1107     int rc;
  1061   1108     Vdbe *p = (Vdbe *)pStmt;
         1109  +#ifdef SQLITE_ENABLE_SQLRR
         1110  +  SRRecBindBlob(pStmt, i, NULL, n);
         1111  +#endif
  1062   1112     rc = vdbeUnbind(p, i);
  1063   1113     if( rc==SQLITE_OK ){
  1064   1114       sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
  1065   1115       sqlite3_mutex_leave(p->db->mutex);
  1066   1116     }
  1067   1117     return rc;
  1068   1118   }

Changes to test/attach.test.

   710    710   #
   711    711   do_test attach-6.1 {
   712    712     catchsql {
   713    713       ATTACH DATABASE 'no-such-file' AS nosuch;
   714    714     }
   715    715   } {0 {}}
   716    716   if {$tcl_platform(platform)=="unix"} {
   717         -  do_test attach-6.2 {
   718    717       sqlite3 dbx cannot-read
   719    718       dbx eval {CREATE TABLE t1(a,b,c)}
   720    719       dbx close
   721    720       file attributes cannot-read -permission 0000
   722    721       if {[file writable cannot-read]} {
   723         -      puts "\n**** Tests do not work when run as root ****"
          722  +    #puts "\n**** Tests do not work when run as root ****"
   724    723         file delete -force cannot-read
   725         -      exit 1
   726         -    }
          724  +    #exit 1
          725  +  } else {
          726  +    do_test attach-6.2 {
   727    727       catchsql {
   728    728         ATTACH DATABASE 'cannot-read' AS noread;
   729    729       }
   730    730     } {1 {unable to open database: cannot-read}}
   731    731     do_test attach-6.2.2 {
   732    732       db errorcode
   733    733     } {14}
          734  +  }
   734    735     file delete -force cannot-read
   735    736   }
   736    737   
   737    738   # Check the error message if we try to access a database that has
   738    739   # not been attached.
   739    740   do_test attach-6.3 {
   740    741     catchsql {

Added test/lock_proxy.test.

            1  +# 2008 June 28
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script is database proxy locks.
           13  +#
           14  +# $Id$
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +
           19  +# This file is only run if using the unix backend compiled with the
           20  +# SQLITE_ENABLE_LOCKING_STYLE macro.
           21  +db close
           22  +if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
           23  +  finish_test
           24  +  return
           25  +}
           26  +db close
           27  +file delete -force test.db.lock
           28  +
           29  +ifcapable lock_proxy_pragmas {
           30  +  set ::using_proxy 0
           31  +  foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
           32  +    set ::using_proxy $value
           33  +  }
           34  +  # Disable the proxy locking for these tests
           35  +  set env(SQLITE_FORCE_PROXY_LOCKING) "0"
           36  +}
           37  +
           38  +
           39  +#####################################################################
           40  +
           41  +# test proxy locking readonly file system handling
           42  +#
           43  +ifcapable lock_proxy_pragmas {
           44  +  if {[file exists /usr/bin/hdiutil]} {
           45  +
           46  +    puts "Creating readonly file system for proxy locking tests..."
           47  +    if {[file exists /Volumes/readonly]} {
           48  +      exec hdiutil detach /Volumes/readonly
           49  +    }
           50  +    if {[file exists readonly.dmg]} {
           51  +      file delete readonly.dmg
           52  +    }
           53  +    exec hdiutil create -megabytes 1 -fs HFS+ readonly.dmg -volname readonly
           54  +    exec hdiutil attach readonly.dmg
           55  +    set sqlite_hostid_num 4
           56  +    set env(SQLITE_FORCE_PROXY_LOCKING) "1"
           57  +
           58  +    sqlite3 db2 /Volumes/readonly/test1.db 
           59  +    execsql {
           60  +      create table x(y);
           61  +    } db2
           62  +    db2 close
           63  +
           64  +    set sqlite_hostid_num 5
           65  +    sqlite3 db2 /Volumes/readonly/test2.db 
           66  +    execsql {
           67  +      create table x(y);
           68  +    } db2
           69  +    db2 close
           70  +
           71  +    set env(SQLITE_FORCE_PROXY_LOCKING) "0"
           72  +    sqlite3 db2 /Volumes/readonly/test3.db 
           73  +    execsql {
           74  +      create table x(y);
           75  +    } db2
           76  +    db2 close
           77  +    set env(SQLITE_FORCE_PROXY_LOCKING) "1"
           78  +    exec hdiutil detach /Volumes/readonly
           79  +    exec hdiutil attach -readonly readonly.dmg
           80  +
           81  +    do_test lock_proxy2.0 {
           82  +      sqlite3 db2 /Volumes/readonly/test1.db
           83  +      catchsql {
           84  +        select * from sqlite_master;
           85  +      } db2
           86  +    } {1 {database is locked}}
           87  +    catch { db2 close }
           88  +    
           89  +    do_test lock_proxy2.1 {
           90  +      sqlite3 db2 /Volumes/readonly/test2.db
           91  +      catchsql {
           92  +        select * from sqlite_master;
           93  +      } db2
           94  +    } {0 {table x x 2 {CREATE TABLE x(y)}}}
           95  +    catch { db2 close }
           96  +
           97  +    do_test lock_proxy2.2 {
           98  +      sqlite3 db2 /Volumes/readonly/test3.db
           99  +      catchsql {
          100  +        select * from sqlite_master;
          101  +      } db2
          102  +    } {0 {table x x 2 {CREATE TABLE x(y)}}}
          103  +    catch { db2 close }
          104  +
          105  +    exec hdiutil detach /Volumes/readonly
          106  +    file delete readonly.dmg
          107  +  }
          108  +  set env(SQLITE_FORCE_PROXY_LOCKING) "0"
          109  +  set sqlite_hostid_num 0
          110  +}
          111  +
          112  +#####################################################################
          113  +
          114  +file delete -force test.db
          115  +
          116  +ifcapable lock_proxy_pragmas {
          117  +  set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
          118  +}
          119  +
          120  +finish_test

Changes to test/main.test.

   289    289     if {$v} {lappend v $msg} {lappend v {}}
   290    290   } {0 {}}
   291    291   
   292    292   # Here are some tests for tokenize.c.  
   293    293   #
   294    294   do_test main-3.1 {
   295    295     catch {db close}
   296         -  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
          296  +  catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
   297    297     file delete -force testdb
   298    298     sqlite3 db testdb
   299    299     set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
   300    300     lappend v $msg
   301    301   } {1 {unrecognized token: "!!"}}
   302    302   do_test main-3.2 {
   303    303     catch {db close}
   304         -  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
          304  +  catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
   305    305     file delete -force testdb
   306    306     sqlite3 db testdb
   307    307     set v [catch {execsql {SELECT * from T1 where ^x}} msg]
   308    308     lappend v $msg
   309    309   } {1 {unrecognized token: "^"}}
   310    310   do_test main-3.2.2 {
   311    311     catchsql {select 'abc}
................................................................................
   417    417   do_test main-3.2.30 {
   418    418     catchsql {select 123--5}
   419    419   } {0 123}
   420    420   
   421    421   
   422    422   do_test main-3.3 {
   423    423     catch {db close}
   424         -  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
          424  +  catch {foreach f [glob -nocomplain testdb/*] {file delete -force $f}}
   425    425     file delete -force testdb
   426    426     sqlite3 db testdb
   427    427     execsql {
   428    428       create table T1(X REAL);  /* C-style comments allowed */
   429    429       insert into T1 values(0.5);
   430    430       insert into T1 values(0.5e2);
   431    431       insert into T1 values(0.5e-002);

Changes to test/malloc_common.tcl.

    74     74         # fails and then subsequent calls succeed. If $::iRepeat is 1, 
    75     75         # then the failure is persistent - once malloc() fails it keeps
    76     76         # failing.
    77     77         #
    78     78         set zRepeat "transient"
    79     79         if {$::iRepeat} {set zRepeat "persistent"}
    80     80         restore_prng_state
    81         -      foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}
           81  +      catch {foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}}
    82     82   
    83     83         do_test ${tn}.${zRepeat}.${::n} {
    84     84     
    85     85           # Remove all traces of database files test.db and test2.db 
    86     86           # from the file-system. Then open (empty database) "test.db" 
    87     87           # with the handle [db].
    88     88           # 

Changes to test/memdb.test.

   409    409       DELETE FROM t1;
   410    410       SELECT count(*) FROM t1;
   411    411     }
   412    412   } 0
   413    413   
   414    414   # Test that auto-vacuum works with in-memory databases.
   415    415   # 
          416  +set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
          417  +if {[lindex $msize 2]!=0} {
   416    418   ifcapable autovacuum {
   417    419     do_test memdb-9.1 {
   418    420       db close
   419    421       sqlite3 db test.db
   420    422       db cache size 0
   421    423       execsql {
   422    424         PRAGMA auto_vacuum = full;
................................................................................
   428    430       set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
   429    431       set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1]
   430    432       execsql { DELETE FROM t1 }
   431    433       set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
   432    434       expr {($memused2 + 2048 < $memused) || $pgovfl==0}
   433    435     } {1}
   434    436   }
          437  +}
   435    438   
   436    439   } ;# ifcapable memorydb
   437    440   
   438    441   finish_test

Changes to test/memsubsys1.test.

   178    178   sqlite3_initialize
   179    179   reset_highwater_marks
   180    180   build_test_db memsubsys1-5 {PRAGMA page_size=4096}
   181    181   #show_memstats
   182    182   do_test memsubsys1-5.3 {
   183    183     set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
   184    184   } 23
          185  +set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
          186  +if {[lindex $msize 2]!=0} {
   185    187   do_test memsubsys1-5.4 {
   186    188     set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
   187    189     expr {$maxreq>4096}
   188    190   } 1
   189    191   do_test memsubsys1-5.5 {
   190    192     set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
   191    193   } 0
   192    194   do_test memsubsys1-5.6 {
   193    195     set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
   194    196     expr {$s_ovfl>6000}
   195    197   } 1
          198  +}
   196    199   
   197    200   # Test 6:  Activate both PAGECACHE and SCRATCH with a 4k page size.
   198    201   # Make it so that SCRATCH is large enough
   199    202   #
   200    203   db close
   201    204   sqlite3_shutdown
   202    205   sqlite3_config_pagecache [expr 4096+$xtra_size] 24
................................................................................
   204    207   sqlite3_initialize
   205    208   reset_highwater_marks
   206    209   build_test_db memsubsys1-6 {PRAGMA page_size=4096}
   207    210   #show_memstats
   208    211   do_test memsubsys1-6.3 {
   209    212     set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
   210    213   } 23
          214  +set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
          215  +if {[lindex $msize 2]!=0} {
   211    216   do_test memsubsys1-6.4 {
   212    217     set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
   213    218     expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)}
   214    219   } 1
          220  +}
   215    221   do_test memsubsys1-6.5 {
   216    222     set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
   217    223   } 1
   218    224   do_test memsubsys1-6.6 {
   219    225     set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
   220    226   } 0
   221    227   
................................................................................
   264    270   reset_highwater_marks
   265    271   do_test memsubsys1-8.1 {
   266    272     set pg_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
   267    273   } 0
   268    274   do_test memsubsys1-8.2 {
   269    275     set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
   270    276   } 0
          277  +if {[lindex $msize 2]!=0} {
   271    278   do_test memsubsys1-8.3 {
   272    279     sqlite3 db :memory:
   273    280     db eval {
   274    281       CREATE TABLE t1(x);
   275    282       INSERT INTO t1 VALUES(zeroblob(400));
   276    283       INSERT INTO t1 VALUES(zeroblob(400));
   277    284       INSERT INTO t1 SELECT * FROM t1;
   278    285       INSERT INTO t1 SELECT * FROM t1;
   279    286       INSERT INTO t1 SELECT * FROM t1;
   280    287     }
   281    288     expr {[lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]>0}
   282    289   } 1
   283    290   db close
          291  +}
   284    292   sqlite3_shutdown
   285    293   sqlite3_config_memstatus 0
   286    294   sqlite3_initialize
   287    295   do_test memsubsys1-8.4 {
   288    296     sqlite3 db :memory:
   289    297     db eval {
   290    298       CREATE TABLE t1(x);

Changes to test/pragma.test.

  1294   1294   
  1295   1295     # Test the lock_proxy_file pragmas.
  1296   1296     #
  1297   1297     db close
  1298   1298     set env(SQLITE_FORCE_PROXY_LOCKING) "0"
  1299   1299   
  1300   1300     sqlite3 db test.db
         1301  +  # set lock proxy name and then query it via pragma interface
  1301   1302     do_test pragma-16.1 {
  1302   1303       execsql {
  1303   1304         PRAGMA lock_proxy_file="mylittleproxy";
  1304   1305         select * from sqlite_master;
  1305   1306       }
  1306   1307       execsql {
  1307   1308         PRAGMA lock_proxy_file;
  1308   1309       } 
  1309   1310     } {mylittleproxy}
  1310   1311   
         1312  +  # 2 database connections can share a lock proxy file
  1311   1313     do_test pragma-16.2 {
  1312   1314       sqlite3 db2 test.db
  1313   1315       execsql {
  1314   1316         PRAGMA lock_proxy_file="mylittleproxy";
  1315   1317       } db2
  1316   1318     } {}
  1317   1319   
  1318   1320     db2 close
         1321  +  # 2nd database connection should auto-name an existing lock proxy file
  1319   1322     do_test pragma-16.2.1 {
  1320   1323       sqlite3 db2 test.db
  1321   1324       execsql {
  1322   1325         PRAGMA lock_proxy_file=":auto:";
  1323   1326         select * from sqlite_master;
  1324   1327       } db2
  1325   1328       execsql {
  1326   1329         PRAGMA lock_proxy_file;
  1327   1330       } db2
  1328   1331     } {mylittleproxy}
  1329   1332   
  1330   1333     db2 close
         1334  +  # 2nd database connection cannot override the lock proxy file
  1331   1335     do_test pragma-16.3 {
  1332   1336       sqlite3 db2 test.db
  1333   1337       execsql {
  1334   1338         PRAGMA lock_proxy_file="myotherproxy";
  1335   1339       } db2
  1336   1340       catchsql {
  1337   1341         select * from sqlite_master;
  1338   1342       } db2
  1339   1343     } {1 {database is locked}}
  1340   1344   
         1345  +  # lock proxy file can be renamed if no other connections are active
  1341   1346     do_test pragma-16.4 {
  1342   1347       db2 close
  1343   1348       db close
  1344   1349       sqlite3 db2 test.db
  1345   1350       execsql {
  1346   1351         PRAGMA lock_proxy_file="myoriginalproxy";
  1347   1352         PRAGMA lock_proxy_file="myotherproxy";
  1348   1353         PRAGMA lock_proxy_file;
  1349   1354       } db2
  1350   1355     } {myotherproxy}
  1351   1356   
  1352   1357     db2 close
  1353   1358     set env(SQLITE_FORCE_PROXY_LOCKING) "1"
         1359  +  # auto-naming should reuse the last proxy name when available
  1354   1360     do_test pragma-16.5 {
  1355   1361       sqlite3 db2 test.db
  1356   1362       execsql {
  1357   1363         PRAGMA lock_proxy_file=":auto:";
  1358   1364         PRAGMA lock_proxy_file;
  1359   1365       } db2
  1360   1366     } {myotherproxy}
  1361   1367     
         1368  +  # auto-naming a new proxy should use a predictable & unique name
  1362   1369     do_test pragma-16.6 {
  1363   1370       db2 close
  1364   1371       sqlite3 db2 test2.db
  1365   1372       set lockpath [execsql {
  1366   1373         PRAGMA lock_proxy_file=":auto:";
  1367   1374         PRAGMA lock_proxy_file;
  1368   1375       } db2]
  1369   1376       string match "*test2.db:auto:" $lockpath
  1370   1377     } {1}
  1371   1378     
  1372   1379     set sqlite_hostid_num 2
         1380  +  # db access should be limited to one host at a time (simulate 2nd host id)
  1373   1381     do_test pragma-16.7 {
  1374   1382       sqlite3 db test2.db
  1375   1383       execsql {
  1376   1384         PRAGMA lock_proxy_file=":auto:";
  1377   1385       } 
  1378   1386       catchsql {
  1379   1387         select * from sqlite_master;
  1380   1388       }
  1381   1389     } {1 {database is locked}}
  1382   1390     db close
  1383   1391     
         1392  +  # default to using proxy locking (simulate network file system detection)
  1384   1393     do_test pragma-16.8 {
  1385   1394       sqlite3 db test2.db
  1386   1395       catchsql {
  1387   1396         select * from sqlite_master;
  1388   1397       } 
  1389   1398     } {1 {database is locked}}
  1390   1399   
  1391   1400     db2 close
         1401  +  # check that db is unlocked after first host connection closes 
  1392   1402     do_test pragma-16.8.1 {
  1393   1403       execsql {
  1394   1404         PRAGMA lock_proxy_file="yetanotherproxy";
         1405  +      select * from sqlite_master;
         1406  +    }
         1407  +    execsql {
  1395   1408         PRAGMA lock_proxy_file;
  1396   1409       } 
  1397   1410     } {yetanotherproxy}
  1398   1411     do_test pragma-16.8.2 {
  1399   1412       execsql {
  1400         -      create table mine(x);
         1413  +      create table if not exists mine(x);
         1414  +      insert into mine values (1);
  1401   1415       } 
  1402   1416     } {}
  1403   1417   
  1404   1418     db close
         1419  +  file delete -force proxytest.db
         1420  +  file delete -force .proxytest.db-conch
  1405   1421     do_test pragma-16.9 {
  1406   1422       sqlite3 db proxytest.db
  1407   1423       set lockpath2 [execsql {
  1408   1424         PRAGMA lock_proxy_file=":auto:";
  1409   1425         PRAGMA lock_proxy_file;
  1410   1426       } db]
  1411   1427       string match "*proxytest.db:auto:" $lockpath2
  1412   1428     } {1}
         1429  +
         1430  +  # ensure creating directories for a lock proxy file works
         1431  +  db close
         1432  +  file delete -force proxytest
         1433  +  do_test pragma-16.10.1 {
         1434  +    sqlite3 db proxytest.db
         1435  +    set lockpath2 [execsql {
         1436  +      PRAGMA lock_proxy_file="./proxytest/sub/dir/lock";
         1437  +      PRAGMA lock_proxy_file;
         1438  +    } db]
         1439  +    string match "*proxytest/sub/dir/lock" $lockpath2
         1440  +  } {1}
         1441  +
         1442  +  # ensure that after deleting the path, setting ":auto:" works correctly
         1443  +  db close
         1444  +  file delete -force proxytest
         1445  +  do_test pragma-16.10.2 {
         1446  +    sqlite3 db proxytest.db
         1447  +    set lockpath2 [execsql {
         1448  +      PRAGMA lock_proxy_file=":auto:";
         1449  +      create table if not exists pt(y);
         1450  +      PRAGMA lock_proxy_file;
         1451  +    } db]
         1452  +    string match "*proxytest/sub/dir/lock" $lockpath2
         1453  +  } {1}
         1454  +
         1455  +  # ensure that if the path can not be created (file instead of dir)
         1456  +  # setting :auto: deals with it by creating a new autonamed lock file
         1457  +  db close
         1458  +  file delete -force proxytest
         1459  +  close [open "proxytest" a]
         1460  +  do_test pragma-16.10.3 {
         1461  +    sqlite3 db proxytest.db
         1462  +    set lockpath2 [execsql {
         1463  +      PRAGMA lock_proxy_file=":auto:";
         1464  +      create table if not exists zz(y);
         1465  +      PRAGMA lock_proxy_file;
         1466  +    } db]
         1467  +    string match "*proxytest.db:auto:" $lockpath2
         1468  +  } {1}
         1469  +
         1470  +  # make sure we can deal with ugly file paths correctly
         1471  +  db close
         1472  +  file delete -force proxytest
         1473  +  do_test pragma-16.10.4 {
         1474  +    sqlite3 db proxytest.db
         1475  +    set lockpath2 [execsql {
         1476  +      PRAGMA lock_proxy_file="./././////./proxytest/../proxytest/sub/dir/lock";
         1477  +      create table if not exists aa(bb);
         1478  +      PRAGMA lock_proxy_file;
         1479  +    } db]
         1480  +    string match "*proxytest/sub/dir/lock" $lockpath2
         1481  +  } {1}
         1482  +
         1483  +  # ensure that if the path can not be created (perm), setting :auto: deals
         1484  +  db close
         1485  +  file delete -force proxytest
         1486  +  do_test pragma-16.10.5 {
         1487  +    sqlite3 db proxytest.db
         1488  +    execsql {
         1489  +      PRAGMA lock_proxy_file="./proxytest/sub/dir/lock";
         1490  +      create table if not exists bb(bb);
         1491  +    }
         1492  +    db close
         1493  +    file delete -force proxytest
         1494  +    file mkdir proxytest
         1495  +    file attributes proxytest -permission 0000
         1496  +    sqlite3 db proxytest.db
         1497  +    set lockpath2 [execsql {
         1498  +      PRAGMA lock_proxy_file=":auto:";
         1499  +      create table if not exists cc(bb);
         1500  +      PRAGMA lock_proxy_file;
         1501  +    } db]
         1502  +    string match "*proxytest.db:auto:" $lockpath2
         1503  +  } {1}
         1504  +
         1505  +  # ensure that if the path can not be created, locking fails
         1506  +  db close
         1507  +  do_test pragma-16.10.6 {
         1508  +    sqlite3 db proxytest.db
         1509  +    catchsql {
         1510  +      PRAGMA lock_proxy_file="./proxytest/sub/dir/lock";
         1511  +      create table if not exists faily(y);
         1512  +      PRAGMA lock_proxy_file;
         1513  +    } db
         1514  +  } {1 {database is locked}}
         1515  +  db close
         1516  +
         1517  +  file attributes proxytest -permission 0777
         1518  +  file delete -force proxytest
  1413   1519   
  1414   1520     set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy
  1415   1521     set sqlite_hostid_num 0
  1416   1522   }
  1417   1523   
  1418   1524   # Parsing of auto_vacuum settings.
  1419   1525   #

Changes to test/quick.test.

    60     60     fts3.test
    61     61     fkey_malloc.test
    62     62     fuzz.test
    63     63     fuzz3.test
    64     64     fuzz_malloc.test
    65     65     in2.test
    66     66     loadext.test
           67  +  lock_proxy.test
    67     68     memleak.test
    68     69     misc7.test
    69     70     misuse.test
    70     71     mutex2.test
    71     72     notify2.test
    72     73     onefile.test
    73     74     permutations.test

Changes to test/tester.tcl.

   357    357   
   358    358       if {[sqlite3_memory_used]>0} {
   359    359         puts "Writing leaks.sql..."
   360    360         sqlite3_memdebug_log sync
   361    361         memdebug_log_sql leaks.sql
   362    362       }
   363    363     }
          364  +  catch {
   364    365     foreach f [glob -nocomplain test.db-*-journal] {
   365    366       file delete -force $f
   366    367     }
          368  +  }
          369  +  catch {
   367    370     foreach f [glob -nocomplain test.db-mj*] {
   368    371       file delete -force $f
   369    372     }
          373  +  }
   370    374     exit [expr {$nErr>0}]
   371    375   }
   372    376   
   373    377   # Display memory statistics for analysis and debugging purposes.
   374    378   #
   375    379   proc show_memstats {} {
   376    380     set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0]

Changes to tool/mksqlite3c.tcl.

   103    103      pcache.h
   104    104      rtree.h
   105    105      sqlite3ext.h
   106    106      sqlite3.h
   107    107      sqliteicu.h
   108    108      sqliteInt.h
   109    109      sqliteLimit.h
          110  +   sqlrr.h
   110    111      vdbe.h
   111    112      vdbeInt.h
   112    113   } {
   113    114     set available_hdr($hdr) 1
   114    115   }
   115    116   set available_hdr(sqliteInt.h) 0
   116    117   
................................................................................
   295    296      fts3_porter.c
   296    297      fts3_tokenizer.c
   297    298      fts3_tokenizer1.c
   298    299   
   299    300      rtree.c
   300    301      icu.c
   301    302      fts3_icu.c
          303  +   sqlrr.c
   302    304   } {
   303    305     copy_file tsrc/$file
   304    306   }
   305    307   
   306    308   close $out