SQLite

Check-in [db4022db64]
Login

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

Overview
Comment:In the unix OS implementation, replace inode hash tables with linked lists. (CVS 5503)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: db4022db64dc5864e6f1d0a20672183879ad43aa
User & Date: drh 2008-07-30 15:27:54.000
Context
2008-07-30
17:28
When opening a zero-size database on unix, write one byte into the file before interrogating the inode number. This works around issues with msdos filesystems mounted on OS-X. Ticket #3260. (CVS 5504) (check-in: a480a8845f user: drh tags: trunk)
15:27
In the unix OS implementation, replace inode hash tables with linked lists. (CVS 5503) (check-in: db4022db64 user: drh tags: trunk)
13:27
Implicit string->numeric conversion should go to an integer value when possible. Ticket #3257. (CVS 5502) (check-in: da0e4bff30 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os_unix.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.193 2008/07/10 00:32:42 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different 
** locking implementations are provided:







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.194 2008/07/30 15:27:54 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX              /* This file is used on unix only */

/*
** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different 
** locking implementations are provided:
307
308
309
310
311
312
313

314
315
316
317
318
319
320
** object keeps a count of the number of unixFile pointing to it.
*/
struct lockInfo {
  struct lockKey key;  /* The lookup key */
  int cnt;             /* Number of SHARED locks held */
  int locktype;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  int nRef;            /* Number of pointers to this structure */

};

/*
** An instance of the following structure serves as the key used
** to locate a particular openCnt structure given its inode.  This
** is the same as the lockKey except that the thread ID is omitted.
*/







>







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
** object keeps a count of the number of unixFile pointing to it.
*/
struct lockInfo {
  struct lockKey key;  /* The lookup key */
  int cnt;             /* Number of SHARED locks held */
  int locktype;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  int nRef;            /* Number of pointers to this structure */
  struct lockInfo *pNext, *pPrev;   /* List of all lockInfo objects */
};

/*
** An instance of the following structure serves as the key used
** to locate a particular openCnt structure given its inode.  This
** is the same as the lockKey except that the thread ID is omitted.
*/
332
333
334
335
336
337
338

339
340
341
342
343
344


345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
*/
struct openCnt {
  struct openKey key;   /* The lookup key */
  int nRef;             /* Number of pointers to this structure */
  int nLock;            /* Number of outstanding locks */
  int nPending;         /* Number of pending close() operations */
  int *aPending;        /* Malloced space holding fd's awaiting a close() */

};

/* 
** These hash tables map inodes and file descriptors (really, lockKey and
** openKey structures) into lockInfo and openCnt structures.  Access to 
** these hash tables must be protected by a mutex.


*/
static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};

/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.  
**
** POSIX locking style fully supports shared and exclusive byte-range locks 
** AFP locking only supports exclusive byte-range locks
** FLOCK only supports a single file-global exclusive lock
** DOTLOCK isn't a true locking style, it refers to the use of a special
**   file named the same as the database file with a '.lock' extension, this
**   can be used on file systems that do not offer any reliable file locking
** NO locking means that no locking will be attempted, this is only used for
**   read-only file systems currently
** UNSUPPORTED means that no locking will be attempted, this is only used for
**   file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX        1
#define LOCKING_STYLE_FLOCK        2
#define LOCKING_STYLE_DOTFILE      3
#define LOCKING_STYLE_NONE         4
#define LOCKING_STYLE_AFP          5

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));







>


|
<
|
|
>
>

|
|

















|

|







333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
*/
struct openCnt {
  struct openKey key;   /* The lookup key */
  int nRef;             /* Number of pointers to this structure */
  int nLock;            /* Number of outstanding locks */
  int nPending;         /* Number of pending close() operations */
  int *aPending;        /* Malloced space holding fd's awaiting a close() */
  struct openCnt *pNext, *pPrev;   /* List of all openCnt objects */
};

/*

** List of all lockInfo and openCnt objects.  This used to be a hash
** table.  But the number of objects is rarely more than a dozen and
** never exceeds a few thousand.  And lookup is not on a critical
** path oo a simple linked list will suffice.
*/
static struct lockInfo *lockList = 0;
static struct openCnt *openList = 0;

