private async Task <bool> TryRemoteSplitPointAsync([NotNull] IFdbTransaction trans, long offset)
        {
            Contract.Requires(trans != null && offset >= 0);

            var b = await GetChunkAtAsync(trans, offset).ConfigureAwait(false);

            if (b.Offset == 0 || b.Key == Slice.Nil)
            {
                return(false);                                                 // in sparse region, or at beginning
            }
            var a = await GetChunkAtAsync(trans, b.Offset - 1).ConfigureAwait(false);

            if (a.Key == Slice.Nil)
            {
                return(false);                                // no previous chunk
            }
            if (a.Offset + a.Data.Count != b.Offset)
            {
                return(false);                                                 // chunks can't be joined
            }
            if (a.Data.Count + b.Data.Count > CHUNK_SMALL)
            {
                return(false);                                                        // chunks shouldn't be joined
            }
            // yay--merge chunks
            trans.Clear(b.Key);
            trans.Set(a.Key, a.Data + b.Data);
            return(true);
        }
Example #2
0
        /// <summary>Decrements the count of an (index, value) pair in the multimap, and optionally removes it if the count reaches zero.</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 decrement</param>
        /// <remarks>If the updated count reaches zero or less, and AllowNegativeValues is not set, the key will be cleared from the map.</remarks>
        public async Task SubtractAsync([NotNull] IFdbTransaction trans, TKey key, TValue value)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }

            Slice k = this.Location.Keys.Encode(key, value);

            if (this.AllowNegativeValues)
            {
                trans.AtomicAdd(k, MinusOne);
                // note: it's faster, but we will end up with counts less than or equal to 0
                // If 'k' does not already exist, its count will be set to -1
            }
            else
            {
                Slice v = await trans.GetAsync(k).ConfigureAwait(false);

                if (this.AllowNegativeValues || v.ToInt64() > 1)                 //note: Slice.Nil.ToInt64() will return 0
                {
                    trans.AtomicAdd(k, MinusOne);
                    //note: since we already read 'k', the AtomicAdd will be optimized into the equivalent of Set(k, v - 1) by the client, unless RYW has been disabled on the transaction
                    //TODO: if AtomicMax ever gets implemented, we could use it to truncate the values to 0
                }
                else
                {
                    trans.Clear(k);
                }
            }
        }
Example #3
0
        /// <summary>Swap the items at positions i1 and i2.</summary>
        public async Task SwapAsync([NotNull] IFdbTransaction tr, long index1, long index2)
        {
            if (tr == null)
            {
                throw new ArgumentNullException("tr");
            }

            if (index1 < 0 || index2 < 0)
            {
                throw new IndexOutOfRangeException(String.Format("Indices ({0}, {1}) must be positive", index1, index2));
            }

            var k1 = GetKeyAt(index1);
            var k2 = GetKeyAt(index2);

            long currentSize = await ComputeSizeAsync(tr).ConfigureAwait(false);

            if (index1 >= currentSize || index2 >= currentSize)
            {
                throw new IndexOutOfRangeException(String.Format("Indices ({0}, {1}) are out of range", index1, index2));
            }

            var vs = await tr.GetValuesAsync(new[] { k1, k2 }).ConfigureAwait(false);

            var v1 = vs[0];
            var v2 = vs[1];

            if (!v2.IsNullOrEmpty)
            {
                tr.Set(k1, v2);
            }
            else if (v1.IsPresent && index1 < currentSize - 1)
            {
                tr.Clear(k1);
            }

            if (!v1.IsNullOrEmpty)
            {
                tr.Set(k2, v1);
            }
            else if (v2.IsPresent && index2 < currentSize - 1)
            {
                tr.Clear(k2);
            }
        }
