Result <Pointer> ExpandLevel(string key, StoredValue value) { if (Level == 0) { return(new ArgumentOutOfRange <Pointer>(nameof(Level))); } var md = InMemoryMd.Create(Level - 1); var leafPointer = (md as InMemoryMd).Add(key, value); if (!leafPointer.HasValue) { return(leafPointer); } switch (md.Type) { case MdType.Pointers: // i.e. we have still not reached the end of the tree Add(new Pointer { MdLocator = md.MdLocator, ValueType = typeof(Pointer).Name }); break; case MdType.Values: // i.e. we are now right above leaf level Add(leafPointer.Value); break; default: return(new ArgumentOutOfRange <Pointer>(nameof(md.Type))); } return(leafPointer); }
Result <Pointer> Set(string key, StoredValue value) { switch (Type) { case MdType.Pointers: return(new InvalidOperation <Pointer>($"Cannot set values directly on pointers. Key {key}, value type {value.ValueType}")); case MdType.Values: _valueFields[key] = value; return(Result.OK(new Pointer { MdLocator = this.MdLocator, MdKey = key, ValueType = value.ValueType })); default: return(new ArgumentOutOfRange <Pointer>(nameof(Type))); } }
// It will return the direct pointer to the stored value // which makes it readily available for indexing at higher levels. Result <Pointer> Add(string key, StoredValue value) { if (IsFull) { return(new MdOutOfEntriesError <Pointer>($"Filled: {Count}/{MdMetadata.Capacity}")); } switch (Type) { case MdType.Pointers: if (Count == 0) { return(ExpandLevel(key, value)); } var target = Locate(_pointerFields[Count].MdLocator); if (target.IsFull) { return(ExpandLevel(key, value)); } return((target as InMemoryMd).Add(key, value)); case MdType.Values: if (_valueFields.ContainsKey(key)) { return(new ValueAlreadyExists <Pointer>($"Key: {key}.")); } _valueFields[key] = value; Count++; return(Result.OK(new Pointer { MdLocator = this.MdLocator, MdKey = key, ValueType = value.ValueType })); default: return(new ArgumentOutOfRange <Pointer>(nameof(Type))); } }
async Task <Result <Pointer> > DirectlyAddToLeaf(string key, StoredValue value) { if (_currentLeaf == null) { _currentLeaf = _head; } else if (_currentLeaf.IsFull) { var result = await _head.AddAsync(key, value).ConfigureAwait(false); var leafResult = await MdAccess.LocateAsync(result.Value.MdLocator); if (leafResult.HasValue) { _currentLeaf = leafResult.Value; } return(result); } return(await _currentLeaf.AddAsync(key, value)); }
public async Task <Result <Pointer> > AddAsync(string key, StoredValue value) { if (_head.IsFull) { // create new head, add pointer to current head in to it. // the level > 0 indicates its role as pointer holder var newHead = await MdAccess.CreateAsync(_head.Level + 1).ConfigureAwait(false); var pointer = new Pointer { MdLocator = _head.MdLocator, ValueType = typeof(Pointer).Name }; await newHead.AddAsync(pointer).ConfigureAwait(false); _head = newHead; await _onHeadAddressChange(newHead.MdLocator).ConfigureAwait(false); } return(await DirectlyAddToLeaf(key, value).ConfigureAwait(false)); }
private InMemoryMd(int level) { MdLocator = new MdLocator(new byte[32], DataProtocol.DEFAULT_PROTOCOL); _rand.NextBytes(MdLocator.XORName); _valueFields["0"] = new StoredValue(level); }
public Task <Result <Pointer> > AddAsync(string key, StoredValue value) { return(Task.FromResult(Add(key, value))); }
public Task <Result <Pointer> > SetAsync(string key, StoredValue value, long expectedVersion = -1) { return(Task.FromResult(Set(key, value))); }
public async Task AddAsync(string type, MdLocator location) { var value = new StoredValue(location); await _dataTree.AddAsync(type, value).ConfigureAwait(false); }