@@ -21,14 +21,19 @@ unsigned long int datatype_defragged = 0;
2121unsigned long int datatype_raw_defragged = 0 ;
2222unsigned long int datatype_resumes = 0 ;
2323unsigned long int datatype_wrong_cursor = 0 ;
24- unsigned long int global_attempts = 0 ;
24+ unsigned long int global_strings_attempts = 0 ;
25+ unsigned long int global_dicts_attempts = 0 ;
2526unsigned long int defrag_started = 0 ;
2627unsigned long int defrag_ended = 0 ;
27- unsigned long int global_defragged = 0 ;
28+ unsigned long int global_strings_defragged = 0 ;
29+ unsigned long int global_dicts_defragged = 0 ;
2830
2931unsigned long global_strings_len = 0 ;
3032RedisModuleString * * global_strings = NULL ;
3133
34+ unsigned long global_dicts_len = 0 ;
35+ RedisModuleDict * * global_dicts = NULL ;
36+
3237static void createGlobalStrings (RedisModuleCtx * ctx , unsigned long count )
3338{
3439 global_strings_len = count ;
@@ -47,20 +52,83 @@ static int defragGlobalStrings(RedisModuleDefragCtx *ctx)
4752 RedisModule_Assert (cursor < global_strings_len );
4853 for (; cursor < global_strings_len ; cursor ++ ) {
4954 RedisModuleString * new = RedisModule_DefragRedisModuleString (ctx , global_strings [cursor ]);
50- global_attempts ++ ;
55+ global_strings_attempts ++ ;
5156 if (new != NULL ) {
5257 global_strings [cursor ] = new ;
53- global_defragged ++ ;
58+ global_strings_defragged ++ ;
5459 }
5560
56- if (cursor % 16 == 0 && RedisModule_DefragShouldStop (ctx )) {
61+ if (RedisModule_DefragShouldStop (ctx )) {
5762 RedisModule_DefragCursorSet (ctx , cursor );
5863 return 1 ;
5964 }
6065 }
6166 return 0 ;
6267}
6368
69+ static void createGlobalDicts (RedisModuleCtx * ctx , unsigned long count ) {
70+ global_dicts_len = count ;
71+ global_dicts = RedisModule_Alloc (sizeof (RedisModuleDict * ) * count );
72+
73+ for (unsigned long i = 0 ; i < count ; i ++ ) {
74+ RedisModuleDict * dict = RedisModule_CreateDict (ctx );
75+ for (unsigned long j = 0 ; j < 100 ; j ++ ) {
76+ RedisModuleString * str = RedisModule_CreateStringFromULongLong (ctx , j );
77+ RedisModule_DictSet (dict , str , str );
78+ }
79+ global_dicts [i ] = dict ;
80+ }
81+ }
82+
83+ static void * defragGlobalDictValueCB (void * data , unsigned char * key , size_t keylen ) {
84+ REDISMODULE_NOT_USED (key );
85+ REDISMODULE_NOT_USED (keylen );
86+ return RedisModule_DefragRedisModuleString (NULL , data );
87+ }
88+
89+ static int defragGlobalDicts (RedisModuleDefragCtx * ctx ) {
90+ static RedisModuleString * seekTo = NULL ;
91+ unsigned long cursor = 0 ;
92+
93+ RedisModule_DefragCursorGet (ctx , & cursor );
94+ RedisModule_Assert (cursor < global_dicts_len );
95+ for (; cursor < global_strings_len ; cursor ++ ) {
96+ RedisModuleString * nextSeekTo = NULL ;
97+ RedisModuleDict * new = RedisModule_DefragRedisModuleDict (ctx , global_dicts [cursor ], defragGlobalDictValueCB , seekTo , & nextSeekTo );
98+ global_dicts_attempts ++ ;
99+ if (new != NULL ) {
100+ global_dicts [cursor ] = new ;
101+ global_dicts_defragged ++ ;
102+ }
103+
104+ if (seekTo ) RedisModule_FreeString (NULL , seekTo );
105+ seekTo = nextSeekTo ;
106+ if (nextSeekTo != NULL ) {
107+ RedisModule_DefragCursorSet (ctx , cursor );
108+ return 1 ;
109+ }
110+ }
111+ return 0 ;
112+ }
113+
114+ typedef enum { DEFRAG_NOT_START , DEFRAG_STRING , DEFRAG_DICT } defrag_module_stage ;
115+ static int defragGlobal (RedisModuleDefragCtx * ctx ) {
116+ static defrag_module_stage stage = DEFRAG_NOT_START ;
117+ if (stage == DEFRAG_NOT_START ) {
118+ stage = DEFRAG_STRING ; /* Start a new global defrag. */
119+ }
120+
121+ if (stage == DEFRAG_STRING ) {
122+ if (defragGlobalStrings (ctx ) != 0 ) return 1 ;
123+ stage = DEFRAG_DICT ;
124+ }
125+ if (stage == DEFRAG_DICT ) {
126+ if (defragGlobalDicts (ctx ) != 0 ) return 1 ;
127+ stage = DEFRAG_NOT_START ;
128+ }
129+ return 0 ;
130+ }
131+
64132static void defragStart (RedisModuleDefragCtx * ctx ) {
65133 REDISMODULE_NOT_USED (ctx );
66134 defrag_started ++ ;
@@ -80,8 +148,10 @@ static void FragInfo(RedisModuleInfoCtx *ctx, int for_crash_report) {
80148 RedisModule_InfoAddFieldLongLong (ctx , "datatype_raw_defragged" , datatype_raw_defragged );
81149 RedisModule_InfoAddFieldLongLong (ctx , "datatype_resumes" , datatype_resumes );
82150 RedisModule_InfoAddFieldLongLong (ctx , "datatype_wrong_cursor" , datatype_wrong_cursor );
83- RedisModule_InfoAddFieldLongLong (ctx , "global_attempts" , global_attempts );
84- RedisModule_InfoAddFieldLongLong (ctx , "global_defragged" , global_defragged );
151+ RedisModule_InfoAddFieldLongLong (ctx , "global_strings_attempts" , global_strings_attempts );
152+ RedisModule_InfoAddFieldLongLong (ctx , "global_strings_defragged" , global_strings_defragged );
153+ RedisModule_InfoAddFieldLongLong (ctx , "global_dicts_attempts" , global_dicts_attempts );
154+ RedisModule_InfoAddFieldLongLong (ctx , "global_dicts_defragged" , global_dicts_defragged );
85155 RedisModule_InfoAddFieldLongLong (ctx , "defrag_started" , defrag_started );
86156 RedisModule_InfoAddFieldLongLong (ctx , "defrag_ended" , defrag_ended );
87157}
@@ -109,8 +179,10 @@ static int fragResetStatsCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
109179 datatype_raw_defragged = 0 ;
110180 datatype_resumes = 0 ;
111181 datatype_wrong_cursor = 0 ;
112- global_attempts = 0 ;
113- global_defragged = 0 ;
182+ global_strings_attempts = 0 ;
183+ global_strings_defragged = 0 ;
184+ global_dicts_attempts = 0 ;
185+ global_dicts_defragged = 0 ;
114186 defrag_started = 0 ;
115187 defrag_ended = 0 ;
116188
@@ -248,6 +320,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
248320 }
249321
250322 createGlobalStrings (ctx , glen );
323+ createGlobalDicts (ctx , glen );
251324
252325 RedisModuleTypeMethods tm = {
253326 .version = REDISMODULE_TYPE_METHOD_VERSION ,
@@ -268,7 +341,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
268341 return REDISMODULE_ERR ;
269342
270343 RedisModule_RegisterInfoFunc (ctx , FragInfo );
271- RedisModule_RegisterDefragFunc (ctx , defragGlobalStrings );
344+ RedisModule_RegisterDefragFunc (ctx , defragGlobal );
272345 RedisModule_RegisterDefragCallbacks (ctx , defragStart , defragEnd );
273346
274347 return REDISMODULE_OK ;
0 commit comments