예제 #1
0
		public async Task Test_Queue_Fast()
		{
			// without high contention protecction

			using (var db = await OpenTestPartitionAsync())
			{
				var location = await GetCleanDirectory(db, "queue");

				var queue = new FdbQueue<int>(location, highContention: false);

				Console.WriteLine("Clear Queue");
				await queue.ClearAsync(db, this.Cancellation);

				Console.WriteLine("Empty? " + await queue.EmptyAsync(db, this.Cancellation));

				Console.WriteLine("Push 10, 8, 6");
				await queue.PushAsync(db, 10, this.Cancellation);
				await queue.PushAsync(db, 8, this.Cancellation);
				await queue.PushAsync(db, 6, this.Cancellation);

#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Empty? " + await queue.EmptyAsync(db, this.Cancellation));

				Console.WriteLine("Pop item: " + await queue.PopAsync(db, this.Cancellation));
				Console.WriteLine("Next item: " + await queue.PeekAsync(db, this.Cancellation));
#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Pop item: " + await queue.PopAsync(db, this.Cancellation));
#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Pop item: " + await queue.PopAsync(db, this.Cancellation));
#if DEBUG
				await DumpSubspace(db, location);
#endif


				Console.WriteLine("Empty? " + await queue.EmptyAsync(db, this.Cancellation));

				Console.WriteLine("Push 5");
				await queue.PushAsync(db, 5, this.Cancellation);
#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Clear Queue");
				await queue.ClearAsync(db, this.Cancellation);
#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Empty? " + await queue.EmptyAsync(db, this.Cancellation));
			}
		}
예제 #2
0
        public async Task Test_Single_Client()
        {
            using (var db = await OpenTestPartitionAsync())
            {
                var location = await GetCleanDirectory(db, "queue");

                var queue = new FdbQueue <int>(location, highContention: false);

                await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);

                for (int i = 0; i < 10; i++)
                {
                    await db.ReadWriteAsync((tr) => queue.PushAsync(tr, i), this.Cancellation);
                }

                for (int i = 0; i < 10; i++)
                {
                    var r = await queue.PopAsync(db, this.Cancellation);

                    Assert.That(r.HasValue, Is.True);
                    Assert.That(r.Value, Is.EqualTo(i));
                }

                bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);

                Assert.That(empty, Is.True);
            }
        }
예제 #3
0
        public async Task Test_Queue_Fast()
        {
            // without high contention protecction

            using (var db = await OpenTestPartitionAsync())
            {
                var location = await GetCleanDirectory(db, "queue");

                var queue = new FdbQueue <int>(location, highContention: false);

                Log("Clear Queue");
                await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);

                Log("Empty? " + await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation));

                Log("Push 10, 8, 6");
                await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 10), this.Cancellation);

                await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 8), this.Cancellation);

                await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 6), this.Cancellation);

#if DEBUG
                await DumpSubspace(db, location);
#endif

                // Empty?
                bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);

                Log("Empty? " + empty);
                Assert.That(empty, Is.False);

                var item = await queue.PopAsync(db, this.Cancellation);

                Log($"Pop item: {item}");
                Assert.That(item.HasValue, Is.True);
                Assert.That(item.Value, Is.EqualTo(10));
                item = await db.ReadWriteAsync((tr) => queue.PeekAsync(tr), this.Cancellation);

                Log($"Next item: {item}");
                Assert.That(item.HasValue, Is.True);
                Assert.That(item.Value, Is.EqualTo(8));
#if DEBUG
                await DumpSubspace(db, location);
#endif

                item = await queue.PopAsync(db, this.Cancellation);

                Log($"Pop item: {item}");
                Assert.That(item.HasValue, Is.True);
                Assert.That(item.Value, Is.EqualTo(8));
#if DEBUG
                await DumpSubspace(db, location);
#endif

                item = await queue.PopAsync(db, this.Cancellation);

                Log($"Pop item: {item}");
                Assert.That(item.HasValue, Is.True);
                Assert.That(item.Value, Is.EqualTo(6));
#if DEBUG
                await DumpSubspace(db, location);
#endif

                empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);

                Log("Empty? " + empty);
                Assert.That(empty, Is.True);

                Log("Push 5");
                await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 5), this.Cancellation);

#if DEBUG
                await DumpSubspace(db, location);
#endif

                Log("Clear Queue");
                await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);

#if DEBUG
                await DumpSubspace(db, location);
#endif

                empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);

                Log("Empty? " + empty);
                Assert.That(empty, Is.True);
            }
        }
