Back to index

php5  5.3.10
Classes | Defines | Typedefs | Functions | Variables
btree_rb.c File Reference
#include "btree.h"
#include "sqliteInt.h"
#include <assert.h>

Go to the source code of this file.

Classes

struct  BtRollbackOp
struct  Rbtree
struct  RbtCursor
struct  BtRbTree
struct  BtRbNode

Defines

#define ROLLBACK_INSERT   1 /* Insert a record */
#define ROLLBACK_DELETE   2 /* Delete a record */
#define ROLLBACK_CREATE   3 /* Create a table */
#define ROLLBACK_DROP   4 /* Drop a table */
#define TRANS_NONE   0 /* No transaction is in progress */
#define TRANS_INTRANSACTION   1 /* A transaction is in progress */
#define TRANS_INCHECKPOINT   2 /* A checkpoint is in progress */
#define TRANS_ROLLBACK
#define SKIP_NONE   0 /* Always step the cursor */
#define SKIP_NEXT   1 /* The next sqliteRbtreeNext() is a no-op */
#define SKIP_PREV   2 /* The next sqliteRbtreePrevious() is a no-op */
#define SKIP_INVALID   3 /* Calls to Next() and Previous() are invalid */

Typedefs

typedef struct BtRbTree
typedef struct BtRbNode
typedef struct BtRollbackOp
typedef struct Rbtree
typedef struct RbtCursor

Functions

