Ejemplo n.º 1
0
/*
** Enter the mutex of every btree in the array.  This routine is
** called at the beginning of sqlite3VdbeExec().  The mutexes are
** exited at the end of the same function.
*/
        void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray)
        {
            int i;

            for (i = 0; i < pArray->nMutex; i++)
            {
                Btree *p = pArray->aBtree[i];
/* Some basic sanity checking */
                assert(i == 0 || pArray->aBtree[i - 1]->pBt < p->pBt);
                assert(!p->locked || p->wantToLock > 0);

/* We should already hold a lock on the database connection */
                assert(sqlite3_mutex_held(p->db->mutex));

/* The Btree is sharable because only sharable Btrees are entered
** into the array in the first place. */
                assert(p->sharable);

                p->wantToLock++;
                if (!p->locked)
                {
                    lockBtreeMutex(p);
                }
            }
        }
Ejemplo n.º 2
0
/*
** Return true if the BtShared mutex is held on the btree, or if the
** B-Tree is not marked as sharable.
**
** This routine is used only from within assert() statements.
*/
        int sqlite3BtreeHoldsMutex(Btree *p)
        {
            assert(p->sharable == 0 || p->locked == 0 || p->wantToLock > 0);
            assert(p->sharable == 0 || p->locked == 0 || p->db == p->pBt->db);
            assert(p->sharable == 0 || p->locked == 0 || sqlite3_mutex_held(p->pBt->mutex));
            assert(p->sharable == 0 || p->locked == 0 || sqlite3_mutex_held(p->db->mutex));

            return(p->sharable == 0 || p->locked);
        }
Ejemplo n.º 3
0
/*
** 2007 August 27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement mutexes on Btree objects.
** This code really belongs in btree.c.  But btree.c is getting too
** big and we want to break it down some.  This packaged seemed like
** a good breakout.
*************************************************************************
**  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
**  C#-SQLite is an independent reimplementation of the SQLite software library
**
**  SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e
**
*************************************************************************
*/
//#include "btreeInt.h"
#if !SQLITE_OMIT_SHARED_CACHE
#if SQLITE_THREADSAFE
/*
** Obtain the BtShared mutex associated with B-Tree handle p. Also,
** set BtShared.db to the database handle associated with p and the
** p->locked boolean to true.
*/
        static void lockBtreeMutex(Btree *p)
        {
            assert(p->locked == 0);
            assert(sqlite3_mutex_notheld(p->pBt->mutex));
            assert(sqlite3_mutex_held(p->db->mutex));

            sqlite3_mutex_enter(p->pBt->mutex);
            p->pBt->db = p->db;
            p->locked  = 1;
        }
Ejemplo n.º 4
0
/*
** Release the BtShared mutex associated with B-Tree handle p and
** clear the p->locked boolean.
*/
        static void unlockBtreeMutex(Btree *p)
        {
            assert(p->locked == 1);
            assert(sqlite3_mutex_held(p->pBt->mutex));
            assert(sqlite3_mutex_held(p->db->mutex));
            assert(p->db == p->pBt->db);

            sqlite3_mutex_leave(p->pBt->mutex);
            p->locked = 0;
        }
Ejemplo n.º 5
0
/*
** Exit the recursive mutex on a Btree.
*/
        void sqlite3BtreeLeave(Btree *p)
        {
            if (p->sharable)
            {
                assert(p->wantToLock > 0);
                p->wantToLock--;
                if (p->wantToLock == 0)
                {
                    unlockBtreeMutex(p);
                }
            }
        }
Ejemplo n.º 6
0
        void sqlite3BtreeEnterAll(sqlite3 db)
        {
            int i;

            for (i = 0; i < db->nDb; i++)
            {
                Btree *p = db->aDb[i].pBt;
                if (p)
                {
                    p->pBt->db = p->db;
                }
            }
        }
Ejemplo n.º 7
0
/*
** Leave the mutex of every btree in the group.
*/
        void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray)
        {
            int i;

            for (i = 0; i < pArray->nMutex; i++)
            {
                Btree *p = pArray->aBtree[i];
/* Some basic sanity checking */
                assert(i == 0 || pArray->aBtree[i - 1]->pBt < p->pBt);
                assert(p->locked);
                assert(p->wantToLock > 0);

/* We should already hold a lock on the database connection */
                assert(sqlite3_mutex_held(p->db->mutex));

                p->wantToLock--;
                if (p->wantToLock == 0)
                {
                    unlockBtreeMutex(p);
                }
            }
        }
