internal T Execute <T>(SocketPool pool, T defaultValue, UseSocket <T> use) { PooledSocket sock = null; try { //Acquire a socket sock = pool.Acquire(); //Use the socket as a parameter to the delegate and return its result. if (sock != null) { return(use(sock)); } } catch (Exception e) { logger.Error("Error in Execute<T>: " + pool.Host, e); //Socket is probably broken if (sock != null) { sock.Close(); } } finally { if (sock != null) { sock.Dispose(); } } return(defaultValue); }
/// <summary> /// This method closes the underlying stream and socket. /// </summary> public void Close() { if (stream != null) { try { stream.Close(); } catch (Exception e) { logger.Error("Error closing stream: " + socketPool.Host, e); } stream = null; } if (socket != null) { try { socket.Shutdown(SocketShutdown.Both); } catch (Exception e) { logger.Error("Error shutting down socket: " + socketPool.Host, e); } try { socket.Close(); } catch (Exception e) { logger.Error("Error closing socket: " + socketPool.Host, e); } socket = null; } }
//Private common store method. private string store(string command, string key, bool keyIsChecked, object value, uint hash, int expiry, ulong unique) { if (!keyIsChecked) { checkKey(key); } return(serverPool.Execute <string>(hash, "", delegate(PooledSocket socket) { SerializedType type; byte[] bytes; //Serialize object efficiently, store the datatype marker in the flags property. try { bytes = Serializer.Serialize(value, out type, CompressionThreshold); } catch (Exception e) { //If serialization fails, return false; logger.Error("Error serializing object for key '" + key + "'.", e); return ""; } //Create commandline string commandline = ""; switch (command) { case "set": case "add": case "replace": commandline = command + " " + keyPrefix + key + " " + (ushort)type + " " + expiry + " " + bytes.Length + "\r\n"; break; case "append": case "prepend": commandline = command + " " + keyPrefix + key + " 0 0 " + bytes.Length + "\r\n"; break; case "cas": commandline = command + " " + keyPrefix + key + " " + (ushort)type + " " + expiry + " " + bytes.Length + " " + unique + "\r\n"; break; } //Write commandline and serialized object. socket.Write(commandline); socket.Write(bytes); socket.Write("\r\n"); return socket.ReadResponse(); })); }
/// <summary> /// Gets a socket from the pool. /// If there are no free sockets, a new one will be created. If something goes /// wrong while creating the new socket, this pool's endpoint will be marked as dead /// and all subsequent calls to this method will return null until the retry interval /// has passed. /// </summary> internal PooledSocket Acquire() { //Do we have free sockets in the pool? //if so - return the first working one. //if not - create a new one. Interlocked.Increment(ref acquired); lock (queue) { while (queue.Count > 0) { PooledSocket socket = queue.Dequeue(); if (socket != null && socket.IsAlive) { Interlocked.Increment(ref reusedsockets); return(socket); } Interlocked.Increment(ref deadsocketsinpool); } } Interlocked.Increment(ref newsockets); //If we know the endpoint is dead, check if it is time for a retry, otherwise return null. if (isEndPointDead) { if (DateTime.Now > deadEndPointRetryTime) { //Retry isEndPointDead = false; } else { //Still dead return(null); } } //Try to create a new socket. On failure, mark endpoint as dead and return null. try { PooledSocket socket = new PooledSocket(this, endPoint, owner.SendReceiveTimeout); //Reset retry timer on success. deadEndPointSecondsUntilRetry = 1; return(socket); } catch (Exception e) { Interlocked.Increment(ref failednewsockets); logger.Error("Error connecting to: " + endPoint.Address, e); //Mark endpoint as dead isEndPointDead = true; //Retry in 2 minutes deadEndPointRetryTime = DateTime.Now.AddSeconds(deadEndPointSecondsUntilRetry); if (deadEndPointSecondsUntilRetry < maxDeadEndPointSecondsUntilRetry) { deadEndPointSecondsUntilRetry = deadEndPointSecondsUntilRetry * 2; //Double retry interval until next time } return(null); } }