/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.  
**
** POSIX locking style fully supports shared and exclusive byte-range locks 
** AFP locking only supports exclusive byte-range locks
** FLOCK only supports a single file-global exclusive lock
** DOTLOCK isn't a true locking style, it refers to the use of a special
**   file named the same as the database file with a '.lock' extension, this
**   can be used on file systems that do not offer any reliable file locking
** NO locking means that no locking will be attempted, this is only used for
**   read-only file systems currently
** UNSUPPORTED means that no locking will be attempted, this is only used for
**   file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX        1
#define LOCKING_STYLE_NONE         2
#define LOCKING_STYLE_DOTFILE      3
#define LOCKING_STYLE_FLOCK        4
#define LOCKING_STYLE_AFP          5

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
519
520
521
522
523
524
525
526










527
528
529
530
531
532
533
534
535
536
537
538
539










540
541
542
543
544
545
546
547
/*
** Release a lockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct lockInfo *pLock){
  if( pLock ){
    pLock->nRef--;
    if( pLock->nRef==0 ){
      sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);










      sqlite3_free(pLock);
    }
  }
}

/*
** Release a openCnt structure previously allocated by findLockInfo().
*/
static void releaseOpenCnt(struct openCnt *pOpen){
  if( pOpen ){
    pOpen->nRef--;
    if( pOpen->nRef==0 ){
      sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);










      free(pOpen->aPending);
      sqlite3_free(pOpen);
    }
  }
}

#ifdef SQLITE_ENABLE_LOCKING_STYLE
/*







|
>
>
>
>
>
>
>
>
>
>












|
>
>
>
>
>
>
>
>
>
>
|







522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
/*
** Release a lockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct lockInfo *pLock){
  if( pLock ){
    pLock->nRef--;
    if( pLock->nRef==0 ){
      if( pLock->pPrev ){
        assert( pLock->pPrev->pNext==pLock );
        pLock->pPrev->pNext = pLock->pNext;
      }else{
        assert( lockList==pLock );
        lockList = pLock->pNext;
      }
      if( pLock->pNext ){
        assert( pLock->pNext->pPrev==pLock );
        pLock->pNext->pPrev = pLock->pPrev;
      }
      sqlite3_free(pLock);
    }
  }
}

/*
** Release a openCnt structure previously allocated by findLockInfo().
*/
static void releaseOpenCnt(struct openCnt *pOpen){
  if( pOpen ){
    pOpen->nRef--;
    if( pOpen->nRef==0 ){
      if( pOpen->pPrev ){
        assert( pOpen->pPrev->pNext==pOpen );
        pOpen->pPrev->pNext = pOpen->pNext;
      }else{
        assert( openList==pOpen );
        openList = pOpen->pNext;
      }
      if( pOpen->pNext ){
        assert( pOpen->pNext->pPrev==pOpen );
        pOpen->pNext->pPrev = pOpen->pPrev;
      }
      sqlite3_free(pOpen->aPending);
      sqlite3_free(pOpen);
    }
  }
}

