示例#1
0
        private int SearchForKey(TreePageEntry entry, Span <byte> key)
        {
            entry.Search(key);

            if (entry.LastMatch < 0)
            {
                entry.LastMatchIndex++;
            }

            return(entry.LastMatch);
        }
示例#2
0
        //public unsafe void Insert(ILowLevelTransaction tx, TreeNodeDataEntry data)
        //{
        //    var cursor = BuildCursor(tx, data.Key);
        //    var match = SearchForKey(cursor.Entry, data.Key);
        //    if (match == 0 && _isUnique)
        //    {
        //        throw new InvalidCastException($"mulpti key");
        //    }

        //    if (!ModifyEntry(cursor.Entry, tx))
        //    {
        //        throw new InvalidOperationException($"modify page failed!");
        //    }

        //    Insert(tx, cursor.Entry, data);
        //}

        //private unsafe void Insert(ILowLevelTransaction tx, TreePageEntry entry, TreeNodeDataEntry data)
        //{
        //    var size = data.Size;
        //    if (size >= PageEntryMaxDataSize)
        //    {
        //        InsertOverflow(tx, entry, data);
        //        return;
        //    }

        //    if (entry.Allocate(entry.LastMatchIndex, (ushort)size, TreeNodeHeaderFlags.Data, out var pos))
        //    {
        //        entry.InsertDataNode(entry.LastMatchIndex, pos, data, 0l);
        //        return;
        //    }

        //    var index = Balance(tx, entry, data.Key, entry.LastMatchIndex);
        //    if (index <= entry.LastMatchIndex)
        //    {
        //        //add to new right page
        //        entry.LastMatchIndex = entry.LastMatchIndex - index;
        //    }

        //    if (!entry.Allocate(entry.LastMatchIndex, (ushort)size, TreeNodeHeaderFlags.Data, out pos))
        //    {
        //        throw new InvalidOperationException("allocate node space faild!");
        //    }

        //    entry.InsertDataNode(entry.LastMatchIndex, pos, data, 0l);
        //}

        //public void InsertOverflow(ILowLevelTransaction tx, TreePageEntry entry, TreeNodeDataEntry data)
        //{
        //    var size = data.Key.Size;
        //    var dataSize = data.Value.Size;
        //    var overflowPages = AllocateOverflows(tx, dataSize);

        //    for (var i = 0; i < overflowPages.Length; i++)
        //    {
        //        var pageSize = Math.Min(OverflowPage.Capacity, dataSize);

        //        overflowPages[i].Write(Constants.PageHeaderSize, data.Value.Data.Slice(i * OverflowPage.Capacity, pageSize));

        //        dataSize -= pageSize;
        //    }

        //    if (entry.Allocate(entry.LastMatchIndex, (ushort)size, TreeNodeHeaderFlags.Data, out var pos))
        //    {
        //        entry.InsertPageRefNode(entry.LastMatchIndex, pos, data.Key, overflowPages[0].Header.PageNumber);
        //        return;
        //    }

        //    var index = Balance(tx, entry, data.Key, entry.LastMatchIndex);
        //    if (index <= entry.LastMatchIndex)
        //    {
        //        //add to new right page
        //        entry.LastMatchIndex = entry.LastMatchIndex - index;
        //    }

        //    if (!entry.Allocate(entry.LastMatchIndex, (ushort)size, TreeNodeHeaderFlags.Data, out pos))
        //    {
        //        throw new InvalidOperationException("allocate node space faild!");
        //    }

        //    entry.InsertPageRefNode(entry.LastMatchIndex, pos, data.Key, overflowPages[0].Header.PageNumber);
        //}

        //public unsafe int Balance(ILowLevelTransaction tx, TreePageEntry entry, TreeNodeDataSlice key, int midIndex)
        //{
        //    var newEntry = AllocateEntry(tx, entry.Header.NodeFlags, entry.Parent, entry.Index + 1);
        //    if (newEntry == null)
        //    {
        //        throw new InvalidOperationException("allocate new page failed!");
        //    }

        //    var balanceIndex = entry.CopyEntriesToNewPage(midIndex, newEntry.Page);
        //    if (balanceIndex > midIndex)
        //    {
        //        Balance(tx, entry, newEntry, newEntry.MinKey);

        //        return balanceIndex;
        //    }

        //    var index = midIndex - balanceIndex;
        //    var newKey = index > 0 ? newEntry.MinKey : key;

        //    Balance(tx, entry, newEntry, newKey);

        //    entry.Page = newEntry.Page;
        //    entry.Index = newEntry.Index;

        //    return balanceIndex;
        //}

        //public unsafe void Balance(ILowLevelTransaction tx, TreePageEntry curEntry, TreePageEntry newEntry, TreeNodeDataSlice key)
        //{
        //    var parent = curEntry.Parent;
        //    if (parent != null && parent.Page != null)
        //    {
        //        ModifyEntry(parent, tx);
        //        Balance(tx, parent, curEntry, newEntry, key);
        //        return;
        //    }

        //    var entry = AllocateEntry(tx, curEntry.Header.NodeFlags, null, curEntry.Index);
        //    if (entry == null)
        //    {
        //        throw new NullReferenceException(nameof(entry));
        //    }

        //    parent = new TreePageEntry(curEntry.Page, 0, null);

        //    newEntry.Parent = parent;
        //    curEntry.Parent = parent;
        //    curEntry.Page = entry.Page;
        //    curEntry.Index = entry.Index;

        //    parent.Page.CopyTo(entry.Page);
        //    parent.Page.Clear();
        //    parent.Page.Header.NodeFlags = TreeNodeFlags.Branch;

        //    Balance(tx, parent, curEntry, newEntry, key);
        //}

        //public unsafe void Balance(ILowLevelTransaction tx, TreePageEntry parent, TreePageEntry curEntry, TreePageEntry newEntry, TreeNodeDataSlice key)
        //{
        //    var index = curEntry.Index;
        //    if (parent.Page.Header.ItemCount == 0)
        //    {
        //        curEntry.Index = 0;
        //        newEntry.Index = 1;

        //        parent.Allocate(0, (ushort)key.Size, TreeNodeHeaderFlags.PageRef, out var curPos);
        //        parent.Page.Allocate(1, 0, TreeNodeHeaderFlags.PageRef, out var newPos);

        //        parent.InsertPageRefNode(0, curPos, key, curEntry.Header.PageNumber);
        //        parent.InsertPageRefNode(1, newPos, new TreeNodeDataSlice(), newEntry.Header.PageNumber);
        //        return;
        //    }

        //    if (!parent.Allocate(index, (ushort)key.Size, TreeNodeHeaderFlags.PageRef, out var pos))
        //    {
        //        var halfIndex = parent.Header.ItemCount / 2;
        //        var halfKey = parent.GetNodeKey(halfIndex - 1);
        //        var balanceIndex = Balance(tx, parent, halfKey, halfIndex);
        //        if (balanceIndex <= halfIndex && balanceIndex <= curEntry.Index)
        //        {
        //            index = curEntry.Index - balanceIndex;
        //            newEntry.Index = index + 1;
        //        }
        //        else if (balanceIndex > halfIndex && balanceIndex < curEntry.Index)
        //        {
        //            index = curEntry.Index - balanceIndex - 1;
        //            newEntry.Index = index + 1;
        //        }

        //        if (!parent.Page.Allocate(index, (ushort)key.Size, TreeNodeHeaderFlags.PageRef, out pos))
        //        {
        //            throw new InvalidOperationException($"balance page:{parent.Page.Header.PageNumber} failed!");
        //        }
        //    }

        //    parent.Page[index + 1].PageNumber = newEntry.Header.PageNumber;
        //    parent.Page.InsertPageRefNode(index, pos, key, curEntry.Header.PageNumber);
        //}

        private TreeCursor BuildCursor(ILowLevelTransaction tx, Span <byte> key)
        {
            if (_root == null)
            {
                _root = tx.GetPage(0, 0).AsTree();
            }

            var entry = new TreePageEntry(_root, 0, null);

            while (entry.SearchPageIfBranch(tx, key, out var page))
            {
                entry = new TreePageEntry(page, entry.LastMatchIndex, entry);
            }

            return(new TreeCursor(new Memory <byte>(key.ToArray()), tx, entry));
        }
示例#3
0
        private bool ModifyEntry(TreePageEntry entry, ILowLevelTransaction tx)
        {
            var lastMatch      = entry.LastMatch;
            var lastMatchIndex = entry.LastMatchIndex;

            var newPage = tx.ModifyPage(entry.Page);

            if (newPage == null)
            {
                return(false);
            }

            entry.Page           = newPage;
            entry.LastMatch      = lastMatch;
            entry.LastMatchIndex = lastMatchIndex;

            State.OnChanged(entry.Page, TreePageChangeFlags.Modify);
            return(true);
        }
示例#4
0
 public TreeCursor(Memory <byte> key, ILowLevelTransaction tx, TreePageEntry entry)
 {
     _key  = key;
     _tx   = tx;
     Entry = entry;
 }
示例#5
0
        private unsafe TreePageEntry AllocateEntry(ILowLevelTransaction tx, TreeNodeFlags nodeFlags, TreePageEntry parent, int index)
        {
            var page = tx.AllocateTrees(Id, 1)[0];

            ref var header = ref page.Header;