diff --git a/manifest b/manifest index fbe09502d8..de4d25111c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfor\sticket\s#297\s-\sbug\sin\ssqliteSortCompare().\s(CVS\s917) -D 2003-04-18T17:45:14 +C fix\sa\smemory\sleak\sin\sbtree_rb.c.\s(CVS\s918) +D 2003-04-18T22:52:39 F Makefile.in df3a4db41a7450468b5fe934d9dd8f723b631249 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -23,7 +23,7 @@ F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183 F src/auth.c 2dd558dba4d8ffbed25fe1644e9af242f389f3e9 F src/btree.c b9487cceb9ea78af9cbae9def34114902f511736 F src/btree.h 529c98cb0715c62214544fbbe50b946f99a85540 -F src/btree_rb.c 7fa4901a65de66522ce31985833f20b98f7baad4 +F src/btree_rb.c b14803c84dc1c8fb51f5db1542237b7b7d411957 F src/build.c 6694013c86c4c480754f515ddab561302c6e732a F src/copy.c 8699e571994934c78f70761a1458d7b9e9e75073 F src/delete.c af65b26d9d13abbf63fdc4e97b88d26c700b04bb @@ -162,7 +162,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 6e948d9aaea109c683ac4fcc4714e335b545d22b -R d350172ce34cbf799885ede2eb5043c7 +P 4ded1965eb83dee0f28c27ba935d615c77331571 +R 2320d7d2beaa3603b04f97d8f781e745 U drh -Z a203462f3c9a0a6b91b58e9eba1fc107 +Z b76abd0e65d7599880199d2a9894cd84 diff --git a/manifest.uuid b/manifest.uuid index 73d465c469..19a9f9b981 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ded1965eb83dee0f28c27ba935d615c77331571 \ No newline at end of file +1e3d0d094776c2a429fa2a3eebc036a0b6374862 \ No newline at end of file diff --git a/src/btree_rb.c b/src/btree_rb.c index de11f9bbfa..5804288dee 100644 --- a/src/btree_rb.c +++ b/src/btree_rb.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree_rb.c,v 1.3 2003/04/16 01:28:16 drh Exp $ +** $Id: btree_rb.c,v 1.4 2003/04/18 22:52:39 drh Exp $ ** ** This file implements an in-core database using Red-Black balanced ** binary trees. @@ -69,7 +69,7 @@ struct BtRollbackOp { #define ROLLBACK_DROP 4 /* Drop a table */ struct Btree { - BtOps *pOps; /* Function table */ + BtOps *pOps; /* Function table */ int aMetaData[SQLITE_N_BTREE_META]; int next_idx; /* next available table index */ @@ -89,10 +89,10 @@ struct Btree { #define TRANS_INTRANSACTION 1 /* A transaction is in progress */ #define TRANS_INCHECKPOINT 2 /* A checkpoint is in progress */ #define TRANS_ROLLBACK 3 /* We are currently rolling back a checkpoint or - * transaction. */ + * transaction. */ struct BtCursor { - BtCursorOps *pOps; /* Function table */ + BtCursorOps *pOps; /* Function table */ Btree *pBtree; BtRbTree *pTree; int iTree; /* Index of pTree in pBtree */ @@ -298,61 +298,61 @@ static void check_redblack_tree(BtRbTree * tree, char ** msg) while( pNode ){ switch( prev_step ){ case 0: - if( pNode->pLeft ){ - pNode = pNode->pLeft; - }else{ - prev_step = 1; - } - break; + 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; + 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 (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; - } + /* 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; + if( pNode->pParent ){ + if( pNode == pNode->pParent->pLeft ) prev_step = 1; + else prev_step = 2; + } + pNode = pNode->pParent; + break; default: assert(0); } } @@ -408,47 +408,47 @@ static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX) }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); - } + 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 ); + /* 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 ); + /* 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 ); } } } @@ -470,7 +470,8 @@ static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX) * properties have been violated, and pX has an "extra black". This function * performs rotations and color-changes to re-balance the tree. */ -static void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent) +static +void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent) { BtRbNode *pSib; @@ -479,58 +480,58 @@ static void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent if( pX == pParent->pLeft ){ pSib = pParent->pRight; if( pSib && !(pSib->isBlack) ){ - pSib->isBlack = 1; - pParent->isBlack = 0; - leftRotate(pTree, pParent); - pSib = pParent->pRight; + pSib->isBlack = 1; + pParent->isBlack = 0; + leftRotate(pTree, pParent); + pSib = pParent->pRight; } if( !pSib ){ - pX = pParent; + pX = pParent; }else if( - (!pSib->pLeft || pSib->pLeft->isBlack) && - (!pSib->pRight || pSib->pRight->isBlack) ) { - pSib->isBlack = 0; - pX = pParent; + (!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; + 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; + pSib->isBlack = 1; + pParent->isBlack = 0; + rightRotate(pTree, pParent); + pSib = pParent->pLeft; } if( !pSib ){ - pX = pParent; + pX = pParent; }else if( (!pSib->pLeft || pSib->pLeft->isBlack) && - (!pSib->pRight || pSib->pRight->isBlack) ){ - pSib->isBlack = 0; - pX = pParent; + (!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; + 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; @@ -573,10 +574,7 @@ int sqliteRBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree) *ppBtree = (Btree *)sqliteMalloc(sizeof(Btree)); sqliteHashInit(&(*ppBtree)->tblHash, SQLITE_HASH_INT, 0); - /* Create binary trees for tables 0, 1 and 2. SQLite assumes these - * tables always exist. At least I think so? */ - btreeCreateTable(*ppBtree, 0); - btreeCreateTable(*ppBtree, 1); + /* Create a binary tree for the SQLITE_MASTER table at location 2 */ btreeCreateTable(*ppBtree, 2); (*ppBtree)->next_idx = 3; (*ppBtree)->pOps = &sqliteBtreeOps; @@ -620,10 +618,9 @@ static int memBtreeDropTable(Btree* tree, int n) assert( tree->eTransState != TRANS_NONE ); memBtreeClearTable(tree, n); - pTree = sqliteHashFind(&tree->tblHash, 0, n); + pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0); assert(pTree); sqliteFree(pTree); - sqliteHashInsert(&tree->tblHash, 0, n, 0); if( tree->eTransState != TRANS_ROLLBACK ){ BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp)); @@ -636,7 +633,7 @@ static int memBtreeDropTable(Btree* tree, int n) } static int memBtreeKeyCompare(BtCursor* pCur, const void *pKey, int nKey, - int nIgnore, int *pRes) + int nIgnore, int *pRes) { assert(pCur); @@ -647,7 +644,7 @@ static int memBtreeKeyCompare(BtCursor* pCur, const void *pKey, int nKey, *pRes = -1; }else{ *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, - pKey, nKey); + pKey, nKey); } } return SQLITE_OK; @@ -681,7 +678,7 @@ static int memBtreeCursor(Btree* tree, int iTable, int wrFlag, BtCursor **ppCur) * If the key exists already in the tree, just replace the data. */ static int memBtreeInsert(BtCursor* pCur, const void *pKey, int nKey, - const void *pDataInput, int nData) + const void *pDataInput, int nData) { void * pData; int match; @@ -715,18 +712,18 @@ static int memBtreeInsert(BtCursor* pCur, const void *pKey, int nKey, 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); + 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; @@ -800,11 +797,11 @@ static int memBtreeMoveto(BtCursor* pCur, const void *pKey, int nKey, int *pRes) pTmp = pCur->pNode; switch( *pRes ){ case 1: /* cursor > key */ - pCur->pNode = pCur->pNode->pLeft; - break; + pCur->pNode = pCur->pNode->pLeft; + break; case -1: /* cursor < key */ - pCur->pNode = pCur->pNode->pRight; - break; + pCur->pNode = pCur->pNode->pRight; + break; } } @@ -894,8 +891,8 @@ static int memBtreeDelete(BtCursor* pCur) pCur->eSkip = SKIP_PREV; } if( pCur->pBtree->eTransState == TRANS_ROLLBACK ){ - sqliteFree(pZ->pKey); - sqliteFree(pZ->pData); + sqliteFree(pZ->pKey); + sqliteFree(pZ->pData); } } @@ -908,7 +905,7 @@ static int memBtreeDelete(BtCursor* pCur) if( pZ->pParent ){ assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight ); ppParentSlot = ((pZ == pZ->pParent->pLeft) - ?&pZ->pParent->pLeft:&pZ->pParent->pRight); + ?&pZ->pParent->pLeft:&pZ->pParent->pRight); *ppParentSlot = pChild; }else{ pCur->pTree->pHead = pChild; @@ -951,22 +948,22 @@ static int memBtreeClearTable(Btree* tree, int n) else { BtRbNode *pTmp = pNode->pParent; if( tree->eTransState == TRANS_ROLLBACK ){ - sqliteFree( pNode->pKey ); - sqliteFree( pNode->pData ); + sqliteFree( pNode->pKey ); + sqliteFree( pNode->pData ); }else{ - BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp)); - 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); + BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp)); + 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; + if( pTmp->pLeft == pNode ) pTmp->pLeft = 0; + else if( pTmp->pRight == pNode ) pTmp->pRight = 0; } pNode = pTmp; } @@ -1016,13 +1013,13 @@ static int memBtreeNext(BtCursor* pCur, int *pRes) if( pCur->pNode->pRight ){ pCur->pNode = pCur->pNode->pRight; while( pCur->pNode->pLeft ) - pCur->pNode = 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; + pX = pCur->pNode; + pCur->pNode = pX->pParent; } } } @@ -1043,13 +1040,13 @@ static int memBtreePrevious(BtCursor* pCur, int *pRes) if( pCur->pNode->pLeft ){ pCur->pNode = pCur->pNode->pLeft; while( pCur->pNode->pRight ) - pCur->pNode = 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; + pX = pCur->pNode; + pCur->pNode = pX->pParent; } } } @@ -1152,11 +1149,11 @@ static char *memBtreeIntegrityCheck(Btree* tree, int* aRoot, int nRoot) static int memBtreeClose(Btree* tree) { HashElem *p; - for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){ + while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){ tree->eTransState = TRANS_ROLLBACK; - memBtreeClearTable(tree, sqliteHashKeysize(p)); - sqliteFree(sqliteHashData(p)); + memBtreeDropTable(tree, sqliteHashKeysize(p)); } + sqliteHashClear(&tree->tblHash); sqliteFree(tree); return SQLITE_OK; } @@ -1220,30 +1217,30 @@ static void execute_rollback_list(Btree *pBtree, BtRollbackOp *pList) while( pList ){ switch( pList->eOp ){ case ROLLBACK_INSERT: - cur.pTree = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab ); - assert(cur.pTree); - cur.iTree = pList->iTab; - cur.eSkip = SKIP_NONE; - memBtreeInsert( &cur, pList->pKey, - pList->nKey, pList->pData, pList->nData ); - break; + cur.pTree = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab ); + assert(cur.pTree); + cur.iTree = pList->iTab; + cur.eSkip = SKIP_NONE; + memBtreeInsert( &cur, pList->pKey, + pList->nKey, pList->pData, pList->nData ); + break; case ROLLBACK_DELETE: - cur.pTree = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab ); - assert(cur.pTree); - cur.iTree = pList->iTab; - cur.eSkip = SKIP_NONE; - memBtreeMoveto(&cur, pList->pKey, pList->nKey, &res); - assert(res == 0); - memBtreeDelete( &cur ); - break; + cur.pTree = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab ); + assert(cur.pTree); + cur.iTree = pList->iTab; + cur.eSkip = SKIP_NONE; + memBtreeMoveto(&cur, pList->pKey, pList->nKey, &res); + assert(res == 0); + memBtreeDelete( &cur ); + break; case ROLLBACK_CREATE: - btreeCreateTable(pBtree, pList->iTab); - break; + btreeCreateTable(pBtree, pList->iTab); + break; case ROLLBACK_DROP: - memBtreeDropTable(pBtree, pList->iTab); - break; + memBtreeDropTable(pBtree, pList->iTab); + break; default: - assert(0); + assert(0); } sqliteFree(pList->pKey); sqliteFree(pList->pData);