/// <summary>Returns a 64-bit integer that
		/// 1) has never and will never be returned by another call to this
		///    method on the same subspace
		/// 2) is nearly as short as possible given the above
		/// </summary>
		public async Task<long> AllocateAsync(IFdbTransaction trans)
		{
			// find the current window size, by reading the last entry in the 'counters' subspace
			long start = 0, count = 0;
			var kv = await trans
				.Snapshot
				.GetRange(this.Counters.ToRange())
				.LastOrDefaultAsync();

			if (kv.Key.IsPresent)
			{
				start = this.Counters.UnpackSingle<long>(kv.Key);
				count = kv.Value.ToInt64();
			}

			// check if the window is full
			int window = GetWindowSize(start);
			if ((count + 1) * 2 >= window)
			{ // advance the window
				trans.ClearRange(this.Counters.Key, this.Counters.Pack(start) + FdbKey.MinValue);
				start += window;
				trans.ClearRange(this.Recent.Key, this.Recent.Pack(start));
			}

			// Increment the allocation count for the current window
			trans.AtomicAdd(this.Counters.Pack(start), Slice.FromFixed64(1));

			// As of the snapshot being read from, the window is less than half
            // full, so this should be expected to take 2 tries.  Under high
            // contention (and when the window advances), there is an additional
            // subsequent risk of conflict for this transaction.
			while (true)
			{
				// Find a random free slot in the current window...
				long candidate;
				lock (m_rnd)
				{
					candidate = start + m_rnd.Next(window);
				}

				// test if the key is used
				var key = this.Recent.Pack(candidate);
				var value = await trans.GetAsync(key).ConfigureAwait(false);

				if (value.IsNull)
				{ // free slot

					// mark as used
					trans.Set(key, Slice.Empty);
					return candidate;
				}

				// no luck this time, try again...
			}
		}
		private Task Scenario3(IFdbTransaction tr)
		{
			var location = FdbSubspace.Create(Slice.FromAscii("TEST"));

			tr.Set(location.Key + (byte)'a', Slice.FromAscii("A"));
			tr.AtomicAdd(location.Key + (byte)'k', Slice.FromFixed32(1));
			tr.Set(location.Key + (byte)'z', Slice.FromAscii("C"));
			tr.ClearRange(location.Key + (byte)'a', location.Key + (byte)'k');
			tr.ClearRange(location.Key + (byte)'k', location.Key + (byte)'z');
			return Task.FromResult<object>(null);
		}
예제 #3
0
        /// <summary>
        /// Delete all key-value pairs associated with the blob.
        /// </summary>
        public void Delete([NotNull] IFdbTransaction trans)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }

            trans.ClearRange(this.Subspace);
        }
        /// <summary>Remove all the values for a specific key</summary>
        /// <param name="trans"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public void Remove([NotNull] IFdbTransaction trans, TKey key)
        {
            if (trans == null)
            {
                throw new ArgumentNullException("trans");
            }

            trans.ClearRange(KeyRange.StartsWith(this.Location.Partial.Keys.Encode(key)));
        }
예제 #5
0
        /// <summary>Insert a new document in the collection</summary>
        public async Task InsertAsync(IFdbTransaction trans, TDocument document)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            var id = this.IdSelector(document);

            if (id == null)
            {
                throw new InvalidOperationException("Cannot insert a document with a null identifier");
            }

            // encode the document
            var packed = this.ValueEncoder.EncodeValue(document);

            var subspace = await this.Location.Resolve(trans);

            if (subspace == null)
            {
                throw new InvalidOperationException($"Location '{this.Location}' referenced by Document Collection Layer was not found.");
            }

            // Key Prefix = ...(id,)
            var key = subspace.EncodePartial(id);

            // clear previous value
            trans.ClearRange(KeyRange.StartsWith(key));

            int remaining = packed.Count;

            if (remaining <= this.ChunkSize)
            {             // stored as a single element
                // Key = ...(id,)
                trans.Set(key, packed);
            }
            else
            {             // splits in as many chunks as necessary
                // Key = ...(id, N) where N is the chunk index (0-based)
                int p     = 0;
                int index = 0;
                while (remaining > 0)
                {
                    int sz = Math.Max(remaining, this.ChunkSize);
                    trans.Set(subspace[id, index], packed.Substring(p, sz));
                    ++index;
                    p         += sz;
                    remaining -= sz;
                }
            }
        }
		private Task Scenario2(IFdbTransaction tr)
		{
			var location = FdbSubspace.Create(Slice.FromAscii("TEST"));
			tr.ClearRange(FdbKeyRange.StartsWith(location.Key));
			for (int i = 0; i < 10; i++)
			{
				tr.Set(location.Pack(i), Slice.FromString("value of " + i));
			}
			return Task.FromResult<object>(null);
		}
        private Task Scenario2(IFdbTransaction tr)
        {
            var location = FdbSubspace.Create(Slice.FromAscii("TEST"));

            tr.ClearRange(FdbKeyRange.StartsWith(location.Key));
            for (int i = 0; i < 10; i++)
            {
                tr.Set(location.Pack(i), Slice.FromString("value of " + i));
            }
            return(Task.FromResult <object>(null));
        }
		/// <summary>Delete a document from the collection</summary>
		/// <param name="trans"></param>
		/// <param name="ids"></param>
		public void DeleteMultiple(IFdbTransaction trans, IEnumerable<TId> ids)
		{
			if (trans == null) throw new ArgumentNullException(nameof(trans));
			if (ids == null) throw new ArgumentNullException(nameof(ids));

			foreach (var id in ids)
			{
				var key = this.Subspace.Keys.EncodePartial(id);
				trans.ClearRange(KeyRange.StartsWith(key));
			}
		}
