本文整理汇总了C#中Voron.Impl.Transaction.ModifyPage方法的典型用法代码示例。如果您正苦于以下问题:C# Transaction.ModifyPage方法的具体用法?C# Transaction.ModifyPage怎么用?C# Transaction.ModifyPage使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Voron.Impl.Transaction
的用法示例。
在下文中一共展示了Transaction.ModifyPage方法的8个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: PageSplitter
public PageSplitter(Transaction tx,
Tree tree,
SliceComparer cmp,
Slice newKey,
int len,
long pageNumber,
NodeFlags nodeType,
ushort nodeVersion,
Cursor cursor,
TreeMutableState treeState)
{
_tx = tx;
_tree = tree;
_cmp = cmp;
_newKey = newKey;
_len = len;
_pageNumber = pageNumber;
_nodeType = nodeType;
_nodeVersion = nodeVersion;
_cursor = cursor;
_treeState = treeState;
Page page = _cursor.Pages.First.Value;
_page = tx.ModifyPage(page.PageNumber, page);
_cursor.Pop();
}
示例2: Delete
public void Delete(Transaction tx, Slice key, ushort? version = null)
{
if (tx.Flags == (TransactionFlags.ReadWrite) == false)
throw new ArgumentException("Cannot delete a value in a read only transaction");
State.IsModified = true;
Lazy<Cursor> lazy;
var page = FindPageFor(tx, key, out lazy);
page.NodePositionFor(key, _cmp);
if (page.LastMatch != 0)
return; // not an exact match, can't delete
page = tx.ModifyPage(page.PageNumber, page);
State.EntriesCount--;
ushort nodeVersion;
RemoveLeafNode(tx, page, out nodeVersion);
CheckConcurrency(key, version, nodeVersion, TreeActionType.Delete);
var treeRebalancer = new TreeRebalancer(tx, this);
var changedPage = page;
while (changedPage != null)
{
changedPage = treeRebalancer.Execute(lazy.Value, changedPage);
}
page.DebugValidate(tx, _cmp, State.RootPageNumber);
}
示例3: DirectAdd
internal byte* DirectAdd(Transaction tx, Slice key, int len, NodeFlags nodeType = NodeFlags.Data, ushort? version = null)
{
Debug.Assert(nodeType == NodeFlags.Data || nodeType == NodeFlags.MultiValuePageRef);
if (tx.Flags == (TransactionFlags.ReadWrite) == false)
throw new ArgumentException("Cannot add a value in a read only transaction");
if (key.Size > tx.DataPager.MaxNodeSize)
throw new ArgumentException(
"Key size is too big, must be at most " + tx.DataPager.MaxNodeSize + " bytes, but was " + key.Size, "key");
Lazy<Cursor> lazy;
var foundPage = FindPageFor(tx, key, out lazy);
var page = tx.ModifyPage(foundPage.PageNumber, foundPage);
ushort nodeVersion = 0;
bool? shouldGoToOverflowPage = null;
if (page.LastMatch == 0) // this is an update operation
{
var node = page.GetNode(page.LastSearchPosition);
Debug.Assert(node->KeySize == key.Size && new Slice(node).Equals(key));
shouldGoToOverflowPage = tx.DataPager.ShouldGoToOverflowPage(len);
byte* pos;
if (shouldGoToOverflowPage == false)
{
// optimization for Data and MultiValuePageRef - try to overwrite existing node space
if (TryOverwriteDataOrMultiValuePageRefNode(node, key, len, nodeType, version, out pos))
return pos;
}
else
{
// optimization for PageRef - try to overwrite existing overflows
if (TryOverwriteOverflowPages(tx, State, node, key, len, version, out pos))
return pos;
}
RemoveLeafNode(tx, page, out nodeVersion);
}
else // new item should be recorded
{
State.EntriesCount++;
}
CheckConcurrency(key, version, nodeVersion, TreeActionType.Add);
var lastSearchPosition = page.LastSearchPosition; // searching for overflow pages might change this
byte* overFlowPos = null;
var pageNumber = -1L;
if (shouldGoToOverflowPage ?? tx.DataPager.ShouldGoToOverflowPage(len))
{
pageNumber = WriteToOverflowPages(tx, State, len, out overFlowPos);
len = -1;
nodeType = NodeFlags.PageRef;
}
byte* dataPos;
if (page.HasSpaceFor(tx, key, len) == false)
{
var cursor = lazy.Value;
cursor.Update(cursor.Pages.First, page);
var pageSplitter = new PageSplitter(tx, this, _cmp, key, len, pageNumber, nodeType, nodeVersion, cursor, State);
dataPos = pageSplitter.Execute();
DebugValidateTree(tx, State.RootPageNumber);
}
else
{
switch (nodeType)
{
case NodeFlags.PageRef:
dataPos = page.AddPageRefNode(lastSearchPosition, key, pageNumber);
break;
case NodeFlags.Data:
dataPos = page.AddDataNode(lastSearchPosition, key, len, nodeVersion);
break;
case NodeFlags.MultiValuePageRef:
dataPos = page.AddMultiValueNode(lastSearchPosition, key, len, nodeVersion);
break;
default:
throw new NotSupportedException("Unknown node type for direct add operation: " + nodeType);
}
page.DebugValidate(tx, _cmp, State.RootPageNumber);
}
if (overFlowPos != null)
return overFlowPos;
return dataPos;
}
示例4: MultiAdd
public void MultiAdd(Transaction tx, Slice key, Slice value, ushort? version = null)
{
if (value == null) throw new ArgumentNullException("value");
int maxNodeSize = tx.DataPager.MaxNodeSize;
if (value.Size > maxNodeSize)
throw new ArgumentException(
"Cannot add a value to child tree that is over " + maxNodeSize + " bytes in size", "value");
if (value.Size == 0)
throw new ArgumentException("Cannot add empty value to child tree");
State.IsModified = true;
Lazy<Cursor> lazy;
var page = FindPageFor(tx, key, out lazy);
if ((page == null || page.LastMatch != 0))
{
MultiAddOnNewValue(tx, key, value, version, maxNodeSize);
return;
}
page = tx.ModifyPage(page.PageNumber, page);
var item = page.GetNode(page.LastSearchPosition);
// already was turned into a multi tree, not much to do here
if (item->Flags == NodeFlags.MultiValuePageRef)
{
var existingTree = OpenOrCreateMultiValueTree(tx, key, item);
existingTree.DirectAdd(tx, value, 0, version: version);
return;
}
var nestedPagePtr = NodeHeader.DirectAccess(tx, item);
var nestedPage = new Page(nestedPagePtr, "multi tree", (ushort) NodeHeader.GetDataSize(tx, item));
var existingItem = nestedPage.Search(value, NativeMethods.memcmp);
if (nestedPage.LastMatch != 0)
existingItem = null;// not an actual match, just greater than
ushort previousNodeRevision = existingItem != null ? existingItem->Version : (ushort)0;
CheckConcurrency(key, value, version, previousNodeRevision, TreeActionType.Add);
if (existingItem != null)
{
// maybe same value added twice?
var tmpKey = new Slice(item);
if (tmpKey.Compare(value, _cmp) == 0)
return; // already there, turning into a no-op
nestedPage.RemoveNode(nestedPage.LastSearchPosition);
}
if (nestedPage.HasSpaceFor(tx, value, 0))
{
// we are now working on top of the modified root page, we can just modify the memory directly
nestedPage.AddDataNode(nestedPage.LastSearchPosition, value, 0, previousNodeRevision);
return;
}
int pageSize = nestedPage.CalcSizeUsed() + Constants.PageHeaderSize;
var newRequiredSize = pageSize + nestedPage.GetRequiredSpace(value, 0);
if (newRequiredSize <= maxNodeSize)
{
// we can just expand the current value... no need to create a nested tree yet
var actualPageSize = (ushort)Math.Min(Utils.NearestPowerOfTwo(newRequiredSize), maxNodeSize);
ExpandMultiTreeNestedPageSize(tx, key, value, nestedPagePtr, actualPageSize, item->DataSize);
return;
}
// we now have to convert this into a tree instance, instead of just a nested page
var tree = Create(tx, _cmp, TreeFlags.MultiValue);
for (int i = 0; i < nestedPage.NumberOfEntries; i++)
{
var existingValue = nestedPage.GetNodeKey(i);
tree.DirectAdd(tx, existingValue, 0);
}
tree.DirectAdd(tx, value, 0, version: version);
tx.AddMultiValueTree(this, key, tree);
// we need to record that we switched to tree mode here, so the next call wouldn't also try to create the tree again
DirectAdd(tx, key, sizeof (TreeRootHeader), NodeFlags.MultiValuePageRef);
}
示例5: SetAsMultiValueTreeRef
public bool SetAsMultiValueTreeRef(Transaction tx, Slice key)
{
Lazy<Cursor> lazy;
var foundPage = FindPageFor(tx, key, out lazy);
var page = tx.ModifyPage(foundPage.PageNumber, foundPage);
if (page.LastMatch != 0)
return false; // not there
var nodeHeader = page.GetNode(page.LastSearchPosition);
if (nodeHeader->Flags == NodeFlags.MultiValuePageRef)
return false;
if (nodeHeader->Flags != NodeFlags.Data)
throw new InvalidOperationException("Only data nodes can be set to MultiValuePageRef");
nodeHeader->Flags = NodeFlags.MultiValuePageRef;
return true;
}
示例6: MultiDelete
public void MultiDelete(Transaction tx, Slice key, Slice value, ushort? version = null)
{
State.IsModified = true;
Lazy<Cursor> lazy;
var page = FindPageFor(tx, key, out lazy);
if (page == null || page.LastMatch != 0)
{
return; //nothing to delete - key not found
}
page = tx.ModifyPage(page.PageNumber, page);
var item = page.GetNode(page.LastSearchPosition);
if (item->Flags == NodeFlags.MultiValuePageRef) //multi-value tree exists
{
var tree = OpenOrCreateMultiValueTree(tx, key, item);
tree.Delete(tx, value, version);
// previously, we would convert back to a simple model if we dropped to a single entry
// however, it doesn't really make sense, once you got enough values to go to an actual nested
// tree, you are probably going to remain that way, or be removed completely.
if (tree.State.EntriesCount != 0)
return;
tx.TryRemoveMultiValueTree(this, key);
tx.FreePage(tree.State.RootPageNumber);
Delete(tx, key);
}
else // we use a nested page here
{
var nestedPage = new Page(NodeHeader.DirectAccess(tx, item), "multi tree", (ushort)NodeHeader.GetDataSize(tx, item));
var nestedItem = nestedPage.Search(value, NativeMethods.memcmp);
if (nestedItem == null) // value not found
return;
CheckConcurrency(key, value, version, nestedItem->Version, TreeActionType.Delete);
nestedPage.RemoveNode(nestedPage.LastSearchPosition);
if (nestedPage.NumberOfEntries == 0)
Delete(tx, key);
}
}
示例7: MultiDelete
public void MultiDelete(Transaction tx, Slice key, Slice value, ushort? version = null)
{
State.IsModified = true;
Lazy<Cursor> lazy;
var page = FindPageFor(tx, key, out lazy);
if (page == null || page.LastMatch != 0)
{
return; //nothing to delete - key not found
}
page = tx.ModifyPage(page.PageNumber, page);
var item = page.GetNode(page.LastSearchPosition);
if (item->Flags == NodeFlags.MultiValuePageRef) //multi-value tree exists
{
var tree = OpenOrCreateMultiValueTree(tx, key, item);
tree.Delete(tx, value, version);
if (tree.State.EntriesCount > 1)
return;
// convert back to simple key/val
var iterator = tree.Iterate(tx);
if (!iterator.Seek(Slice.BeforeAllKeys))
throw new InvalidDataException(
"MultiDelete() failed : sub-tree is empty where it should not be, this is probably a Voron bug.");
var dataToSave = iterator.CurrentKey;
var ptr = DirectAdd(tx, key, dataToSave.Size);
dataToSave.CopyTo(ptr);
tx.TryRemoveMultiValueTree(this, key);
tx.FreePage(tree.State.RootPageNumber);
}
else //the regular key->value pattern
{
Delete(tx, key, version);
}
}
示例8: MultiAdd
public void MultiAdd(Transaction tx, Slice key, Slice value, ushort? version = null)
{
if (value == null) throw new ArgumentNullException("value");
if (value.Size > tx.DataPager.MaxNodeSize)
throw new ArgumentException(
"Cannot add a value to child tree that is over " + tx.DataPager.MaxNodeSize + " bytes in size", "value");
if (value.Size == 0)
throw new ArgumentException("Cannot add empty value to child tree");
State.IsModified = true;
Lazy<Cursor> lazy;
var page = FindPageFor(tx, key, out lazy);
if (page == null || page.LastMatch != 0)
{
var ptr = DirectAdd(tx, key, value.Size, version: version);
value.CopyTo(ptr);
return;
}
page = tx.ModifyPage(page.PageNumber, page);
var item = page.GetNode(page.LastSearchPosition);
CheckConcurrency(key, version, item->Version, TreeActionType.Add);
var existingValue = new Slice(DirectRead(tx, key), (ushort) item->DataSize);
if (existingValue.Compare(value, _cmp) == 0)
return; //nothing to do, the exact value is already there
if (item->Flags == NodeFlags.MultiValuePageRef)
{
var tree = OpenOrCreateMultiValueTree(tx, key, item);
tree.DirectAdd(tx, value, 0);
}
else // need to turn to tree
{
var tree = Create(tx, _cmp, TreeFlags.MultiValue);
var current = NodeHeader.GetData(tx, item);
tree.DirectAdd(tx, current, 0);
tree.DirectAdd(tx, value, 0);
tx.AddMultiValueTree(this, key, tree);
// we need to record that we switched to tree mode here, so the next call wouldn't also try to create the tree again
DirectAdd(tx, key, sizeof (TreeRootHeader), NodeFlags.MultiValuePageRef);
}
}