Esempio n. 1
0
 private IRadixTreeNode NewNode(DbItemReference parentReference)
 {
     return(new RadixTreeNode(0)
     {
         ParentNodeReference = parentReference,
     });
 }
Esempio n. 2
0
        /// <summary>
        /// Allocates a new value and produces reference to it.
        /// </summary>
        /// <param name="value">Value to allocate</param>
        /// <returns>Reference to allocated value</returns>
        public DbItemReference AllocateNew(TValue value)
        {
            var reference = new DbItemReference(_index++, 0);

            _dictionary.Add(reference.ToString(), value);
            return(reference);
        }
Esempio n. 3
0
        /// <summary>
        /// Reallocates already allocated value and produces reference to it.
        /// </summary>
        /// <param name="reference">Reference to the already allocated value</param>
        /// <param name="newValue">New value to allocate</param>
        /// <returns>Reference to reallocated value</returns>
        public DbItemReference Reallocate(DbItemReference reference, TValue newValue)
        {
            var str = reference.ToString();

            _dictionary.Remove(str);
            return(AllocateNew(newValue));
        }
Esempio n. 4
0
        public IRadixTreeNode Fetch(DbItemReference reference)
        {
            if (DbItemReference.IsNull(reference))
            {
                return(null);
            }

            var page = _pageManager.FetchPage(reference.PageIndex);

            if (page.BackingObject == null)
            {
                var obj1 = RadixTreePageBackingObject.FromPage(page);
                page = new Page(_pageManager, page.Index, () => Serialize(obj1), obj1);
            }

            var backingObject = (RadixTreePageBackingObject)page.BackingObject;

            var obj = backingObject.Items[reference.ItemIndex];

            var result = obj as IRadixTreeNode;

            if (result == null)
            {
                result           = NodeFromBytes((byte[])obj);
                result.Reference = (DbItemReference)reference.Clone();
                backingObject.Items[reference.ItemIndex] = result;
            }

            return(result);
        }
Esempio n. 5
0
        public byte[] GetItemSegment(DbItemReference reference, long startIndex, long endIndex)
        {
            var item   = _items[reference.PageIndex];
            var result = new byte[endIndex - startIndex];

            Array.Copy(item, startIndex, result, 0, result.Length);
            return(result);
        }
        public RadixTreeNodeMemoryStorage()
        {
            // initialize and add root node
            var root = NewNode(DbItemReference.Null);

            _rootNodeReference = root.Reference;
            _nodes.Add(root.Reference.ToString(), root);
        }
Esempio n. 7
0
        public DbItemReference Allocate(byte[] content)
        {
            _items[_lastNumber] = content;
            var reference = new DbItemReference(_lastNumber, 0);

            _lastNumber++;

            return(reference);
        }
        public void Remove(DbItemReference reference)
        {
            if (_rootNodeReference.Equals(reference))
            {
                throw new ArgumentOutOfRangeException(nameof(reference), "Unable to delete the root node");
            }

            _nodes.Remove(reference.ToString());
        }
 private IRadixTreeNode NewNode(DbItemReference parentReference)
 {
     _index++;
     return(new RadixTreeNode(0)
     {
         Reference = new DbItemReference(_index, 0),
         ParentNodeReference = parentReference,
     });
 }
Esempio n. 10
0
 /// <summary>
 /// Release allocated value.
 /// </summary>
 /// <param name="reference">Reference to allocated value</param>
 public void Free(DbItemReference reference)
 {
     //if (IsVersioningEnabled)
     //{
     //    var record = new VersionedRecord(_memoryManager.Get(reference).RawData, _memoryManager, SnapshotData);
     //    record.Expire(DataTankerTransaction.Current.Id);
     //}
     //else
     _memoryManager.Free(reference);
 }
Esempio n. 11
0
        public static VersionInfo Read(Stream stream)
        {
            var result = new VersionInfo();
            var buffer = new byte[sizeof(int)];

            stream.Read(buffer, 0, sizeof(int));
            result.CreateChangeNumber = BitConverter.ToInt32(buffer, 0);
            stream.Read(buffer, 0, sizeof(int));
            result.ExpireChangeNumber = BitConverter.ToInt32(buffer, 0);
            result.VersionReference   = DbItemReference.Read(stream);

            return(result);
        }
