Esempio n. 1
0
        public void Serialization()
        {
            var nodeOp1 = new NodeOperation(
                NodeOperation.OperationKind.Create,
                10,
                "A",
                new ArraySegment <byte>(new byte[] { 1, 2, 3, }));
            var nodeOp2 = new NodeOperation(
                NodeOperation.OperationKind.Update,
                11,
                "BB",
                new ArraySegment <byte>(new byte[] { 2, 3, 4, 5, }));
            var nodeOp3 = new NodeOperation(
                NodeOperation.OperationKind.Delete,
                12,
                "CCC",
                default);

            var opData = NodeOperation.GetOperationData(new[] { nodeOp1, nodeOp2, nodeOp3, });

            Assert.AreEqual(1, opData.Count);

            var ops = NodeOperation.GetNodeOperationFromBytes(opData.First()).ToArray();

            Assert.AreEqual(3, ops.Length);

            Assert.AreEqual(NodeOperation.OperationKind.Create, ops[0].Operation);
            Assert.AreEqual("A", ops[0].Key);
            Assert.AreEqual(3, ops[0].Value.Count);

            Assert.AreEqual(NodeOperation.OperationKind.Update, ops[1].Operation);
            Assert.AreEqual("BB", ops[1].Key);
            Assert.AreEqual(4, ops[1].Value.Count);

            Assert.AreEqual(NodeOperation.OperationKind.Delete, ops[2].Operation);
            Assert.AreEqual("CCC", ops[2].Key);
            Assert.AreEqual(0, ops[2].Value.Count);
            Assert.IsNull(ops[2].Value.Array);

            Assert.IsNotNull(ops[0].ToString());
            Assert.IsNotNull(ops[1].ToString());
            Assert.IsNotNull(ops[2].ToString());
        }
Esempio n. 2
0
        private async Task ProcessIncomingRequests()
        {
            CancellationToken cancellation = this.cancellationTokenSource.Token;
            var replicationTaskSem         = new SemaphoreSlim(128, 128);

            try
            {
                while (!cancellation.IsCancellationRequested)
                {
                    var ops = new List <PendingOperation>();
                    var op  = this.pendingOperations.Take(cancellation);

                    do
                    {
                        ops.Add(op);
                    }while (this.pendingOperations.TryTake(out op));

                    var opData = NodeOperation.GetOperationData(ops.Select(o => o.Operation));

                    try
                    {
                        await replicationTaskSem.WaitAsync(cancellation).ConfigureAwait(false);

                        var replicateTask = this.stateReplicator.ReplicateAsync(opData, cancellation, out long lsn);
                        var unsed         = replicateTask.ContinueWith(
                            t =>
                        {
                            replicationTaskSem.Release();

                            foreach (var operation in ops)
                            {
                                switch (operation.Operation.Operation)
                                {
                                case NodeOperation.OperationKind.Nop:
                                    // No operation, primary is telling its sequence number to secondaries.
                                    break;

                                case NodeOperation.OperationKind.Create:
                                case NodeOperation.OperationKind.Update:
                                    var data = new byte[operation.Operation.Value.Count];
                                    Array.Copy(operation.Operation.Value.Array, operation.Operation.Value.Offset, data, 0, operation.Operation.Value.Count);
                                    this.kvsData.AddOrUpdate(operation.Operation.Key, operation.Operation.SequenceNumber, data);
                                    break;

                                case NodeOperation.OperationKind.Delete:
                                    this.kvsData.TryRemove(operation.Operation.Key, operation.Operation.SequenceNumber);
                                    break;

                                default:
                                    throw new InvalidOperationException();
                                }

                                operation.OnCommit();
                            }
                        });

                        // Writes to disk while the replication to secondaries is started.
                        await this.operationLoggerPrimary.WriteOperations(lsn, opData);

                        ServiceEventSource.Current.ServiceMessage(this.Context, $"Replicated and persisted on primary, SN={lsn}");
                        Interlocked.Exchange(ref this.lastSequenceNumber, lsn);
                    }
                    catch (Exception ex) when(!(ex is OperationCanceledException))
                    {
                        foreach (var operation in ops)
                        {
                            operation.OnFailure();
                        }
                    }
                }

                SpinWait.SpinUntil(() => replicationTaskSem.CurrentCount == 128);
            }
            catch (OperationCanceledException)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "ProcessIncomingRequests operation cancelled.");
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "ProcessIncomingRequests unhandled exception: {0}", ex);
            }
            finally
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "ProcessIncomingRequests terminated.");
            }
        }