예제 #4
0
        private static async Task RunMultiClientTest(IFdbDatabase db, KeySubspace location, bool highContention, string desc, int K, int NUM, CancellationToken ct)
        {
            Log("Starting {0} test with {1} threads and {2} iterations", desc, K, NUM);

            var queue = new FdbQueue <string>(location, highContention);
            await db.WriteAsync((tr) => queue.Clear(tr), ct);

            // use a CTS to ensure that everything will stop in case of problems...
            using (var go = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var tok = go.Token;

                var pushLock = new AsyncCancelableMutex(tok);
                var popLock  = new AsyncCancelableMutex(tok);

                int pushCount = 0;
                int popCount  = 0;
                int stalls    = 0;

                var pushTreads = Enumerable.Range(0, K)
                                 .Select(async id =>
                {
                    try
                    {
                        // wait for the signal
                        await pushLock.Task.ConfigureAwait(false);

                        var res = new List <string>(NUM);

                        for (int i = 0; i < NUM; i++)
                        {
                            var item = id.ToString() + "." + i.ToString();
                            await db.ReadWriteAsync((tr) => queue.PushAsync(tr, item), tok).ConfigureAwait(false);

                            Interlocked.Increment(ref pushCount);
                            res.Add(item);
                        }

                        return(res);
                    }
                    catch (Exception e)
                    {
                        Log("PushThread[" + id + "] failed: " + e);
                        Assert.Fail("PushThread[" + id + "] failed: " + e.Message);
                        throw;
                    }
                }).ToArray();

                var popThreads = Enumerable.Range(0, K)
                                 .Select(async id =>
                {
                    try
                    {
                        // make everyone wait a bit, to ensure that they all start roughly at the same time
                        await popLock.Task.ConfigureAwait(false);

                        var res = new List <string>(NUM);

                        int i = 0;
                        while (i < NUM)
                        {
                            var item = await queue.PopAsync(db, tok).ConfigureAwait(false);
                            if (item.HasValue)
                            {
                                Interlocked.Increment(ref popCount);
                                res.Add(item.Value);
                                ++i;
                            }
                            else
                            {
                                Interlocked.Increment(ref stalls);
                                await Task.Delay(10).ConfigureAwait(false);
                            }
                        }

                        return(res);
                    }
                    catch (Exception e)
                    {
                        Log("PopThread[" + id + "] failed: " + e);
                        Assert.Fail("PopThread[" + id + "] failed: " + e.Message);
                        throw;
                    }
                }).ToArray();

                var sw = Stopwatch.StartNew();

                pushLock.Set(async: true);
                await Task.Delay(100);

                popLock.Set(async: true);

                //using (var timer = new Timer((_) =>
                //{
                //	var __ = TestHelpers.DumpSubspace(db, location);
                //}, null, 1000, 4000))
                {
                    await Task.WhenAll(pushTreads);

                    await Task.WhenAll(popThreads);
                }

                sw.Stop();
                Log("> Finished {0} test in {1} seconds", desc, sw.Elapsed.TotalSeconds);
                Log("> Pushed {0}, Popped {1} and Stalled {2}", pushCount, popCount, stalls);

                var pushedItems = pushTreads.SelectMany(t => t.Result).ToList();
                var poppedItems = popThreads.SelectMany(t => t.Result).ToList();

                Assert.That(pushCount, Is.EqualTo(K * NUM));
                Assert.That(popCount, Is.EqualTo(K * NUM));

                // all pushed items should have been popped (with no duplicates)
                Assert.That(poppedItems, Is.EquivalentTo(pushedItems));

                // the queue should be empty
                bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), ct);

                Assert.That(empty, Is.True);
            }
        }
		public async Task Test_Queue_Fast()
		{
			// without high contention protecction

			using (var db = await OpenTestPartitionAsync())
			{
				var location = await GetCleanDirectory(db, "queue");

				var queue = new FdbQueue<int>(location, highContention: false);

				Console.WriteLine("Clear Queue");
				await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);

				Console.WriteLine("Empty? " + await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation));

				Console.WriteLine("Push 10, 8, 6");
				await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 10), this.Cancellation);
				await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 8), this.Cancellation);
				await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 6), this.Cancellation);

#if DEBUG
				await DumpSubspace(db, location);
#endif

				// Empty?
				bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);
				Console.WriteLine("Empty? " + empty);
				Assert.That(empty, Is.False);

				Optional<int> item = await queue.PopAsync(db, this.Cancellation);
				Console.WriteLine("Pop item: " + item);
				Assert.That((int)item, Is.EqualTo(10));
				item = await db.ReadWriteAsync((tr) => queue.PeekAsync(tr), this.Cancellation);
				Console.WriteLine("Next item: " + item);
				Assert.That((int)item, Is.EqualTo(8));
#if DEBUG
				await DumpSubspace(db, location);
#endif

				item = await queue.PopAsync(db, this.Cancellation);
				Console.WriteLine("Pop item: " + item);
				Assert.That((int)item, Is.EqualTo(8));
#if DEBUG
				await DumpSubspace(db, location);