Example #4
0
        /// <summary>Remove a value for a specific key</summary>
        /// <param name="trans"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public void Remove([NotNull] IFdbTransaction trans, TKey key, TValue value)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }

            trans.Clear(this.Location.Keys.Encode(key, value));
        }
            /// <summary>Remove a value for a specific key</summary>
            /// <param name="trans"></param>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public void Remove(IFdbTransaction trans, TKey key, TValue value)
            {
                if (trans == null)
                {
                    throw new ArgumentNullException(nameof(trans));
                }

                trans.Clear(this.Subspace[key, value]);
            }
        /// <summary>Remove an entity from the index</summary>
        /// <param name="trans">Transaction to use</param>
        /// <param name="id">Id of the entity that has been deleted</param>
        /// <param name="value">Previous value of the entity in the index</param>
        public void Remove([NotNull] IFdbTransaction trans, TId id, TValue value)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }

            trans.Clear(this.Subspace.Keys[value, id]);
        }
        /// <summary>Remove a single entry from the map</summary>
        /// <param name="trans">Transaction used for the operation</param>
        /// <param name="id">Key of the entry to remove</param>
        /// <remarks>If the entry did not exist, the operation will not do anything.</remarks>
        public void Remove([NotNull] IFdbTransaction trans, TKey id)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            trans.Clear(this.Subspace.Keys[id]);
        }
        /// <summary>Remove a single entry from the map</summary>
        /// <param name="trans">Transaction used for the operation</param>
        /// <param name="id">Key of the entry to remove</param>
        /// <remarks>If the entry did not exist, the operation will not do anything.</remarks>
        public void Remove([NotNull] IFdbTransaction trans, TKey id)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }

            trans.Clear(this.Location.Keys.Encode(id));
        }
Example #9
0
        /// <summary>
        /// Drop a student from a class
        /// </summary>
        public async Task Drop(IFdbTransaction tr, string s, string c)
        {
            var rec = AttendsKey(s, c);

            if ((await tr.GetAsync(rec)).IsNullOrEmpty)
            {             // not taking this class
                return;
            }

            var students = Int32.Parse((await tr.GetAsync(ClassKey(c))).ToStringAscii());

            tr.Set(ClassKey(c), Slice.FromStringAscii((students + 1).ToString()));
            tr.Clear(rec);
        }
        private async Task <Optional <T> > PopSimpleAsync([NotNull] IFdbTransaction tr)
        {
#if DEBUG
            tr.Annotate("PopSimple()");
#endif

            var firstItem = await GetFirstItemAsync(tr).ConfigureAwait(false);

            if (firstItem.Key.IsNull)
            {
                return(default(Optional <T>));
            }

            tr.Clear(firstItem.Key);
            return(this.Encoder.DecodeValue(firstItem.Value));
        }
Example #11
0
        /// <summary>Remove a field of an hashset</summary>
        /// <param name="trans"></param>
        /// <param name="id"></param>
        /// <param name="field"></param>
        public void DeleteValue(IFdbTransaction trans, IVarTuple id, string field)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }
            if (string.IsNullOrEmpty(field))
            {
                throw new ArgumentNullException(nameof(field));
            }

            trans.Clear(GetFieldKey(id, field));
        }
        /// <summary>Update the indexed values of an entity</summary>
        /// <param name="trans">Transaction to use</param>
        /// <param name="id">Id of the entity that has changed</param>
        /// <param name="newValue">Previous value of this entity in the index</param>
        /// <param name="previousValue">New value of this entity in the index</param>
        /// <returns>True if a change was performed in the index; otherwise false (if <paramref name="previousValue"/> and <paramref name="newValue"/>)</returns>
        /// <remarks>If <paramref name="newValue"/> and <paramref name="previousValue"/> are identical, then nothing will be done. Otherwise, the old index value will be deleted and the new value will be added</remarks>
        public bool Update([NotNull] IFdbTransaction trans, TId id, TValue newValue, TValue previousValue)
        {
            if (!this.ValueComparer.Equals(newValue, previousValue))
            {
                // remove previous value
                if (this.IndexNullValues || previousValue != null)
                {
                    trans.Clear(this.Subspace.Keys[previousValue, id]);
                }

                // add new value
                if (this.IndexNullValues || newValue != null)
                {
                    trans.Set(this.Subspace.Keys[newValue, id], Slice.Empty);
                }

                // cannot be both null, so we did at least something)
                return(true);
            }
            return(false);
        }
            public async Task EraseAsync(IFdbTransaction trans, Slice key)
            {
                if (trans == null)
                {
                    throw new ArgumentNullException(nameof(trans));
                }

                if (!(await ContainsAsync(trans, key).ConfigureAwait(false)))
                {
                    return;
                }

                for (int level = 0; level < MAX_LEVELS; level++)
                {
                    // This could be optimized with hash
                    var k = this.Subspace.Encode(level, key);
                    var c = await trans.GetAsync(k).ConfigureAwait(false);

                    if (c.HasValue)
                    {
                        trans.Clear(k);
                    }
                    if (level == 0)
                    {
                        continue;
                    }

                    var prevKey = await GetPreviousNodeAsync(trans, level, key);

                    Contract.Assert(prevKey != key);
                    long countChange = -1;
                    if (c.HasValue)
                    {
                        countChange += DecodeCount(c);
                    }

                    trans.AtomicAdd64(this.Subspace.Encode(level, prevKey), countChange);
                }
            }