#ifdef SQLITE_ENABLE_LOCKING_STYLE
/*
659
660
661
662
663
664
665

666


667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

690


691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
    testThreadLockingBehavior(fd);
  }
  key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
#endif
  memset(&key2, 0, sizeof(key2));
  key2.dev = statbuf.st_dev;
  key2.ino = statbuf.st_ino;

  pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));


  if( pLock==0 ){
    struct lockInfo *pOld;
    pLock = sqlite3_malloc( sizeof(*pLock) );
    if( pLock==0 ){
      rc = SQLITE_NOMEM;
      goto exit_findlockinfo;
    }
    pLock->key = key1;
    pLock->nRef = 1;
    pLock->cnt = 0;
    pLock->locktype = 0;
    pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
    if( pOld!=0 ){
      assert( pOld==pLock );
      sqlite3_free(pLock);
      rc = SQLITE_NOMEM;
      goto exit_findlockinfo;
    }
  }else{
    pLock->nRef++;
  }
  *ppLock = pLock;
  if( ppOpen!=0 ){

    pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));


    if( pOpen==0 ){
      struct openCnt *pOld;
      pOpen = sqlite3_malloc( sizeof(*pOpen) );
      if( pOpen==0 ){
        releaseLockInfo(pLock);
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pOpen->key = key2;
      pOpen->nRef = 1;
      pOpen->nLock = 0;
      pOpen->nPending = 0;
      pOpen->aPending = 0;
      pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
      if( pOld!=0 ){
        assert( pOld==pOpen );
        sqlite3_free(pOpen);
        releaseLockInfo(pLock);
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
    }else{
      pOpen->nRef++;
    }
    *ppOpen = pOpen;
  }

exit_findlockinfo:







>
|
>
>

<









<
<
|
|
|
|
<





>
|
>
>

<











|
<
|
|
<
|
<
<







682
683
684
685
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
701
702


703
704
705
706

707
708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728

729
730

731


732
733
734
735
736
737
738
    testThreadLockingBehavior(fd);
  }
  key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
#endif
  memset(&key2, 0, sizeof(key2));
  key2.dev = statbuf.st_dev;
  key2.ino = statbuf.st_ino;
  pLock = lockList;
  while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
    pLock = pLock->pNext;
  }
  if( pLock==0 ){

    pLock = sqlite3_malloc( sizeof(*pLock) );
    if( pLock==0 ){
      rc = SQLITE_NOMEM;
      goto exit_findlockinfo;
    }
    pLock->key = key1;
    pLock->nRef = 1;
    pLock->cnt = 0;
    pLock->locktype = 0;


    pLock->pNext = lockList;
    pLock->pPrev = 0;
    if( lockList ) lockList->pPrev = pLock;
    lockList = pLock;

  }else{
    pLock->nRef++;
  }
  *ppLock = pLock;
  if( ppOpen!=0 ){
    pOpen = openList;
    while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
      pOpen = pOpen->pNext;
    }
    if( pOpen==0 ){

      pOpen = sqlite3_malloc( sizeof(*pOpen) );
      if( pOpen==0 ){
        releaseLockInfo(pLock);
        rc = SQLITE_NOMEM;
        goto exit_findlockinfo;
      }
      pOpen->key = key2;
      pOpen->nRef = 1;
      pOpen->nLock = 0;
      pOpen->nPending = 0;
      pOpen->aPending = 0;
      pOpen->pNext = openList;

      pOpen->pPrev = 0;
      if( openList ) openList->pPrev = pOpen;

      openList = pOpen;


    }else{
      pOpen->nRef++;
    }
    *ppOpen = pOpen;
  }

exit_findlockinfo:
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
      pOpen->nLock--;
      assert( pOpen->nLock>=0 );
      if( pOpen->nLock==0 && pOpen->nPending>0 ){
        int i;
        for(i=0; i<pOpen->nPending; i++){
          close(pOpen->aPending[i]);
        }
        free(pOpen->aPending);
        pOpen->nPending = 0;
        pOpen->aPending = 0;
      }
    }
  }
  leaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;







|







1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
      pOpen->nLock--;
      assert( pOpen->nLock>=0 );
      if( pOpen->nLock==0 && pOpen->nPending>0 ){
        int i;
        for(i=0; i<pOpen->nPending; i++){
          close(pOpen->aPending[i]);
        }
        sqlite3_free(pOpen->aPending);
        pOpen->nPending = 0;
        pOpen->aPending = 0;
      }
    }
  }
  leaveMutex();
  if( rc==SQLITE_OK ) pFile->locktype = locktype;
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
      /* If there are outstanding locks, do not actually close the file just
      ** yet because that would clear those locks.  Instead, add the file
      ** descriptor to pOpen->aPending.  It will be automatically closed when
      ** the last lock is cleared.
      */
      int *aNew;
      struct openCnt *pOpen = pFile->pOpen;
      aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;







|







1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
      /* If there are outstanding locks, do not actually close the file just
      ** yet because that would clear those locks.  Instead, add the file
      ** descriptor to pOpen->aPending.  It will be automatically closed when
      ** the last lock is cleared.
      */
      int *aNew;
      struct openCnt *pOpen = pFile->pOpen;
      aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
      if( aNew==0 ){
        /* If a malloc fails, just leak the file descriptor */
      }else{
        pOpen->aPending = aNew;
        pOpen->aPending[pOpen->nPending] = pFile->h;
        pOpen->nPending++;
        pFile->h = -1;
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
    dotlockUnlock(id, NO_LOCK);
    sqlite3_free(pFile->lockingContext);
  }
  return closeUnixFile(id);
}


#pragma mark No locking

/*
** The nolockLockingContext is void
*/
typedef void nolockLockingContext;

static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) {







|







1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
    dotlockUnlock(id, NO_LOCK);
    sqlite3_free(pFile->lockingContext);
  }
  return closeUnixFile(id);
}


#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** The nolockLockingContext is void
*/
typedef void nolockLockingContext;