Esempio n. 12
0
        private DbItemReference GetVersionReferenceByRecordReference(DbItemReference reference)
        {
            if (IsVersioningEnabled)
            {
                var record = new VersionedRecord(_memoryManager.Get(reference).RawData, _memoryManager, SnapshotData);

                if (record.HasVisibleVersionTo(DataTankerTransaction.Current.Id))
                {
                    reference = record.GetMatchingVersionReference(DataTankerTransaction.Current.Id);
                }
            }

            return(reference);
        }
Esempio n. 13
0
        /// <summary>
        /// Fetches value by its reference.
        /// </summary>
        /// <param name="reference">Reference to the value</param>
        /// <returns>The instance of value</returns>
        public TValue Fetch(DbItemReference reference)
        {
            var item = _memoryManager.Get(reference);

            if (IsVersioningEnabled)
            {
                var record = new VersionedRecord(item.RawData, _memoryManager, SnapshotData);

                if (record.HasVisibleVersionTo(DataTankerTransaction.Current.Id))
                {
                    item = record.GetMatchingVersion(DataTankerTransaction.Current.Id);
                }
            }

            return(_valueSerializer.Deserialize(item.RawData));
        }
Esempio n. 14
0
        public void MultipageItemSegments()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var fsm = new FreeSpaceMap(manager);

                var memoryManager = new MemoryManager(fsm, manager);

                var             content   = GenerateRandomSequence(4096 * 5 + 100);
                DbItemReference reference = memoryManager.Allocate(content);

                // check full content
                Assert.IsTrue(AreEqualByteArrays(content, memoryManager.GetItemSegment(reference, 0, content.Length - 1)));

                var bytes = new byte[2];

                // check first two bytes
                Array.Copy(content, 0, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 0, 1)));

                // check next two bytes
                Array.Copy(content, 2, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 2, 3)));

                // check last two bytes
                Array.Copy(content, content.Length - 2, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, content.Length - 2, content.Length - 1)));

                //last but two bytes
                Array.Copy(content, content.Length - 4, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, content.Length - 4, content.Length - 3)));

                //all except first two bytes and last two bytes
                bytes = new byte[content.Length - 4];
                Array.Copy(content, 2, bytes, 0, content.Length - 4);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 2, content.Length - 3)));
            }
        }
Esempio n. 15
0
        public void Remove(DbItemReference reference)
        {
            if (_rootNodeReference.Equals(reference))
            {
                throw new ArgumentOutOfRangeException(nameof(reference), "Unable to delete the root node");
            }

            var page = _pageManager.FetchPage(reference.PageIndex);

            if (page.BackingObject == null)
            {
                var obj = RadixTreePageBackingObject.FromPage(page);
                page = new Page(_pageManager, reference.PageIndex, () => Serialize(obj), obj);
            }

            var backingObject = (RadixTreePageBackingObject)page.BackingObject;

            if (backingObject.Items.Count == reference.ItemIndex + 1)
            {
                backingObject.Items.RemoveAt(reference.ItemIndex);
            }
            else
            {
                backingObject.Items[reference.ItemIndex] = null;
            }

            if (backingObject.Items.Any(item => item != null))
            {
                _pageManager.UpdatePage(page);
            }
            else
            {
                _pageManager.RemovePage(page.Index);
                if (_recentPages.Contains(page.Index))
                {
                    _recentPages.Remove(page.Index);
                }
            }
        }
Esempio n. 16
0
        private IRadixTreeNode NodeFromBytes(byte[] nodeBytes)
        {
            var result = new RadixTreeNode(0);

            using (var ms = new MemoryStream(nodeBytes, false))
            {
                var buffer = new byte[PageFormatter.OnPagePointerSize];

                ms.Read(buffer, 0, PageFormatter.OnPagePointerSize); // overall size

                ms.Read(buffer, 0, PageFormatter.OnPagePointerSize); // prefix length
                short prefixLength = BitConverter.ToInt16(buffer, 0);
                var   prefix       = new byte[prefixLength];
                ms.Read(prefix, 0, prefixLength); // prefix itself
                result.Prefix              = prefix;
                result.ValueReference      = DbItemReference.Read(ms);
                result.ParentNodeReference = DbItemReference.Read(ms);

                if (DbItemReference.IsNull(result.ValueReference))
                {
                    result.ValueReference = null;
                }
                if (DbItemReference.IsNull(result.ParentNodeReference))
                {
                    result.ParentNodeReference = null;
                }

                ms.Read(buffer, 0, sizeof(short));
                var nodeCount = BitConverter.ToInt16(buffer, 0);
                for (int i = 0; i < nodeCount; i++)
                {
                    var key   = (byte)ms.ReadByte();
                    var value = DbItemReference.Read(ms);
                    result.Entries.Add(new KeyValuePair <byte, DbItemReference>(key, value));
                }

                return(result);
            }
        }