Example #14
0
        /// <summary>Get and pops the last item off the Vector.</summary>
        public async Task <Optional <T> > PopAsync([NotNull] IFdbTransaction tr)
        {
            if (tr == null)
            {
                throw new ArgumentNullException("tr");
            }

            var keyRange = this.Subspace.Keys.ToRange();

            // Read the last two entries so we can check if the second to last item
            // is being represented sparsely. If so, we will be required to set it
            // to the default value
            var lastTwo = await tr
                          .GetRange(keyRange, new FdbRangeOptions { Reverse = true, Limit = 2 })
                          .ToListAsync()
                          .ConfigureAwait(false);

            // Vector was empty
            if (lastTwo.Count == 0)
            {
                return(default(Optional <T>));
            }

            //note: keys are reversed so indices[0] = last, indices[1] = second to last
            var indices = lastTwo.Select(kvp => this.Subspace.Keys.DecodeFirst <long>(kvp.Key)).ToList();

            if (indices[0] == 0)
            {             // Vector has size one
                //pass
            }
            else if (lastTwo.Count == 1 || indices[0] > indices[1] + 1)
            {             // Second to last item is being represented sparsely
                tr.Set(GetKeyAt(indices[0] - 1), this.Encoder.EncodeValue(this.DefaultValue));
            }

            tr.Clear(lastTwo[0].Key);

            return(this.Encoder.DecodeValue(lastTwo[0].Value));
        }