예제 #9
0
        /// <summary>Remove all fields of an hashset</summary>
        /// <param name="id"></param>
        public void Delete(IFdbTransaction trans, IVarTuple id)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            // remove all fields of the hash
            trans.ClearRange(KeyRange.StartsWith(GetKey(id)));
        }
        /// <summary>Insert a new document in the collection</summary>
        public void Insert(IFdbTransaction trans, TDocument document)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            var id = this.IdSelector(document);

            if (id == null)
            {
                throw new InvalidOperationException("Cannot insert a document with a null identifier");
            }

            // encode the document
            var packed = this.ValueEncoder.EncodeValue(document);

            // Key Prefix = ...(id,)
            var key = this.Location.Partial.Keys.Encode(id);

            // clear previous value
            trans.ClearRange(KeyRange.StartsWith(key));

            int remaining = packed.Count;

            if (remaining <= this.ChunkSize)
            {             // stored as a single element
                // Key = ...(id,)
                trans.Set(key, packed);
            }
            else
            {             // splits in as many chunks as necessary
                // Key = ...(id, N) where N is the chunk index (0-based)
                int p     = 0;
                int index = 0;
                while (remaining > 0)
                {
                    int sz = Math.Max(remaining, this.ChunkSize);
                    trans.Set(this.Location.Keys.Encode(id, index), packed.Substring(p, sz));
                    ++index;
                    p         += sz;
                    remaining -= sz;
                }
            }
        }
        /// <summary>Delete a document from the collection</summary>
        /// <param name="trans"></param>
        /// <param name="id"></param>
        public void Delete(IFdbTransaction trans, TId id)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            var key = this.Location.Partial.Keys.Encode(id);

            trans.ClearRange(KeyRange.StartsWith(key));
        }
        /// <summary>Delete a document from the collection</summary>
        /// <param name="trans"></param>
        /// <param name="ids"></param>
        public void DeleteMultiple(IFdbTransaction trans, IEnumerable <TId> ids)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (ids == null)
            {
                throw new ArgumentNullException(nameof(ids));
            }

            foreach (var key in this.Location.Partial.Keys.Encode(ids))
            {
                trans.ClearRange(KeyRange.StartsWith(key));
            }
        }
예제 #13
0
        /// <summary>Delete a document from the collection</summary>
        /// <param name="trans"></param>
        /// <param name="id"></param>
        public async Task DeleteAsync(IFdbTransaction trans, TId id)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            var subspace = await this.Location.Resolve(trans);

            if (subspace == null)
            {
                throw new InvalidOperationException($"Location '{this.Location}' referenced by Document Collection Layer was not found.");
            }

            var key = subspace.EncodePartial(id);

            trans.ClearRange(KeyRange.StartsWith(key));
        }
예제 #14
0
        /// <summary>Grow or shrink the size of the Vector.</summary>
        public async Task ResizeAsync([NotNull] IFdbTransaction tr, long length)
        {
            if (tr == null)
            {
                throw new ArgumentNullException("tr");
            }

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

            if (length < currentSize)
            {
                tr.ClearRange(GetKeyAt(length), this.Subspace.Keys.ToRange().End);

                // Check if the new end of the vector was being sparsely represented
                if (await ComputeSizeAsync(tr).ConfigureAwait(false) < length)
                {
                    tr.Set(GetKeyAt(length - 1), this.Encoder.EncodeValue(this.DefaultValue));
                }
            }
            else if (length > currentSize)
            {
                tr.Set(GetKeyAt(length - 1), this.Encoder.EncodeValue(this.DefaultValue));
            }
        }
		private void ClearTask(IFdbTransaction tr, Slice taskId)
		{
			tr.Annotate("Deleting task {0}", taskId.ToAsciiOrHexaString());

			// clear all metadata about the task
			tr.ClearRange(FdbKeyRange.StartsWith(this.TaskStore.Pack(taskId)));
			// decrement pending number of tasks
			this.Counters.Decrement(tr, COUNTER_PENDING_TASKS);
		}
        /// <summary>Clear the entire content of a subspace</summary>
        public static void ClearRange(this IFdbTransaction trans, [NotNull] FdbSubspace subspace)
        {
            Contract.Requires(trans != null && subspace != null);

            trans.ClearRange(FdbKeyRange.StartsWith(subspace.Key));
        }