Esempio n. 17
0
        private TKey BuildKeyForNode(IRadixTreeNode node)
        {
            var prefixes = new List <byte[]>();

            while (!DbItemReference.IsNull(node.ParentNodeReference))
            {
                prefixes.Add(node.Prefix);
                node = _nodeStorage.Fetch(node.ParentNodeReference);
            }

            prefixes.Reverse();

            using (var ms = new MemoryStream())
            {
                foreach (var prefix in prefixes.Where(p => p != null))
                {
                    ms.Write(prefix, 0, prefix.Length);
                }

                return(_keySerializer.Deserialize(ms.ToArray()));
            }
        }
Esempio n. 18
0
        private void CheckRoot()
        {
            if (_rootNodeReference == null)
            {
                var headerPage = _pageManager.FetchPage(0);

                _rootPageIndex = ((HeadingPageHeader)PageFormatter.GetPageHeader(headerPage)).AccessMethodPageIndex;
                var page = _pageManager.FetchPage(_rootPageIndex);

                var items = PageFormatter.ReadVariableSizeItems(page);
                if (items.Any())
                {
                    // root page already has an item
                    _rootNodeReference = new DbItemReference(_rootPageIndex, 0);
                }
                else
                {
                    var node = new RadixTreeNode(256);
                    PageFormatter.AddVariableSizeItem(page, GetNodeBytes(node, GetNodeSize(0, 256)));
                    _rootNodeReference = new DbItemReference(_rootPageIndex, 0);
                    _pageManager.UpdatePage(page);
                }
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Removes key-value pair by key.
        /// </summary>
        /// <param name="key">The key</param>
        public void Remove(TKey key)
        {
            var            binaryKey = _keySerializer.Serialize(key);
            int            keyOffset;
            int            nodePrefixOffset;
            bool           isFullMatch;
            IRadixTreeNode node = FindMostSuitableNode(binaryKey, out keyOffset, out nodePrefixOffset, out isFullMatch);

            if (isFullMatch)
            {
                _valueStorage.Free(node.ValueReference);
                node.ValueReference = null;

                if (node.Entries.Any())
                {
                    if (node.Prefix != null && node.Entries.Count == 1)
                    {
                        var child = _nodeStorage.Fetch(node.Entries[0].Value);

                        var newPrefixLength = node.Prefix.Length + child.Prefix.Length;
                        if (newPrefixLength <= MaxPrefixLength)
                        {
                            var newPrefix = new byte[newPrefixLength];

                            Buffer.BlockCopy(node.Prefix, 0, newPrefix, 0, node.Prefix.Length);
                            Buffer.BlockCopy(child.Prefix, 0, newPrefix, node.Prefix.Length, child.Prefix.Length);

                            child.Prefix = newPrefix;
                            child.ParentNodeReference = node.ParentNodeReference;

                            _nodeStorage.Remove(node.Reference);
                            bool reallocated;
                            child = UpdateOrReallocateNode(child, out reallocated);

                            var parent = _nodeStorage.Fetch(child.ParentNodeReference);
                            int index;
                            FindSuitableEntry(parent.Entries, child.Prefix[0], out index);
                            parent.Entries[index] = new KeyValuePair <byte, DbItemReference>(child.Prefix[0], child.Reference);

                            UpdateOrFail(parent);
                        }
                        else
                        {
                            UpdateOrFail(node);
                        }
                    }
                    else
                    {
                        UpdateOrFail(node);
                    }
                }
                else
                {
                    while (!DbItemReference.IsNull(node.ParentNodeReference))
                    {
                        var parentNode = _nodeStorage.Fetch(node.ParentNodeReference);
                        int index;
                        FindSuitableEntry(parentNode.Entries, node.Prefix[0], out index);
                        parentNode.Entries.RemoveAt(index);
                        _nodeStorage.Remove(node.Reference);

                        if (parentNode.Entries.Any() || parentNode.ValueReference != null ||
                            DbItemReference.IsNull(parentNode.ParentNodeReference))
                        {
                            UpdateOrFail(parentNode);
                            break;
                        }

                        node = parentNode;
                    }
                }
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Inserts or updates key value pair.
        /// </summary>
        /// <param name="key">The key</param>
        /// <param name="value">The value</param>
        public void Set(TKey key, TValue value)
        {
            var  binaryKey = _keySerializer.Serialize(key);
            int  keyOffset;
            int  nodePrefixOffset;
            bool isFullMatch;

            IRadixTreeNode targetNode = FindMostSuitableNode(binaryKey, out keyOffset, out nodePrefixOffset, out isFullMatch);

            if (isFullMatch)
            {
                // here we needn't any manipulation with key prefixes
                // simply update the existing or allocate a new value
                targetNode.ValueReference =
                    targetNode.ValueReference != null
                        ? _valueStorage.Reallocate(targetNode.ValueReference, value)
                        : _valueStorage.AllocateNew(value);

                UpdateOrFail(targetNode);
                return;
            }

            // we have a partial match
            var remainingKeyPart = new byte[binaryKey.Length - keyOffset];

            var nodeChain = new List <IRadixTreeNode>();

            if (remainingKeyPart.Length > 0)
            {
                Buffer.BlockCopy(binaryKey, keyOffset, remainingKeyPart, 0, remainingKeyPart.Length);

                // the remaining prefix may exceed the _maxPrefixLength
                // we must create a chain of nodes, where each node
                // contain part of the prefix remaining
                nodeChain = CreateNodeChain(remainingKeyPart);
            }

            if (targetNode.Prefix != null && nodePrefixOffset < targetNode.Prefix.Length)
            {
                // we got into splitting update:
                // the targetNode is split into newParentNode and targetNode itself
                // nodeChain (if has any items) is attached to newParentNode as a child

                // split prefix
                byte[] remainingPrefix;
                byte[] prefixForNewParent;

                SplitPrefix(targetNode.Prefix, nodePrefixOffset, out prefixForNewParent, out remainingPrefix);

                targetNode.Prefix = remainingPrefix;

                var newParentNode = _nodeStorage.Create(prefixForNewParent.Length, 2);

                newParentNode.Prefix = prefixForNewParent;
                newParentNode.ParentNodeReference = targetNode.ParentNodeReference;
                targetNode.ParentNodeReference    = newParentNode.Reference;

                var valueReference = _valueStorage.AllocateNew(value);
                if (nodeChain.Any())
                {
                    nodeChain.First().ParentNodeReference = newParentNode.Reference;
                    nodeChain.Last().ValueReference       = valueReference;
                }
                else
                {
                    newParentNode.ValueReference = valueReference;
                }

                // add links to child nodes
                foreach (var item in GetChildLinks(nodeChain.FirstOrDefault(), targetNode))
                {
                    newParentNode.Entries.Add(item);
                }

                if (nodeChain.Any())
                {
                    foreach (var node in nodeChain)
                    {
                        UpdateOrFail(node);
                    }
                }

                UpdateOrFail(newParentNode);
                UpdateOrFail(targetNode);

                // change link in parent node if needed
                if (!DbItemReference.IsNull(newParentNode.ParentNodeReference))
                {
                    AdjustParentNodeLink(newParentNode, true);
                }
            }
            else
            {
                // here is keeping update
                // all nodes above remain intact

                byte b = remainingKeyPart[0];
                int  index;
                FindSuitableEntry(targetNode.Entries, b, out index);

                targetNode.Entries.Insert(index, new KeyValuePair <byte, DbItemReference>(b, (DbItemReference)(nodeChain.First().Reference.Clone())));
                bool reallocated;
                targetNode = UpdateOrReallocateNode(targetNode, out reallocated);

                if (reallocated)
                {
                    AdjustParentNodeLink(targetNode, true);
                    AdjustLinksInChildNodes(targetNode, true);
                }

                nodeChain.First().ParentNodeReference = targetNode.Reference;
                nodeChain.Last().ValueReference       = _valueStorage.AllocateNew(value);

                foreach (var node in nodeChain)
                {
                    UpdateOrFail(node);
                }
            }
        }
        public IRadixTreeNode Fetch(DbItemReference reference)
        {
            var str = reference.ToString();

            return(_nodes.ContainsKey(str) ? _nodes[str] : null);
        }
Esempio n. 22
0
 public void Free(DbItemReference reference)
 {
     _items.Remove(reference.PageIndex);
 }
Esempio n. 23
0
 public DbItemReference Reallocate(DbItemReference reference, byte[] newContent)
 {
     _items[reference.PageIndex] = newContent;
     return(new DbItemReference(reference.PageIndex, 0));
 }
Esempio n. 24
0
        private KeyValuePair <TKey, DbItemReference> IndexEntryFromBytes(byte[] bytes)
        {
            short keyLength = BitConverter.ToInt16(bytes, 0);
            var   keyBytes  = new byte[keyLength];

            Buffer.BlockCopy(bytes, sizeof(Int16), keyBytes, 0, keyLength);
            return(new KeyValuePair <TKey, DbItemReference>(_keySerializer.Deserialize(keyBytes), DbItemReference.FromBytes(bytes, _maxKeySize + _keyLengthSize)));
        }
Esempio n. 25
0
 public DbItem Get(DbItemReference reference)
 {
     return(new DbItem(_items[reference.PageIndex]));
 }
Esempio n. 26
0
        /// <summary>
        /// Gets the segment of binary representation of value.
        /// </summary>
        /// <param name="reference">Reference to the value</param>
        /// <param name="startIndex">The start index of binary representation</param>
        /// <param name="endIndex">The end index of binary representation</param>
        /// <returns>The array of bytes containing specified segment of value</returns>
        public byte[] GetRawDataSegment(DbItemReference reference, long startIndex, long endIndex)
        {
            reference = GetVersionReferenceByRecordReference(reference);

            return(_memoryManager.GetItemSegment(reference, startIndex, endIndex));
        }
Esempio n. 27
0
        /// <summary>
        /// Retreives the length of value (in bytes) by its reference.
        /// </summary>
        /// <param name="reference">Reference to the value</param>
        /// <returns>The length of referenced value</returns>
        public long GetRawDataLength(DbItemReference reference)
        {
            reference = GetVersionReferenceByRecordReference(reference);

            return(_memoryManager.GetLength(reference));
        }
Esempio n. 28
0
 public long GetLength(DbItemReference reference)
 {
     return(_items[reference.PageIndex].Length);
 }
Esempio n. 29
0
 /// <summary>
 /// Reallocates already allocated value and produces reference to it.
 /// </summary>
 /// <param name="reference">Reference to the already allocated value</param>
 /// <param name="newValue">New value to allocate</param>
 /// <returns>Reference to reallocated value</returns>
 public DbItemReference Reallocate(DbItemReference reference, TValue newValue)
 {
     return(_memoryManager.Reallocate(reference, _valueSerializer.Serialize(newValue)));
 }
Esempio n. 30
0
        /// <summary>
        /// Gets the key next to the specified key.
        /// The existence of the specified key is not required.
        /// </summary>
        /// <returns>The key next to specified key</returns>
        public TKey NextTo(TKey key)
        {
            var            binaryKey = _keySerializer.Serialize(key);
            int            keyOffset;
            int            nodePrefixOffset;
            bool           isFullMatch;
            IRadixTreeNode targetNode = FindMostSuitableNode(binaryKey, out keyOffset, out nodePrefixOffset, out isFullMatch);

            if (isFullMatch || keyOffset == binaryKey.Length)
            {
                if (targetNode.Entries.Any())
                {
                    targetNode = _nodeStorage.Fetch(targetNode.Entries.First().Value);
                }
                else
                {
                    while (!DbItemReference.IsNull(targetNode.ParentNodeReference))
                    {
                        var parent = _nodeStorage.Fetch(targetNode.ParentNodeReference);
                        targetNode = GetChildNextTo(parent, targetNode.Prefix[0]);
                        if (targetNode != null)
                        {
                            break;
                        }
                        targetNode = parent;
                    }
                }
            }
            else
            {
                byte b = binaryKey[keyOffset];
                while (true)
                {
                    var child = GetChildNextTo(targetNode, b);
                    if (child != null)
                    {
                        targetNode = child;
                        break;
                    }

                    if (DbItemReference.IsNull(targetNode.ParentNodeReference))
                    {
                        break;
                    }

                    b          = targetNode.Prefix[0];
                    targetNode = _nodeStorage.Fetch(targetNode.ParentNodeReference);
                }
            }

            if (DbItemReference.IsNull(targetNode.ParentNodeReference))
            {
                return(default(TKey));
            }

            while (DbItemReference.IsNull(targetNode.ValueReference) && targetNode.Entries.Any())
            {
                targetNode = _nodeStorage.Fetch(targetNode.Entries.First().Value);
            }

            return(BuildKeyForNode(targetNode));
        }