1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Threading ;
5+ using ServiceStack . Redis ;
6+ using ServiceStack . Redis . Generic ;
7+ using ServiceStack . Text ;
8+
9+ namespace TestRedisConnection
10+ {
11+ public class HashCollectionStressTests
12+ {
13+ private IRedisClientsManager clientsManager ;
14+ private int running = 0 ;
15+ private long writeCount = 0 ;
16+ private long readCount = 0 ;
17+
18+ public void Execute ( string ipAddress , int noOfThreads = 64 )
19+ {
20+ clientsManager = new PooledRedisClientManager ( ipAddress ) ;
21+
22+ var StartedAt = DateTime . UtcNow ;
23+ Interlocked . Increment ( ref running ) ;
24+
25+ "Starting HashCollectionStressTests with {0} threads" . Print ( noOfThreads ) ;
26+ var threads = new List < Thread > ( ) ;
27+ for ( int i = 0 ; i < noOfThreads ; i ++ )
28+ {
29+ threads . Add ( new Thread ( WorkerLoop ) ) ;
30+ }
31+ threads . ForEach ( t => t . Start ( ) ) ;
32+
33+ "Press Enter to Stop..." . Print ( ) ;
34+ Console . ReadLine ( ) ;
35+
36+ Interlocked . Decrement ( ref running ) ;
37+
38+ "Writes: {0}, Reads: {1}" . Print ( writeCount , readCount ) ;
39+ "{0} EndedAt: {1}" . Print ( GetType ( ) . Name , DateTime . UtcNow . ToLongTimeString ( ) ) ;
40+ "{0} TimeTaken: {1}s" . Print ( GetType ( ) . Name , ( DateTime . UtcNow - StartedAt ) . TotalSeconds ) ;
41+
42+ "\n Press Enter to Quit..." . Print ( ) ;
43+ Console . ReadLine ( ) ;
44+ }
45+
46+ public void WorkerLoop ( )
47+ {
48+ while ( Interlocked . CompareExchange ( ref running , 0 , 0 ) > 0 )
49+ {
50+ var redisCollection = new RedisCachedCollection < string , string > (
51+ clientsManager , "Thread: " + Thread . CurrentThread . ManagedThreadId ) ;
52+
53+ redisCollection . ContainsKey ( "key" ) ;
54+ Interlocked . Increment ( ref readCount ) ;
55+
56+ redisCollection [ "key" ] = "value " + readCount ;
57+ Interlocked . Increment ( ref writeCount ) ;
58+
59+ var value = redisCollection [ "key" ] ;
60+ Interlocked . Increment ( ref readCount ) ;
61+
62+ if ( value == null )
63+ Console . WriteLine ( "value == null" ) ;
64+ }
65+ }
66+ }
67+
68+ public class RedisCachedCollection < TKey , TValue > : IEnumerable < TValue >
69+ {
70+ private readonly string collectionKey ;
71+ private Func < TValue , TKey > idAction ;
72+ private readonly IRedisClientsManager clientsManager ;
73+
74+ public RedisCachedCollection ( IRedisClientsManager clientsManager , string collectionKey )
75+ {
76+ this . clientsManager = clientsManager ;
77+ this . collectionKey = string . Format ( "urn:{0}:{1}" , "XXXXX" , collectionKey ) ;
78+ }
79+
80+ public IRedisClient RedisConnection
81+ {
82+ get
83+ {
84+ return clientsManager . GetClient ( ) ;
85+ }
86+ }
87+
88+ private IRedisHash < TKey , TValue > GetCollection ( IRedisClient redis )
89+ {
90+ var _redisTypedClient = redis . As < TValue > ( ) ;
91+ return _redisTypedClient . GetHash < TKey > ( collectionKey ) ;
92+ }
93+
94+ public void Add ( TValue obj )
95+ {
96+ TKey Id = GetUniqueIdAction ( obj ) ;
97+
98+ RetryAction ( ( redis ) =>
99+ {
100+ GetCollection ( redis ) . Add ( Id , obj ) ;
101+ } ) ;
102+ }
103+
104+ public bool Remove ( TValue obj )
105+ {
106+ TKey Id = GetUniqueIdAction ( obj ) ;
107+ TKey defaultv = default ( TKey ) ;
108+
109+ return RetryAction < bool > ( ( redis ) =>
110+ {
111+ if ( ! Id . Equals ( defaultv ) )
112+ {
113+ {
114+ return GetCollection ( redis ) . Remove ( Id ) ;
115+ }
116+ }
117+ return false ;
118+ } ) ;
119+
120+ }
121+
122+ public TValue this [ TKey id ]
123+ {
124+ get
125+ {
126+ return RetryAction < TValue > ( ( redis ) =>
127+ {
128+ if ( GetCollection ( redis ) . ContainsKey ( id ) )
129+ return GetCollection ( redis ) [ id ] ;
130+ return default ( TValue ) ;
131+ } ) ;
132+ }
133+ set
134+ {
135+ RetryAction ( ( redis ) =>
136+ {
137+ GetCollection ( redis ) [ id ] = value ;
138+ } ) ;
139+ }
140+ }
141+ public int Count
142+ {
143+ get
144+ {
145+ return RetryAction < int > ( ( redis ) =>
146+ {
147+ return GetCollection ( redis ) . Count ;
148+ } ) ;
149+ }
150+ }
151+
152+ public IEnumerable < TValue > Where ( Func < TValue , bool > predicate )
153+ {
154+ return RetryAction ( ( redis ) =>
155+ {
156+ return GetCollection ( redis ) . Values . Where ( predicate ) ;
157+ } ) ;
158+ }
159+
160+ public bool Any ( Func < TValue , bool > predicate )
161+ {
162+ return RetryAction < bool > ( ( redis ) =>
163+ {
164+ return GetCollection ( redis ) . Values . Any ( predicate ) ;
165+ } ) ;
166+ }
167+
168+
169+ public IEnumerator < TValue > GetEnumerator ( )
170+ {
171+ return RetryAction < IEnumerator < TValue > > ( ( redis ) =>
172+ {
173+ return GetCollection ( redis ) . Values . GetEnumerator ( ) ;
174+ } ) ;
175+ }
176+
177+ System . Collections . IEnumerator System . Collections . IEnumerable . GetEnumerator ( )
178+ {
179+ return RetryAction ( redis =>
180+ {
181+ return ( ( System . Collections . IEnumerable ) GetCollection ( redis ) . Values ) . GetEnumerator ( ) ;
182+ } ) ;
183+
184+ }
185+
186+ public void Clear ( )
187+ {
188+ RetryAction ( ( redis ) =>
189+ {
190+ GetCollection ( redis ) . Clear ( ) ;
191+ } ) ;
192+ }
193+
194+ public bool Contains ( TValue obj )
195+ {
196+ TKey Id = GetUniqueIdAction ( obj ) ;
197+ return RetryAction < bool > ( ( redis ) =>
198+ {
199+ return GetCollection ( redis ) . ContainsKey ( Id ) ;
200+ } ) ;
201+ }
202+
203+ public bool ContainsKey ( TKey obj )
204+ {
205+ return RetryAction < bool > ( ( redis ) =>
206+ {
207+ return GetCollection ( redis ) . ContainsKey ( obj ) ;
208+ } ) ;
209+ }
210+
211+ public void CopyTo ( TValue [ ] array , int arrayIndex )
212+ {
213+ RetryAction ( ( redis ) =>
214+ {
215+ GetCollection ( redis ) . Values . CopyTo ( array , arrayIndex ) ;
216+ } ) ;
217+ }
218+
219+ public bool IsReadOnly
220+ {
221+ get
222+ {
223+ return RetryAction < bool > ( ( redis ) =>
224+ {
225+ return GetCollection ( redis ) . IsReadOnly ;
226+ } ) ;
227+ }
228+ }
229+
230+ public Func < TValue , TKey > GetUniqueIdAction
231+ {
232+ get
233+ {
234+ return idAction ;
235+ }
236+ set
237+ {
238+ idAction = value ;
239+ }
240+ }
241+
242+ private void RetryAction ( Action < IRedisClient > action )
243+ {
244+ int i = 0 ;
245+ while ( true )
246+ {
247+ try
248+ {
249+ using ( var redis = RedisConnection )
250+ {
251+ action ( redis ) ;
252+ return ;
253+ }
254+ }
255+ catch ( Exception ex )
256+ {
257+ Console . WriteLine ( ex ) ;
258+ throw ;
259+
260+ //if (i++ < 3)
261+ //{
262+ // continue;
263+ //}
264+ //throw;
265+ }
266+ }
267+ }
268+
269+ private TOut RetryAction < TOut > ( Func < IRedisClient , TOut > action )
270+ {
271+ int i = 0 ;
272+
273+ while ( true )
274+ {
275+ try
276+ {
277+ using ( var redis = RedisConnection )
278+ {
279+ TOut result = action ( redis ) ;
280+ return result ;
281+ }
282+ }
283+ catch ( Exception ex )
284+ {
285+
286+ if ( i ++ < 3 )
287+ {
288+
289+ continue ;
290+ }
291+
292+ throw ;
293+ }
294+ }
295+ }
296+ }
297+ }
0 commit comments