public void Send(MemcachedCommand command)
        {
            Thread.MemoryBarrier();
            InitiateCommand(command);

            _writeAsync.BeginAsync(_stream);
        }
        private MemcachedCommand GetNextCommandAfterPreviousSendCompleted(MemcachedCommand command)
        {
            lock (_gate)
            {
                _pendingSends.Dequeue();
                if (_isWriterConnectionOpen && _isReaderConnectionOpen && !_hasBeenDisposed && _pendingSends.Count > 0)
                {
                    var commandBeingSent = _pendingSends.Peek();
                    _pendingReceives[commandBeingSent.Id] = commandBeingSent;
                    return commandBeingSent;
                }

                return null;
            }
        }
        private void WriteCommandHeader(MemcachedCommand command)
        {
            command.BeginWriting();

            WriteRequestHeader(_sendBuffer, command.Opcode, command.RequestHeader);

            const int requestHeaderSize = 24;

            _currentByteInSendBuffer += requestHeaderSize;

            command.WriteExtras(new ArraySegment<byte>(_sendBuffer, _currentByteInSendBuffer, command.RequestHeader.ExtrasLength));

            _currentByteInSendBuffer += command.RequestHeader.ExtrasLength;

            command.WriteKey(new ArraySegment<byte>(_sendBuffer, _currentByteInSendBuffer, command.RequestHeader.KeyLength));

            _currentByteInSendBuffer += command.RequestHeader.KeyLength;
        }
 public WriteState(MemcachedCommand command)
 {
     Command = command;
     TotalBytesInValue = command.RequestHeader.TotalBodyLength - command.RequestHeader.KeyLength - command.RequestHeader.ExtrasLength;
     CurrentByteInValue = 0;
 }
        public bool TrySend(MemcachedCommand command)
        {
            bool isWriterIdle = false;
            lock (_gate)
            {
                if (_hasBeenDisposed)
                    return false;

                var areEitherReaderOrWriterClosed = !_isReaderConnectionOpen || !_isWriterConnectionOpen;

                if (areEitherReaderOrWriterClosed || _hasBeenDisposed)
                {
                    return false;
                }

                _pendingSends.Enqueue(command);

                isWriterIdle = _pendingSends.Count == 1;

                if (isWriterIdle)
                {
                    _pendingReceives[command.Id] = command;
                }
            }

            if (isWriterIdle)
            {
                _requestWriter.Send(command);
            }

            return true;
        }
 private void RemoveFromPendingReceives(MemcachedCommand command)
 {
     lock (_gate)
     {
         _pendingReceives.Remove(command.Id);
     }
 }
        private void OnErrorReceived(MemcachedCommand command)
        {
            RemoveFromPendingReceives(command);

            switch (command.ResponseStatus)
            {
                case ResponseStatus.VbucketBelongsToAnotherServer:
                case ResponseStatus.Busy:
                case ResponseStatus.TemporaryFailure:
                    {
                        var ev = OnRecoverableError;
                        if (ev != null)
                        {
                            ev(this.ServerId, command);
                        }
                    }
                    break;
                case ResponseStatus.NoError:
                    throw new Exception("Should be impossible to get here...");
                default:
                    //The error is not something we can deal with inside the library itself, either the caller screwed up, or there was a catastrophic failure.
                    command.NotifyComplete();
                    break;
            }
        }
        private void SendCommandWithVBucketId(MemcachedCommand command)
        {
            Cluster cluster = _cluster;

            command.SetVBucketId(cluster.GetVBucket(command.Key));

            SendCommand(cluster, command);
        }
        private static void SendByLinearlyPollingServers(Cluster cluster, string lastServerTriedToSendToId, MemcachedCommand command)
        {
            int indexOfServerToTry = GetIndexOfNextServerInCluster(cluster, lastServerTriedToSendToId);
            for (int i = 0; i < cluster.Servers.Count; i++)
            {
                if (cluster.Servers[indexOfServerToTry].TrySend(command))
                {
                    return;
                }

                indexOfServerToTry = MathUtils.CircularIncrement(indexOfServerToTry, cluster.Servers.Count);
            }

            command.NotifyComplete(ResponseStatus.DisconnectionOccuredWhileOperationWaitingToBeSent);
        }
        private void OnWrongVBucketForServer(string lastServerTriedToSendToId, MemcachedCommand command)
        {
            Cluster cluster = _cluster;

            var fastForwardedServers = cluster.GetFastForwardedServersForVBucket(command.VBucketId);

            if (fastForwardedServers == null ||
                !TrySendCommand(fastForwardedServers, command))
            {
                SendByLinearlyPollingServers(cluster, lastServerTriedToSendToId, command);
                return;
            }
        }
        private void OnPossiblyRecoverableMemcachedError(string serverid, MemcachedCommand command)
        {
            var cluster = _cluster;

            switch (command.ResponseStatus)
            {
                case ResponseStatus.VbucketBelongsToAnotherServer:
                    OnWrongVBucketForServer(serverid, command);
                    break;
                case ResponseStatus.Busy:
                case ResponseStatus.TemporaryFailure:
                    SendCommand(cluster, command); //Retry
                    break;
                default:
                    throw new Exception("Should be impossible to get here...");
            }
        }
 private static bool TrySendCommand(List<Server> serversForVbucket, MemcachedCommand command)
 {
     for (int iServer = 0; iServer < serversForVbucket.Count; iServer++)
     {
         if (serversForVbucket[iServer].TrySend(command))
         {
             return true;
         }
     }
     return false;
 }
        private static bool TrySendCommand(Cluster cluster, MemcachedCommand command)
        {
            var serversForVbucket = cluster.GetServersForVBucket(command.VBucketId);

            return TrySendCommand(serversForVbucket, command);
        }
 private static void SendCommand(Cluster cluster, MemcachedCommand command)
 {
     if (!TrySendCommand(cluster, command))
     {
         command.NotifyComplete(ResponseStatus.DisconnectionOccuredWhileOperationWaitingToBeSent);
     }
 }
        private void InitiateCommand(MemcachedCommand command)
        {
            WriteCommandHeader(command);

            _writeState = new WriteState(command);
        }
 private void OnCommandResponseReceived(MemcachedCommand command)
 {
     RemoveFromPendingReceives(command);
     command.NotifyComplete();
 }
Exemple #17
0
 public bool TrySend(MemcachedCommand command)
 {
     return this.MemcachedClient.TrySend(command);
 }