public void QueueSemantics() { var queue = new SlidingWindowQueue(); queue.Add(new TransactionData(-1, 0, this.Data)); Assert.ThrowsAny <ArgumentException>(() => queue.Add(new TransactionData(-1, 0, this.Data))); Assert.ThrowsAny <ArgumentException>(() => queue.Add(new TransactionData(-2, -1, this.Data))); queue.Add(new TransactionData(0, 1, this.Data)); Assert.ThrowsAny <ArgumentException>(() => queue.Add(new TransactionData(-1, 0, this.Data))); }
private SlidingWindowQueue GenerateQueueWithData(int numTransactions) { var queue = new SlidingWindowQueue(); for (int i = 0; i < numTransactions; ++i) { queue.Add(new TransactionData(i - 1, i, this.Data)); } return(queue); }
// case 6 public void OneAddAndSlideTaskConcurrently() { var queue = new SlidingWindowQueue(); long numTotalTransactionsAdded = 0; long numTotalTransactionsRemoved = 0; const int MaxTimeToWaitInMs = 1000 * 20; // 20 seconds of test var addTask = Task.Run(async() => { var rand = new Random(); var watch = Stopwatch.StartNew(); while (watch.ElapsedMilliseconds < MaxTimeToWaitInMs) { long numTransactionsAddedLocal = Interlocked.Read(ref numTotalTransactionsAdded); int transactionsAdded = rand.Next(100, 1000); for (int i = 1; i <= transactionsAdded; ++i) { var lsn = numTransactionsAddedLocal + i; queue.Add(new TransactionData(lsn - 1, lsn, this.Data)); Interlocked.Increment(ref numTotalTransactionsAdded); } // Console.WriteLine($"Added total : {numTransactionsAddedLocal + transactionsAdded}"); await Task.Delay(rand.Next(0, 10)); } }); var slideTask = Task.Run(async() => { var rand = new Random(); var watch = Stopwatch.StartNew(); while (watch.ElapsedMilliseconds < MaxTimeToWaitInMs) { if (addTask.IsCompleted) { break; } long numTransactionsAddedLocal = Interlocked.Read(ref numTotalTransactionsAdded); var transactions = queue.GetTransactions(numTransactionsAddedLocal); int numRemovedTransactions = queue.SlideWindowTill(numTransactionsAddedLocal); numTotalTransactionsRemoved += numRemovedTransactions; // Console.WriteLine($"Removed total : {numTotalTransactionsRemoved}"); Assert.True(transactions.Count == numRemovedTransactions, $"{transactions.Count} == {numRemovedTransactions} : " + $"No more transactions can be added with lsn less than {numTransactionsAddedLocal}"); long lastTransactionLsn = long.MinValue; // all transactions are received in monotonically increasing lsn. foreach (var transaction in transactions) { Assert.True(transaction.Lsn >= lastTransactionLsn); lastTransactionLsn = transaction.Lsn; Assert.Equal(this.Data, transaction.Data); } await Task.Delay(rand.Next(0, 10)); } }); Task.WaitAll(new Task[] { addTask, slideTask }); Console.WriteLine($"Added : {numTotalTransactionsAdded} Removed: {numTotalTransactionsRemoved}"); Assert.True(numTotalTransactionsAdded >= numTotalTransactionsRemoved, "Not possible : Removed more transactions than added."); Assert.True(queue.SlideWindowTill(numTotalTransactionsAdded + 1) == (numTotalTransactionsAdded - numTotalTransactionsRemoved)); }
// We don't support multiple producer or multiple consumer. public void OneProducerMultiConsumerFail() { var queue = new SlidingWindowQueue(); long numTotalTransactionsAdded = 0; long numTotalTransactionsRemoved = 0; const int MaxTimeToWaitInMs = 1000 * 20; // 20 seconds of test var rand = new Random(); Func <Task> runProducer = async() => { var watch = Stopwatch.StartNew(); while (watch.ElapsedMilliseconds < MaxTimeToWaitInMs) { var numTransactions = Interlocked.Read(ref numTotalTransactionsAdded); int transactionsToAdd = rand.Next(100, 1000); for (int i = 1; i <= transactionsToAdd; ++i) { var lsn = numTransactions + i; queue.Add(new TransactionData(lsn - 1, lsn, this.Data)); } Interlocked.Exchange(ref numTotalTransactionsAdded, numTransactions + transactionsToAdd); await Task.Delay(rand.Next(0, 2)); } }; Func <int, Task> runConsumer = async(int index) => { var watch = Stopwatch.StartNew(); while (watch.ElapsedMilliseconds < MaxTimeToWaitInMs) { var numTransactions = Interlocked.Read(ref numTotalTransactionsAdded); var transactions = queue.GetTransactions(numTransactions); var numRemoved = queue.SlideWindowTill(numTransactions); Assert.True(transactions.Count >= numRemoved); while (true) { var totalRemoved = Interlocked.Read(ref numTotalTransactionsRemoved); if (totalRemoved == Interlocked.CompareExchange(ref numTotalTransactionsRemoved, totalRemoved + numRemoved, totalRemoved)) { break; } } await Task.Delay(rand.Next(0, 10)); } }; const int numConsumers = 10; var allTasks = new List <Task>(1 + numConsumers); allTasks.Add(runProducer()); for (int i = 0; i < numConsumers; ++i) { allTasks.Add(runConsumer(i)); } try { Task.WaitAll(allTasks.ToArray()); } catch (AggregateException ex) { foreach (var e in ex.Flatten().InnerExceptions) { if (!e.Message.Contains("SlidingWindowQueue :")) { throw; } } } }