private void OnMemcacheError(MemcacheResponseHeader header, IMemcacheRequest request) { if (MemcacheError != null) { MemcacheError(header, request); } }
/// <summary> /// Sends a request with the policy defined with the configuration object, to multiple nodes if the replicas setting /// is different from zero. /// </summary> /// <param name="request">A memcache request derived from RedundantRequest</param> /// <returns> /// True if the request was sent to at least one node. The caller will receive a callback (if not null). /// False if the request could not be sent to any node. In that case, the callback will not be called. /// </returns> protected bool SendRequest(IMemcacheRequest request) { int countTrySends = 0; int countTrySendsOK = 0; foreach (var node in _cluster.Locator.Locate(request)) { countTrySends++; if (node.TrySend(request, _configuration.QueueTimeout)) { countTrySendsOK++; } // Break after trying to send the request to replicas+1 nodes if (countTrySends > request.Replicas) { break; } } // The callback will not be called if (countTrySendsOK == 0) { return(false); } // If the request was sent to less than Replicas+1 nodes, fail the remaining ones. for (; countTrySendsOK <= request.Replicas; countTrySendsOK++) { request.Fail(); } return(true); }
private bool SendRequest(IMemcacheRequest request, ManualResetEventSlim callAvailable = null) { try { var buffer = request.GetQueryBuffer(); if (_clientConfig.QueueLength > 0 && _pendingRequests.Count >= _clientConfig.QueueLength) { // The request queue is full, the transport will be put back in the pool after the queue is not full anymore Interlocked.Exchange(ref _transportAvailableInReceive, 1); if (!_pendingRequests.IsEmpty) { // the receive will reset the flag after the next dequeue return(false); } if (0 == Interlocked.CompareExchange(ref _transportAvailableInReceive, 0, 1)) { // the flag has already been reset (by the receive) return(false); } } _pendingRequests.Enqueue(request); SendAsynch(buffer, 0, buffer.Length, callAvailable); } catch (Exception e) { TransportFailureOnSend(e); return(false); } return(true); }
public bool TrySend(IMemcacheRequest request, int timeout) { try { var tries = 0; IMemcacheTransport transport; while (!IsClosing() && !_tokenSource.IsCancellationRequested && ++tries <= _configuration.PoolSize && _transportPool.TryTake(out transport, timeout, _tokenSource.Token)) { if (transport.TrySend(request)) { return(true); } } } catch (OperationCanceledException) { // someone called for a cancel on the pool.TryTake and already raised the problem return(false); } return(false); }
private void OnMemcacheResponse(MemcacheResponseHeader h, IMemcacheRequest e) { if (MemcacheResponse != null) { MemcacheResponse(h, e); } }
/// <summary> /// Sends a request with the policy defined with the configuration object, to multiple nodes if the replicas setting /// is different from zero. /// </summary> /// <param name="request">A memcache request derived from RedundantRequest</param> /// <returns> /// True if the request was sent to at least one node. The caller will receive a callback (if not null). /// False if the request could not be sent to any node. In that case, the callback will not be called. /// </returns> protected bool SendRequest(IMemcacheRequest request) { int countTrySends = 0; int countTrySendsOK = 0; foreach (var node in _locator.Locate(request.Key)) { countTrySends++; if (node.TrySend(request, _configuration.QueueTimeout)) { countTrySendsOK++; } // Break after trying to send the request to replicas+1 nodes if (countTrySends > request.Replicas) { break; } } if (countTrySendsOK == 0) { // The callback will not be called return(false); } else { // Call Fail() on the request as many times as node.TrySend returned false for (; countTrySendsOK < countTrySends; countTrySendsOK++) { request.Fail(); } return(true); } }
public IEnumerable <IMemcacheNode> Locate(IMemcacheRequest req) { var key = req.Key; if (key == null) { throw new ArgumentNullException("key"); } var ld = _lookupData; switch (ld.Nodes.Length) { case 0: yield break; case 1: var firstNode = ld.Nodes[0]; if (!firstNode.IsDead) { yield return(firstNode); } yield break; } // Return alive JsonNodes only. foreach (var retNode in LocateNode(ld, GetKeyHash(key))) { if (retNode != null && !retNode.IsDead) { yield return(retNode); } } }
public IEnumerable <IMemcacheNode> Locate(IMemcacheRequest req) { // Compute the vBucket's index using a modified CRC32 var vBucketIndex = Hash.Compute(req.Key) & HashMask; req.VBucket = (ushort)vBucketIndex; return(YieldingLocate(req, vBucketIndex)); }
public SaslPlainTextToken(string zone, string user, string password) { _authenticationStatus = new TaskCompletionSource<Status>(); _request = new SaslPlainRequest { Zone = zone, User = user, Password = password, Callback = _authenticationStatus.SetResult, }; }
public SaslPlainTextToken(string zone, string user, string password) { _authenticationStatus = new TaskCompletionSource <Status>(); _request = new SaslPlainRequest { Zone = zone, User = user, Password = password, Callback = _authenticationStatus.SetResult, }; }
public bool TrySend(IMemcacheRequest req) { if (!IsAlive) { return(false); } else { req.HandleResponse(Response, null, Extra, Message); return(true); } }
public bool TrySend(IMemcacheRequest req) { if (!IsAlive) { return false; } else { req.HandleResponse(Response, null, Extra, Message); return true; } }
public bool TrySend(IMemcacheRequest req) { if (!_broken) { return(true); } if (TransportDead != null) { TransportDead(this); } return(false); }
private IEnumerable<IMemcacheNode> YieldingLocate(IMemcacheRequest req, uint vBucketIndex) { // Check for non-configured, badly configured, or dead cluster if (Nodes == null || Nodes.Count == 0 || VBucketMap == null || VBucketMap.Length != 1024) yield break; // Yield replica in the same order (the first one being the master) foreach (var node in VBucketMap[vBucketIndex]) if (0 <= node && node < Nodes.Count) yield return Nodes[node]; else continue; }
public IEnumerable<IMemcacheNode> Locate(IMemcacheRequest req) { // Compute the vBucket's index using a modified CRC32 var vBucketIndex = Hash.Compute(req.Key) & HashMask; var couchbaseReq = req as ICouchbaseRequest; if (couchbaseReq != null) couchbaseReq.VBucket = (ushort)vBucketIndex; // the call to the yield is done in another method in order to // have the VBucket changed before we start iterating over the // located nodes return YieldingLocate(req, vBucketIndex); }
/// <summary> /// Synchronously sends a request /// </summary> /// <param name="request" /> public bool TrySend(IMemcacheRequest request) { if (request == null || _disposed) { return(false); } if (!_initialized && !Initialize()) { return(false); } return(SendRequest(request)); }
public bool TrySend(IMemcacheRequest request, int timeout) { LastRequest = request; trySendCounter++; if (timeout == 0) { LastRequest.HandleResponse(new MemcacheResponseHeader { Status = DefaultResponse, ExtraLength = 4 }, request.Key, new byte[4], new byte[0]); } return(true); }
public IEnumerable<IMemcacheNode> Locate(IMemcacheRequest req) { int position = Interlocked.Increment(ref _lastPosition) % _nodes.Count; position = position >= 0 ? position : position + _nodes.Count; for(int i = 0; i < _nodes.Count; ++i) { var selectedNode = _nodes[position]; if (!selectedNode.IsDead) yield return selectedNode; position++; if (position >= _nodes.Count) position = 0; } }
public IEnumerable <IMemcacheNode> Locate(IMemcacheRequest req) { // Compute the vBucket's index using a modified CRC32 var vBucketIndex = Hash.Compute(req.Key) & HashMask; var couchbaseReq = req as ICouchbaseRequest; if (couchbaseReq != null) { couchbaseReq.VBucket = (ushort)vBucketIndex; } // the call to the yield is done in another method in order to // have the VBucket changed before we start iterating over the // located nodes return(YieldingLocate(req, vBucketIndex)); }
public Status StepAuthenticate(TimeSpan authTimeout, out IMemcacheRequest stepRequest) { if (_started) { stepRequest = null; if (!_authenticationStatus.Task.Wait(authTimeout)) { throw new AuthenticationException("Authentication has timed out"); } return(_authenticationStatus.Task.Result); } _started = true; stepRequest = _request; return(Status.StepRequired); }
private bool Authenticate() { bool authDone = false; IMemcacheRequest request = null; Status authStatus = Status.NoError; if (_clientConfig.Authenticator != null) { var mre = new ManualResetEventSlim(); var authenticationToken = _clientConfig.Authenticator.CreateToken(); while (authenticationToken != null && !authDone) { authStatus = authenticationToken.StepAuthenticate(out request); switch (authStatus) { // auth OK, clear the token case Status.NoError: authenticationToken = null; authDone = true; break; case Status.StepRequired: if (request == null) { throw new AuthenticationException("Unable to authenticate : step required but no request from token"); } if (!SendRequest(request, mre)) { throw new AuthenticationException("Unable to authenticate : unable to send authentication request"); } break; default: throw new AuthenticationException("Unable to authenticate : status " + authStatus.ToString()); } } mre.Wait(); } return(true); }
private IEnumerable <IMemcacheNode> YieldingLocate(IMemcacheRequest req, uint vBucketIndex) { // Check for non-configured, badly configured, or dead cluster if (Nodes == null || Nodes.Count == 0 || VBucketMap == null || VBucketMap.Length != 1024) { yield break; } // Yield replica in the same order (the first one being the master) foreach (var node in VBucketMap[vBucketIndex]) { if (0 <= node && node < Nodes.Count) { yield return(Nodes[node]); } else { continue; } } }
private IMemcacheRequest DequeueToMatch(MemcacheResponseHeader header) { IMemcacheRequest result = null; if (header.Opcode.IsQuiet()) { throw new MemcacheException("No way we can match a quiet request !"); } else { // hacky case on partial response for stat command if (header.Opcode == Opcode.Stat && header.TotalBodyLength != 0 && header.Status == Status.NoError) { if (!_pendingRequests.TryPeek(out result)) { throw new MemcacheException("Received a response when no request is pending"); } } else { if (!_pendingRequests.TryDequeue(out result)) { throw new MemcacheException("Received a response when no request is pending"); } } if (result.RequestId != header.Opaque) { result.Fail(); throw new MemcacheException("Received a response that doesn't match with the sent request queue : sent " + result.ToString() + " received " + header.ToString()); } } AvailableInReceive(); return(result); }
private void OnMemcacheResponse(MemcacheResponseHeader h, IMemcacheRequest e) { if (MemcacheResponse != null) MemcacheResponse(h, e); }
public bool TrySend(IMemcacheRequest request, int timeout) { try { var tries = 0; IMemcacheTransport transport; while (!IsClosing() && !_tokenSource.IsCancellationRequested && ++tries <= _configuration.PoolSize && _transportPool.TryTake(out transport, timeout, _tokenSource.Token)) { if (transport.TrySend(request)) return true; } } catch (OperationCanceledException) { // someone called for a cancel on the pool.TryTake and already raised the problem return false; } return false; }
public void AuthenticationFailed() { var sentMutex = new ManualResetEventSlim(false); using (var serverStub = new ServerMock()) { IMemcacheRequest authenticationRequest = null; // a token that fails var authenticatorTokenFailing = new Moq.Mock <IAuthenticationToken>(); authenticatorTokenFailing .Setup(t => t.StepAuthenticate(Moq.It.IsAny <TimeSpan>(), out authenticationRequest)) .Returns(Status.TemporaryFailure); // a token that works var authenticatorTokenOk = new Moq.Mock <IAuthenticationToken>(); authenticatorTokenOk .Setup(t => t.StepAuthenticate(Moq.It.IsAny <TimeSpan>(), out authenticationRequest)) .Returns(Status.NoError); // an authenticator that returns one failing token followed by working tokens bool alreadyFailed = false; var authenticator = new Moq.Mock <IMemcacheAuthenticator>(); authenticator .Setup(auth => auth.CreateToken()) .Returns(() => { if (alreadyFailed) { return(authenticatorTokenOk.Object); } alreadyFailed = true; return(authenticatorTokenFailing.Object); }); // setup the request to send bool requestFailed = false; bool requestAchieved = false; var request = new Moq.Mock <IMemcacheRequest>(); request .Setup(r => r.Fail()) .Callback(() => { requestFailed = true; sentMutex.Set(); }); request .Setup(r => r.HandleResponse( Moq.It.Is <Headers.MemcacheResponseHeader>(h => h.Status == Status.NoError), Moq.It.IsAny <byte[]>(), Moq.It.IsAny <byte[]>(), Moq.It.IsAny <byte[]>())) .Callback(() => { requestAchieved = true; sentMutex.Set(); }); var queryBuffer = new byte[MemcacheRequestHeader.Size]; new MemcacheRequestHeader().ToData(queryBuffer); request .Setup(r => r.GetQueryBuffer()) .Returns(queryBuffer); IMemcacheTransport transportToWork = null; var transportToFail = new MemcacheTransport( serverStub.ListenEndPoint, new MemcacheClientConfiguration { SocketTimeout = TimeSpan.Zero, Authenticator = authenticator.Object, }, _ => { }, t => { Interlocked.Exchange(ref transportToWork, t); }, false, () => false); new MemcacheResponseHeader { Status = Status.NoError, Opcode = Opcode.Get, }.ToData(serverStub.ResponseHeader); Exception raised = null; transportToFail.TransportError += e => // when the transport fails collect the exception Interlocked.Exchange(ref raised, e); var sent = transportToFail.TrySend(request.Object); Assert.IsFalse(sent, "The request send should fail"); Assert.IsNotNull(raised, "The authentication should have failed"); // wait for reconnection to happen (should be done in a instant timer) Assert.That(ref transportToWork, (!Is.Null).After(1000, 10), "The working transport should have been set"); sent = transportToWork.TrySend(request.Object); Assert.IsTrue(sent, "The request should have been sent"); var received = sentMutex.Wait(TimeSpan.FromMinutes(5)); Assert.IsTrue(received, "The response should have been received"); Assert.IsFalse(requestFailed, "The request should not have failed"); Assert.IsTrue(requestAchieved, "The request should have achieved"); } }
public Status StepAuthenticate(TimeSpan authTimeout, out IMemcacheRequest stepRequest) { if (_started) { stepRequest = null; if (!_authenticationStatus.Task.Wait(authTimeout)) throw new AuthenticationException("Authentication has timed out"); return _authenticationStatus.Task.Result; } _started = true; stepRequest = _request; return Status.StepRequired; }
public bool TrySend(IMemcacheRequest request, int timeout) { return _queue.TryAdd(request, timeout); }
public bool TrySend(IMemcacheRequest req) { if (!_broken) return true; if (TransportDead != null) TransportDead(this); return false; }
/// <summary> /// Synchronously sends a request /// </summary> /// <param name="request" /> public bool TrySend(IMemcacheRequest request) { if (request == null || _disposed || _ongoingShutdown == 1) return false; if (!_initialized && !Initialize()) return false; return SendRequest(request); }
public bool TryTake(out IMemcacheRequest request, int timeout) { return(_queue.TryTake(out request, timeout)); }
public void Add(IMemcacheRequest request) { _queue.Add(request); }
private bool SendRequest(IMemcacheRequest request, ManualResetEventSlim callAvailable = null) { try { var buffer = request.GetQueryBuffer(); if (_clientConfig.QueueLength > 0 && _pendingRequests.Count >= _clientConfig.QueueLength) { // The request queue is full, the transport will be put back in the pool after the queue is not full anymore Interlocked.Exchange(ref _transportAvailableInReceive, 1); if (!_pendingRequests.IsEmpty) // the receive will reset the flag after the next dequeue return false; if (0 == Interlocked.CompareExchange(ref _transportAvailableInReceive, 0, 1)) // the flag has already been reset (by the receive) return false; } _pendingRequests.Enqueue(request); SendAsynch(buffer, 0, buffer.Length, callAvailable); } catch (Exception e) { TransportFailureOnSend(e); return false; } return true; }
public bool TryTake(out IMemcacheRequest request, int timeout) { return _queue.TryTake(out request, timeout); }
public bool TrySend(IMemcacheRequest request, int timeout) { return(_queue.TryAdd(request, timeout)); }