1313using System ;
1414using System . Collections . Generic ;
1515using System . Threading ;
16+ using ServiceStack . Caching ;
1617using ServiceStack . Logging ;
1718
1819namespace ServiceStack . Redis
@@ -23,12 +24,12 @@ namespace ServiceStack.Redis
2324 /// 1 master and multiple replicated read slaves.
2425 /// </summary>
2526 public partial class PooledRedisClientManager
26- : IRedisClientsManager , IRedisFailover
27+ : IRedisClientsManager , IRedisFailover , IHandleClientDispose
2728 {
2829 private static readonly ILog Log = LogManager . GetLogger ( typeof ( PooledRedisClientManager ) ) ;
2930
3031 private const string PoolTimeoutError =
31- "Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use." ;
32+ "Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use." ;
3233
3334 protected readonly int PoolSizeMultiplier = 10 ;
3435 public int RecheckPoolAfterMs = 100 ;
@@ -218,31 +219,7 @@ public IRedisClient GetClient()
218219 WritePoolIndex ++ ;
219220 inActiveClient . Active = true ;
220221
221- if ( this . ConnectTimeout != null )
222- {
223- inActiveClient . ConnectTimeout = this . ConnectTimeout . Value ;
224- }
225-
226- if ( this . SocketSendTimeout . HasValue )
227- {
228- inActiveClient . SendTimeout = this . SocketSendTimeout . Value ;
229- }
230- if ( this . SocketReceiveTimeout . HasValue )
231- {
232- inActiveClient . ReceiveTimeout = this . SocketReceiveTimeout . Value ;
233- }
234- if ( this . IdleTimeOutSecs . HasValue )
235- {
236- inActiveClient . IdleTimeOutSecs = this . IdleTimeOutSecs . Value ;
237- }
238-
239- inActiveClient . NamespacePrefix = NamespacePrefix ;
240-
241- //Reset database to default if changed
242- if ( inActiveClient . Db != Db )
243- {
244- inActiveClient . ChangeDb ( Db ) ;
245- }
222+ InitClient ( inActiveClient ) ;
246223
247224 return inActiveClient ;
248225 }
@@ -260,7 +237,7 @@ private RedisClient GetInActiveWriteClient()
260237 for ( int x = 0 ; x < ReadWriteHosts . Count ; x ++ )
261238 {
262239 var nextHostIndex = ( desiredIndex + x ) % ReadWriteHosts . Count ;
263- var nextHost = ReadWriteHosts [ nextHostIndex ] ;
240+ RedisEndpoint nextHost = ReadWriteHosts [ nextHostIndex ] ;
264241 for ( var i = nextHostIndex ; i < writeClients . Length ; i += ReadWriteHosts . Count )
265242 {
266243 if ( writeClients [ i ] != null && ! writeClients [ i ] . Active && ! writeClients [ i ] . HadExceptions )
@@ -269,16 +246,8 @@ private RedisClient GetInActiveWriteClient()
269246 {
270247 if ( writeClients [ i ] != null )
271248 writeClients [ i ] . DisposeConnection ( ) ;
272- var client = RedisClientFactory . CreateRedisClient ( nextHost . Host , nextHost . Port ) ;
273-
274- if ( nextHost . RequiresAuth )
275- client . Password = nextHost . Password ;
276-
277- client . Id = RedisClientCounter ++ ;
278- client . ClientManager = this ;
279- client . NamespacePrefix = NamespacePrefix ;
280- client . ConnectionFilter = ConnectionFilter ;
281249
250+ var client = InitNewClient ( nextHost ) ;
282251 writeClients [ i ] = client ;
283252
284253 return client ;
@@ -288,6 +257,34 @@ private RedisClient GetInActiveWriteClient()
288257 return null ;
289258 }
290259
260+ private RedisClient InitNewClient ( RedisEndpoint nextHost )
261+ {
262+ var client = RedisClientFactory . CreateRedisClient ( nextHost ) ;
263+ client . Id = Interlocked . Increment ( ref RedisClientCounter ) ;
264+ client . ClientManager = this ;
265+ client . ConnectionFilter = ConnectionFilter ;
266+ if ( NamespacePrefix != null )
267+ client . NamespacePrefix = NamespacePrefix ;
268+
269+ return client ;
270+ }
271+
272+ private void InitClient ( RedisClient client )
273+ {
274+ if ( this . ConnectTimeout != null )
275+ client . ConnectTimeout = this . ConnectTimeout . Value ;
276+ if ( this . SocketSendTimeout . HasValue )
277+ client . SendTimeout = this . SocketSendTimeout . Value ;
278+ if ( this . SocketReceiveTimeout . HasValue )
279+ client . ReceiveTimeout = this . SocketReceiveTimeout . Value ;
280+ if ( this . IdleTimeOutSecs . HasValue )
281+ client . IdleTimeOutSecs = this . IdleTimeOutSecs . Value ;
282+ if ( this . NamespacePrefix != null )
283+ client . NamespacePrefix = NamespacePrefix ;
284+ if ( client . Db != Db ) //Reset database to default if changed
285+ client . ChangeDb ( Db ) ;
286+ }
287+
291288 /// <summary>
292289 /// Returns a ReadOnly client using the hosts defined in ReadOnlyHosts.
293290 /// </summary>
@@ -314,31 +311,7 @@ public virtual IRedisClient GetReadOnlyClient()
314311 ReadPoolIndex ++ ;
315312 inActiveClient . Active = true ;
316313
317- if ( this . ConnectTimeout != null )
318- {
319- inActiveClient . ConnectTimeout = this . ConnectTimeout . Value ;
320- }
321-
322- if ( this . SocketSendTimeout . HasValue )
323- {
324- inActiveClient . SendTimeout = this . SocketSendTimeout . Value ;
325- }
326- if ( this . SocketReceiveTimeout . HasValue )
327- {
328- inActiveClient . ReceiveTimeout = this . SocketReceiveTimeout . Value ;
329- }
330- if ( this . IdleTimeOutSecs . HasValue )
331- {
332- inActiveClient . IdleTimeOutSecs = this . IdleTimeOutSecs . Value ;
333- }
334-
335- inActiveClient . NamespacePrefix = NamespacePrefix ;
336-
337- //Reset database to default if changed
338- if ( inActiveClient . Db != Db )
339- {
340- inActiveClient . ChangeDb ( Db ) ;
341- }
314+ InitClient ( inActiveClient ) ;
342315
343316 return inActiveClient ;
344317 }
@@ -365,14 +338,8 @@ private RedisClient GetInActiveReadClient()
365338 {
366339 if ( readClients [ i ] != null )
367340 readClients [ i ] . DisposeConnection ( ) ;
368- var client = RedisClientFactory . CreateRedisClient ( nextHost . Host , nextHost . Port ) ;
369-
370- if ( nextHost . RequiresAuth )
371- client . Password = nextHost . Password ;
372-
373- client . ClientManager = this ;
374- client . ConnectionFilter = ConnectionFilter ;
375341
342+ var client = InitNewClient ( nextHost ) ;
376343 readClients [ i ] = client ;
377344
378345 return client ;
@@ -500,19 +467,19 @@ public Dictionary<string, string> GetStats()
500467 }
501468
502469 var ret = new Dictionary < string , string >
503- {
504- { "writeClientsPoolSize" , "" + writeClientsPoolSize } ,
505- { "writeClientsCreated" , "" + writeClientsCreated } ,
506- { "writeClientsWithExceptions" , "" + writeClientsWithExceptions } ,
507- { "writeClientsInUse" , "" + writeClientsInUse } ,
508- { "writeClientsConnected" , "" + writeClientsConnected } ,
509-
510- { "readClientsPoolSize" , "" + readClientsPoolSize } ,
511- { "readClientsCreated" , "" + readClientsCreated } ,
512- { "readClientsWithExceptions" , "" + readClientsWithExceptions } ,
513- { "readClientsInUse" , "" + readClientsInUse } ,
514- { "readClientsConnected" , "" + readClientsConnected } ,
515- } ;
470+ {
471+ { "writeClientsPoolSize" , "" + writeClientsPoolSize } ,
472+ { "writeClientsCreated" , "" + writeClientsCreated } ,
473+ { "writeClientsWithExceptions" , "" + writeClientsWithExceptions } ,
474+ { "writeClientsInUse" , "" + writeClientsInUse } ,
475+ { "writeClientsConnected" , "" + writeClientsConnected } ,
476+
477+ { "readClientsPoolSize" , "" + readClientsPoolSize } ,
478+ { "readClientsCreated" , "" + readClientsCreated } ,
479+ { "readClientsWithExceptions" , "" + readClientsWithExceptions } ,
480+ { "readClientsInUse" , "" + readClientsInUse } ,
481+ { "readClientsConnected" , "" + readClientsConnected } ,
482+ } ;
516483
517484 return ret ;
518485 }
@@ -613,5 +580,60 @@ protected void Dispose(RedisClient redisClient)
613580 redisClient . Host , redisClient . Port ) , ex ) ;
614581 }
615582 }
583+
584+ public ICacheClient GetCacheClient ( )
585+ {
586+ return new RedisClientManagerCacheClient ( this ) ;
587+ }
588+
589+ public ICacheClient GetReadOnlyCacheClient ( )
590+ {
591+ return new RedisClientManagerCacheClient ( this ) { ReadOnly = true } ;
592+ }
616593 }
594+
595+ public partial class PooledRedisClientManager : IRedisClientCacheManager
596+ {
597+ /// <summary>
598+ /// Manage a client acquired from the PooledRedisClientManager
599+ /// Dispose method will release the client back to the pool.
600+ /// </summary>
601+ public class DisposablePooledClient < T > : IDisposable where T : RedisNativeClient
602+ {
603+ private T client ;
604+ private readonly PooledRedisClientManager clientManager ;
605+
606+ /// <summary>
607+ /// wrap the acquired client
608+ /// </summary>
609+ /// <param name="clientManager"></param>
610+ public DisposablePooledClient ( PooledRedisClientManager clientManager )
611+ {
612+ this . clientManager = clientManager ;
613+ if ( clientManager != null )
614+ client = ( T ) clientManager . GetClient ( ) ;
615+ }
616+
617+ /// <summary>
618+ /// access the wrapped client
619+ /// </summary>
620+ public T Client { get { return client ; } }
621+
622+ /// <summary>
623+ /// release the wrapped client back to the pool
624+ /// </summary>
625+ public void Dispose ( )
626+ {
627+ if ( client != null )
628+ clientManager . DisposeClient ( client ) ;
629+ client = null ;
630+ }
631+ }
632+
633+ public DisposablePooledClient < T > GetDisposableClient < T > ( ) where T : RedisNativeClient
634+ {
635+ return new DisposablePooledClient < T > ( this ) ;
636+ }
637+ }
638+
617639}
0 commit comments