From 6f235cc5de8bce58e90201397cd44f63e5324c50 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Thu, 4 Jun 2009 14:46:08 +0000 Subject: [PATCH] Reduce the stack usage of balance_quick(). (CVS 6715) FossilOrigin-Name: e7ad68e93b19b59cb16205c4b48fd9d6492dbb02 --- manifest | 14 ++++----- manifest.uuid | 2 +- src/btree.c | 83 +++++++++++++++++++++++++++------------------------ 3 files changed, 52 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 62014dfe2d..bca1af7cf5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\supdates\sto\scomments\sin\stest\sscripts.\s(CVS\s6714) -D 2009-06-04T02:47:04 +C Reduce\sthe\sstack\susage\sof\sbalance_quick().\s(CVS\s6715) +D 2009-06-04T14:46:08 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 8b8fb7823264331210cddf103831816c286ba446 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -106,7 +106,7 @@ F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71 F src/backup.c ff50af53184a5fd7bdee4d620b5dabef74717c79 F src/bitvec.c 0ef0651714728055d43de7a4cdd95e703fac0119 F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c -F src/btree.c 708b9373d573aeb6c61899ed2fcc498a98a20b12 +F src/btree.c ca83629673417074c919b9dc4a2003d69d52de9f F src/btree.h f70b694e8c163227369a66863b01fbff9009f323 F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5 F src/build.c 20e02fd72249159ff6829009f3029d16d59cdff5 @@ -733,7 +733,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P bc6c2d894b711361808a19b673803186d3a28369 -R 9dd9dd8b1b74bf1fededc820a0a5d128 -U shane -Z 1d673d399a0b5a991b96f6d097baa1ce +P 453ff88f73a01a54ff464563effdb63014b1972c +R 10cf14b6134b53081d5b29cc87d78754 +U danielk1977 +Z ea544126f0e51edd041f5bf4bda237c8 diff --git a/manifest.uuid b/manifest.uuid index 7b243df3b9..a66193193c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -453ff88f73a01a54ff464563effdb63014b1972c \ No newline at end of file +e7ad68e93b19b59cb16205c4b48fd9d6492dbb02 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index aee553c8a6..dc9d9aadcc 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.613 2009/06/04 00:11:56 drh Exp $ +** $Id: btree.c,v 1.614 2009/06/04 14:46:08 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -1173,7 +1173,6 @@ int sqlite3BtreeInitPage(MemPage *pPage){ } #endif - /* Compute the total free space on the page */ pc = get2byte(&data[hdr+1]); nFree = data[hdr+7] + top; @@ -5198,55 +5197,61 @@ static int balance(BtCursor*, int); ** which is also the right-most entry on the page. */ static int balance_quick(BtCursor *pCur){ - int rc; - MemPage *pNew = 0; - Pgno pgnoNew; - u8 *pCell; - u16 szCell; - CellInfo info; - MemPage *pPage = pCur->apPage[pCur->iPage]; - MemPage *pParent = pCur->apPage[pCur->iPage-1]; - BtShared *pBt = pPage->pBt; - int parentIdx = pParent->nCell; /* pParent new divider cell index */ - int parentSize; /* Size of new divider cell */ - u8 parentCell[64]; /* Space for the new divider cell */ + MemPage *const pPage = pCur->apPage[pCur->iPage]; + BtShared *const pBt = pCur->pBt; + MemPage *pNew = 0; /* Newly allocated page */ + int rc; /* Return Code */ + Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->nCell>0 ); - /* Allocate a new page. Insert the overflow cell from pPage - ** into it. Then remove the overflow cell from pPage. - */ + /* Allocate a new page. This page will become the right-sibling of pPage */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + if( rc==SQLITE_OK ){ - pCell = pPage->aOvfl[0].pCell; - szCell = cellSizePtr(pPage, pCell); + /* The parentCell buffer is used to store a temporary copy of the divider + ** cell that will be inserted into pParent. Such a cell consists of a 4 + ** byte page number followed by a variable length integer. In other + ** words, at most 13 bytes. Hence the parentCell buffer must be at + ** least 13 bytes in size. + */ + MemPage * const pParent = pCur->apPage[pCur->iPage-1]; + u8 parentCell[13]; + u8 *pOut = &parentCell[4]; + u8 *pCell = pPage->aOvfl[0].pCell; + u16 szCell = cellSizePtr(pPage, pCell); + u8 *pStop; + assert( sqlite3PagerIswriteable(pNew->pDbPage) ); zeroPage(pNew, pPage->aData[0]); assemblePage(pNew, 1, &pCell, &szCell); pPage->nOverflow = 0; - /* pPage is currently the right-child of pParent. Change this - ** so that the right-child is the new page allocated above and - ** pPage is the next-to-right child. + /* Create a divider cell to insert into pParent. The divider cell + ** consists of a 4-byte page number (the page number of pPage) and + ** a variable length key value (which must be the same value as the + ** largest key on pPage). ** - ** Ignore the return value of the call to fillInCell(). fillInCell() - ** may only return other than SQLITE_OK if it is required to allocate - ** one or more overflow pages. Since an internal table B-Tree cell - ** may never spill over onto an overflow page (it is a maximum of - ** 13 bytes in size), it is not neccessary to check the return code. - ** - ** Similarly, the insertCell() function cannot fail if the page - ** being inserted into is already writable and the cell does not - ** contain an overflow pointer. So ignore this return code too. + ** To find the largest key value on pPage, first find the right-most + ** cell on pPage. The first two fields of this cell are the + ** record-length (a variable length integer at most 32-bits in size) + ** and the key value (a variable length integer, may have any value). + ** The first of the while(...) loops below skips over the record-length + ** field. The second while(...) loop copies the key value from the + ** cell on pPage into the parentCell buffer. */ - assert( pPage->nCell>0 ); + put4byte(parentCell, pPage->pgno); pCell = findCell(pPage, pPage->nCell-1); - sqlite3BtreeParseCellPtr(pPage, pCell, &info); - fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); - assert( parentSize<64 ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); - put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); + pStop = &pCell[9]; + while( (*(pCell++)&0x80) && pCellnCell, parentCell, pOut-parentCell, 0, 0); + + /* Set the right-child pointer of pParent to point to the new page. */ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); /* If this is an auto-vacuum database, update the pointer map @@ -5642,7 +5647,7 @@ static int balance_nonroot(BtCursor *pCur){ szNew[i-1] = szLeft; } - /* Either we found one or more cells (cntnew[0])>0) or we are the + /* Either we found one or more cells (cntnew[0])>0) or pPage is ** a virtual root page. A virtual root page is when the real root ** page is page 1 and we are the only child of that page. */