#endif

				item = await queue.PopAsync(db, this.Cancellation);
				Console.WriteLine("Pop item: " + item);
				Assert.That((int)item, Is.EqualTo(6));
#if DEBUG
				await DumpSubspace(db, location);
#endif

				empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);
				Console.WriteLine("Empty? " + empty);
				Assert.That(empty, Is.True);

				Console.WriteLine("Push 5");
				await db.ReadWriteAsync((tr) => queue.PushAsync(tr, 5), this.Cancellation);
#if DEBUG
				await DumpSubspace(db, location);
#endif

				Console.WriteLine("Clear Queue");
				await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);
#if DEBUG
				await DumpSubspace(db, location);
#endif

				empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);
				Console.WriteLine("Empty? " + empty);
				Assert.That(empty, Is.True);
			}
		}
		private static async Task RunMultiClientTest(IFdbDatabase db, FdbSubspace location, bool highContention, string desc, int K, int NUM, CancellationToken ct)
		{
			Console.WriteLine("Starting {0} test with {1} threads and {2} iterations", desc, K, NUM);

			var queue = new FdbQueue<string>(location, highContention);
			await db.WriteAsync((tr) => queue.Clear(tr), ct);

			// use a CTS to ensure that everything will stop in case of problems...
			using (var go = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
			{
				var tok = go.Token;

				var pushLock = new AsyncCancelableMutex(tok);
				var popLock = new AsyncCancelableMutex(tok);

				int pushCount = 0;
				int popCount = 0;
				int stalls = 0;

				var pushTreads = Enumerable.Range(0, K)
					.Select(async id =>
					{
						// wait for the signal
						await pushLock.Task.ConfigureAwait(false);

						var res = new List<string>(NUM);

						for (int i = 0; i < NUM; i++)
						{
							var item = id.ToString() + "." + i.ToString();
							await db.ReadWriteAsync((tr) => queue.PushAsync(tr, item), tok).ConfigureAwait(false);

							Interlocked.Increment(ref pushCount);
							res.Add(item);
						}

						return res;
					}).ToArray();

				var popThreads = Enumerable.Range(0, K)
					.Select(async id =>
					{
						// make everyone wait a bit, to ensure that they all start roughly at the same time
						await popLock.Task.ConfigureAwait(false);

						var res = new List<string>(NUM);

						int i = 0;
						while (i < NUM)
						{
							var item = await queue.PopAsync(db, tok).ConfigureAwait(false);
							if (item.HasValue)
							{
								Interlocked.Increment(ref popCount);
								res.Add(item.Value);
								++i;
							}
							else
							{
								Interlocked.Increment(ref stalls);
								await Task.Delay(10).ConfigureAwait(false);
							}
						}

						return res;
					}).ToArray();

				var sw = Stopwatch.StartNew();

				pushLock.Set(async: true);
				await Task.Delay(100);
				popLock.Set(async: true);

				//using (var timer = new Timer((_) =>
				//{
				//	var __ = TestHelpers.DumpSubspace(db, location);
				//}, null, 1000, 4000))
				{

					await Task.WhenAll(pushTreads);
					await Task.WhenAll(popThreads);
				}

				sw.Stop();
				Console.WriteLine("> Finished {0} test in {1} seconds", desc, sw.Elapsed.TotalSeconds);
				Console.WriteLine("> Pushed {0}, Popped {1} and Stalled {2}", pushCount, popCount, stalls);

				var pushedItems = pushTreads.SelectMany(t => t.Result).ToList();
				var poppedItems = popThreads.SelectMany(t => t.Result).ToList();

				Assert.That(pushCount, Is.EqualTo(K * NUM));
				Assert.That(popCount, Is.EqualTo(K * NUM));

				// all pushed items should have been popped (with no duplicates)
				Assert.That(poppedItems, Is.EquivalentTo(pushedItems));

				// the queue should be empty
				bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), ct);
				Assert.That(empty, Is.True);
			}
		}
		public async Task Test_Single_Client()
		{
			using (var db = await OpenTestPartitionAsync())
			{
				var location = await GetCleanDirectory(db, "queue");

				var queue = new FdbQueue<int>(location, highContention: false);

				await db.WriteAsync((tr) => queue.Clear(tr), this.Cancellation);

				for (int i = 0; i < 10; i++)
				{
					await db.ReadWriteAsync((tr) => queue.PushAsync(tr, i), this.Cancellation);
				}

				for (int i = 0; i < 10; i++)
				{
					var r = await queue.PopAsync(db, this.Cancellation);
					Assert.That(r.HasValue, Is.True);
					Assert.That(r.Value, Is.EqualTo(i));
				}

				bool empty = await db.ReadAsync((tr) => queue.EmptyAsync(tr), this.Cancellation);
				Assert.That(empty, Is.True);
			}

		}