static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) {
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
/*
** Close a file.
*/
static int nolockClose(sqlite3_file *id) {
  return closeUnixFile(id);
}

#endif /* SQLITE_ENABLE_LOCKING_STYLE */


/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {







<
<







2013
2014
2015
2016
2017
2018
2019


2020
2021
2022
2023
2024
2025
2026
/*
** Close a file.
*/
static int nolockClose(sqlite3_file *id) {
  return closeUnixFile(id);
}




/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
2043
2044
2045
2046
2047
2048
2049
2050

2051




2052
2053
2054
2055
2056
2057
2058
** and assigned here also.
*/
static int fillInUnixFile(
  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  int h,                  /* Open file descriptor of file being opened */
  int dirfd,              /* Directory file descriptor */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename   /* Name of the file being opened */

){




  /* Macro to define the static contents of an sqlite3_io_methods 
  ** structure for a unix backend file. Different locking methods
  ** require different functions for the xClose, xLock, xUnlock and
  ** xCheckReservedLock methods.
  */
  #define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) {    \
    1,                          /* iVersion */                           \







|
>

>
>
>
>







2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
** and assigned here also.
*/
static int fillInUnixFile(
  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
  int h,                  /* Open file descriptor of file being opened */
  int dirfd,              /* Directory file descriptor */
  sqlite3_file *pId,      /* Write to the unixFile structure here */
  const char *zFilename,  /* Name of the file being opened */
  int noLock              /* Omit locking if true */
){
  int eLockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc = SQLITE_OK;

  /* Macro to define the static contents of an sqlite3_io_methods 
  ** structure for a unix backend file. Different locking methods
  ** require different functions for the xClose, xLock, xUnlock and
  ** xCheckReservedLock methods.
  */
  #define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) {    \
    1,                          /* iVersion */                           \
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084




2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
    xCheckReservedLock,         /* xCheckReservedLock */                 \
    unixFileControl,            /* xFileControl */                       \
    unixSectorSize,             /* xSectorSize */                        \
    unixDeviceCharacteristics   /* xDeviceCapabilities */                \
  }
  static sqlite3_io_methods aIoMethod[] = {
    IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) 

#ifdef SQLITE_ENABLE_LOCKING_STYLE
   ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
   ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
   ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
#endif
  };

  int eLockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc = SQLITE_OK;





  assert( pNew->pLock==NULL );
  assert( pNew->pOpen==NULL );

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);

  assert(LOCKING_STYLE_POSIX==1);
  assert(LOCKING_STYLE_FLOCK==2);
  assert(LOCKING_STYLE_DOTFILE==3);
  assert(LOCKING_STYLE_NONE==4);
  assert(LOCKING_STYLE_AFP==5);
  eLockingStyle = detectLockingStyle(pVfs, zFilename, h);


  switch( eLockingStyle ){

    case LOCKING_STYLE_POSIX: {
      enterMutex();
      rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
      leaveMutex();







>

<

|



|
|
|
|
>
>
>
>









|
<
<
|
|
|
>







2090
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121


2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
    xCheckReservedLock,         /* xCheckReservedLock */                 \
    unixFileControl,            /* xFileControl */                       \
    unixSectorSize,             /* xSectorSize */                        \
    unixDeviceCharacteristics   /* xDeviceCapabilities */                \
  }
  static sqlite3_io_methods aIoMethod[] = {
    IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) 
   ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
#ifdef SQLITE_ENABLE_LOCKING_STYLE

   ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
   ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
   ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
#endif
  };
  /* The order of the IOMETHODS macros above is important.  It must be the
  ** same order as the LOCKING_STYLE numbers
  */
  assert(LOCKING_STYLE_POSIX==1);
  assert(LOCKING_STYLE_NONE==2);
  assert(LOCKING_STYLE_DOTFILE==3);
  assert(LOCKING_STYLE_FLOCK==4);
  assert(LOCKING_STYLE_AFP==5);

  assert( pNew->pLock==NULL );
  assert( pNew->pOpen==NULL );

  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  pNew->h = h;
  pNew->dirfd = dirfd;
  SET_THREADID(pNew);

  if( noLock ){


    eLockingStyle = LOCKING_STYLE_NONE;
  }else{
    eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
  }

  switch( eLockingStyle ){

    case LOCKING_STYLE_POSIX: {
      enterMutex();
      rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
      leaveMutex();
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
  int flags,
  int *pOutFlags
){
  int fd = 0;                    /* File descriptor returned by open() */
  int dirfd = -1;                /* Directory file descriptor */
  int oflags = 0;                /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */


  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);








>







2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
  int flags,
  int *pOutFlags
){
  int fd = 0;                    /* File descriptor returned by open() */
  int dirfd = -1;                /* Directory file descriptor */
  int oflags = 0;                /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);

2371
2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383
2384
2385
    }
  }