예제 #17
0
 /// <inheritdoc />
 public virtual void ClearRange(ReadOnlySpan <byte> beginKeyInclusive, ReadOnlySpan <byte> endKeyExclusive)
 {
     ThrowIfDisposed();
     m_transaction.ClearRange(beginKeyInclusive, endKeyExclusive);
 }
        /// <summary>Returns a 64-bit integer that
        /// 1) has never and will never be returned by another call to this
        ///    method on the same subspace
        /// 2) is nearly as short as possible given the above
        /// </summary>
        public async Task <long> AllocateAsync([NotNull] IFdbTransaction trans)
        {
            if (trans == null)
            {
                throw new ArgumentNullException(nameof(trans));
            }

            // find the current window size, by reading the last entry in the 'counters' subspace
            long start = 0, count = 0;
            var  kv = await trans
                      .Snapshot
                      .GetRange(this.Counters.Keys.ToRange())
                      .LastOrDefaultAsync();

            if (kv.Key.IsPresent)
            {
                start = this.Counters.Keys.Decode <long>(kv.Key);
                count = kv.Value.ToInt64();
            }

            // check if the window is full
            int window = GetWindowSize(start);

            if ((count + 1) * 2 >= window)
            {             // advance the window
                if (FdbDirectoryLayer.AnnotateTransactions)
                {
                    trans.Annotate("Advance allocator window size to {0} starting at {1}", window, start + window);
                }
                trans.ClearRange(this.Counters.GetPrefix(), this.Counters.Keys.Encode(start) + FdbKey.MinValue);
                start += window;
                count  = 0;
                trans.ClearRange(this.Recent.GetPrefix(), this.Recent.Keys.Encode(start));
            }

            // Increment the allocation count for the current window
            trans.AtomicAdd64(this.Counters.Keys.Encode(start), 1);

            // As of the snapshot being read from, the window is less than half
            // full, so this should be expected to take 2 tries.  Under high
            // contention (and when the window advances), there is an additional
            // subsequent risk of conflict for this transaction.
            while (true)
            {
                // Find a random free slot in the current window...
                long candidate;
                lock (m_rnd)
                {
                    candidate = start + m_rnd.Next(window);
                }

                // test if the key is used
                var key   = this.Recent.Keys.Encode(candidate);
                var value = await trans.GetAsync(key).ConfigureAwait(false);

                if (value.IsNull)
                {                 // free slot
                    // mark as used
                    trans.Set(key, Slice.Empty);
                    if (FdbDirectoryLayer.AnnotateTransactions)
                    {
                        trans.Annotate("Allocated prefix {0} from window [{1}..{2}] ({3} used)", candidate, start, start + window - 1, count + 1);
                    }
                    return(candidate);
                }

                // no luck this time, try again...
            }
        }
 public virtual void ClearRange(Slice beginKeyInclusive, Slice endKeyExclusive)
 {
     ThrowIfDisposed();
     m_transaction.ClearRange(beginKeyInclusive, endKeyExclusive);
 }
		/// <summary>
		/// Delete all key-value pairs associated with the blob.
		/// </summary>
		public void Delete(IFdbTransaction trans)
		{
			if (trans == null) throw new ArgumentNullException("trans");

			trans.ClearRange(this.Subspace);
		}
        public static async Task <long> AllocateAsync(IFdbTransaction trans, ITypedKeySubspace <int, long> subspace, Random rng)
        {
            Contract.NotNull(trans);

            // find the current window size, by reading the last entry in the 'counters' subspace
            long start = 0, count = 0;
            var  kv = await trans
                      .Snapshot
                      .GetRange(subspace.EncodePartialRange(COUNTERS))
                      .LastOrDefaultAsync();

            if (kv.Key.Count != 0)
            {
                start = subspace.DecodeLast(kv.Key);
                count = kv.Value.ToInt64();
            }

            // check if the window is full
            int window = GetWindowSize(start);

            if ((count + 1) * 2 >= window)
            {             // advance the window
                if (FdbDirectoryLayer.AnnotateTransactions)
                {
                    trans.Annotate("Advance allocator window size to {0} starting at {1}", window, start + window);
                }
                trans.ClearRange(subspace[COUNTERS, 0], subspace[COUNTERS, start + 1]);
                start += window;
                count  = 0;
                trans.ClearRange(subspace[RECENT, 0], subspace[RECENT, start]);
            }

            // Increment the allocation count for the current window
            trans.AtomicAdd64(subspace[COUNTERS, start], 1);

            // As of the snapshot being read from, the window is less than half
            // full, so this should be expected to take 2 tries.  Under high
            // contention (and when the window advances), there is an additional
            // subsequent risk of conflict for this transaction.
            while (true)
            {
                // Find a random free slot in the current window...
                long candidate;
                lock (rng)
                {
                    candidate = start + rng.Next(window);
                }

                // test if the key is used
                var key   = subspace[RECENT, candidate];
                var value = await trans.GetAsync(key).ConfigureAwait(false);

                if (value.IsNull)
                {                 // free slot
                    // mark as used
                    trans.Set(key, Slice.Empty);
                    if (FdbDirectoryLayer.AnnotateTransactions)
                    {
                        trans.Annotate("Allocated prefix {0} from window [{1}..{2}] ({3} used)", candidate, start, start + window - 1, count + 1);
                    }
                    return(candidate);
                }

                // no luck this time, try again...
            }
        }
		/// <summary>Resursively remove a node (including the content), all its children</summary>
		private async Task RemoveRecursive(IFdbTransaction tr, FdbSubspace node)
		{
			Contract.Requires(tr != null && node != null);

			//note: we could use Task.WhenAll to remove the children, but there is a risk of task explosion if the subtree is very large...
			await SubdirNamesAndNodes(tr, node).ForEachAsync((kvp) => RemoveRecursive(tr, kvp.Value)).ConfigureAwait(false);

			// remove ALL the contents
			if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing all content located under {0}", node.Key);
			tr.ClearRange(FdbKeyRange.StartsWith(ContentsOfNode(node, FdbTuple.Empty, Slice.Empty).Key));
			// and all the metadata for this folder
			if (FdbDirectoryLayer.AnnotateTransactions) tr.Annotate("Removing all metadata for folder under {0}", node.Key);
			tr.ClearRange(node.ToRange());
		}
예제 #23
0
		/// <summary>Remove all the values for a specific key</summary>
		/// <param name="trans"></param>
		/// <param name="key"></param>
		/// <returns></returns>
		public void Remove([NotNull] IFdbTransaction trans, TKey key)
		{
			if (trans == null) throw new ArgumentNullException(nameof(trans));

			trans.ClearRange(KeyRange.StartsWith(this.Subspace.Keys.EncodePartial(key)));
		}
 /// <summary>Remove all items from the queue.</summary>
 public void Clear(IFdbTransaction tr)
 {
     Contract.NotNull(tr, nameof(tr));
     tr.ClearRange(this.Subspace.ToRange());
 }
            //TODO: get_range

            /// <summary>Clears the entire set.</summary>
            public Task ClearAllAsync(IFdbTransaction trans)
            {
                trans.ClearRange(this.Subspace.ToRange());
                return(SetupLevelsAsync(trans));
            }
		/// <summary>Resursively remove a node (including the content), all its children</summary>
		private async Task RemoveRecursive(IFdbTransaction tr, FdbSubspace node)
		{
			Contract.Requires(tr != null && node != null);

			//note: we could use Task.WhenAll to remove the children, but there is a risk of task explosion if the subtree is very large...
			await SubdirNamesAndNodes(tr, node).ForEachAsync((kvp) => RemoveRecursive(tr, kvp.Value)).ConfigureAwait(false);

			tr.ClearRange(FdbKeyRange.StartsWith(ContentsOfNode(node, FdbTuple.Empty, Slice.Empty).Key));
			tr.ClearRange(node.ToRange());
		}
		/// <summary>Remove all fields of an hashset</summary>
		/// <param name="id"></param>
		public void Delete(IFdbTransaction trans, IFdbTuple id)
		{
			if (trans == null) throw new ArgumentNullException("trans");
			if (id == null) throw new ArgumentNullException("id");

			// remove all fields of the hash
			trans.ClearRange(FdbKeyRange.StartsWith(GetKey(id)));
		}
		private async Task MakeSparseAsync(IFdbTransaction trans, long start, long end)
		{
			await MakeSplitPointAsync(trans, start).ConfigureAwait(false);
			await MakeSplitPointAsync(trans, end).ConfigureAwait(false);
			trans.ClearRange(DataKey(start), DataKey(end));
		}