public void Validate()
        {
#if DEBUG
            using (RootLock root = LockRoot(LockType.Read, "Validate", true))
                Validate(root.Pin, null, int.MinValue, int.MaxValue);
#endif
        }
Exemplo n.º 2
0
            /// <inheritdoc />
            public void Dispose()
            {
                //Inner most lock disposed first
                ChildLock?.Dispose();

                //Then global root lock.
                RootLock?.Dispose();
            }
Exemplo n.º 3
0
            public bool MoveNext()
            {
                if (_enumComplete)
                {
                    return(false);
                }

                if (++_currentOffset < _currentLimit)
                {
                    if (_fnContinue == null || _fnContinue(CurrentKey))
                    {
                        return(true);
                    }

                    Array.Clear(_currentSet, 0, _currentSet.Length);
                    _currentOffset = 0;
                    _currentLimit  = 0;
                    _enumComplete  = true;
                    return(false);
                }

                bool success = false;

                using (RootLock root = _tree.LockRoot(LockType.Read, "Enumerator"))
                {
                    int     offset;
                    NodePin next;

                    if (_hasMore && SeekNext(root.Pin, _nextKey, out next, out offset, out _nextKey, out _hasMore))
                    {
                        using (next)
                        {
                            FillFromNode(next.Ptr);
                            _currentOffset = offset;
                        }
                        success = true;
                    }
                }

                if (success)
                {
                    if (_currentOffset >= _currentLimit)
                    {
                        return(MoveNext());
                    }

                    if (_fnContinue == null || _fnContinue(CurrentKey))
                    {
                        return(true);
                    }
                }

                Array.Clear(_currentSet, 0, _currentSet.Length);
                _currentOffset = 0;
                _currentLimit  = 0;
                _enumComplete  = true;
                return(false);
            }
