Browse files

Updated Acquire methods of PooledSocket to use PooledSocketResult ins…

…tead of direct or null returns.
  • Loading branch information...
1 parent 40a8272 commit 2cfc500fa371fc1eadd70805eee7b8aaa1d95449 @johnzablocki johnzablocki committed Apr 23, 2012
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

0 comments on commit 2cfc500

Please sign in to comment.