#ifdef FD_CLOEXEC
  fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif


  return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath);
}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){







>
|







2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
    }
  }

#ifdef FD_CLOEXEC
  fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif

  noLock = eType!=SQLITE_OPEN_MAIN_DB;
  return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock);
}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
Changes to src/test1.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.315 2008/07/12 14:52:20 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.316 2008/07/30 15:27:54 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;

  Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
  return TCL_OK;
}

#ifndef SQLITE_OMIT_DISKIO
#if 0
/*
** Usage:  sqlite3OsOpenReadWrite <filename>
*/
static int test_sqlite3OsOpenReadWrite(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_file *pFile;
  int rc;
  int dummy;
  char zBuf[100];

  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
       Tcl_GetString(objv[0]), " filename", 0);
    return TCL_ERROR;
  }

  rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  sqlite3TestMakePointerStr(interp, zBuf, pFile);
  Tcl_SetResult(interp, zBuf, 0);
  return TCL_ERROR;
}

/*
** Usage:  sqlite3OsClose <file handle>
*/
static int test_sqlite3OsClose(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_file *pFile;
  int rc;

  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
       Tcl_GetString(objv[0]), " filehandle", 0);
    return TCL_ERROR;
  }

  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
    return TCL_ERROR;
  }
  rc = sqlite3OsClose(&pFile);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3OsLock <file handle> <locktype>
*/
static int test_sqlite3OsLock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_file * pFile;
  int rc;

  if( objc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
        Tcl_GetString(objv[0]), 
        " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
    return TCL_ERROR;
  }

  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
    return TCL_ERROR;
  }

  if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
    rc = sqlite3OsLock(pFile, SHARED_LOCK);
  }
  else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
    rc = sqlite3OsLock(pFile, RESERVED_LOCK);
  }
  else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
    rc = sqlite3OsLock(pFile, PENDING_LOCK);
  }
  else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
    rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
  }else{
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
        Tcl_GetString(objv[0]), 
        " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
    return TCL_ERROR;
  }

  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3OsUnlock <file handle>
*/
static int test_sqlite3OsUnlock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_file * pFile;
  int rc;

  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
       Tcl_GetString(objv[0]), " filehandle", 0);
    return TCL_ERROR;
  }

  if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
    return TCL_ERROR;
  }
  rc = sqlite3OsUnlock(pFile, NO_LOCK);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Usage:  sqlite3OsTempFileName
*/
static int test_sqlite3OsTempFileName(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  char zFile[SQLITE_TEMPNAME_SIZE];
  int rc;

  rc = sqlite3OsTempFileName(zFile);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  Tcl_AppendResult(interp, zFile, 0);
  return TCL_OK;
}
#endif
#endif

/*
** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
**
** Set the db->magic value.  This is used to test error recovery logic.
*/
static int sqlite_set_magic(
  void * clientData,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3783
3784
3785
3786
3787
3788
3789

































































































































































3790
3791
3792
3793
3794
3795
3796
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;

  Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
  return TCL_OK;
}


































































































































































/*
** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
**
** Set the db->magic value.  This is used to test error recovery logic.
*/
static int sqlite_set_magic(
  void * clientData,
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
     { "vfs_initfail_test",          vfs_initfail_test,   0   },
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },

     /* Functions from os.h */
#ifndef SQLITE_OMIT_DISKIO
#if 0
     { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
     { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
     { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
     { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
   
     /* Custom test interfaces */
     { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    },
#endif
#endif
#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
     { "add_test_function",       test_function, 0           },
#endif
     { "sqlite3_test_errstr",     test_errstr, 0             },
     { "tcl_variable_type",       tcl_variable_type, 0       },







<
<
<
<
<
<
<
<
<
<
<







4644
4645
4646
4647
4648
4649
4650











4651
4652
4653
4654
4655
4656
4657
     { "vfs_initfail_test",          vfs_initfail_test,   0   },
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },

     /* Functions from os.h */











#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
     { "add_test_function",       test_function, 0           },
#endif
     { "sqlite3_test_errstr",     test_errstr, 0             },
     { "tcl_variable_type",       tcl_variable_type, 0       },