From b58ed04fc43ec0d4eb57ed37338d39de28a9251f Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 15 Jun 2019 15:27:12 +0800 Subject: [PATCH 1/4] Save TextSocketHelper.cs with utf-8 encoding --- Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs index 5da403e6..99e6455f 100644 --- a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs +++ b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Text; using System.Collections.Generic; @@ -58,7 +58,7 @@ public static string ReadResponse(PooledSocket socket) /// private static string ReadLine(PooledSocket socket) { - MemoryStream ms = new MemoryStream(50); + var ms = new MemoryStream(50); bool gotR = false; //byte[] buffer = new byte[1]; From b2bf7c373d963be4954f93febc97d50c54a52e42 Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 15 Jun 2019 16:30:52 +0800 Subject: [PATCH 2/4] Convert tab to spaces in TextSocketHelper --- .../Protocol/Text/TextSocketHelper.cs | 231 +++++++++--------- 1 file changed, 115 insertions(+), 116 deletions(-) diff --git a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs index 99e6455f..972800e4 100644 --- a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs +++ b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs @@ -5,122 +5,121 @@ namespace Enyim.Caching.Memcached.Protocol.Text { - internal static class TextSocketHelper - { - private const string GenericErrorResponse = "ERROR"; - private const string ClientErrorResponse = "CLIENT_ERROR "; - private const string ServerErrorResponse = "SERVER_ERROR "; - private const int ErrorResponseLength = 13; - - public const string CommandTerminator = "\r\n"; - - private static readonly Enyim.Caching.ILog log = Enyim.Caching.LogManager.GetLogger(typeof(TextSocketHelper)); - - /// - /// Reads the response of the server. - /// - /// The data sent by the memcached server. - /// The server did not sent a response or an empty line was returned. - /// The server did not specified any reason just returned the string ERROR. - or - The server returned a SERVER_ERROR, in this case the Message of the exception is the message returned by the server. - /// The server did not recognize the request sent by the client. The Message of the exception is the message returned by the server. - public static string ReadResponse(PooledSocket socket) - { - string response = TextSocketHelper.ReadLine(socket); - - if (log.IsDebugEnabled) - log.Debug("Received response: " + response); - - if (String.IsNullOrEmpty(response)) - throw new MemcachedClientException("Empty response received."); - - if (String.Compare(response, GenericErrorResponse, StringComparison.Ordinal) == 0) - throw new NotSupportedException("Operation is not supported by the server or the request was malformed. If the latter please report the bug to the developers."); - - if (response.Length >= ErrorResponseLength) - { - if (String.Compare(response, 0, ClientErrorResponse, 0, ErrorResponseLength, StringComparison.Ordinal) == 0) - { - throw new MemcachedClientException(response.Remove(0, ErrorResponseLength)); - } - else if (String.Compare(response, 0, ServerErrorResponse, 0, ErrorResponseLength, StringComparison.Ordinal) == 0) - { - throw new MemcachedException(response.Remove(0, ErrorResponseLength)); - } - } - - return response; - } - - - /// - /// Reads a line from the socket. A line is terninated by \r\n. - /// - /// - private static string ReadLine(PooledSocket socket) - { - var ms = new MemoryStream(50); - - bool gotR = false; - //byte[] buffer = new byte[1]; - - int data; - - while (true) - { - data = socket.ReadByte(); - - if (data == 13) - { - gotR = true; - continue; - } - - if (gotR) - { - if (data == 10) - break; - - ms.WriteByte(13); - - gotR = false; - } - - ms.WriteByte((byte)data); - } - - string retval = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length); - - if (log.IsDebugEnabled) - log.Debug("ReadLine: " + retval); - - return retval; - } - - /// - /// Gets the bytes representing the specified command. returned buffer can be used to streamline multiple writes into one Write on the Socket - /// using the - /// - /// The command to be converted. - /// The buffer containing the bytes representing the command. The command must be terminated by \r\n. - /// The Nagle algorithm is disabled on the socket to speed things up, so it's recommended to convert a command into a buffer - /// and use the to send the command and the additional buffers in one transaction. - public unsafe static IList> GetCommandBuffer(string value) - { - var data = new ArraySegment(Encoding.ASCII.GetBytes(value)); - - return new ArraySegment[] { data }; - } - - public unsafe static IList> GetCommandBuffer(string value, IList> list) - { - var data = new ArraySegment(Encoding.ASCII.GetBytes(value)); - - list.Add(data); - - return list; - } - - } + internal static class TextSocketHelper + { + private const string GenericErrorResponse = "ERROR"; + private const string ClientErrorResponse = "CLIENT_ERROR "; + private const string ServerErrorResponse = "SERVER_ERROR "; + private const int ErrorResponseLength = 13; + + public const string CommandTerminator = "\r\n"; + + private static readonly Enyim.Caching.ILog log = Enyim.Caching.LogManager.GetLogger(typeof(TextSocketHelper)); + + /// + /// Reads the response of the server. + /// + /// The data sent by the memcached server. + /// The server did not sent a response or an empty line was returned. + /// The server did not specified any reason just returned the string ERROR. - or - The server returned a SERVER_ERROR, in this case the Message of the exception is the message returned by the server. + /// The server did not recognize the request sent by the client. The Message of the exception is the message returned by the server. + public static string ReadResponse(PooledSocket socket) + { + string response = TextSocketHelper.ReadLine(socket); + + if (log.IsDebugEnabled) + log.Debug("Received response: " + response); + + if (String.IsNullOrEmpty(response)) + throw new MemcachedClientException("Empty response received."); + + if (String.Compare(response, GenericErrorResponse, StringComparison.Ordinal) == 0) + throw new NotSupportedException("Operation is not supported by the server or the request was malformed. If the latter please report the bug to the developers."); + + if (response.Length >= ErrorResponseLength) + { + if (String.Compare(response, 0, ClientErrorResponse, 0, ErrorResponseLength, StringComparison.Ordinal) == 0) + { + throw new MemcachedClientException(response.Remove(0, ErrorResponseLength)); + } + else if (String.Compare(response, 0, ServerErrorResponse, 0, ErrorResponseLength, StringComparison.Ordinal) == 0) + { + throw new MemcachedException(response.Remove(0, ErrorResponseLength)); + } + } + + return response; + } + + /// + /// Reads a line from the socket. A line is terninated by \r\n. + /// + /// + private static string ReadLine(PooledSocket socket) + { + var ms = new MemoryStream(50); + + bool gotR = false; + //byte[] buffer = new byte[1]; + + int data; + + while (true) + { + data = socket.ReadByte(); + + if (data == 13) + { + gotR = true; + continue; + } + + if (gotR) + { + if (data == 10) + break; + + ms.WriteByte(13); + + gotR = false; + } + + ms.WriteByte((byte)data); + } + + string retval = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length); + + if (log.IsDebugEnabled) + log.Debug("ReadLine: " + retval); + + return retval; + } + + /// + /// Gets the bytes representing the specified command. returned buffer can be used to streamline multiple writes into one Write on the Socket + /// using the + /// + /// The command to be converted. + /// The buffer containing the bytes representing the command. The command must be terminated by \r\n. + /// The Nagle algorithm is disabled on the socket to speed things up, so it's recommended to convert a command into a buffer + /// and use the to send the command and the additional buffers in one transaction. + public unsafe static IList> GetCommandBuffer(string value) + { + var data = new ArraySegment(Encoding.ASCII.GetBytes(value)); + + return new ArraySegment[] { data }; + } + + public unsafe static IList> GetCommandBuffer(string value, IList> list) + { + var data = new ArraySegment(Encoding.ASCII.GetBytes(value)); + + list.Add(data); + + return list; + } + + } } #region [ License information ] From f42d21a6f4dafc065fdcfe4043c33b6451be0080 Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 15 Jun 2019 16:31:44 +0800 Subject: [PATCH 3/4] Fix infinite loop issue in TextSocketHelper.ReadLine --- Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs index 972800e4..421c5028 100644 --- a/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs +++ b/Enyim.Caching/Memcached/Protocol/Text/TextSocketHelper.cs @@ -68,6 +68,11 @@ private static string ReadLine(PooledSocket socket) { data = socket.ReadByte(); + if (data == -1) + { + return string.Empty; + } + if (data == 13) { gotR = true; From 7b788e523c274f10ab77088b7d12dbd405c7f162 Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 15 Jun 2019 16:43:13 +0800 Subject: [PATCH 4/4] Add ExecuteRemoveAsync method into IMemcachedResultsClient --- Enyim.Caching/IMemcachedResultsClient.cs | 76 ++++++++++++------------ 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/Enyim.Caching/IMemcachedResultsClient.cs b/Enyim.Caching/IMemcachedResultsClient.cs index 32cec69f..cc85b327 100644 --- a/Enyim.Caching/IMemcachedResultsClient.cs +++ b/Enyim.Caching/IMemcachedResultsClient.cs @@ -2,55 +2,57 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Enyim.Caching.Memcached; using Enyim.Caching.Memcached.Results; namespace Enyim.Caching { - /// - /// Interface for API methods that return detailed operation results - /// - public interface IMemcachedResultsClient - { - IGetOperationResult ExecuteGet(string key); - IGetOperationResult ExecuteGet(string key); - IDictionary ExecuteGet(IEnumerable keys); + /// + /// Interface for API methods that return detailed operation results + /// + public interface IMemcachedResultsClient + { + IGetOperationResult ExecuteGet(string key); + IGetOperationResult ExecuteGet(string key); + IDictionary ExecuteGet(IEnumerable keys); - IGetOperationResult ExecuteTryGet(string key, out object value); - - IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value); - IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value, DateTime expiresAt); - IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value, TimeSpan validFor); + IGetOperationResult ExecuteTryGet(string key, out object value); - IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value); - IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, ulong cas); - IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, DateTime expiresAt, ulong cas); - IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, TimeSpan validFor, ulong cas); + IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value); + IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value, DateTime expiresAt); + IStoreOperationResult ExecuteStore(StoreMode mode, string key, object value, TimeSpan validFor); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor); + IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value); + IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, ulong cas); + IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, DateTime expiresAt, ulong cas); + IStoreOperationResult ExecuteCas(StoreMode mode, string key, object value, TimeSpan validFor, ulong cas); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, ulong cas); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt, ulong cas); - IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor, ulong cas); - - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta); - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt); - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor); - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, ulong cas); - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt, ulong cas); - IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor, ulong cas); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, ulong cas); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt, ulong cas); + IMutateOperationResult ExecuteDecrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor, ulong cas); - IConcatOperationResult ExecuteAppend(string key, ArraySegment data); - IConcatOperationResult ExecuteAppend(string key, ulong cas, ArraySegment data); - - IConcatOperationResult ExecutePrepend(string key, ArraySegment data); - IConcatOperationResult ExecutePrepend(string key, ulong cas, ArraySegment data); + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta); + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt); + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor); - IRemoveOperationResult ExecuteRemove(string key); - } + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, ulong cas); + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, DateTime expiresAt, ulong cas); + IMutateOperationResult ExecuteIncrement(string key, ulong defaultValue, ulong delta, TimeSpan validFor, ulong cas); + + IConcatOperationResult ExecuteAppend(string key, ArraySegment data); + IConcatOperationResult ExecuteAppend(string key, ulong cas, ArraySegment data); + + IConcatOperationResult ExecutePrepend(string key, ArraySegment data); + IConcatOperationResult ExecutePrepend(string key, ulong cas, ArraySegment data); + + IRemoveOperationResult ExecuteRemove(string key); + Task ExecuteRemoveAsync(string key); + } } #region [ License information ]