engine/sqlite/src/btmutex.cpp
author teknolog
Wed, 26 May 2010 10:44:32 +0100
changeset 131 87e863f6f840
parent 2 29cda98b007e
permissions -rw-r--r--
Fix for bug 2719.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     1
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     2
** 2007 August 27
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     3
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     4
** The author disclaims copyright to this source code.  In place of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     5
** a legal notice, here is a blessing:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     6
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     7
**    May you do good and not evil.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     8
**    May you find forgiveness for yourself and forgive others.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     9
**    May you share freely, never taking more than you give.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    10
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    11
*************************************************************************
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    12
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    13
** $Id: btmutex.cpp 1282 2008-11-13 09:31:33Z LarsPson $
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    14
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    15
** This file contains code used to implement mutexes on Btree objects.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    16
** This code really belongs in btree.c.  But btree.c is getting too
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    17
** big and we want to break it down some.  This packaged seemed like
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    18
** a good breakout.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    19
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    20
#include "btreeInt.h"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    21
#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    22
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    23
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    24
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    25
** Enter a mutex on the given BTree object.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    26
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    27
** If the object is not sharable, then no mutex is ever required
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    28
** and this routine is a no-op.  The underlying mutex is non-recursive.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    29
** But we keep a reference count in Btree.wantToLock so the behavior
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    30
** of this interface is recursive.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    31
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    32
** To avoid deadlocks, multiple Btrees are locked in the same order
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    33
** by all database connections.  The p->pNext is a list of other
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    34
** Btrees belonging to the same database connection as the p Btree
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    35
** which need to be locked after p.  If we cannot get a lock on
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    36
** p, then first unlock all of the others on p->pNext, then wait
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    37
** for the lock to become available on p, then relock all of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    38
** subsequent Btrees that desire a lock.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    39
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    40
void sqlite3BtreeEnter(Btree *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    41
  Btree *pLater;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    42
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    43
  /* Some basic sanity checking on the Btree.  The list of Btrees
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    44
  ** connected by pNext and pPrev should be in sorted order by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    45
  ** Btree.pBt value. All elements of the list should belong to
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    46
  ** the same connection. Only shared Btrees are on the list. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    47
  assert( p->pNext==0 || p->pNext->pBt>p->pBt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    48
  assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    49
  assert( p->pNext==0 || p->pNext->db==p->db );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    50
  assert( p->pPrev==0 || p->pPrev->db==p->db );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    51
  assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    52
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    53
  /* Check for locking consistency */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    54
  assert( !p->locked || p->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    55
  assert( p->sharable || p->wantToLock==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    56
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    57
  /* We should already hold a lock on the database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    58
  assert( sqlite3_mutex_held(p->db->mutex) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    59
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    60
  if( !p->sharable ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    61
  p->wantToLock++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    62
  if( p->locked ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    63
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    64
  /* In most cases, we should be able to acquire the lock we
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    65
  ** want without having to go throught the ascending lock
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    66
  ** procedure that follows.  Just be sure not to block.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    67
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    68
  if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    69
    p->locked = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    70
    return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    71
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    72
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    73
  /* To avoid deadlock, first release all locks with a larger
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    74
  ** BtShared address.  Then acquire our lock.  Then reacquire
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    75
  ** the other BtShared locks that we used to hold in ascending
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    76
  ** order.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    77
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    78
  for(pLater=p->pNext; pLater; pLater=pLater->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    79
    assert( pLater->sharable );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    80
    assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    81
    assert( !pLater->locked || pLater->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    82
    if( pLater->locked ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    83
      sqlite3_mutex_leave(pLater->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    84
      pLater->locked = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    85
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    86
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    87
  sqlite3_mutex_enter(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    88
  p->locked = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    89
  for(pLater=p->pNext; pLater; pLater=pLater->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    90
    if( pLater->wantToLock ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    91
      sqlite3_mutex_enter(pLater->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    92
      pLater->locked = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    93
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    94
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    95
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    96
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    97
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    98
** Exit the recursive mutex on a Btree.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    99
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   100
void sqlite3BtreeLeave(Btree *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   101
  if( p->sharable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   102
    assert( p->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   103
    p->wantToLock--;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   104
    if( p->wantToLock==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   105
      assert( p->locked );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   106
      sqlite3_mutex_leave(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   107
      p->locked = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   108
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   109
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   110
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   111
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   112
#ifndef NDEBUG
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   113
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   114
** Return true if the BtShared mutex is held on the btree.  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   115
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   116
** This routine makes no determination one why or another if the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   117
** database connection mutex is held.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   118
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   119
** This routine is used only from within assert() statements.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   120
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   121
int sqlite3BtreeHoldsMutex(Btree *p){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   122
  return (p->sharable==0 ||
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   123
             (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   124
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   125
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   126
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   127
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   128
#ifndef SQLITE_OMIT_INCRBLOB
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   129
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   130
** Enter and leave a mutex on a Btree given a cursor owned by that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   131
** Btree.  These entry points are used by incremental I/O and can be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   132
** omitted if that module is not used.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   133
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   134
void sqlite3BtreeEnterCursor(BtCursor *pCur){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   135
  sqlite3BtreeEnter(pCur->pBtree);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   136
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   137
void sqlite3BtreeLeaveCursor(BtCursor *pCur){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   138
  sqlite3BtreeLeave(pCur->pBtree);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   139
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   140
#endif /* SQLITE_OMIT_INCRBLOB */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   141
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   142
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   143
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   144
** Enter the mutex on every Btree associated with a database
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   145
** connection.  This is needed (for example) prior to parsing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   146
** a statement since we will be comparing table and column names
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   147
** against all schemas and we do not want those schemas being
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   148
** reset out from under us.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   149
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   150
** There is a corresponding leave-all procedures.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   151
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   152
** Enter the mutexes in accending order by BtShared pointer address
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   153
** to avoid the possibility of deadlock when two threads with
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   154
** two or more btrees in common both try to lock all their btrees
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   155
** at the same instant.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   156
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   157
void sqlite3BtreeEnterAll(sqlite3 *db){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   158
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   159
  Btree *p, *pLater;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   160
  assert( sqlite3_mutex_held(db->mutex) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   161
  for(i=0; i<db->nDb; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   162
    p = db->aDb[i].pBt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   163
    if( p && p->sharable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   164
      p->wantToLock++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   165
      if( !p->locked ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   166
        assert( p->wantToLock==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   167
        while( p->pPrev ) p = p->pPrev;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   168
        while( p->locked && p->pNext ) p = p->pNext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   169
        for(pLater = p->pNext; pLater; pLater=pLater->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   170
          if( pLater->locked ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   171
            sqlite3_mutex_leave(pLater->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   172
            pLater->locked = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   173
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   174
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   175
        while( p ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   176
          sqlite3_mutex_enter(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   177
          p->locked++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   178
          p = p->pNext;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   179
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   180
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   181
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   182
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   183
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   184
void sqlite3BtreeLeaveAll(sqlite3 *db){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   185
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   186
  Btree *p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   187
  assert( sqlite3_mutex_held(db->mutex) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   188
  for(i=0; i<db->nDb; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   189
    p = db->aDb[i].pBt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   190
    if( p && p->sharable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   191
      assert( p->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   192
      p->wantToLock--;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   193
      if( p->wantToLock==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   194
        assert( p->locked );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   195
        sqlite3_mutex_leave(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   196
        p->locked = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   197
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   198
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   199
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   200
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   201
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   202
#ifndef NDEBUG
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   203
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   204
** Return true if the current thread holds the database connection
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   205
** mutex and all required BtShared mutexes.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   206
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   207
** This routine is used inside assert() statements only.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   208
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   209
int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   210
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   211
  if( !sqlite3_mutex_held(db->mutex) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   212
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   213
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   214
  for(i=0; i<db->nDb; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   215
    Btree *p;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   216
    p = db->aDb[i].pBt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   217
    if( p && p->sharable &&
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   218
         (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   219
      return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   220
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   221
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   222
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   223
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   224
#endif /* NDEBUG */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   225
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   226
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   227
** Potentially dd a new Btree pointer to a BtreeMutexArray.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   228
** Really only add the Btree if it can possibly be shared with
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   229
** another database connection.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   230
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   231
** The Btrees are kept in sorted order by pBtree->pBt.  That
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   232
** way when we go to enter all the mutexes, we can enter them
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   233
** in order without every having to backup and retry and without
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   234
** worrying about deadlock.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   235
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   236
** The number of shared btrees will always be small (usually 0 or 1)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   237
** so an insertion sort is an adequate algorithm here.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   238
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   239
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   240
  int i, j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   241
  BtShared *pBt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   242
  if( pBtree==0 || pBtree->sharable==0 ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   243
#ifndef NDEBUG
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   244
  {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   245
    for(i=0; i<pArray->nMutex; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   246
      assert( pArray->aBtree[i]!=pBtree );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   247
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   248
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   249
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   250
  assert( pArray->nMutex>=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   251
  assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   252
  pBt = pBtree->pBt;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   253
  for(i=0; i<pArray->nMutex; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   254
    assert( pArray->aBtree[i]!=pBtree );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   255
    if( pArray->aBtree[i]->pBt>pBt ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   256
      for(j=pArray->nMutex; j>i; j--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   257
        pArray->aBtree[j] = pArray->aBtree[j-1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   258
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   259
      pArray->aBtree[i] = pBtree;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   260
      pArray->nMutex++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   261
      return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   262
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   263
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   264
  pArray->aBtree[pArray->nMutex++] = pBtree;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   265
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   266
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   267
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   268
** Enter the mutex of every btree in the array.  This routine is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   269
** called at the beginning of sqlite3VdbeExec().  The mutexes are
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   270
** exited at the end of the same function.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   271
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   272
void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   273
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   274
  for(i=0; i<pArray->nMutex; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   275
    Btree *p = pArray->aBtree[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   276
    /* Some basic sanity checking */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   277
    assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   278
    assert( !p->locked || p->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   279
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   280
    /* We should already hold a lock on the database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   281
    assert( sqlite3_mutex_held(p->db->mutex) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   282
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   283
    p->wantToLock++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   284
    if( !p->locked && p->sharable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   285
      sqlite3_mutex_enter(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   286
      p->locked = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   287
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   288
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   289
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   290
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   291
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   292
** Leave the mutex of every btree in the group.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   293
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   294
void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   295
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   296
  for(i=0; i<pArray->nMutex; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   297
    Btree *p = pArray->aBtree[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   298
    /* Some basic sanity checking */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   299
    assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   300
    assert( p->locked || !p->sharable );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   301
    assert( p->wantToLock>0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   302
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   303
    /* We should already hold a lock on the database connection */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   304
    assert( sqlite3_mutex_held(p->db->mutex) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   305
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   306
    p->wantToLock--;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   307
    if( p->wantToLock==0 && p->locked ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   308
      sqlite3_mutex_leave(p->pBt->mutex);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   309
      p->locked = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   310
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   311
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   312
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   313
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   314
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   315
#endif  /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */