Exemplo n.º 1
0
        /// <summary>Change the layer id of this directory</summary>
        public static Task <FdbDirectorySubspace> ChangeLayerAsync([NotNull] this FdbDirectorySubspace subspace, [NotNull] IFdbRetryable db, Slice newLayer, CancellationToken ct)
        {
            Contract.NotNull(subspace, nameof(subspace));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => subspace.ChangeLayerAsync(tr, newLayer), ct));
        }
Exemplo n.º 2
0
        /// <summary>Creates a directory with the given <paramref name="path"/> (creating parent directories if necessary).
        /// An error is raised if the given directory already exists.
        /// </summary>
        public static Task <FdbDirectorySubspace> CreateAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, FdbDirectoryPath path, CancellationToken ct)
        {
            Contract.NotNull(directory, nameof(directory));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => directory.CreateAsync(tr, path, Slice.Nil), ct));
        }
Exemplo n.º 3
0
        /// <summary>Change the layer id of the <paramref name="directory"/> at <paramref name="path"/></summary>
        public static Task <FdbDirectorySubspace> ChangeLayerAsync([NotNull] this FdbDirectoryLayer directory, [NotNull] IFdbRetryable db, FdbDirectoryPath path, Slice newLayer, CancellationToken ct)
        {
            Contract.NotNull(directory, nameof(directory));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => directory.ChangeLayerAsync(tr, path, newLayer), ct));
        }
Exemplo n.º 4
0
        /// <summary>Removes the directory, its contents, and all subdirectories.
        /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
        /// </summary>
        public static Task <bool> TryRemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, FdbDirectoryPath path, CancellationToken ct)
        {
            Contract.NotNull(directory, nameof(directory));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => directory.TryRemoveAsync(tr, path), ct));
        }
Exemplo n.º 5
0
        /// <summary>Attempts to move the current directory to <paramref name="newPath"/>.
        /// There is no effect on the physical prefix of the given directory, or on clients that already have the directory open.
        /// </summary>
        public static Task <FdbDirectorySubspace> TryMoveToAsync([NotNull] this FdbDirectorySubspace subspace, [NotNull] IFdbRetryable db, FdbDirectoryPath newPath, CancellationToken ct)
        {
            Contract.NotNull(subspace, nameof(subspace));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => subspace.TryMoveToAsync(tr, newPath), ct));
        }
Exemplo n.º 6
0
        /// <summary>Attempts to move the directory found at <paramref name="oldPath"/> to <paramref name="newPath"/>.
        /// There is no effect on the physical prefix of the given directory, or on clients that already have the directory open.
        /// </summary>
        public static Task <FdbDirectorySubspace> TryMoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, FdbDirectoryPath oldPath, FdbDirectoryPath newPath, CancellationToken ct)
        {
            Contract.NotNull(directory, nameof(directory));
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync((tr) => directory.TryMoveAsync(tr, oldPath, newPath), ct));
        }
