@@ -21,15 +21,16 @@ use redis_module::{
21
21
use redismodule_cmd:: { Command , ArgType , Collection } ;
22
22
use std:: collections:: { HashMap , HashSet } ;
23
23
use std:: collections:: hash_map:: Entry ;
24
- use std:: sync:: { Arc , RwLock , RwLockWriteGuard } ;
24
+ use std:: sync:: { Arc , RwLock } ;
25
25
use types:: * ;
26
26
27
27
static PREFIX : & str = "hnsw" ;
28
28
29
+ type IndexArc = Arc < RwLock < IndexT > > ;
29
30
type IndexT = Index < f32 , f32 > ;
30
31
31
32
lazy_static ! {
32
- static ref INDICES : Arc <RwLock <HashMap <String , IndexT >>> =
33
+ static ref INDICES : Arc <RwLock <HashMap <String , IndexArc >>> =
33
34
Arc :: new( RwLock :: new( HashMap :: new( ) ) ) ;
34
35
}
35
36
@@ -118,20 +119,20 @@ fn new_index(ctx: &Context, args: Vec<String>) -> RedisResult {
118
119
}
119
120
None => {
120
121
// create index
121
- let mut index = Index :: new (
122
+ let index = Index :: new (
122
123
& index_name,
123
124
Box :: new ( hnsw:: metrics:: euclidean) ,
124
125
data_dim,
125
126
m,
126
127
ef_construction,
127
128
) ;
128
129
ctx. log_debug ( format ! ( "{:?}" , index) . as_str ( ) ) ;
129
- key. set_value :: < IndexRedis > ( & HNSW_INDEX_REDIS_TYPE , ( & mut index) . into ( ) ) ?;
130
+ key. set_value :: < IndexRedis > ( & HNSW_INDEX_REDIS_TYPE , ( & index) . into ( ) ) ?;
130
131
// Add index to global hashmap
131
132
INDICES
132
133
. write ( )
133
134
. unwrap ( )
134
- . insert ( index_name, index) ;
135
+ . insert ( index_name, Arc :: new ( RwLock :: new ( index) ) ) ;
135
136
}
136
137
}
137
138
@@ -148,14 +149,17 @@ fn get_index(ctx: &Context, args: Vec<String>) -> RedisResult {
148
149
let name_suffix = parsed. remove ( "name" ) . unwrap ( ) . as_string ( ) ?;
149
150
let index_name = format ! ( "{}.{}" , PREFIX , name_suffix) ;
150
151
151
- let mut indices = INDICES . write ( ) . unwrap ( ) ;
152
+ let index = load_index ( ctx, & index_name) ?;
153
+ let index = match index. try_read ( ) {
154
+ Ok ( index) => index,
155
+ Err ( e) => return Err ( e. to_string ( ) . into ( ) )
156
+ } ;
152
157
153
- let index = load_index ( ctx, & mut indices, & index_name) ?;
154
158
ctx. log_debug ( format ! ( "Index: {:?}" , index) . as_str ( ) ) ;
155
159
ctx. log_debug ( format ! ( "Layers: {:?}" , index. layers. len( ) ) . as_str ( ) ) ;
156
160
ctx. log_debug ( format ! ( "Nodes: {:?}" , index. nodes. len( ) ) . as_str ( ) ) ;
157
161
158
- let index_redis: IndexRedis = index. into ( ) ;
162
+ let index_redis: IndexRedis = ( & * index) . into ( ) ;
159
163
160
164
Ok ( index_redis. as_redisvalue ( ) )
161
165
}
@@ -193,7 +197,8 @@ fn delete_index(ctx: &Context, args: Vec<String>) -> RedisResult {
193
197
Ok ( 1_usize . into ( ) )
194
198
}
195
199
196
- fn load_index < ' a > ( ctx : & Context , indices : & ' a mut RwLockWriteGuard < HashMap < String , IndexT > > , index_name : & str ) -> Result < & ' a mut IndexT , RedisError > {
200
+ fn load_index ( ctx : & Context , index_name : & str ) -> Result < IndexArc , RedisError > {
201
+ let mut indices = INDICES . write ( ) . unwrap ( ) ;
197
202
// check if index is in global hashmap
198
203
let index = match indices. entry ( index_name. to_string ( ) ) {
199
204
Entry :: Occupied ( o) => o. into_mut ( ) ,
@@ -208,11 +213,11 @@ fn load_index<'a>(ctx: &Context, indices: &'a mut RwLockWriteGuard<HashMap<Strin
208
213
None => return Err ( format ! ( "Index: {} does not exist" , index_name) . into ( ) ) ,
209
214
} ;
210
215
let index = make_index ( ctx, index_redis) ?;
211
- v. insert ( index)
216
+ v. insert ( Arc :: new ( RwLock :: new ( index) ) )
212
217
}
213
218
} ;
214
219
215
- Ok ( index)
220
+ Ok ( index. clone ( ) )
216
221
}
217
222
218
223
fn make_index ( ctx : & Context , ir : & IndexRedis ) -> Result < IndexT , RedisError > {
@@ -284,13 +289,13 @@ fn make_index(ctx: &Context, ir: &IndexRedis) -> Result<IndexT, RedisError> {
284
289
fn update_index (
285
290
ctx : & Context ,
286
291
index_name : & str ,
287
- index : & mut IndexT ,
292
+ index : & IndexT ,
288
293
) -> Result < ( ) , RedisError > {
289
294
let key = ctx. open_key_writable ( index_name) ;
290
295
match key. get_value :: < IndexRedis > ( & HNSW_INDEX_REDIS_TYPE ) ? {
291
296
Some ( _) => {
292
297
ctx. log_debug ( format ! ( "update index: {}" , index_name) . as_str ( ) ) ;
293
- key. set_value :: < IndexRedis > ( & HNSW_INDEX_REDIS_TYPE , index. into ( ) ) ?;
298
+ key. set_value :: < IndexRedis > ( & HNSW_INDEX_REDIS_TYPE , ( & * index) . into ( ) ) ?;
294
299
}
295
300
None => {
296
301
return Err ( RedisError :: String ( format ! (
@@ -318,8 +323,11 @@ fn add_node(ctx: &Context, args: Vec<String>) -> RedisResult {
318
323
let dataf64 = parsed. remove ( "data" ) . unwrap ( ) . as_f64vec ( ) ?;
319
324
let data = dataf64. iter ( ) . map ( |d| * d as f32 ) . collect :: < Vec < f32 > > ( ) ;
320
325
321
- let mut indices = INDICES . write ( ) . unwrap ( ) ;
322
- let index = load_index ( ctx, & mut indices, & index_name) ?;
326
+ let index = load_index ( ctx, & index_name) ?;
327
+ let mut index = match index. try_write ( ) {
328
+ Ok ( index) => index,
329
+ Err ( e) => return Err ( e. to_string ( ) . into ( ) )
330
+ } ;
323
331
324
332
let up = |name : String , node : Node < f32 > | {
325
333
write_node ( ctx, & name, ( & node) . into ( ) ) . unwrap ( ) ;
@@ -335,7 +343,7 @@ fn add_node(ctx: &Context, args: Vec<String>) -> RedisResult {
335
343
write_node ( ctx, & node_name, node. into ( ) ) ?;
336
344
337
345
// update index in redis
338
- update_index ( ctx, & index_name, index) ?;
346
+ update_index ( ctx, & index_name, & index) ?;
339
347
340
348
Ok ( "OK" . into ( ) )
341
349
}
@@ -350,12 +358,15 @@ fn delete_node(ctx: &Context, args: Vec<String>) -> RedisResult {
350
358
let index_suffix = parsed. remove ( "index" ) . unwrap ( ) . as_string ( ) ?;
351
359
let node_suffix = parsed. remove ( "node" ) . unwrap ( ) . as_string ( ) ?;
352
360
353
- let mut indices = INDICES . write ( ) . unwrap ( ) ;
354
361
let index_name = format ! ( "{}.{}" , PREFIX , index_suffix) ;
355
- let index = load_index ( ctx, & mut indices, & index_name) ?;
356
-
357
362
let node_name = format ! ( "{}.{}.{}" , PREFIX , index_suffix, node_suffix) ;
358
363
364
+ let index = load_index ( ctx, & index_name) ?;
365
+ let mut index = match index. try_write ( ) {
366
+ Ok ( index) => index,
367
+ Err ( e) => return Err ( e. to_string ( ) . into ( ) )
368
+ } ;
369
+
359
370
// TODO return error if node has more than 1 strong_count
360
371
let node = index. nodes . get ( & node_name) . unwrap ( ) ;
361
372
if Arc :: strong_count ( & node. 0 ) > 1 {
@@ -387,7 +398,7 @@ fn delete_node(ctx: &Context, args: Vec<String>) -> RedisResult {
387
398
} ;
388
399
389
400
// update index in redis
390
- update_index ( ctx, & index_name, index) ?;
401
+ update_index ( ctx, & index_name, & index) ?;
391
402
392
403
Ok ( 1_usize . into ( ) )
393
404
}
@@ -449,9 +460,12 @@ fn search_knn(ctx: &Context, args: Vec<String>) -> RedisResult {
449
460
let dataf64 = parsed. remove ( "query" ) . unwrap ( ) . as_f64vec ( ) ?;
450
461
let data = dataf64. iter ( ) . map ( |d| * d as f32 ) . collect :: < Vec < f32 > > ( ) ;
451
462
452
- let mut indices = INDICES . write ( ) . unwrap ( ) ;
453
463
let index_name = format ! ( "{}.{}" , PREFIX , index_suffix) ;
454
- let index = load_index ( ctx, & mut indices, & index_name) ?;
464
+ let index = load_index ( ctx, & index_name) ?;
465
+ let index = match index. try_read ( ) {
466
+ Ok ( index) => index,
467
+ Err ( e) => return Err ( e. to_string ( ) . into ( ) )
468
+ } ;
455
469
456
470
ctx. log_debug (
457
471
format ! (
0 commit comments