Example #15
0
        /// <summary>Remove one or more fields of an hashset</summary>
        /// <param name="trans"></param>
        /// <param name="id"></param>
        /// <param name="fields"></param>
        public void Delete(IFdbTransaction trans, IVarTuple id, params string[] fields)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }
            if (fields == null)
            {
                throw new ArgumentNullException(nameof(fields));
            }

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field))
                {
                    throw new ArgumentException("Field cannot have an empty name", nameof(fields));
                }
                trans.Clear(GetFieldKey(id, field));
            }
        }
		/// <summary>Remove an existing node from its parents</summary>
		/// <returns>True if the parent node was found, otherwise false</returns>
		private async Task<bool> RemoveFromParent(IFdbTransaction tr, IFdbTuple path)
		{
			Contract.Requires(tr != null && path != null);

			var parent = await FindAsync(tr, path.Substring(0, path.Count - 1)).ConfigureAwait(false);
			if (parent.Exists)
			{
				if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing path {0} from its parent folder at {1}", path, parent.Subspace.Key);
				tr.Clear(GetSubDirKey(parent.Subspace, path.Get<string>(-1)));
				return true;
			}
			return false;
		}
		/// <summary>Remove an existing node from its parents</summary>
		/// <returns>True if the parent node was found, otherwise false</returns>
		private async Task<bool> RemoveFromParent(IFdbTransaction tr, IFdbTuple path)
		{
			Contract.Requires(tr != null && path != null);

			var parent = await FindAsync(tr, path.Substring(0, path.Count - 1)).ConfigureAwait(false);
			if (parent.Exists)
			{
				tr.Clear(GetSubDirKey(parent.Subspace, path.Get<string>(-1)));
				return true;
			}
			return false;
		}
		// Compare the behavior of the MemoryDB against a FoundationDB database

		private async Task Scenario1(IFdbTransaction tr)
		{
			tr.Set(Slice.FromAscii("hello"), Slice.FromAscii("world!"));
			tr.Clear(Slice.FromAscii("removed"));
			var result = await tr.GetAsync(Slice.FromAscii("narf"));
		}
		/// <summary>
		/// Drop a student from a class
		/// </summary>
		public async Task Drop(IFdbTransaction tr, string s, string c)
		{
			var rec = AttendsKey(s, c);
			if ((await tr.GetAsync(rec)).IsNullOrEmpty)
			{ // not taking this class
				return;
			}

			var students = Int32.Parse((await tr.GetAsync(ClassKey(c))).ToAscii());
			tr.Set(ClassKey(c), Slice.FromAscii((students + 1).ToString()));
			tr.Clear(rec);
		}
 public virtual void Clear(Slice key)
 {
     ThrowIfDisposed();
     m_transaction.Clear(key);
 }
 public void Clear([NotNull] IFdbTransaction trans, T key)
 {
     trans.Clear(EncodeKey(key));
 }
        // Compare the behavior of the MemoryDB against a FoundationDB database

        private async Task Scenario1(IFdbTransaction tr)
        {
            tr.Set(Slice.FromAscii("hello"), Slice.FromAscii("world!"));
            tr.Clear(Slice.FromAscii("removed"));
            var result = await tr.GetAsync(Slice.FromAscii("narf"));
        }
		private async Task<bool> TryRemoteSplitPointAsync(IFdbTransaction trans, long offset)
		{
			Contract.Requires(trans != null && offset >= 0);

			var b = await GetChunkAtAsync(trans, offset).ConfigureAwait(false);
			if (b.Offset == 0 || b.Key == Slice.Nil) return false; // in sparse region, or at beginning

			var a = await GetChunkAtAsync(trans, b.Offset - 1).ConfigureAwait(false);
			if (a.Key == Slice.Nil) return false; // no previous chunk

			if (a.Offset + a.Data.Count != b.Offset) return false; // chunks can't be joined
			if (a.Data.Count + b.Data.Count > CHUNK_SMALL) return false;  // chunks shouldn't be joined
			// yay--merge chunks
			trans.Clear(b.Key);
			trans.Set(a.Key, a.Data + b.Data);
			return true;
		}
 public void Clear([NotNull] IFdbTransaction trans, FdbTuple <T1, T2> key)
 {
     trans.Clear(EncodeKey(key));
 }
 public void Clear([NotNull] IFdbTransaction trans, T1 key1, T2 key2)
 {
     trans.Clear(EncodeKey(key1, key2));
 }
Example #26
0
 /// <inheritdoc />
 public virtual void Clear(ReadOnlySpan <byte> key)
 {
     ThrowIfDisposed();
     m_transaction.Clear(key);
 }
		/// <summary>Remove a field of an hashset</summary>
		/// <param name="trans"></param>
		/// <param name="id"></param>
		/// <param name="field"></param>
		public void DeleteValue(IFdbTransaction trans, IFdbTuple id, string field)
		{
			if (trans == null) throw new ArgumentNullException("trans");
			if (id == null) throw new ArgumentNullException("id");
			if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field");

			trans.Clear(GetFieldKey(id, field));
		}
		/// <summary>Remove one or more fields of an hashset</summary>
		/// <param name="trans"></param>
		/// <param name="id"></param>
		/// <param name="fields"></param>
		public void Delete(IFdbTransaction trans, IFdbTuple id, params string[] fields)
		{
			if (trans == null) throw new ArgumentNullException("trans");
			if (id == null) throw new ArgumentNullException("id");
			if (fields == null) throw new ArgumentNullException("fields");

			foreach (var field in fields)
			{
				if (string.IsNullOrEmpty(field)) throw new ArgumentException("Field cannot have an empty name", "fields");
				trans.Clear(GetFieldKey(id, field));
			}
		}
Example #29
0
 /// <summary>Remove an entity from the index</summary>
 public void Remove(IFdbTransaction trans, TId id, TValue value)
 {
     trans.Clear(this.Subspace[value, id]);
 }