/// <summary>Increments the count of an (index, value) pair in the multimap.</summary> /// <param name="trans">Transaction used for the operation</param> /// <param name="key">Key of the entry</param> /// <param name="value">Value for the <paramref name="key"/> to increment</param> /// <remarks>If the (index, value) pair does not exist, its value is considered to be 0</remarks> /// <exception cref="System.ArgumentNullException">If <paramref name="trans"/> is null.</exception> public void Add(IFdbTransaction trans, TKey key, TValue value) { //note: this method does not need to be async, but subtract is, so it's better if both methods have the same shape. if (trans == null) { throw new ArgumentNullException(nameof(trans)); } trans.AtomicIncrement64(this.Subspace[key, value]); }
/// <summary>Increments the count of an (index, value) pair in the multimap.</summary> /// <param name="trans">Transaction used for the operation</param> /// <param name="key">Key of the entry</param> /// <param name="value">Value for the <paramref name="key"/> to increment</param> /// <remarks>If the (index, value) pair does not exist, its value is considered to be 0</remarks> /// <exception cref="System.ArgumentNullException">If <paramref name="trans"/> is null.</exception> public Task AddAsync([NotNull] IFdbTransaction trans, TKey key, TValue value) { //note: this method does not need to be async, but subtract is, so it's better if both methods have the same shape. if (trans == null) { throw new ArgumentNullException(nameof(trans)); } trans.AtomicIncrement64(this.Subspace.Keys[key, value]); return(Task.CompletedTask); }
public async Task InsertAsync(IFdbTransaction trans, Slice key) { if (trans == null) { throw new ArgumentNullException(nameof(trans)); } if (await ContainsAsync(trans, key).ConfigureAwait(false)) { return; } int keyHash = key.GetHashCode(); //TODO: proper hash function? //Console.WriteLine("Inserting " + key + " with hash " + keyHash.ToString("x")); for (int level = 0; level < MAX_LEVELS; level++) { var prevKey = await GetPreviousNodeAsync(trans, level, key); if ((keyHash & ((1 << (level * LEVEL_FAN_POW)) - 1)) != 0) { //Console.WriteLine("> [" + level + "] Incrementing previous key: " + FdbKey.Dump(prevKey)); trans.AtomicIncrement64(this.Subspace.Encode(level, prevKey)); } else { //Console.WriteLine("> [" + level + "] inserting and updating previous key: " + FdbKey.Dump(prevKey)); // Insert into this level by looking at the count of the previous // key in the level and recounting the next lower level to correct // the counts var prevCount = DecodeCount(await trans.GetAsync(this.Subspace.Encode(level, prevKey)).ConfigureAwait(false)); var newPrevCount = await SlowCountAsync(trans, level - 1, prevKey, key); var count = checked ((prevCount - newPrevCount) + 1); // print "insert", key, "level", level, "count", count, // "splits", prevKey, "oldC", prevCount, "newC", newPrevCount trans.Set(this.Subspace.Encode(level, prevKey), EncodeCount(newPrevCount)); trans.Set(this.Subspace.Encode(level, key), EncodeCount(count)); } } }