本文整理汇总了C#中BtCursor类的典型用法代码示例。如果您正苦于以下问题:C# BtCursor类的具体用法?C# BtCursor怎么用?C# BtCursor使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
BtCursor类属于命名空间,在下文中一共展示了BtCursor类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: CloseCursor
public static RC CloseCursor(BtCursor cur)
{
var btree = cur.Btree;
if (btree != null)
{
var bt = cur.Bt;
btree.Enter();
ClearCursor(cur);
if (cur.Prev != null)
cur.Prev.Next = cur.Next;
else
bt.Cursor = cur.Next;
if (cur.Next != null)
cur.Next.Prev = cur.Prev;
for (var i = 0; i <= cur.ID; i++)
releasePage(cur.Pages[i]);
unlockBtreeIfUnused(bt);
invalidateOverflowCache(cur);
btree.Leave();
}
return RC.OK;
}
示例2: sqlite3BtreeLeaveCursor
//# define sqlite3BtreeLeaveCursor(X)
static void sqlite3BtreeLeaveCursor( BtCursor X )
{
}
示例3: sqlite3VdbeMemFromBtree
/*
** Move data out of a btree key or data field and into a Mem structure.
** The data or key is taken from the entry that pCur is currently pointing
** to. offset and amt determine what portion of the data or key to retrieve.
** key is true to get the key or false to get data. The result is written
** into the pMem element.
**
** The pMem structure is assumed to be uninitialized. Any prior content
** is overwritten without being freed.
**
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
*/
private static int sqlite3VdbeMemFromBtree(
BtCursor pCur, /* Cursor pointing at record to retrieve. */
int offset, /* Offset from the start of data to return bytes from. */
int amt, /* Number of bytes to return. */
bool key, /* If true, retrieve from the btree key, not data. */
Mem pMem /* OUT: Return data in this Mem structure. */
)
{
byte[] zData; /* Data from the btree layer */
int available = 0; /* Number of bytes available on the local btree page */
int rc = SQLITE_OK; /* Return code */
Debug.Assert(sqlite3BtreeCursorIsValid(pCur));
/* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
** that both the BtShared and database handle mutexes are held. */
Debug.Assert((pMem.flags & MEM_RowSet) == 0);
int outOffset = -1;
if (key)
{
zData = sqlite3BtreeKeyFetch(pCur, ref available, ref outOffset);
}
else
{
zData = sqlite3BtreeDataFetch(pCur, ref available, ref outOffset);
}
Debug.Assert(zData != null);
if (offset + amt <= available && (pMem.flags & MEM_Dyn) == 0)
{
sqlite3VdbeMemRelease(pMem);
pMem.zBLOB = sqlite3Malloc(amt);
Buffer.BlockCopy(zData, offset, pMem.zBLOB, 0, amt);//pMem.z = &zData[offset];
pMem.flags = MEM_Blob | MEM_Ephem;
}
else if (SQLITE_OK == (rc = sqlite3VdbeMemGrow(pMem, amt + 2, 0)))
{
pMem.enc = 0;
pMem.type = SQLITE_BLOB;
pMem.z = null;
pMem.zBLOB = sqlite3Malloc(amt);
pMem.flags = MEM_Blob | MEM_Dyn | MEM_Term;
if (key)
{
rc = sqlite3BtreeKey(pCur, (u32)offset, (u32)amt, pMem.zBLOB);
}
else
{
rc = sqlite3BtreeData(pCur, (u32)offset, (u32)amt, pMem.zBLOB);//pMem.z = pMem_z ;
}
//pMem.z[amt] = 0;
//pMem.z[amt+1] = 0;
if (rc != SQLITE_OK)
{
sqlite3VdbeMemRelease(pMem);
}
}
pMem.n = amt;
sqlite3_free(ref zData);
return rc;
}
示例4: sqlite3BtreeLeaveCursor
void sqlite3BtreeLeaveCursor(BtCursor *pCur){
sqlite3BtreeLeave(pCur->pBtree);
}
示例5: CursorHints
public static void CursorHints(BtCursor cur, uint mask)
{
Debug.Assert(mask == BTREE_BULKLOAD || mask == 0);
cur.Hints = (byte)mask;
}
示例6: PutData
public static RC PutData(BtCursor cur, uint offset, uint amount, byte[] z)
{
Debug.Assert(cursorHoldsMutex(cur));
Debug.Assert(MutexEx.Held(cur.Btree.Ctx.Mutex));
Debug.Assert(cur.IsIncrblobHandle);
RC rc = restoreCursorPosition(cur);
if (rc != RC.OK)
return rc;
Debug.Assert(cur.State != CURSOR.REQUIRESEEK);
if (cur.State != CURSOR.VALID)
return RC.ABORT;
// Check some assumptions:
// (a) the cursor is open for writing,
// (b) there is a read/write transaction open,
// (c) the connection holds a write-lock on the table (if required),
// (d) there are no conflicting read-locks, and
// (e) the cursor points at a valid row of an intKey table.
if (!cur.WrFlag)
return RC.READONLY;
Debug.Assert((cur.Bt.BtsFlags & BTS.READ_ONLY) == 0 && cur.Bt.InTransaction == TRANS.WRITE);
Debug.Assert(hasSharedCacheTableLock(cur.Btree, cur.RootID, false, LOCK.WRITE));
Debug.Assert(!hasReadConflicts(cur.Btree, cur.RootID));
Debug.Assert(cur.Pages[cur.ID].IntKey);
return accessPayload(cur, offset, amount, z, 1);
}
示例7: Delete
public static RC Delete(BtCursor cur)
{
Btree p = cur.Btree;
BtShared bt = p.Bt;
Debug.Assert(cursorHoldsMutex(cur));
Debug.Assert(bt.InTransaction == TRANS.WRITE);
Debug.Assert((bt.BtsFlags & BTS.READ_ONLY) == 0);
Debug.Assert(cur.WrFlag);
Debug.Assert(hasSharedCacheTableLock(p, cur.RootID, cur.KeyInfo != null, LOCK.WRITE));
Debug.Assert(!hasReadConflicts(p, cur.RootID));
if (C._NEVER(cur.Idxs[cur.ID] >= cur.Pages[cur.ID].Cells) || C._NEVER(cur.State != CURSOR.VALID))
return RC.ERROR; // Something has gone awry.
int cellDepth = cur.ID; // Depth of node containing pCell
uint cellIdx = cur.Idxs[cellDepth]; // Index of cell to delete
MemPage page = cur.Pages[cellDepth]; // Page to delete cell from
uint cell_ = findCell(page, cellIdx); // Pointer to cell to delete
// If the page containing the entry to delete is not a leaf page, move the cursor to the largest entry in the tree that is smaller than
// the entry being deleted. This cell will replace the cell being deleted from the internal node. The 'previous' entry is used for this instead
// of the 'next' entry, as the previous entry is always a part of the sub-tree headed by the child page of the cell being deleted. This makes
// balancing the tree following the delete operation easier.
RC rc;
if (!page.Leaf)
{
int notUsed = 0;
rc = Previous(cur, ref notUsed);
if (rc != RC.OK) return rc;
}
// Save the positions of any other cursors open on this table before making any modifications. Make the page containing the entry to be
// deleted writable. Then free any overflow pages associated with the entry and finally remove the cell itself from within the page.
rc = saveAllCursors(bt, cur.RootID, cur);
if (rc != RC.OK) return rc;
// If this is a delete operation to remove a row from a table b-tree, invalidate any incrblob cursors open on the row being deleted.
if (cur.KeyInfo == null)
invalidateIncrblobCursors(p, cur.Info.Key, false);
rc = Pager.Write(page.DBPage);
if (rc != RC.OK) return rc;
rc = clearCell(page, cell_);
dropCell(page, cellIdx, cellSizePtr(page, cell_), ref rc);
if (rc != RC.OK) return rc;
// If the cell deleted was not located on a leaf page, then the cursor is currently pointing to the largest entry in the sub-tree headed
// by the child-page of the cell that was just deleted from an internal node. The cell from the leaf node needs to be moved to the internal
// node to replace the deleted cell.
if (!page.Leaf)
{
MemPage leaf = cur.Pages[cur.ID];
Pid n = cur.Pages[cellDepth + 1].ID;
cell_ = findCell(leaf, (uint)leaf.Cells - 1);
ushort sizeCell = cellSizePtr(leaf, cell_);
Debug.Assert(MX_CELL_SIZE(bt) >= sizeCell);
//allocateTempSpace(bt);
//byte[] tmp = Bt.TmpSpace;
rc = Pager.Write(leaf.DBPage);
{ byte[] cell_4 = new byte[sizeCell + 4]; Buffer.BlockCopy(leaf.Data, (int)cell_ - 4, cell_4, 0, (int)sizeCell + 4); insertCell(page, cellIdx, cell_4, (ushort)(sizeCell + 4), null, n, ref rc); }
dropCell(leaf, (uint)(leaf.Cells - 1), sizeCell, ref rc);
if (rc != RC.OK) return rc;
}
// Balance the tree. If the entry deleted was located on a leaf page, then the cursor still points to that page. In this case the first
// call to balance() repairs the tree, and the if(...) condition is never true.
//
// Otherwise, if the entry deleted was on an internal node page, then pCur is pointing to the leaf page from which a cell was removed to
// replace the cell deleted from the internal node. This is slightly tricky as the leaf node may be underfull, and the internal node may
// be either under or overfull. In this case run the balancing algorithm on the leaf node first. If the balance proceeds far enough up the
// tree that we can be sure that any problem in the internal node has been corrected, so be it. Otherwise, after balancing the leaf node,
// walk the cursor up the tree to the internal node and balance it as well.
rc = balance(cur);
if (rc == RC.OK && cur.ID > cellDepth)
{
while (cur.ID > cellDepth)
releasePage(cur.Pages[cur.ID--]);
rc = balance(cur);
}
if (rc == RC.OK)
moveToRoot(cur);
return rc;
}
示例8: saveCursorPosition
static RC saveCursorPosition(BtCursor cur)
{
Debug.Assert(cur.State == CURSOR.VALID);
Debug.Assert(cur.Key == null);
Debug.Assert(cursorHoldsMutex(cur));
var rc = KeySize(cur, ref cur.KeyLength);
Debug.Assert(rc == RC.OK); // KeySize() cannot fail
// If this is an intKey table, then the above call to BtreeKeySize() stores the integer key in pCur.nKey. In this case this value is
// all that is required. Otherwise, if pCur is not open on an intKey table, then malloc space for and store the pCur.nKey bytes of key data.
if (!cur.Pages[0].IntKey)
{
var key = C._alloc((int)cur.KeyLength);
rc = Key(cur, 0, (uint)cur.KeyLength, key);
if (rc == RC.OK)
cur.Key = key;
}
Debug.Assert(!cur.Pages[0].IntKey || cur.Key == null);
if (rc == RC.OK)
{
btreeReleaseAllCursorPages(cur);
cur.State = CURSOR.REQUIRESEEK;
}
invalidateOverflowCache(cur);
return rc;
}
示例9: Next_
public static RC Next_(BtCursor cur, ref int res)
{
Debug.Assert(cursorHoldsMutex(cur));
var rc = restoreCursorPosition(cur);
if (rc != RC.OK)
return rc;
if (cur.State == CURSOR.INVALID)
{
res = 1;
return RC.OK;
}
if (cur.SkipNext > 0)
{
cur.SkipNext = 0;
res = 0;
return RC.OK;
}
cur.SkipNext = 0;
MemPage page = cur.Pages[cur.ID];
uint idx = ++cur.Idxs[cur.ID];
Debug.Assert(page.IsInit);
cur.Info.Size = 0;
cur.ValidNKey = false;
if (idx >= page.Cells)
{
if (!page.Leaf)
{
rc = moveToChild(cur, ConvertEx.Get4(page.Data, page.HdrOffset + 8));
if (rc != RC.OK) return rc;
rc = moveToLeftmost(cur);
res = 0;
return rc;
}
do
{
if (cur.ID == 0)
{
res = 1;
cur.State = CURSOR.INVALID;
return RC.OK;
}
moveToParent(cur);
page = cur.Pages[cur.ID];
} while (cur.Idxs[cur.ID] >= page.Cells);
res = 0;
if (page.IntKey)
rc = Next_(cur, ref res);
else
rc = RC.OK;
return rc;
}
res = 0;
if (page.Leaf)
return RC.OK;
rc = moveToLeftmost(cur);
return rc;
}
示例10: Eof
public static bool Eof(BtCursor cur)
{
// TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries have been deleted? This API will need to change to return an error code
// as well as the boolean result value.
return (cur.State != CURSOR.VALID);
}
示例11: btreeReleaseAllCursorPages
static void btreeReleaseAllCursorPages(BtCursor cur)
{
for (int i = 0; i <= cur.ID; i++)
{
releasePage(cur.Pages[i]);
cur.Pages[i] = null;
}
cur.ID = -1;
}
示例12: MovetoUnpacked
public static RC MovetoUnpacked(BtCursor cur, UnpackedRecord idxKey, long intKey, int biasRight, out int res)
{
Debug.Assert(cursorHoldsMutex(cur));
Debug.Assert(MutexEx.Held(cur.Btree.Ctx.Mutex));
Debug.Assert((idxKey == null) == (cur.KeyInfo == null));
// If the cursor is already positioned at the point we are trying to move to, then just return without doing any work
if (cur.State == CURSOR.VALID && cur.ValidNKey && cur.Pages[0].IntKey)
{
if (cur.Info.Key == intKey)
{
res = 0;
return RC.OK;
}
if (cur.AtLast != 0 && cur.Info.Key < intKey)
{
res = -1;
return RC.OK;
}
}
res = -1;
var rc = moveToRoot(cur);
if (rc != RC.OK)
return rc;
Debug.Assert(cur.RootID == 0 || cur.Pages[cur.ID] != null);
Debug.Assert(cur.RootID == 0 || cur.Pages[cur.ID].IsInit);
Debug.Assert(cur.State == CURSOR.INVALID || cur.Pages[cur.ID].Cells > 0);
if (cur.State == CURSOR.INVALID)
{
res = -1;
Debug.Assert(cur.RootID == 0 || cur.Pages[cur.ID].Cells == 0);
return RC.OK;
}
Debug.Assert(cur.Pages[0].IntKey || idxKey != null);
int c;
for (; ; )
{
// pPage->nCell must be greater than zero. If this is the root-page the cursor would have been INVALID above and this for(;;) loop
// not run. If this is not the root-page, then the moveToChild() routine would have already detected db corruption. Similarly, pPage must
// be the right kind (index or table) of b-tree page. Otherwise a moveToChild() or moveToRoot() call would have detected corruption.
MemPage page = cur.Pages[cur.ID];
Debug.Assert(page.Cells > 0);
Debug.Assert(page.IntKey == (idxKey == null));
uint idx;
uint lwr = 0;
uint upr = (uint)(page.Cells - 1);
if (biasRight != 0)
cur.Idxs[cur.ID] = (ushort)(idx = upr);
else
cur.Idxs[cur.ID] = (ushort)(idx = (upr + lwr) / 2);
for (; ; )
{
Debug.Assert(idx == cur.Idxs[cur.ID]);
cur.Info.Size = 0;
uint cell_ = findCell(page, idx) + page.ChildPtrSize; // Pointer to current cell in pPage
if (page.IntKey)
{
if (page.HasData)
{
uint dummy = 0;
cell_ += ConvertEx.GetVarint32(page.Data, cell_, out dummy);
}
long cellKeyLength = 0;
ConvertEx.GetVarint(page.Data, cell_, out cellKeyLength);
if (cellKeyLength == intKey)
c = 0;
else if (cellKeyLength < intKey)
c = -1;
else
c = +1;
cur.ValidNKey = true;
cur.Info.Key = cellKeyLength;
}
else
{
// The maximum supported page-size is 65536 bytes. This means that the maximum number of record bytes stored on an index B-Tree
// page is less than 16384 bytes and may be stored as a 2-byte varint. This information is used to attempt to avoid parsing
// the entire cell by checking for the cases where the record is stored entirely within the b-tree page by inspecting the first
// 2 bytes of the cell.
int cellLength = page.Data[cell_ + 0];
if (cellLength <= page.Max1bytePayload)
{
// This branch runs if the record-size field of the cell is a single byte varint and the record fits entirely on the main b-tree page.
c = _vdbe.RecordCompare(cellLength, page.Data, cell_ + 1, idxKey);
}
else if ((page.Data[cell_ + 1] & 0x80) == 0 && (cellLength = ((cellLength & 0x7f) << 7) + page.Data[cell_ + 1]) <= page.MaxLocal)
{
// The record-size field is a 2 byte varint and the record fits entirely on the main b-tree page.
c = _vdbe.RecordCompare(cellLength, page.Data, cell_ + 2, idxKey);
}
else
{
// The record flows over onto one or more overflow pages. In this case the whole cell needs to be parsed, a buffer allocated
// and accessPayload() used to retrieve the record into the buffer before VdbeRecordCompare() can be called.
var cellBody = new byte[page.Data.Length - cell_ + page.ChildPtrSize];
Buffer.BlockCopy(page.Data, (int)cell_ - page.ChildPtrSize, cellBody, 0, cellBody.Length);
btreeParseCellPtr(page, cellBody, ref cur.Info);
cellLength = (int)cur.Info.Key;
var cellKey = C._alloc(cellLength);
//.........这里部分代码省略.........
示例13: Last
public static RC Last(BtCursor cur, ref int res)
{
Debug.Assert(cursorHoldsMutex(cur));
Debug.Assert(MutexEx.Held(cur.Btree.Ctx.Mutex));
// If the cursor already points to the last entry, this is a no-op.
if (cur.State == CURSOR.VALID && cur.AtLast != 0)
{
#if DEBUG
// This block serves to Debug.Assert() that the cursor really does point to the last entry in the b-tree.
for (var ii = 0; ii < cur.ID; ii++)
Debug.Assert(cur.Idxs[ii] == cur.Pages[ii].Cells);
Debug.Assert(cur.Idxs[cur.ID] == cur.Pages[cur.ID].Cells - 1);
Debug.Assert(cur.Pages[cur.ID].Leaf);
#endif
return RC.OK;
}
var rc = moveToRoot(cur);
if (rc == RC.OK)
{
if (cur.State == CURSOR.INVALID)
{
Debug.Assert(cur.Pages[cur.ID].Cells == 0);
res = 1;
}
else
{
Debug.Assert(cur.State == CURSOR.VALID);
res = 0;
rc = moveToRightmost(cur);
cur.AtLast = (byte)(rc == RC.OK ? 1 : 0);
}
}
return rc;
}
示例14: First
public static RC First(BtCursor cur, ref int res)
{
Debug.Assert(cursorHoldsMutex(cur));
Debug.Assert(MutexEx.Held(cur.Btree.Ctx.Mutex));
var rc = moveToRoot(cur);
if (rc == RC.OK)
{
if (cur.State == CURSOR.INVALID)
{
Debug.Assert(cur.Pages[cur.ID].Cells == 0);
res = 1;
}
else
{
Debug.Assert(cur.Pages[cur.ID].Cells > 0);
res = 0;
rc = moveToLeftmost(cur);
}
}
return rc;
}
示例15: balance
static RC balance(BtCursor cur)
{
#if DEBUG
int balance_quick_called = 0;
int balance_deeper_called = 0;
#else
int balance_quick_called = 0;
int balance_deeper_called = 0;
#endif
byte[] free = null;
int min = (int)cur.Bt.UsableSize * 2 / 3;
RC rc = RC.OK;
do
{
int pageID = cur.ID;
MemPage page = cur.Pages[pageID];
if (pageID == 0)
{
if (page.Overflows != 0)
{
// The root page of the b-tree is overfull. In this case call the balance_deeper() function to create a new child for the root-page
// and copy the current contents of the root-page to it. The next iteration of the do-loop will balance the child page.
Debug.Assert(balance_deeper_called++ == 0);
rc = balance_deeper(page, ref cur.Pages[1]);
if (rc == RC.OK)
{
cur.ID = 1;
cur.Idxs[0] = 0;
cur.Idxs[1] = 0;
Debug.Assert(cur.Pages[1].Overflows != 0);
}
}
else
break;
}
else if (page.Overflows == 0 && page.Frees <= min)
break;
else
{
MemPage parent = cur.Pages[pageID - 1];
ushort idx = cur.Idxs[pageID - 1];
rc = Pager.Write(parent.DBPage);
if (rc == RC.OK)
{
#if !OMIT_QUICKBALANCE
if (page.HasData && page.Overflows == 1 && page.OvflIdxs[0] == page.Cells && parent.ID != 1 && parent.Cells == idx)
{
// Call balance_quick() to create a new sibling of pPage on which to store the overflow cell. balance_quick() inserts a new cell
// into pParent, which may cause pParent overflow. If this happens, the next interation of the do-loop will balance pParent
// use either balance_nonroot() or balance_deeper(). Until this happens, the overflow cell is stored in the aBalanceQuickSpace[] buffer.
//
// The purpose of the following assert() is to check that only a single call to balance_quick() is made for each call to this
// function. If this were not verified, a subtle bug involving reuse of the aBalanceQuickSpace[] might sneak in.
Debug.Assert((balance_quick_called++) == 0);
rc = balance_quick(parent, page, _balanceQuickSpace);
}
else
#endif
{
// In this case, call balance_nonroot() to redistribute cells between pPage and up to 2 of its sibling pages. This involves
// modifying the contents of pParent, which may cause pParent to become overfull or underfull. The next iteration of the do-loop
// will balance the parent page to correct this.
//
// If the parent page becomes overfull, the overflow cell or cells are stored in the pSpace buffer allocated immediately below.
// A subsequent iteration of the do-loop will deal with this by calling balance_nonroot() (balance_deeper() may be called first,
// but it doesn't deal with overflow cells - just moves them to a different page). Once this subsequent call to balance_nonroot()
// has completed, it is safe to release the pSpace buffer used by the previous call, as the overflow cell data will have been
// copied either into the body of a database page or into the new pSpace buffer passed to the latter call to balance_nonroot().
byte[] space = null; //PCache.PageAlloc2((int)cur.Bt.PageSize);
rc = balance_nonroot(parent, idx, space, pageID == 1, cur.Hints != 0);
if (free != null)
{
// If pFree is not NULL, it points to the pSpace buffer used by a previous call to balance_nonroot(). Its contents are
// now stored either on real database pages or within the new pSpace buffer, so it may be safely freed here.
PCache.PageFree2(ref free);
}
// The pSpace buffer will be freed after the next call to balance_nonroot(), or just before this function returns, whichever comes first.
free = space;
}
}
page.Overflows = 0;
// The next iteration of the do-loop balances the parent page.
releasePage(page);
cur.ID--;
}
} while (rc == RC.OK);
if (free != null)
PCache.PageFree2(ref free);
return rc;
}