private int AddRange(NodePin thisLock, ref KeyRange range, AddRangeInfo value, NodePin parent, int parentIx) { int counter = 0; Node me = thisLock.Ptr; if (me.Count == me.Size && parent != null) { using (NodeTransaction trans = _storage.BeginTransaction()) { TKey splitAt; if (parent.Ptr.IsRoot) //Is root node { Node rootNode = trans.BeginUpdate(parent); using (NodePin newRoot = trans.Create(parent, false)) { rootNode.ReplaceChild(0, thisLock.Handle, newRoot.Handle); newRoot.Ptr.Insert(0, new Element(default(TKey), thisLock.Handle)); using (NodePin next = Split(trans, ref thisLock, newRoot, 0, out splitAt, true)) using (thisLock) { trans.Commit(); GC.KeepAlive(thisLock); GC.KeepAlive(next); } return(AddRange(newRoot, ref range, value, parent, parentIx)); } } trans.BeginUpdate(parent); using (NodePin next = Split(trans, ref thisLock, parent, parentIx, out splitAt, true)) using (thisLock) { trans.Commit(); if (_keyComparer.Compare(value.Current.Key, splitAt) >= 0) { thisLock.Dispose(); range.SetMinKey(splitAt); return(AddRange(next, ref range, value, parent, parentIx + 1)); } next.Dispose(); range.SetMaxKey(splitAt); return(AddRange(thisLock, ref range, value, parent, parentIx)); } } } if (parent != null) { parent.Dispose(); } if (me.IsLeaf) { using (NodeTransaction trans = _storage.BeginTransaction()) { me = trans.BeginUpdate(thisLock); int inserted = 0; while (me.Count < me.Size && !value.IsComplete && range.IsKeyInRange(value.Current.Key)) { int ordinal; bool exists = me.BinarySearch(_itemComparer, new Element(value.Current.Key), out ordinal); DuplicateKeyException.Assert(!exists || value.AllowUpdate); if (exists) { me.SetValue(ordinal, value.Current.Key, value.Current.Value, _keyComparer); trans.UpdateValue(value.Current.Key, value.Current.Value); } else { me.Insert(ordinal, new Element(value.Current.Key, value.Current.Value)); trans.AddValue(value.Current.Key, value.Current.Value); inserted++; } counter++; value.MoveNext(); } trans.Commit(); if (_hasCount && inserted > 0) { int count = _count, test; while (count != (test = Interlocked.CompareExchange(ref _count, count + inserted, count))) { count = test; } } } } else { int ordinal; me.BinarySearch(_itemComparer, new Element(value.Current.Key), out ordinal); if (ordinal >= me.Count) { ordinal = me.Count - 1; } if (ordinal > 0) { range.SetMinKey(me[ordinal - 1].Key); } if (ordinal < (me.Count - 1)) { range.SetMaxKey(me[ordinal + 1].Key); } using (NodePin child = _storage.Lock(thisLock, me[ordinal].ChildNode)) counter += AddRange(child, ref range, value, thisLock, ordinal); } return(counter); }