Esempio n. 1
0
        /// <summary>
        /// Completes or retries the buffer flush operation.
        /// </summary>
        private void FlushBufferCompleteOrRetry(
            DataStreamerClientBuffer <TK, TV> buffer,
            ClientSocket socket,
            TaskCompletionSource <object> tcs,
            Exception exception)
        {
            if (exception == null)
            {
                // Successful flush.
                Interlocked.Add(ref _entriesSent, buffer.Count);
                ReturnPooledArray(buffer.Entries);
                tcs.SetResult(null);

                return;
            }

            if (_cancelled || (!socket.IsDisposed && !ShouldRetry(exception)))
            {
                // Socket is still connected: this error does not need to be retried.
                ReturnPooledArray(buffer.Entries);
                tcs.SetException(exception);

                return;
            }

            // Release receiver thread, perform retry on a separate thread.
            ThreadPool.QueueUserWorkItem(_ => FlushBufferRetry(buffer, socket, tcs));
        }
        /// <summary>
        /// Initializes a new instance of <see cref="DataStreamerClientPerNodeBuffer{TK,TV}"/>.
        /// </summary>
        /// <param name="client">Streamer.</param>
        /// <param name="socket">Socket for the node.</param>
        public DataStreamerClientPerNodeBuffer(DataStreamerClient <TK, TV> client, ClientSocket socket)
        {
            Debug.Assert(client != null);

            _client    = client;
            _socket    = socket;
            _semaphore = new SemaphoreSlim(client.Options.PerNodeParallelOperations);

            _buffer = new DataStreamerClientBuffer <TK, TV>(_client.GetPooledArray(), this, null);
        }
        /// <summary>
        /// Initializes a new instance of <see cref="DataStreamerClientBuffer{TK,TV}"/>.
        /// </summary>
        public DataStreamerClientBuffer(
            DataStreamerClientEntry <TK, TV>[] entries,
            DataStreamerClientPerNodeBuffer <TK, TV> parent,
            DataStreamerClientBuffer <TK, TV> previous)
        {
            Debug.Assert(parent != null);

            _entries  = entries;
            _parent   = parent;
            _previous = previous;
        }
Esempio n. 4
0
        /// <summary>
        /// Writes buffer data to the specified writer.
        /// </summary>
        private void WriteBuffer(DataStreamerClientBuffer <TK, TV> buffer, BinaryWriter w)
        {
            w.WriteInt(_cacheId);
            w.WriteByte((byte)_flags);
            w.WriteInt(ServerBufferSizeAuto); // Server per-node buffer size.
            w.WriteInt(ServerBufferSizeAuto); // Server per-thread buffer size.

            if (_options.Receiver != null)
            {
                var rcvHolder = new StreamReceiverHolder(_options.Receiver,
                                                         (rec, grid, cache, stream, keepBinary) =>
                                                         StreamReceiverHolder.InvokeReceiver((IStreamReceiver <TK, TV>)rec, grid, cache, stream,
                                                                                             keepBinary));

                w.WriteObjectDetached(rcvHolder);
                w.WriteByte(ClientPlatformId.Dotnet);
            }
            else
            {
                w.WriteObject <object>(null);
            }

            var count = buffer.Count;

            w.WriteInt(count);

            var entries = buffer.Entries;

            for (var i = 0; i < count; i++)
            {
                var entry = entries[i];

                if (entry.IsEmpty)
                {
                    continue;
                }

                w.WriteObjectDetached(entry.Key);

                if (entry.Remove)
                {
                    w.WriteObject <object>(null);
                }
                else
                {
                    w.WriteObjectDetached(entry.Val);
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Re-adds obsolete buffer entries to new buffers and returns the array to the pool.
        /// </summary>
        private void ReAddEntriesAndReturnBuffer(DataStreamerClientBuffer <TK, TV> buffer)
        {
            var count   = buffer.Count;
            var entries = buffer.Entries;

            for (var i = 0; i < count; i++)
            {
                var entry = entries[i];

                if (!entry.IsEmpty)
                {
                    AddNoLock(entry);
                }
            }

            ReturnPooledArray(entries);
        }
        /// <summary>
        /// Checks if entire buffer chain is already flushed.
        /// </summary>
        private bool CheckChainFlushed()
        {
            var previous = _previous;

            if (previous == null)
            {
                return(_flushed);
            }

            if (!previous.CheckChainFlushed())
            {
                return(false);
            }

            _previous = null;

            return(_flushed);
        }
Esempio n. 7
0
        /// <summary>
        /// Flushes the specified buffer asynchronously.
        /// </summary>
        internal Task FlushBufferAsync(
            DataStreamerClientBuffer <TK, TV> buffer,
            ClientSocket socket,
            SemaphoreSlim semaphore)
        {
            semaphore.Wait();

            var tcs = new TaskCompletionSource <object>();

            FlushBufferInternalAsync(buffer, socket, tcs);

            return(tcs.Task.ContWith(t =>
            {
                semaphore.Release();

                _exception = _exception ?? t.Exception;

                return t.Result;
            }, TaskContinuationOptions.ExecuteSynchronously));
        }
Esempio n. 8
0
 private void FlushBufferInternalAsync(
     DataStreamerClientBuffer <TK, TV> buffer,
     ClientSocket socket,
     TaskCompletionSource <object> tcs)
 {
     try
     {
         socket.DoOutInOpAsync(
             ClientOp.DataStreamerStart,
             ctx => WriteBuffer(buffer, ctx.Writer),
             ctx => (object)null,
             syncCallback: true)
         .ContWith(
             t => FlushBufferCompleteOrRetry(buffer, socket, tcs, t.Exception),
             TaskContinuationOptions.ExecuteSynchronously);
     }
     catch (Exception exception)
     {
         FlushBufferCompleteOrRetry(buffer, socket, tcs, exception);
     }
 }
Esempio n. 9
0
        private void FlushBufferRetry(
            DataStreamerClientBuffer <TK, TV> buffer,
            ClientSocket failedSocket,
            TaskCompletionSource <object> tcs)
        {
            try
            {
                // Connection failed. Remove disconnected socket from the map.
                DataStreamerClientPerNodeBuffer <TK, TV> removed;
                _buffers.TryRemove(failedSocket, out removed);

                // Re-add entries to other buffers.
                ReAddEntriesAndReturnBuffer(buffer);

                if (removed != null)
                {
                    var remaining = removed.Close();

                    while (remaining != null)
                    {
                        if (remaining.MarkFlushed())
                        {
                            ReAddEntriesAndReturnBuffer(remaining);
                        }

                        remaining = remaining.Previous;
                    }
                }

                // Note: if initial flush was caused by full buffer, not requested by the user,
                // we don't need to force flush everything here - just re-add entries to other buffers.
                FlushInternalAsync().ContWith(flushTask => flushTask.SetAsResult(tcs));
            }
            catch (Exception e)
            {
                tcs.SetException(e);
            }
        }
 /// <summary>
 /// Flushes the specified buffer asynchronously.
 /// </summary>
 public Task FlushBufferAsync(DataStreamerClientBuffer <TK, TV> buffer)
 {
     return(_client.FlushBufferAsync(buffer, _socket, _semaphore));
 }