static int memRbtreeMoveto (RbtCursor *pCur, const void *pKey, int nKey, int *pRes)
static int memRbtreeClearTable (Rbtree *tree, int n)
static int memRbtreeNext (RbtCursor *pCur, int *pRes)
static int memRbtreeLast (RbtCursor *pCur, int *pRes)
static int memRbtreePrevious (RbtCursor *pCur, int *pRes)
static int checkReadLocks (RbtCursor *pCur)
static int key_compare (void const *pKey1, int nKey1, void const *pKey2, int nKey2)
static void leftRotate (BtRbTree *pTree, BtRbNode *pX)
static void rightRotate (BtRbTree *pTree, BtRbNode *pX)
static char * append_val (char *orig, char const *val)
static char * append_node (char *orig, BtRbNode *pNode, int indent)
static void print_node (BtRbNode *pNode)
static void check_redblack_tree (BtRbTree *tree, char **msg)
static void do_insert_balancing (BtRbTree *pTree, BtRbNode *pX)
static void do_delete_balancing (BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
static void btreeCreateTable (Rbtree *pRbtree, int n)
static void btreeLogRollbackOp (Rbtree *pRbtree, BtRollbackOp *pRollbackOp)
int sqliteRbtreeOpen (const char *zFilename, int mode, int nPg, Btree **ppBtree)
static int memRbtreeCreateTable (Rbtree *tree, int *n)
static int memRbtreeDropTable (Rbtree *tree, int n)
static int memRbtreeKeyCompare (RbtCursor *pCur, const void *pKey, int nKey, int nIgnore, int *pRes)
static int memRbtreeCursor (Rbtree *tree, int iTable, int wrFlag, RbtCursor **ppCur)
static int memRbtreeInsert (RbtCursor *pCur, const void *pKey, int nKey, const void *pDataInput, int nData)
static int memRbtreeDelete (RbtCursor *pCur)
static int memRbtreeFirst (RbtCursor *pCur, int *pRes)
static int memRbtreeKeySize (RbtCursor *pCur, int *pSize)
static int memRbtreeKey (RbtCursor *pCur, int offset, int amt, char *zBuf)
static int memRbtreeDataSize (RbtCursor *pCur, int *pSize)
static int memRbtreeData (RbtCursor *pCur, int offset, int amt, char *zBuf)
static int memRbtreeCloseCursor (RbtCursor *pCur)
static int memRbtreeGetMeta (Rbtree *tree, int *aMeta)
static int memRbtreeUpdateMeta (Rbtree *tree, int *aMeta)
static char * memRbtreeIntegrityCheck (Rbtree *tree, int *aRoot, int nRoot)
static int memRbtreeSetCacheSize (Rbtree *tree, int sz)
static int memRbtreeSetSafetyLevel (Rbtree *pBt, int level)
static int memRbtreeBeginTrans (Rbtree *tree)
static void deleteRollbackList (BtRollbackOp *pOp)
static int memRbtreeCommit (Rbtree *tree)
static int memRbtreeClose (Rbtree *tree)
static void execute_rollback_list (Rbtree *pRbtree, BtRollbackOp *pList)
static int memRbtreeRollback (Rbtree *tree)
static int memRbtreeBeginCkpt (Rbtree *tree)
static int memRbtreeCommitCkpt (Rbtree *tree)
static int memRbtreeRollbackCkpt (Rbtree *tree)
static struct PagermemRbtreePager (Rbtree *tree)
static const char * memRbtreeGetFilename (Rbtree *pBt)
static int memRbtreeCopyFile (Rbtree *pBt, Rbtree *pBt2)

Variables

static BtOps sqliteRbtreeOps
static BtCursorOps sqliteRbtreeCursorOps

Class Documentation

struct BtRollbackOp

Definition at line 55 of file btree_rb.c.

Collaboration diagram for BtRollbackOp:
Class Members
u8 eOp
int iTab
int nData
int nKey
void * pData
void * pKey
BtRollbackOp * pNext
struct Rbtree

Definition at line 73 of file btree_rb.c.

Collaboration diagram for Rbtree:
Class Members
int aMetaData
u8 eTransState
u8 isAnonymous
int next_idx
BtRollbackOp * pCheckRollback
BtRollbackOp * pCheckRollbackTail
BtOps * pOps
BtRollbackOp * pTransRollback
Hash tblHash
struct RbtCursor

Definition at line 95 of file btree_rb.c.

Collaboration diagram for RbtCursor:
Class Members
u8 eSkip
int iTree
BtRbNode * pNode
BtCursorOps * pOps
Rbtree * pRbtree
RbtCursor * pShared
BtRbTree * pTree
u8 wrFlag
struct BtRbTree

Definition at line 114 of file btree_rb.c.

Collaboration diagram for BtRbTree:
Class Members
RbtCursor * pCursors
BtRbNode * pHead
struct BtRbNode

Definition at line 119 of file btree_rb.c.

Collaboration diagram for BtRbNode:
Class Members
u8 isBlack
int nBlackHeight
int nData
int nKey
void * pData
void * pKey
BtRbNode * pLeft
BtRbNode * pParent
BtRbNode * pRight

Define Documentation

#define ROLLBACK_CREATE   3 /* Create a table */

Definition at line 70 of file btree_rb.c.

#define ROLLBACK_DELETE   2 /* Delete a record */

Definition at line 69 of file btree_rb.c.

#define ROLLBACK_DROP   4 /* Drop a table */

Definition at line 71 of file btree_rb.c.

#define ROLLBACK_INSERT   1 /* Insert a record */

Definition at line 68 of file btree_rb.c.

#define SKIP_INVALID   3 /* Calls to Next() and Previous() are invalid */

Definition at line 112 of file btree_rb.c.

#define SKIP_NEXT   1 /* The next sqliteRbtreeNext() is a no-op */

Definition at line 110 of file btree_rb.c.

#define SKIP_NONE   0 /* Always step the cursor */

Definition at line 109 of file btree_rb.c.

#define SKIP_PREV   2 /* The next sqliteRbtreePrevious() is a no-op */

Definition at line 111 of file btree_rb.c.

#define TRANS_INCHECKPOINT   2 /* A checkpoint is in progress */

Definition at line 92 of file btree_rb.c.

#define TRANS_INTRANSACTION   1 /* A transaction is in progress */

Definition at line 91 of file btree_rb.c.

#define TRANS_NONE   0 /* No transaction is in progress */

Definition at line 90 of file btree_rb.c.

#define TRANS_ROLLBACK
Value:
3  /* We are currently rolling back a checkpoint or
                                 * transaction. */

Definition at line 93 of file btree_rb.c.


Typedef Documentation

typedef struct BtRbNode

Definition at line 32 of file btree_rb.c.

typedef struct BtRbTree

Definition at line 31 of file btree_rb.c.

typedef struct BtRollbackOp

Definition at line 33 of file btree_rb.c.

typedef struct RbtCursor

Definition at line 35 of file btree_rb.c.

typedef struct Rbtree

Definition at line 34 of file btree_rb.c.


Function Documentation

static char* append_node ( char *  orig,
BtRbNode pNode,
int  indent 
) [static]

Definition at line 278 of file btree_rb.c.

{
  char buf[128];
  int i;

  for( i=0; i<indent; i++ ){
      orig = append_val(orig, " ");
  }

  sprintf(buf, "%p", pNode);
  orig = append_val(orig, buf);

  if( pNode ){
    indent += 3;
    if( pNode->isBlack ){
      orig = append_val(orig, " B \n");
    }else{
      orig = append_val(orig, " R \n");
    }
    orig = append_node( orig, pNode->pLeft, indent );
    orig = append_node( orig, pNode->pRight, indent );
  }else{
    orig = append_val(orig, "\n");
  }
  return orig;

Here is the call graph for this function:

Here is the caller graph for this function:

static char* append_val ( char *  orig,
char const *  val 
) [static]

Definition at line 261 of file btree_rb.c.

                                                      {
  char *z;
  if( !orig ){
    z = sqliteStrDup( val );
  } else{
    z = 0;
    sqliteSetString(&z, orig, val, (char*)0);
    sqliteFree( orig );
  }
  return z;

Here is the call graph for this function:

Here is the caller graph for this function:

static void btreeCreateTable ( Rbtree pRbtree,
int  n 
) [static]

Definition at line 584 of file btree_rb.c.

{
  BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree));
  sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl);

Here is the call graph for this function:

Here is the caller graph for this function:

static void btreeLogRollbackOp ( Rbtree pRbtree,
BtRollbackOp pRollbackOp 
) [static]

Definition at line 594 of file btree_rb.c.

{
  assert( pRbtree->eTransState == TRANS_INCHECKPOINT ||
      pRbtree->eTransState == TRANS_INTRANSACTION );
  if( pRbtree->eTransState == TRANS_INTRANSACTION ){
    pRollbackOp->pNext = pRbtree->pTransRollback;
    pRbtree->pTransRollback = pRollbackOp;
  }
  if( pRbtree->eTransState == TRANS_INCHECKPOINT ){
    if( !pRbtree->pCheckRollback ){
      pRbtree->pCheckRollbackTail = pRollbackOp;
    }
    pRollbackOp->pNext = pRbtree->pCheckRollback;
    pRbtree->pCheckRollback = pRollbackOp;
  }

Here is the caller graph for this function:

static void check_redblack_tree ( BtRbTree tree,
char **  msg 
) [static]

Definition at line 327 of file btree_rb.c.

{
  BtRbNode *pNode;

  /* 0 -> came from parent 
   * 1 -> came from left
   * 2 -> came from right */
  int prev_step = 0;

  pNode = tree->pHead;
  while( pNode ){
    switch( prev_step ){
      case 0:
        if( pNode->pLeft ){
          pNode = pNode->pLeft;
        }else{ 
          prev_step = 1;
        }
        break;
      case 1:
        if( pNode->pRight ){
          pNode = pNode->pRight;
          prev_step = 0;
        }else{
          prev_step = 2;
        }
        break;
      case 2:
        /* Check red-black property (1) */
        if( !pNode->isBlack &&
            ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
              (pNode->pRight && !pNode->pRight->isBlack) )
          ){
          char buf[128];
          sprintf(buf, "Red node with red child at %p\n", pNode);
          *msg = append_val(*msg, buf);
          *msg = append_node(*msg, tree->pHead, 0);
          *msg = append_val(*msg, "\n");
        }

        /* Check red-black property (2) */
        { 
          int leftHeight = 0;
          int rightHeight = 0;
          if( pNode->pLeft ){
            leftHeight += pNode->pLeft->nBlackHeight;
            leftHeight += (pNode->pLeft->isBlack?1:0);
          }
          if( pNode->pRight ){
            rightHeight += pNode->pRight->nBlackHeight;
            rightHeight += (pNode->pRight->isBlack?1:0);
          }
          if( leftHeight != rightHeight ){
            char buf[128];
            sprintf(buf, "Different black-heights at %p\n", pNode);
            *msg = append_val(*msg, buf);
            *msg = append_node(*msg, tree->pHead, 0);
            *msg = append_val(*msg, "\n");
          }
          pNode->nBlackHeight = leftHeight;
        }

        if( pNode->pParent ){
          if( pNode == pNode->pParent->pLeft ) prev_step = 1;
          else prev_step = 2;
        }
        pNode = pNode->pParent;
        break;
      default: assert(0);
    }
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static int checkReadLocks ( RbtCursor pCur) [static]

Definition at line 159 of file btree_rb.c.

                                          {
  RbtCursor *p;
  assert( pCur->wrFlag );
  for(p=pCur->pTree->pCursors; p; p=p->pShared){
    if( p!=pCur ){
      if( p->wrFlag==0 ) return SQLITE_LOCKED;
      p->pNode = 0;
    }
  }
  return SQLITE_OK;

Here is the caller graph for this function:

static void deleteRollbackList ( BtRollbackOp pOp) [static]

Definition at line 1276 of file btree_rb.c.

                                                 {
  while( pOp ){
    BtRollbackOp *pTmp = pOp->pNext;
    sqliteFree(pOp->pData);
    sqliteFree(pOp->pKey);
    sqliteFree(pOp);
    pOp = pTmp;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_delete_balancing ( BtRbTree pTree,
BtRbNode pX,
BtRbNode pParent 
) [static]

Definition at line 513 of file btree_rb.c.

{
  BtRbNode *pSib; 

  /* TODO: Comment this code! */
  while( pX != pTree->pHead && (!pX || pX->isBlack) ){
    if( pX == pParent->pLeft ){
      pSib = pParent->pRight;
      if( pSib && !(pSib->isBlack) ){
        pSib->isBlack = 1;
        pParent->isBlack = 0;
        leftRotate(pTree, pParent);
        pSib = pParent->pRight;
      }
      if( !pSib ){
        pX = pParent;
      }else if( 
          (!pSib->pLeft  || pSib->pLeft->isBlack) &&
          (!pSib->pRight || pSib->pRight->isBlack) ) {
        pSib->isBlack = 0;
        pX = pParent;
      }else{
        if( (!pSib->pRight || pSib->pRight->isBlack) ){
          if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
          pSib->isBlack = 0;
          rightRotate( pTree, pSib );
          pSib = pParent->pRight;
        }
        pSib->isBlack = pParent->isBlack;
        pParent->isBlack = 1;
        if( pSib->pRight ) pSib->pRight->isBlack = 1;
        leftRotate(pTree, pParent);
        pX = pTree->pHead;
      }
    }else{
      pSib = pParent->pLeft;
      if( pSib && !(pSib->isBlack) ){
        pSib->isBlack = 1;
        pParent->isBlack = 0;
        rightRotate(pTree, pParent);
        pSib = pParent->pLeft;
      }
      if( !pSib ){
        pX = pParent;
      }else if( 
          (!pSib->pLeft  || pSib->pLeft->isBlack) &&
          (!pSib->pRight || pSib->pRight->isBlack) ){
        pSib->isBlack = 0;
        pX = pParent;
      }else{
        if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
          if( pSib->pRight ) pSib->pRight->isBlack = 1;
          pSib->isBlack = 0;
          leftRotate( pTree, pSib );
          pSib = pParent->pLeft;
        }
        pSib->isBlack = pParent->isBlack;
        pParent->isBlack = 1;
        if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
        rightRotate(pTree, pParent);
        pX = pTree->pHead;
      }
    }
    pParent = pX->pParent;
  }
  if( pX ) pX->isBlack = 1;

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_insert_balancing ( BtRbTree pTree,
BtRbNode pX 
) [static]

Definition at line 406 of file btree_rb.c.

{
  /* In the first iteration of this loop, pX points to the red node just
   * inserted in the tree. If the parent of pX exists (pX is not the root
   * node) and is red, then the properties of the red-black tree are
   * violated.
   *
   * At the start of any subsequent iterations, pX points to a red node
   * with a red parent. In all other respects the tree is a legal red-black
   * binary tree. */
  while( pX != pTree->pHead && !pX->pParent->isBlack ){
    BtRbNode *pUncle;
    BtRbNode *pGrandparent;

    /* Grandparent of pX must exist and must be black. */
    pGrandparent = pX->pParent->pParent;
    assert( pGrandparent );
    assert( pGrandparent->isBlack );

    /* Uncle of pX may or may not exist. */
    if( pX->pParent == pGrandparent->pLeft ) 
      pUncle = pGrandparent->pRight;
    else 
      pUncle = pGrandparent->pLeft;

    /* If the uncle of pX exists and is red, we do the following:
     *       |                 |
     *      G(b)              G(r)
     *      /  \              /  \        
     *   U(r)   P(r)       U(b)  P(b)
     *            \                \
     *           X(r)              X(r)
     *
     *     BEFORE             AFTER
     * pX is then set to G. If the parent of G is red, then the while loop
     * will run again.  */
    if( pUncle && !pUncle->isBlack ){
      pGrandparent->isBlack = 0;
      pUncle->isBlack = 1;
      pX->pParent->isBlack = 1;
      pX = pGrandparent;
    }else{

      if( pX->pParent == pGrandparent->pLeft ){
        if( pX == pX->pParent->pRight ){
          /* If pX is a right-child, do the following transform, essentially
           * to change pX into a left-child: 
           *       |                  | 
           *      G(b)               G(b)
           *      /  \               /  \        
           *   P(r)   U(b)        X(r)  U(b)
           *      \                /
           *     X(r)            P(r) <-- new X
           *
           *     BEFORE             AFTER
           */
          pX = pX->pParent;
          leftRotate(pTree, pX);
        }

        /* Do the following transform, which balances the tree :) 
         *       |                  | 
         *      G(b)               P(b)
         *      /  \               /  \        
         *   P(r)   U(b)        X(r)  G(r)
         *    /                         \
         *  X(r)                        U(b)
         *
         *     BEFORE             AFTER
         */
        assert( pGrandparent == pX->pParent->pParent );
        pGrandparent->isBlack = 0;
        pX->pParent->isBlack = 1;
        rightRotate( pTree, pGrandparent );

      }else{
        /* This code is symetric to the illustrated case above. */
        if( pX == pX->pParent->pLeft ){
          pX = pX->pParent;
          rightRotate(pTree, pX);
        }
        assert( pGrandparent == pX->pParent->pParent );
        pGrandparent->isBlack = 0;
        pX->pParent->isBlack = 1;
        leftRotate( pTree, pGrandparent );
      }
    }
  }
  pTree->pHead->isBlack = 1;

Here is the call graph for this function:

Here is the caller graph for this function:

static void execute_rollback_list ( Rbtree pRbtree,
BtRollbackOp pList 
) [static]

Definition at line 1316 of file btree_rb.c.

{
  BtRollbackOp *pTmp;
  RbtCursor cur;
  int res;

  cur.pRbtree = pRbtree;
  cur.wrFlag = 1;
  while( pList ){
    switch( pList->eOp ){
      case ROLLBACK_INSERT:
        cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
        assert(cur.pTree);
        cur.iTree  = pList->iTab;
        cur.eSkip  = SKIP_NONE;
        memRbtreeInsert( &cur, pList->pKey,
            pList->nKey, pList->pData, pList->nData );
        break;
      case ROLLBACK_DELETE:
        cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
        assert(cur.pTree);
        cur.iTree  = pList->iTab;
        cur.eSkip  = SKIP_NONE;
        memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
        assert(res == 0);
        memRbtreeDelete( &cur );
        break;
      case ROLLBACK_CREATE:
        btreeCreateTable(pRbtree, pList->iTab);
        break;
      case ROLLBACK_DROP:
        memRbtreeDropTable(pRbtree, pList->iTab);
        break;
      default:
        assert(0);
    }
    sqliteFree(pList->pKey);
    sqliteFree(pList->pData);
    pTmp = pList->pNext;
    sqliteFree(pList);
    pList = pTmp;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static int key_compare ( void const *  pKey1,
int  nKey1,
void const *  pKey2,
int  nKey2 
) [static]

Definition at line 181 of file btree_rb.c.

{
  int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2);
  if( mcmp == 0){
    if( nKey1 == nKey2 ) return 0;
    return ((nKey1 < nKey2)?-1:1);
  }
  return ((mcmp>0)?1:-1);

Here is the caller graph for this function:

static void leftRotate ( BtRbTree pTree,
BtRbNode pX 
) [static]

Definition at line 204 of file btree_rb.c.

{
  BtRbNode *pY;
  BtRbNode *pb;
  pY = pX->pRight;
  pb = pY->pLeft;

  pY->pParent = pX->pParent;
  if( pX->pParent ){
    if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
    else pX->pParent->pRight = pY;
  }
  pY->pLeft = pX;
  pX->pParent = pY;
  pX->pRight = pb;
  if( pb ) pb->pParent = pX;
  if( pTree->pHead == pX ) pTree->pHead = pY;

Here is the caller graph for this function:

static int memRbtreeBeginCkpt ( Rbtree tree) [static]

Definition at line 1372 of file btree_rb.c.

static int memRbtreeBeginTrans ( Rbtree tree) [static]

Definition at line 1263 of file btree_rb.c.

{
  if( tree->eTransState != TRANS_NONE ) 
    return SQLITE_ERROR;

  assert( tree->pTransRollback == 0 );
  tree->eTransState = TRANS_INTRANSACTION;
  return SQLITE_OK;
static int memRbtreeClearTable ( Rbtree tree,
int  n 
) [static]

Definition at line 1025 of file btree_rb.c.

{
  BtRbTree *pTree;
  BtRbNode *pNode;

  pTree = sqliteHashFind(&tree->tblHash, 0, n);
  assert(pTree);

  pNode = pTree->pHead;
  while( pNode ){
    if( pNode->pLeft ){
      pNode = pNode->pLeft;
    }
    else if( pNode->pRight ){
      pNode = pNode->pRight;
    }
    else {
      BtRbNode *pTmp = pNode->pParent;
      if( tree->eTransState == TRANS_ROLLBACK ){
        sqliteFree( pNode->pKey );
        sqliteFree( pNode->pData );
      }else{
        BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp));
        if( pRollbackOp==0 ) return SQLITE_NOMEM;
        pRollbackOp->eOp = ROLLBACK_INSERT;
        pRollbackOp->iTab = n;
        pRollbackOp->nKey = pNode->nKey;
        pRollbackOp->pKey = pNode->pKey;
        pRollbackOp->nData = pNode->nData;
        pRollbackOp->pData = pNode->pData;
        btreeLogRollbackOp(tree, pRollbackOp);
      }
      sqliteFree( pNode );
      if( pTmp ){
        if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
        else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
      }
      pNode = pTmp;
    }
  }

  pTree->pHead = 0;
  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static int memRbtreeClose ( Rbtree tree) [static]

Definition at line 1300 of file btree_rb.c.

Here is the call graph for this function:

static int memRbtreeCloseCursor ( RbtCursor pCur) [static]

Definition at line 1208 of file btree_rb.c.

{
  if( pCur->pTree->pCursors==pCur ){
    pCur->pTree->pCursors = pCur->pShared;
  }else{
    RbtCursor *p = pCur->pTree->pCursors;
    while( p && p->pShared!=pCur ){ p = p->pShared; }
    assert( p!=0 );
    if( p ){
      p->pShared = pCur->pShared;
    }
  }
  sqliteFree(pCur);
  return SQLITE_OK;

Here is the call graph for this function:

static int memRbtreeCommit ( Rbtree tree) [static]

Definition at line 1286 of file btree_rb.c.

                                        {
  /* Just delete pTransRollback and pCheckRollback */
  deleteRollbackList(tree->pCheckRollback);
  deleteRollbackList(tree->pTransRollback);
  tree->pTransRollback = 0;
  tree->pCheckRollback = 0;
  tree->pCheckRollbackTail = 0;
  tree->eTransState = TRANS_NONE;
  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static int memRbtreeCommitCkpt ( Rbtree tree) [static]

Definition at line 1383 of file btree_rb.c.

static int memRbtreeCopyFile ( Rbtree pBt,
Rbtree pBt2 
) [static]

Definition at line 1437 of file btree_rb.c.

                                                       {
  return SQLITE_INTERNAL;  /* Not implemented */
static int memRbtreeCreateTable ( Rbtree tree,
int n 
) [static]

Definition at line 643 of file btree_rb.c.

{
  assert( tree->eTransState != TRANS_NONE );

  *n = tree->next_idx++;
  btreeCreateTable(tree, *n);
  if( sqlite_malloc_failed ) return SQLITE_NOMEM;

  /* Set up the rollback structure (if we are not doing this as part of a
   * rollback) */
  if( tree->eTransState != TRANS_ROLLBACK ){
    BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
    if( pRollbackOp==0 ) return SQLITE_NOMEM;
    pRollbackOp->eOp = ROLLBACK_DROP;
    pRollbackOp->iTab = *n;
    btreeLogRollbackOp(tree, pRollbackOp);
  }

  return SQLITE_OK;

Here is the call graph for this function:

static int memRbtreeCursor ( Rbtree tree,
int  iTable,
int  wrFlag,
RbtCursor **  ppCur 
) [static]

Definition at line 713 of file btree_rb.c.

 {
  RbtCursor *pCur;
  assert(tree);
  pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
  pCur->pTree  = sqliteHashFind(&tree->tblHash, 0, iTable);
  assert( pCur->pTree );
  pCur->pRbtree = tree;
  pCur->iTree  = iTable;
  pCur->pOps = &sqliteRbtreeCursorOps;
  pCur->wrFlag = wrFlag;
  pCur->pShared = pCur->pTree->pCursors;
  pCur->pTree->pCursors = pCur;

  assert( (*ppCur)->pTree );
  return SQLITE_OK;

Here is the call graph for this function:

static int memRbtreeData ( RbtCursor pCur,
int  offset,
int  amt,
char *  zBuf 
) [static]

Definition at line 1196 of file btree_rb.c.

{
  if( !pCur->pNode ) return 0;
  if( (amt + offset) <= pCur->pNode->nData ){
    memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
  }else{
    memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
    amt = pCur->pNode->nData-offset;
  }
  return amt;
static int memRbtreeDataSize ( RbtCursor pCur,
int pSize 
) [static]

Definition at line 1186 of file btree_rb.c.

{
  if( pCur->pNode ){
    *pSize = pCur->pNode->nData;
  }else{
    *pSize = 0;
  }
  return SQLITE_OK;
static int memRbtreeDelete ( RbtCursor pCur) [static]

Definition at line 919 of file btree_rb.c.

{
  BtRbNode *pZ;      /* The one being deleted */
  BtRbNode *pChild;  /* The child of the spliced out node */

  /* It is illegal to call sqliteRbtreeDelete() if we are
  ** not in a transaction */
  assert( pCur->pRbtree->eTransState != TRANS_NONE );

  /* Make sure some other cursor isn't trying to read this same table */
  if( checkReadLocks(pCur) ){
    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
  }

  pZ = pCur->pNode;
  if( !pZ ){
    return SQLITE_OK;
  }

  /* If we are not currently doing a rollback, set up a rollback op for this 
   * deletion */
  if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
    BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
    if( pOp==0 ) return SQLITE_NOMEM;
    pOp->iTab = pCur->iTree;
    pOp->nKey = pZ->nKey;
    pOp->pKey = pZ->pKey;
    pOp->nData = pZ->nData;
    pOp->pData = pZ->pData;
    pOp->eOp = ROLLBACK_INSERT;
    btreeLogRollbackOp(pCur->pRbtree, pOp);
  }

  /* First do a standard binary-tree delete (node pZ is to be deleted). How
   * to do this depends on how many children pZ has:
   *
   * If pZ has no children or one child, then splice out pZ.  If pZ has two
   * children, splice out the successor of pZ and replace the key and data of
   * pZ with the key and data of the spliced out successor.  */
  if( pZ->pLeft && pZ->pRight ){
    BtRbNode *pTmp;
    int dummy;
    pCur->eSkip = SKIP_NONE;
    memRbtreeNext(pCur, &dummy);
    assert( dummy == 0 );
    if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
      sqliteFree(pZ->pKey);
      sqliteFree(pZ->pData);
    }
    pZ->pData = pCur->pNode->pData;
    pZ->nData = pCur->pNode->nData;
    pZ->pKey = pCur->pNode->pKey;
    pZ->nKey = pCur->pNode->nKey;
    pTmp = pZ;
    pZ = pCur->pNode;
    pCur->pNode = pTmp;
    pCur->eSkip = SKIP_NEXT;
  }else{
    int res;
    pCur->eSkip = SKIP_NONE;
    memRbtreeNext(pCur, &res);
    pCur->eSkip = SKIP_NEXT;
    if( res ){
      memRbtreeLast(pCur, &res);
      memRbtreePrevious(pCur, &res);
      pCur->eSkip = SKIP_PREV;
    }
    if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
        sqliteFree(pZ->pKey);
        sqliteFree(pZ->pData);
    }
  }

  /* pZ now points at the node to be spliced out. This block does the 
   * splicing. */
  {
    BtRbNode **ppParentSlot = 0;
    assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */
    pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight);
    if( pZ->pParent ){
      assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
      ppParentSlot = ((pZ == pZ->pParent->pLeft)
          ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
      *ppParentSlot = pChild;
    }else{
      pCur->pTree->pHead = pChild;
    }
    if( pChild ) pChild->pParent = pZ->pParent;
  }

  /* pZ now points at the spliced out node. pChild is the only child of pZ, or
   * NULL if pZ has no children. If pZ is black, and not the tree root, then we
   * will have violated the "same number of black nodes in every path to a
   * leaf" property of the red-black tree. The code in do_delete_balancing()
   * repairs this. */
  if( pZ->isBlack ){ 
    do_delete_balancing(pCur->pTree, pChild, pZ->pParent);
  }

  sqliteFree(pZ);
  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static int memRbtreeDropTable ( Rbtree tree,
int  n 
) [static]

Definition at line 667 of file btree_rb.c.

{
  BtRbTree *pTree;
  assert( tree->eTransState != TRANS_NONE );

  memRbtreeClearTable(tree, n);
  pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
  assert(pTree);
  assert( pTree->pCursors==0 );
  sqliteFree(pTree);

  if( tree->eTransState != TRANS_ROLLBACK ){
    BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
    if( pRollbackOp==0 ) return SQLITE_NOMEM;
    pRollbackOp->eOp = ROLLBACK_CREATE;
    pRollbackOp->iTab = n;
    btreeLogRollbackOp(tree, pRollbackOp);
  }

  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static int memRbtreeFirst ( RbtCursor pCur,
int pRes 
) [static]

Definition at line 1070 of file btree_rb.c.

{
  if( pCur->pTree->pHead ){
    pCur->pNode = pCur->pTree->pHead;
    while( pCur->pNode->pLeft ){
      pCur->pNode = pCur->pNode->pLeft;
    }
  }
  if( pCur->pNode ){
    *pRes = 0;
  }else{
    *pRes = 1;
  }
  pCur->eSkip = SKIP_NONE;
  return SQLITE_OK;
static const char* memRbtreeGetFilename ( Rbtree pBt) [static]

Definition at line 1430 of file btree_rb.c.

                                                    {
  return 0;  /* A NULL return indicates there is no underlying file */
static int memRbtreeGetMeta ( Rbtree tree,
int aMeta 
) [static]

Definition at line 1224 of file btree_rb.c.

{
  memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META );
  return SQLITE_OK;
static int memRbtreeInsert ( RbtCursor pCur,
const void *  pKey,
int  nKey,
const void *  pDataInput,
int  nData 
) [static]

Definition at line 744 of file btree_rb.c.

 {
  void * pData;
  int match;

  /* It is illegal to call sqliteRbtreeInsert() if we are
  ** not in a transaction */
  assert( pCur->pRbtree->eTransState != TRANS_NONE );

  /* Make sure some other cursor isn't trying to read this same table */
  if( checkReadLocks(pCur) ){
    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
  }

  /* Take a copy of the input data now, in case we need it for the 
   * replace case */
  pData = sqliteMallocRaw(nData);
  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
  memcpy(pData, pDataInput, nData);

  /* Move the cursor to a node near the key to be inserted. If the key already
   * exists in the table, then (match == 0). In this case we can just replace
   * the data associated with the entry, we don't need to manipulate the tree.
   * 
   * If there is no exact match, then the cursor points at what would be either
   * the predecessor (match == -1) or successor (match == 1) of the
   * searched-for key, were it to be inserted. The new node becomes a child of
   * this node.
   * 
   * The new node is initially red.
   */
  memRbtreeMoveto( pCur, pKey, nKey, &match);
  if( match ){
    BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
    if( pNode==0 ) return SQLITE_NOMEM;
    pNode->nKey = nKey;
    pNode->pKey = sqliteMallocRaw(nKey);
    if( sqlite_malloc_failed ) return SQLITE_NOMEM;
    memcpy(pNode->pKey, pKey, nKey);
    pNode->nData = nData;
    pNode->pData = pData; 
    if( pCur->pNode ){
      switch( match ){
        case -1:
          assert( !pCur->pNode->pRight );
          pNode->pParent = pCur->pNode;
          pCur->pNode->pRight = pNode;
          break;
        case 1:
          assert( !pCur->pNode->pLeft );
          pNode->pParent = pCur->pNode;
          pCur->pNode->pLeft = pNode;
          break;
        default:
          assert(0);
      }
    }else{
      pCur->pTree->pHead = pNode;
    }

    /* Point the cursor at the node just inserted, as per SQLite requirements */
    pCur->pNode = pNode;

    /* A new node has just been inserted, so run the balancing code */
    do_insert_balancing(pCur->pTree, pNode);

    /* Set up a rollback-op in case we have to roll this operation back */
    if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
      BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
      if( pOp==0 ) return SQLITE_NOMEM;
      pOp->eOp = ROLLBACK_DELETE;
      pOp->iTab = pCur->iTree;
      pOp->nKey = pNode->nKey;
      pOp->pKey = sqliteMallocRaw( pOp->nKey );
      if( sqlite_malloc_failed ) return SQLITE_NOMEM;
      memcpy( pOp->pKey, pNode->pKey, pOp->nKey );
      btreeLogRollbackOp(pCur->pRbtree, pOp);
    }

  }else{ 
    /* No need to insert a new node in the tree, as the key already exists.
     * Just clobber the current nodes data. */

    /* Set up a rollback-op in case we have to roll this operation back */
    if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
      BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
      if( pOp==0 ) return SQLITE_NOMEM;
      pOp->iTab = pCur->iTree;
      pOp->nKey = pCur->pNode->nKey;
      pOp->pKey = sqliteMallocRaw( pOp->nKey );
      if( sqlite_malloc_failed ) return SQLITE_NOMEM;
      memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey );
      pOp->nData = pCur->pNode->nData;
      pOp->pData = pCur->pNode->pData;
      pOp->eOp = ROLLBACK_INSERT;
      btreeLogRollbackOp(pCur->pRbtree, pOp);
    }else{
      sqliteFree( pCur->pNode->pData );
    }

    /* Actually clobber the nodes data */
    pCur->pNode->pData = pData;
    pCur->pNode->nData = nData;
  }

  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static char* memRbtreeIntegrityCheck ( Rbtree tree,
int aRoot,
int  nRoot 
) [static]

Definition at line 1241 of file btree_rb.c.

{
  char * msg = 0;
  HashElem *p;

  for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
    BtRbTree *pTree = sqliteHashData(p);
    check_redblack_tree(pTree, &msg);
  }

  return msg;

Here is the call graph for this function:

static int memRbtreeKey ( RbtCursor pCur,
int  offset,
int  amt,
char *  zBuf 
) [static]

Definition at line 1174 of file btree_rb.c.

{
  if( !pCur->pNode ) return 0;
  if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
    memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
  }else{
    memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
    amt = pCur->pNode->nKey-offset;
  }
  return amt;
static int memRbtreeKeyCompare ( RbtCursor pCur,
const void *  pKey,
int  nKey,
int  nIgnore,
int pRes 
) [static]

Definition at line 689 of file btree_rb.c.

{
  assert(pCur);

  if( !pCur->pNode ) {
    *pRes = -1;
  } else {
    if( (pCur->pNode->nKey - nIgnore) < 0 ){
      *pRes = -1;
    }else{
      *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, 
          pKey, nKey);
    }
  }
  return SQLITE_OK;

Here is the call graph for this function:

static int memRbtreeKeySize ( RbtCursor pCur,
int pSize 
) [static]

Definition at line 1164 of file btree_rb.c.

{
  if( pCur->pNode ){
    *pSize = pCur->pNode->nKey;
  }else{
    *pSize = 0;
  }
  return SQLITE_OK;
static int memRbtreeLast ( RbtCursor pCur,
int pRes 
) [static]

Definition at line 1087 of file btree_rb.c.

{
  if( pCur->pTree->pHead ){
    pCur->pNode = pCur->pTree->pHead;
    while( pCur->pNode->pRight ){
      pCur->pNode = pCur->pNode->pRight;
    }
  }
  if( pCur->pNode ){
    *pRes = 0;
  }else{
    *pRes = 1;
  }
  pCur->eSkip = SKIP_NONE;
  return SQLITE_OK;

Here is the caller graph for this function:

static int memRbtreeMoveto ( RbtCursor pCur,
const void *  pKey,
int  nKey,
int pRes 
) [static]

Definition at line 870 of file btree_rb.c.

 {
  BtRbNode *pTmp = 0;

  pCur->pNode = pCur->pTree->pHead;
  *pRes = -1;
  while( pCur->pNode && *pRes ) {
    *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
    pTmp = pCur->pNode;
    switch( *pRes ){
      case 1:    /* cursor > key */
        pCur->pNode = pCur->pNode->pLeft;
        break;
      case -1:   /* cursor < key */
        pCur->pNode = pCur->pNode->pRight;
        break;
    }
  } 

  /* If (pCur->pNode == NULL), then we have failed to find a match. Set
   * pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
   * last node traversed in the search. In either case the relation ship
   * between pTmp and the searched for key is already stored in *pRes. pTmp is
   * either the successor or predecessor of the key we tried to move to. */
  if( !pCur->pNode ) pCur->pNode = pTmp;
  pCur->eSkip = SKIP_NONE;

  return SQLITE_OK;

Here is the call graph for this function:

Here is the caller graph for this function:

static int memRbtreeNext ( RbtCursor pCur,
int pRes 
) [static]

Definition at line 1110 of file btree_rb.c.

{
  if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
    if( pCur->pNode->pRight ){
      pCur->pNode = pCur->pNode->pRight;
      while( pCur->pNode->pLeft )
        pCur->pNode = pCur->pNode->pLeft;
    }else{
      BtRbNode * pX = pCur->pNode;
      pCur->pNode = pX->pParent;
      while( pCur->pNode && (pCur->pNode->pRight == pX) ){
        pX = pCur->pNode;
        pCur->pNode = pX->pParent;
      }
    }
  }
  pCur->eSkip = SKIP_NONE;

  if( !pCur->pNode ){
    *pRes = 1;
  }else{
    *pRes = 0;
  }

  return SQLITE_OK;

Here is the caller graph for this function:

static struct Pager* memRbtreePager ( Rbtree tree) [static, read]

Definition at line 1422 of file btree_rb.c.

{
  return 0;
static int memRbtreePrevious ( RbtCursor pCur,
int pRes 
) [static]

Definition at line 1137 of file btree_rb.c.

{
  if( pCur->pNode && pCur->eSkip != SKIP_PREV ){
    if( pCur->pNode->pLeft ){
      pCur->pNode = pCur->pNode->pLeft;
      while( pCur->pNode->pRight )
        pCur->pNode = pCur->pNode->pRight;
    }else{
      BtRbNode * pX = pCur->pNode;
      pCur->pNode = pX->pParent;
      while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
        pX = pCur->pNode;
        pCur->pNode = pX->pParent;
      }
    }
  }
  pCur->eSkip = SKIP_NONE;

  if( !pCur->pNode ){
    *pRes = 1;
  }else{
    *pRes = 0;
  }

  return SQLITE_OK;

Here is the caller graph for this function:

static int memRbtreeRollback ( Rbtree tree) [static]

Definition at line 1360 of file btree_rb.c.

Here is the call graph for this function:

static int memRbtreeRollbackCkpt ( Rbtree tree) [static]

Definition at line 1397 of file btree_rb.c.

Here is the call graph for this function:

static int memRbtreeSetCacheSize ( Rbtree tree,
int  sz 
) [static]

Definition at line 1254 of file btree_rb.c.

{
  return SQLITE_OK;
static int memRbtreeSetSafetyLevel ( Rbtree pBt,
int  level 
) [static]

Definition at line 1259 of file btree_rb.c.

                                                          {
  return SQLITE_OK;
static int memRbtreeUpdateMeta ( Rbtree tree,
int aMeta 
) [static]

Definition at line 1230 of file btree_rb.c.

{
  memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META );
  return SQLITE_OK;
static void print_node ( BtRbNode pNode) [static]

Definition at line 310 of file btree_rb.c.

{
    char * str = append_node(0, pNode, 0);
    printf("%s", str);

    /* Suppress a warning message about print_node() being unused */
    (void)print_node;

Here is the call graph for this function:

static void rightRotate ( BtRbTree pTree,
BtRbNode pX 
) [static]

Definition at line 236 of file btree_rb.c.

{
  BtRbNode *pY;
  BtRbNode *pb;
  pY = pX->pLeft;
  pb = pY->pRight;

  pY->pParent = pX->pParent;
  if( pX->pParent ){
    if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
    else pX->pParent->pRight = pY;
  }
  pY->pRight = pX;
  pX->pParent = pY;
  pX->pLeft = pb;
  if( pb ) pb->pParent = pX;
  if( pTree->pHead == pX ) pTree->pHead = pY;

Here is the caller graph for this function:

int sqliteRbtreeOpen ( const char *  zFilename,
int  mode,
int  nPg,
Btree **  ppBtree 
)

Definition at line 611 of file btree_rb.c.

 {
  Rbtree **ppRbtree = (Rbtree**)ppBtree;
  *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
  if( sqlite_malloc_failed ) goto open_no_mem;
  sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);

  /* Create a binary tree for the SQLITE_MASTER table at location 2 */
  btreeCreateTable(*ppRbtree, 2);
  if( sqlite_malloc_failed ) goto open_no_mem;
  (*ppRbtree)->next_idx = 3;
  (*ppRbtree)->pOps = &sqliteRbtreeOps;
  /* Set file type to 4; this is so that "attach ':memory:' as ...."  does not
  ** think that the database in uninitialised and refuse to attach
  */
  (*ppRbtree)->aMetaData[2] = 4;
  
  return SQLITE_OK;

open_no_mem:
  *ppBtree = 0;
  return SQLITE_NOMEM;

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:
 {
    (int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto,
    (int(*)(BtCursor*)) memRbtreeDelete,
    (int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert,
    (int(*)(BtCursor*,int*)) memRbtreeFirst,
    (int(*)(BtCursor*,int*)) memRbtreeLast,
    (int(*)(BtCursor*,int*)) memRbtreeNext,
    (int(*)(BtCursor*,int*)) memRbtreePrevious,
    (int(*)(BtCursor*,int*)) memRbtreeKeySize,
    (int(*)(BtCursor*,int,int,char*)) memRbtreeKey,
    (int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare,
    (int(*)(BtCursor*,int*)) memRbtreeDataSize,
    (int(*)(BtCursor*,int,int,char*)) memRbtreeData,
    (int(*)(BtCursor*)) memRbtreeCloseCursor,




}

Definition at line 39 of file btree_rb.c.

static BtOps sqliteRbtreeOps [static]
Initial value:
 {
    (int(*)(Btree*)) memRbtreeClose,
    (int(*)(Btree*,int)) memRbtreeSetCacheSize,
    (int(*)(Btree*,int)) memRbtreeSetSafetyLevel,
    (int(*)(Btree*)) memRbtreeBeginTrans,
    (int(*)(Btree*)) memRbtreeCommit,
    (int(*)(Btree*)) memRbtreeRollback,
    (int(*)(Btree*)) memRbtreeBeginCkpt,
    (int(*)(Btree*)) memRbtreeCommitCkpt,
    (int(*)(Btree*)) memRbtreeRollbackCkpt,
    (int(*)(Btree*,int*)) memRbtreeCreateTable,
    (int(*)(Btree*,int*)) memRbtreeCreateTable,
    (int(*)(Btree*,int)) memRbtreeDropTable,
    (int(*)(Btree*,int)) memRbtreeClearTable,
    (int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor,
    (int(*)(Btree*,int*)) memRbtreeGetMeta,
    (int(*)(Btree*,int*)) memRbtreeUpdateMeta,
    (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
    (const char*(*)(Btree*)) memRbtreeGetFilename,
    (int(*)(Btree*,Btree*)) memRbtreeCopyFile,
    (struct Pager*(*)(Btree*)) memRbtreePager,



}

Definition at line 38 of file btree_rb.c.