Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated Acquire methods of PooledSocket to use PooledSocketResult ins…

…tead of direct or null returns.
  • Loading branch information...
commit 2cfc500fa371fc1eadd70805eee7b8aaa1d95449 1 parent 40a8272
@johnzablocki johnzablocki authored
View
2  Enyim.Caching/Enyim.Caching.csproj
@@ -256,8 +256,10 @@
<Compile Include="Memcached\Results\Factories\IRemoveOperationResultFactory.cs" />
<Compile Include="Memcached\Results\GetOperationResult`1.cs" />
<Compile Include="Memcached\Results\IGetOperationResult`1.cs" />
+ <Compile Include="Memcached\Results\IPooledSocketResult.cs" />
<Compile Include="Memcached\Results\IRemoveOperationResult.cs" />
<Compile Include="Memcached\Results\Factories\IStoreOperationResultFactory.cs" />
+ <Compile Include="Memcached\Results\PooledSocketResult.cs" />
<Compile Include="Memcached\Results\RemoveOperationResult.cs" />
<Compile Include="Memcached\Results\GetOperationResult.cs" />
<Compile Include="Memcached\Results\ICasOperationResult.cs" />
View
94 Enyim.Caching/Memcached/MemcachedNode.cs
@@ -9,6 +9,8 @@
using Enyim.Caching.Memcached.Protocol.Binary;
using System.Runtime.Serialization;
using System.IO;
+using Enyim.Caching.Memcached.Results;
+using Enyim.Caching.Memcached.Results.Extensions;
namespace Enyim.Caching.Memcached
{
@@ -114,7 +116,7 @@ public bool Ping()
/// Acquires a new item from the pool
/// </summary>
/// <returns>An <see cref="T:PooledSocket"/> instance which is connected to the memcached server, or <value>null</value> if the pool is dead.</returns>
- public PooledSocket Acquire()
+ public IPooledSocketResult Acquire()
{
if (!this.isInitialized)
lock (this.internalPoolImpl)
@@ -130,9 +132,11 @@ public PooledSocket Acquire()
}
catch (Exception e)
{
- log.Error("Acquire failed. Maybe we're already disposed?", e);
-
- return null;
+ var message = "Acquire failed. Maybe we're already disposed?";
+ log.Error(message, e);
+ var result = new PooledSocketResult();
+ result.Fail(message, e);
+ return result;
}
}
@@ -265,35 +269,45 @@ public DateTime MarkedAsDeadUtc
/// Acquires a new item from the pool
/// </summary>
/// <returns>An <see cref="T:PooledSocket"/> instance which is connected to the memcached server, or <value>null</value> if the pool is dead.</returns>
- public PooledSocket Acquire()
+ public IPooledSocketResult Acquire()
{
+ var result = new PooledSocketResult();
+ var message = string.Empty;
+
bool hasDebug = log.IsDebugEnabled;
if (hasDebug) log.Debug("Acquiring stream from pool. " + this.endPoint);
if (!this.isAlive || this.isDisposed)
{
- if (hasDebug) log.Debug("Pool is dead or disposed, returning null. " + this.endPoint);
+ message = "Pool is dead or disposed, returning null. " + this.endPoint;
+ result.Fail(message);
+
+ if (hasDebug) log.Debug(message);
- return null;
+ return result;
}
PooledSocket retval = null;
if (!this.semaphore.WaitOne(this.queueTimeout))
{
- if (hasDebug) log.Debug("Pool is full, timeouting. " + this.endPoint);
+ message = "Pool is full, timeouting. " + this.endPoint;
+ if (hasDebug) log.Debug(message);
+ result.Fail(message, new TimeoutException());
// everyone is so busy
- throw new TimeoutException();
+ return result;
}
// maybe we died while waiting
if (!this.isAlive)
{
- if (hasDebug) log.Debug("Pool is dead, returning null. " + this.endPoint);
+ message = "Pool is dead, returning null. " + this.endPoint;
+ if (hasDebug) log.Debug(message);
+ result.Fail(message);
- return null;
+ return result;
}
// do we have free items?
@@ -305,33 +319,42 @@ public PooledSocket Acquire()
{
retval.Reset();
- if (hasDebug) log.Debug("Socket was reset. " + retval.InstanceId);
+ message = "Socket was reset. " + retval.InstanceId;
+ if (hasDebug) log.Debug(message);
- return retval;
+ result.Pass(message);
+ result.Value = retval;
+ return result;
}
catch (Exception e)
{
- log.Error("Failed to reset an acquired socket.", e);
+ message = "Failed to reset an acquired socket.";
+ log.Error(message, e);
this.MarkAsDead();
-
- return null;
+ result.Fail(message, e);
+ return result;
}
#endregion
}
// free item pool is empty
- if (hasDebug) log.Debug("Could not get a socket from the pool, Creating a new item. " + this.endPoint);
+ message = "Could not get a socket from the pool, Creating a new item. " + this.endPoint;
+ if (hasDebug) log.Debug(message);
+
try
{
// okay, create the new item
retval = this.CreateSocket();
+ result.Value = retval;
+ result.Pass();
}
catch (Exception e)
{
- log.Error("Failed to create socket. " + this.endPoint, e);
+ message = "Failed to create socket. " + this.endPoint;
+ log.Error(message, e);
// eventhough this item failed the failure policy may keep the pool alive
// so we need to make sure to release the semaphore, so new connections can be
@@ -340,13 +363,13 @@ public PooledSocket Acquire()
semaphore.Release();
this.MarkAsDead();
-
- return null;
+ result.Fail(message);
+ return result;
}
if (hasDebug) log.Debug("Done.");
- return retval;
+ return result;
}
private void MarkAsDead()
@@ -487,29 +510,44 @@ protected internal virtual PooledSocket CreateSocket()
// return retval;
//}
- protected virtual bool ExecuteOperation(IOperation op)
+ protected virtual IPooledSocketResult ExecuteOperation(IOperation op)
{
- using (var socket = this.Acquire())
+ var result = this.Acquire();
+ if (result.Success && result.HasValue)
+ {
try
{
- if (socket == null) return false;
+ var socket = result.Value;
var b = op.GetBuffer();
socket.Write(b);
- return op.ReadResponse(socket);
+ result.Success = op.ReadResponse(socket);
+ return result;
}
catch (IOException e)
{
log.Error(e);
- return false;
+ result.Fail("Exception reading response", e);
+ return result;
}
+ finally
+ {
+ ((IDisposable)result.Value).Dispose();
+ }
+ }
+ else
+ {
+ result.Fail("Failed to obtain socket from pool");
+ return result;
+ }
+
}
protected virtual bool ExecuteOperationAsync(IOperation op, Action<bool> next)
{
- var socket = this.Acquire();
+ var socket = this.Acquire().Value;
if (socket == null) return false;
var b = op.GetBuffer();
@@ -555,7 +593,7 @@ bool IMemcachedNode.Ping()
bool IMemcachedNode.Execute(IOperation op)
{
- return this.ExecuteOperation(op);
+ return this.ExecuteOperation(op).Success;
}
bool IMemcachedNode.ExecuteAsync(IOperation op, Action<bool> next)
View
33 Enyim.Caching/Memcached/Results/IPooledSocketResult.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Enyim.Caching.Memcached.Results
+{
+ public interface IPooledSocketResult : INullableOperationResult<PooledSocket>
+ {
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ * @copyright 2012 Attila Kiskó, enyim.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
36 Enyim.Caching/Memcached/Results/PooledSocketResult.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Enyim.Caching.Memcached.Results
+{
+ public class PooledSocketResult : OperationResultBase, IPooledSocketResult
+ {
+ public bool HasValue { get { return Value != null; } }
+
+ public PooledSocket Value { get; set; }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ * @copyright 2012 Attila Kiskó, enyim.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
Please sign in to comment.
Something went wrong with that request. Please try again.