Exemplo n.º 4
0
        private RemoveResult RemoveEntry(TKey key, TValue removeValue) //where T : IRemoveValue<TKey, TValue>
        {
            RemoveResult result;

            using (RootLock root = LockRoot(LockType.Delete, "Remove"))
                result = Delete(root.Pin, key, removeValue, null, int.MinValue);
            DebugComplete("Removed({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 5
0
        private InsertResult AddEntry(TKey key, TValue value) //where T : ICreateOrUpdateValue<TKey, TValue>
        {
            InsertResult result;

            using (RootLock root = LockRoot(LockType.Insert, "AddOrUpdate"))
                result = Insert(root.Pin, key, value, null, int.MinValue);
            DebugComplete("Added({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 6
0
        //TODO: not sure about the functionality of this function after changes
        /// <summary>
        /// Updates an element with the provided key to the value if it exists.
        /// </summary>
        /// <returns>Returns true if the key provided was found and updated to the value.</returns>
        /// <param name="key">The object to use as the key of the element to update.</param>
        /// <param name="value">The new value for the key if found.</param>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.</exception>
        public bool TryUpdate(TKey key, TValue value)
        {
            UpdateInfo ui = new UpdateInfo(value);
            bool       result;

            using (RootLock root = LockRoot(LockType.Update, "Update"))
                result = Update(root.Pin, key, value, default(TValue)); //TODO: old value can be any value
            DebugComplete("Updated({0}) = {1}", key, result);
            return(ui.Updated);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the value associated with the specified key.
        /// </summary>
        public bool TryGetValue(TKey key, out IDictionary <TValue, byte> value)
        {
            bool result;

            value = null;
            using (RootLock root = LockRoot(LockType.Read, "TryGetValue"))
                result = Search(root.Pin, key, ref value);
            DebugComplete("Found({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Gets the value associated with the specified key.
        /// </summary>
        public bool TryGetValue(TKey key, out TValue value)
        {
            bool result;

            value = default(TValue);
            using (RootLock root = LockRoot(LockType.Read, "TryGetValue"))
                result = Search(root.Pin, key, ref value);
            DebugComplete("Found({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Modify the value associated with the result of the provided update method
        /// as an atomic operation, Allows for reading/writing a single record within
        /// the tree lock.  Be cautious about the behavior and performance of the code
        /// provided as it can cause a dead-lock to occur.  If the method returns an
        /// instance who .Equals the original, no update is applied.
        /// </summary>
        public bool TryUpdate(TKey key, KeyValueUpdate <TKey, TValue> fnUpdate)
        {
            UpdateInfo ui = new UpdateInfo(fnUpdate);
            bool       result;

            using (RootLock root = LockRoot(LockType.Update, "Update"))
                result = Update(root.Pin, key, ref ui);
            DebugComplete("Updated({0}) = {1}", key, result);
            return(ui.Updated);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Updates an element with the provided key to the value if it exists.
        /// </summary>
        /// <returns>Returns true if the key provided was found and updated to the value.</returns>
        /// <param name="key">The object to use as the key of the element to update.</param>
        /// <param name="value">The new value for the key if found.</param>
        /// <param name="comparisonValue">The value that is compared to the value of the element with key.</param>
        public bool TryUpdate(TKey key, TValue value, TValue comparisonValue)
        {
            UpdateIfValue ui = new UpdateIfValue(value, comparisonValue);
            bool          result;

            using (RootLock root = LockRoot(LockType.Update, "Update"))
                result = Update(root.Pin, key, ref ui);
            DebugComplete("Updated({0}) = {1}", key, result);
            return(ui.Updated);
        }
Exemplo n.º 11
0
 /// <summary>
 /// Due to the cost of upkeep, this must be enable each time the object is created via a call to
 /// EnableCount() which itself must be done before any writer threads are active for it to be
 /// accurate.  This requires that the entire tree be loaded (sequentially) in order to build
 /// the initial working count.  Once completed, members like Add() and Remove() will keep the
 /// initial count accurate.
 /// </summary>
 public void EnableCount()
 {
     if (_hasCount)
     {
         return;
     }
     _keyCount = 0;
     using (RootLock root = LockRoot(LockType.Read, "EnableCount", true))
         CountValues(root.Pin, out _keyCount, out _valueCount);
     _hasCount = true;
 }
Exemplo n.º 12
0
 /// <summary>
 /// Due to the cost of upkeep, this must be enable each time the object is created via a call to
 /// EnableCount() which itself must be done before any writer threads are active for it to be
 /// accurate.  This requires that the entire tree be loaded (sequentially) in order to build
 /// the initial working count.  Once completed, members like Add() and Remove() will keep the
 /// initial count accurate.
 /// </summary>
 public void EnableCount()
 {
     if (_hasCount)
     {
         return;
     }
     _count = 0;
     using (RootLock root = LockRoot(LockType.Read, "EnableCount", true))
         _count = CountValues(root.Pin);
     _hasCount = true;
 }
Exemplo n.º 13
0
        private RemoveResult RemoveEntry <T>(TKey key, ref T removeValue) where T : IRemoveValue <TKey, TValue>
        {
            RemoveResult result;

            using (RootLock root = LockRoot(LockType.Delete, "Remove"))
                result = Delete(root.Pin, key, ref removeValue, null, int.MinValue);
            if (result == RemoveResult.Removed && _hasCount)
            {
                Interlocked.Decrement(ref _count);
            }
            DebugComplete("Removed({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 14
0
        private InsertResult AddEntry <T>(TKey key, ref T info) where T : ICreateOrUpdateValue <TKey, TValue>
        {
            InsertResult result;

            using (RootLock root = LockRoot(LockType.Insert, "AddOrUpdate"))
                result = Insert(root.Pin, key, ref info, null, int.MinValue);
            if (result == InsertResult.Inserted && _hasCount)
            {
                Interlocked.Increment(ref _count);
            }
            DebugComplete("Added({0}) = {1}", key, result);
            return(result);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Optimized insert of presorted key/value pairs.
        /// If the input is not presorted, please use AddRange() instead.
        /// </summary>
        /// <param name="items">The ordered list of items to insert</param>
        /// <param name="allowUpdates">True to overwrite any existing records</param>
        /// <returns>The total number of records inserted or updated</returns>
        public int AddRangeSorted(IEnumerable <KeyValuePair <TKey, TValue> > items, bool allowUpdates)
        {
            int result = 0;

            using (AddRangeInfo bulk = new AddRangeInfo(allowUpdates, items))
            {
                while (!bulk.IsComplete)
                {
                    KeyRange range = new KeyRange(_keyComparer);
                    using (RootLock root = LockRoot(LockType.Insert, "BulkInsert"))
                        result += AddRange(root.Pin, ref range, bulk, null, int.MinValue);
                }
            }
            DebugComplete("AddRange({0} records)", result);
            return(result);
        }
 public void Reset()
 {
     if (_hasStart)
     {
         _enumComplete  = false;
         _currentLimit  = 0;
         _currentOffset = 0;
         _hasMore       = true;
         _nextKey       = _startKey;
     }
     else
     {
         using (RootLock root = _tree.LockRoot(LockType.Read, "Enumerator"))
             using (NodePin first = SeekFirst(root.Pin, out _nextKey, out _hasMore))
             {
                 FillFromNode(first.Ptr);
                 _enumComplete = _currentLimit == 0;
             }
     }
 }
 public void Print(TextWriter output, DebugFormat format)
 {
     using (RootLock root = LockRoot(LockType.Read, "Print", true))
         Print(root.Pin, output, 0, format);
 }
Exemplo n.º 18
0
 /// <summary>
 /// Returns the first key and it's associated value.
 /// </summary>
 public bool TryGetFirst(out KeyValuePair <TKey, IDictionary <TValue, byte> > item)
 {
     using (RootLock root = LockRoot(LockType.Read, "TryGetFirst"))
         return(TryGetEdge(root.Pin, true, out item));
 }
Exemplo n.º 19
0
        /// <summary>
        /// Rewrite the entire BTree as a transaction to include the provided items.  This method is Thread safe.
        /// If the input is already sorted, use BulkInsertOptions overload to specify InputIsSorted = true.
        /// </summary>
        public int BulkInsert(IEnumerable <KeyValuePair <TKey, TValue> > items, BulkInsertOptions bulkOptions)
        {
            NodePin oldRoot = null;

            if (bulkOptions.InputIsSorted == false)
            {
                KeyValueSerializer <TKey, TValue> kvserializer = new KeyValueSerializer <TKey, TValue>(_options.KeySerializer, _options.ValueSerializer);
                items = new OrderedKeyValuePairs <TKey, TValue>(_options.KeyComparer, items, kvserializer)
                {
                    DuplicateHandling = bulkOptions.DuplicateHandling
                };
            }

            List <IStorageHandle> handles = new List <IStorageHandle>();

            try
            {
                int counter = 0;
                using (RootLock root = LockRoot(LockType.Insert, "Merge", false))
                {
                    if (root.Pin.Ptr.Count != 1)
                    {
                        throw new InvalidDataException();
                    }

                    NodeHandle oldRootHandle = root.Pin.Ptr[0].ChildNode;
                    oldRoot = _storage.Lock(root.Pin, oldRootHandle);

                    if (oldRoot.Ptr.Count == 0 || bulkOptions.ReplaceContents)
                    {
                        // Currently empty, so just enforce duplicate keys...
                        items = OrderedKeyValuePairs <TKey, TValue>
                                .WithDuplicateHandling(items,
                                                       new KeyValueComparer <TKey, TValue>(_options.KeyComparer),
                                                       bulkOptions.DuplicateHandling);
                    }
                    else
                    {
                        // Merging with existing data and enforce duplicate keys...
                        items = OrderedKeyValuePairs <TKey, TValue>
                                .Merge(_options.KeyComparer, bulkOptions.DuplicateHandling, EnumerateNodeContents(oldRoot), items);
                    }

                    Node newtree = BulkWrite(handles, ref counter, items);
                    if (newtree == null) // null when enumeration was empty
                    {
                        return(0);
                    }

                    using (NodeTransaction trans = _storage.BeginTransaction())
                    {
                        Node rootNode = trans.BeginUpdate(root.Pin);
                        rootNode.ReplaceChild(0, oldRootHandle, new NodeHandle(newtree.StorageHandle));
                        trans.Commit();
                    }

                    _count = counter;
                }

                //point of no return...
                handles.Clear();
                DeleteTree(oldRoot);
                oldRoot = null;

                if (bulkOptions.CommitOnCompletion)
                {
                    //Since transaction logs do not deal with bulk-insert, we need to commit our current state
                    Commit();
                }
                return(counter);
            }
            catch
            {
                if (oldRoot != null)
                {
                    oldRoot.Dispose();
                }

                foreach (IStorageHandle sh in handles)
                {
                    try { _storage.Storage.Destroy(sh); }
                    catch (ThreadAbortException) { throw; }
                    catch { continue; }
                }
                throw;
            }
        }
Exemplo n.º 20
0
 /// <summary>
 /// Returns the last key and it's associated value.
 /// </summary>
 public bool TryGetLast(out KeyValuePair <TKey, TValue> item)
 {
     using (RootLock root = LockRoot(LockType.Read, "TryGetLast"))
         return(TryGetEdge(root.Pin, false, out item));
 }