Exemplo n.º 7
0
        /// <summary>Removes the directory, its contents, and all subdirectories.
        /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
        /// </summary>
        public static Task <bool> TryRemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] string name, CancellationToken ct)
        {
            Contract.NotNull(directory, nameof(directory));
            Contract.NotNull(db, nameof(db));
            Contract.NotNull(name, nameof(name));

            return(db.ReadWriteAsync((tr) => directory.TryRemoveAsync(tr, new [] { name }), ct));
        }
        /// <summary>Reads the value associated with <paramref name="key"/>, and returns a Watch that will complete after a subsequent change to key in the database.</summary>
        /// <param name="db">Database instance.</param>
        /// <param name="key">Key to be looked up in the database</param>
        /// <param name="cancellationToken">Token that can be used to cancel the Watch from the outside.</param>
        /// <returns>A new Watch that will track any changes to <paramref name="key"/> in the database, and whose <see cref="FdbWatch.Value">Value</see> property contains the current value of the key.</returns>
        public static Task <FdbWatch> GetAndWatch([NotNull] this IFdbRetryable db, Slice key, CancellationToken cancellationToken)
        {
            Contract.NotNull(db, nameof(db));

            return(db.ReadWriteAsync(async(tr) =>
            {
                var result = await tr.GetAsync(key).ConfigureAwait(false);
                var watch = tr.Watch(key, cancellationToken);
                watch.Value = result.Memoize();
                return watch;
            }, cancellationToken));
        }
        /// <summary>Add and Schedule a new Task in the worker pool</summary>
        /// <param name="db"></param>
        /// <param name="taskId"></param>
        /// <param name="taskBody"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        public async Task ScheduleTaskAsync(IFdbRetryable db, Slice taskId, Slice taskBody, CancellationToken ct = default(CancellationToken))
        {
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            var now = DateTime.UtcNow;

            await db.ReadWriteAsync(async (tr) =>
            {
                Interlocked.Increment(ref m_schedulingAttempts);
#if DEBUG
                if (tr.Context.Retries > 0)
                {
                    Console.WriteLine($"# retry n°{tr.Context.Retries} for task {taskId:P}");
                }
#endif
                tr.Annotate("I want to schedule {0:P}", taskId);

                // find a random worker from the idle ring
                var randomWorkerKey = await FindRandomItem(tr, this.IdleRing).ConfigureAwait(false);

                if (randomWorkerKey.Key != null)
                {
                    Slice workerId = this.IdleRing.Keys.Decode <Slice>(randomWorkerKey.Key);

                    tr.Annotate("Assigning {0:P} to {1:P}", taskId, workerId);

                    // remove worker from the idle ring
                    tr.Clear(this.IdleRing.Keys.Encode(workerId));
                    this.Counters.Decrement(tr, COUNTER_IDLE);

                    // assign task to the worker
                    tr.Set(this.BusyRing.Keys.Encode(workerId), taskId);
                    this.Counters.Increment(tr, COUNTER_BUSY);
                }
                else
                {
                    tr.Annotate("Queueing {0:P}", taskId);

                    await PushQueueAsync(tr, this.UnassignedTaskRing, taskId).ConfigureAwait(false);
                }

                // store the task in the db
                StoreTask(tr, taskId, now, taskBody);
            },
                                    success : (tr) =>
            {
                Interlocked.Increment(ref m_schedulingMessages);
            },
                                    ct : ct).ConfigureAwait(false);
        }
        /// <summary>Removes the directory, its contents, and all subdirectories.
        /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
        /// </summary>
        public static Task <bool> TryRemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, IEnumerable <string> path, CancellationToken ct)
        {
            if (directory == null)
            {
                throw new ArgumentNullException(nameof(directory));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }

            return(db.ReadWriteAsync((tr) => directory.TryRemoveAsync(tr, path), ct));
        }
        /// <summary>Removes the directory, its contents, and all subdirectories.
        /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
        /// </summary>
        public static Task RemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, CancellationToken ct)
        {
            if (directory == null)
            {
                throw new ArgumentNullException(nameof(directory));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }

            return(db.ReadWriteAsync((tr) => directory.RemoveAsync(tr), ct));
        }
        /// <summary>Change the layer id of this directory</summary>
        public static Task <FdbDirectorySubspace> ChangeLayerAsync([NotNull] this FdbDirectorySubspace subspace, [NotNull] IFdbRetryable db, Slice newLayer, CancellationToken ct)
        {
            if (subspace == null)
            {
                throw new ArgumentNullException(nameof(subspace));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }

            return(db.ReadWriteAsync((tr) => subspace.ChangeLayerAsync(tr, newLayer), ct));
        }
        /// <summary>Removes the directory, its contents, and all subdirectories.
        /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
        /// </summary>
        public static Task RemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, IEnumerable <string> path, CancellationToken cancellationToken)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }

            return(db.ReadWriteAsync((tr) => directory.RemoveAsync(tr, path), cancellationToken));
        }
        /// <summary>Reads the value associated with <paramref name="key"/>, and returns a Watch that will complete after a subsequent change to key in the database.</summary>
        /// <param name="db">Database instance.</param>
        /// <param name="key">Key to be looked up in the database</param>
        /// <param name="cancellationToken">Token that can be used to cancel the Watch from the outside.</param>
        /// <returns>A new Watch that will track any changes to <paramref name="key"/> in the database, and whose <see cref="FdbWatch.Value">Value</see> property contains the current value of the key.</returns>
        public static Task <FdbWatch> GetAndWatch(this IFdbRetryable db, Slice key, CancellationToken cancellationToken)
        {
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }

            return(db.ReadWriteAsync(async(tr) =>
            {
                var result = await tr.GetAsync(key).ConfigureAwait(false);
                var watch = tr.Watch(key, cancellationToken);
                watch.Value = result.Memoize();
                return watch;
            }, cancellationToken));
        }
 /// <summary>Removes the directory, its contents, and all subdirectories.
 /// Warning: Clients that have already opened the directory might still insert data into its contents after it is removed.
 /// </summary>
 public static Task RemoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] string name, CancellationToken cancellationToken)
 {
     if (directory == null)
     {
         throw new ArgumentNullException("directory");
     }
     if (db == null)
     {
         throw new ArgumentNullException("db");
     }
     if (name == null)
     {
         throw new ArgumentNullException("name");
     }
     return(db.ReadWriteAsync((tr) => directory.RemoveAsync(tr, new [] { name }), cancellationToken));
 }
 /// <summary>Attempts to create a directory with the given <paramref name="name"/>.
 /// If <paramref name="layer"/> is specified, it is recorded with the directory and will be checked by future calls to open.
 /// </summary>
 public static Task <FdbDirectorySubspace> TryCreateAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] string name, Slice layer, CancellationToken ct)
 {
     if (directory == null)
     {
         throw new ArgumentNullException(nameof(directory));
     }
     if (db == null)
     {
         throw new ArgumentNullException(nameof(db));
     }
     if (name == null)
     {
         throw new ArgumentNullException(nameof(name));
     }
     return(db.ReadWriteAsync((tr) => directory.TryCreateAsync(tr, new[] { name }, layer), ct));
 }
 /// <summary>Change the layer id of the directory at <param name="path"/></summary>
 public static Task <FdbDirectorySubspace> ChangeLayerAsync([NotNull] this FdbDirectoryLayer directory, [NotNull] IFdbRetryable db, IEnumerable <string> path, Slice newLayer, CancellationToken ct)
 {
     if (directory == null)
     {
         throw new ArgumentNullException(nameof(directory));
     }
     if (db == null)
     {
         throw new ArgumentNullException(nameof(db));
     }
     if (path == null)
     {
         throw new ArgumentNullException(nameof(path));                           //REVIEW: or not?
     }
     return(db.ReadWriteAsync((tr) => directory.ChangeLayerAsync(tr, path, newLayer), ct));
 }
        /// <summary>Attempts to move the current directory to <paramref name="newPath"/>.
        /// There is no effect on the physical prefix of the given directory, or on clients that already have the directory open.
        /// </summary>
        public static Task <FdbDirectorySubspace> TryMoveToAsync([NotNull] this FdbDirectorySubspace subspace, [NotNull] IFdbRetryable db, [NotNull] IEnumerable <string> newPath, CancellationToken ct)
        {
            if (subspace == null)
            {
                throw new ArgumentNullException(nameof(subspace));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            if (newPath == null)
            {
                throw new ArgumentNullException(nameof(newPath));
            }

            return(db.ReadWriteAsync((tr) => subspace.TryMoveToAsync(tr, newPath), ct));
        }
        /// <summary>Opens the directory with the given <paramref name="path"/>.
        /// If the directory does not exist, it is created (creating parent directories if necessary).
        /// If layer is specified, it is checked against the layer of an existing directory or set as the layer of a new directory.
        /// </summary>
        public static Task <FdbDirectorySubspace> CreateOrOpenAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] IEnumerable <string> path, Slice layer, CancellationToken ct)
        {
            if (directory == null)
            {
                throw new ArgumentNullException(nameof(directory));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            return(db.ReadWriteAsync((tr) => directory.CreateOrOpenAsync(tr, path, layer), ct));
        }
        // this helper class contain extension methods to help deal with IFdbDatabase vs IFdbTransaction

        #region CreateOrOpen...

        /// <summary>Opens the directory with the given <paramref name="path"/>.
        /// If the directory does not exist, it is created (creating parent directories if necessary).
        /// If layer is specified, it is checked against the layer of an existing directory or set as the layer of a new directory.
        /// </summary>
        public static Task <FdbDirectorySubspace> CreateOrOpenAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] IEnumerable <string> path, CancellationToken cancellationToken)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            return(db.ReadWriteAsync((tr) => directory.CreateOrOpenAsync(tr, path, Slice.Nil), cancellationToken));
        }
        /// <summary>Opens the directory with the given <paramref name="name"/>.
        /// If the directory does not exist, it is created (creating parent directories if necessary).
        /// If layer is specified, it is checked against the layer of an existing directory or set as the layer of a new directory.
        /// </summary>
        public static Task <FdbDirectorySubspace> CreateOrOpenAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] string name, Slice layer, CancellationToken cancellationToken)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            return(db.ReadWriteAsync((tr) => directory.CreateOrOpenAsync(tr, new[] { name }, layer), cancellationToken));
        }
        /// <summary>Moves the directory found at <paramref name="oldPath"/> to <paramref name="newPath"/>.
        /// There is no effect on the physical prefix of the given directory, or on clients that already have the directory open.
        /// An error is raised if the old directory does not exist, a directory already exists at `new_path`, or the parent directory of `new_path` does not exist.
        /// </summary>
        public static Task <FdbDirectorySubspace> MoveAsync([NotNull] this IFdbDirectory directory, [NotNull] IFdbRetryable db, [NotNull] IEnumerable <string> oldPath, [NotNull] IEnumerable <string> newPath, CancellationToken ct)
        {
            if (directory == null)
            {
                throw new ArgumentNullException(nameof(directory));
            }
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            if (oldPath == null)
            {
                throw new ArgumentNullException(nameof(oldPath));
            }
            if (newPath == null)
            {
                throw new ArgumentNullException(nameof(newPath));
            }

            return(db.ReadWriteAsync((tr) => directory.MoveAsync(tr, oldPath, newPath), ct));
        }
		/// <summary>Add and Schedule a new Task in the worker pool</summary>
		/// <param name="db"></param>
		/// <param name="taskId"></param>
		/// <param name="taskBody"></param>
		/// <param name="ct"></param>
		/// <returns></returns>
		public async Task ScheduleTaskAsync(IFdbRetryable db, Slice taskId, Slice taskBody, CancellationToken ct = default(CancellationToken))
		{
			if (db == null) throw new ArgumentNullException("db");
			var now = DateTime.UtcNow;

			await db.ReadWriteAsync(async (tr) =>
			{
				Interlocked.Increment(ref m_schedulingAttempts);
#if DEBUG
				if (tr.Context.Retries > 0) Console.WriteLine("# retry n°" + tr.Context.Retries + " for task " + taskId.ToAsciiOrHexaString());
#endif
				tr.Annotate("I want to schedule {0}", taskId.ToAsciiOrHexaString());

				// find a random worker from the idle ring
				var randomWorkerKey = await FindRandomItem(tr, this.IdleRing).ConfigureAwait(false);

				if (randomWorkerKey.Key != null)
				{
					Slice workerId = this.IdleRing.UnpackSingle<Slice>(randomWorkerKey.Key);

					tr.Annotate("Assigning {0} to {1}", taskId.ToAsciiOrHexaString(), workerId.ToAsciiOrHexaString());

					// remove worker from the idle ring
					tr.Clear(this.IdleRing.Pack(workerId));
					this.Counters.Decrement(tr, COUNTER_IDLE);

					// assign task to the worker
					tr.Set(this.BusyRing.Pack(workerId), taskId);
					this.Counters.Increment(tr, COUNTER_BUSY);
				}
				else
				{
					tr.Annotate("Queueing {0}", taskId.ToAsciiOrHexaString());

					await PushQueueAsync(tr, this.UnassignedTaskRing, taskId).ConfigureAwait(false);
				}

				// store the task in the db
				StoreTask(tr, taskId, now, taskBody);
			}, 
			onDone: (tr) =>
			{
				Interlocked.Increment(ref m_schedulingMessages);
			},
			cancellationToken: ct).ConfigureAwait(false);
		}