Ejemplo n.º 8
0
/*
** Add a new Btree pointer to a BtreeMutexArray.
** if the pointer can possibly be shared with
** another database connection.
**
** The pointers are kept in sorted order by pBtree->pBt.  That
** way when we go to enter all the mutexes, we can enter them
** in order without every having to backup and retry and without
** worrying about deadlock.
**
** The number of shared btrees will always be small (usually 0 or 1)
** so an insertion sort is an adequate algorithm here.
*/
        void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree)
        {
            int       i, j;
            BtShared *pBt;

            if (pBtree == 0 || pBtree->sharable == 0)
            {
                return;
            }
#if !NDEBUG
            {
                for (i = 0; i < pArray->nMutex; i++)
                {
                    assert(pArray->aBtree[i] != pBtree);
                }
            }
#endif
            assert(pArray->nMutex >= 0);
            assert(pArray->nMutex < ArraySize(pArray->aBtree) - 1);
            pBt = pBtree->pBt;
            for (i = 0; i < pArray->nMutex; i++)
            {
                assert(pArray->aBtree[i] != pBtree);
                if (pArray->aBtree[i]->pBt > pBt)
                {
                    for (j = pArray->nMutex; j > i; j--)
                    {
                        pArray->aBtree[j] = pArray->aBtree[j - 1];
                    }
                    pArray->aBtree[i] = pBtree;
                    pArray->nMutex++;
                    return;
                }
            }
            pArray->aBtree[pArray->nMutex++] = pBtree;
        }
Ejemplo n.º 9
0
/*
** The following are special cases for mutex enter routines for use
** in single threaded applications that use shared cache.  Except for
** these two routines, all mutex operations are no-ops in that case and
** are null #defines in btree.h.
**
** If shared cache is disabled, then all btree mutex routines, including
** the ones below, are no-ops and are null #defines in btree.h.
*/

        void sqlite3BtreeEnter(Btree *p)
        {
            p->pBt->db = p->db;
        }
Ejemplo n.º 10
0
/*
** Return true if a particular Btree requires a lock.  Return FALSE if
** no lock is ever required since it is not sharable.
*/
        int sqlite3BtreeSharable(Btree *p)
        {
            return(p->sharable);
        }
Ejemplo n.º 11
0
/*
** Enter a mutex on the given BTree object.
**
** If the object is not sharable, then no mutex is ever required
** and this routine is a no-op.  The underlying mutex is non-recursive.
** But we keep a reference count in Btree.wantToLock so the behavior
** of this interface is recursive.
**
** To avoid deadlocks, multiple Btrees are locked in the same order
** by all database connections.  The p->pNext is a list of other
** Btrees belonging to the same database connection as the p Btree
** which need to be locked after p.  If we cannot get a lock on
** p, then first unlock all of the others on p->pNext, then wait
** for the lock to become available on p, then relock all of the
** subsequent Btrees that desire a lock.
*/
        void sqlite3BtreeEnter(Btree *p)
        {
            Btree *pLater;

            /* Some basic sanity checking on the Btree.  The list of Btrees
            ** connected by pNext and pPrev should be in sorted order by
            ** Btree.pBt value. All elements of the list should belong to
            ** the same connection. Only shared Btrees are on the list. */
            assert(p->pNext == 0 || p->pNext->pBt > p->pBt);
            assert(p->pPrev == 0 || p->pPrev->pBt < p->pBt);
            assert(p->pNext == 0 || p->pNext->db == p->db);
            assert(p->pPrev == 0 || p->pPrev->db == p->db);
            assert(p->sharable || (p->pNext == 0 && p->pPrev == 0));

            /* Check for locking consistency */
            assert(!p->locked || p->wantToLock > 0);
            assert(p->sharable || p->wantToLock == 0);

            /* We should already hold a lock on the database connection */
            assert(sqlite3_mutex_held(p->db->mutex));

            /* Unless the database is sharable and unlocked, then BtShared.db
            ** should already be set correctly. */
            assert((p->locked == 0 && p->sharable) || p->pBt->db == p->db);

            if (!p->sharable)
            {
                return;
            }
            p->wantToLock++;
            if (p->locked)
            {
                return;
            }

            /* In most cases, we should be able to acquire the lock we
            ** want without having to go throught the ascending lock
            ** procedure that follows.  Just be sure not to block.
            */
            if (sqlite3_mutex_try(p->pBt->mutex) == SQLITE_OK)
            {
                p->pBt->db = p->db;
                p->locked  = 1;
                return;
            }

            /* To avoid deadlock, first release all locks with a larger
            ** BtShared address.  Then acquire our lock.  Then reacquire
            ** the other BtShared locks that we used to hold in ascending
            ** order.
            */
            for (pLater = p->pNext; pLater; pLater = pLater->pNext)
            {
                assert(pLater->sharable);
                assert(pLater->pNext == 0 || pLater->pNext->pBt > pLater->pBt);
                assert(!pLater->locked || pLater->wantToLock > 0);
                if (pLater->locked)
                {
                    unlockBtreeMutex(pLater);
                }
            }
            lockBtreeMutex(p);
            for (pLater = p->pNext; pLater; pLater = pLater->pNext)
            {
                if (pLater->wantToLock)
                {
                    lockBtreeMutex(pLater);
                }
            }
        }