@@ -13,6 +13,9 @@ struct RdbxToJson;
13
13
typedef enum
14
14
{
15
15
R2J_IDLE = 0 ,
16
+ R2J_AUX_FIELDS ,
17
+ R2J_FUNCTIONS ,
18
+
16
19
R2J_IN_DB ,
17
20
R2J_IN_KEY ,
18
21
@@ -53,6 +56,8 @@ struct RdbxToJson {
53
56
unsigned int count_db ;
54
57
};
55
58
59
+ const char * jsonMetaPrefix = "__" ; /* Distinct meta from data with prefix string. */
60
+
56
61
static void outputPlainEscaping (RdbxToJson * ctx , char * p , size_t len ) {
57
62
while (len -- ) {
58
63
switch (* p ) {
@@ -121,6 +126,7 @@ static RdbxToJson *initRdbToJsonCtx(RdbParser *p, const char *outfilename, RdbxT
121
126
ctx -> conf .includeAuxField = 0 ;
122
127
ctx -> conf .includeFunc = 0 ;
123
128
ctx -> conf .includeStreamMeta = 0 ;
129
+ ctx -> conf .includeDbInfo = 0 ;
124
130
125
131
/* override configuration if provided */
126
132
if (conf ) ctx -> conf = * conf ;
@@ -136,15 +142,63 @@ static RdbxToJson *initRdbToJsonCtx(RdbParser *p, const char *outfilename, RdbxT
136
142
137
143
/*** Handling common ***/
138
144
145
+ static RdbRes toJsonDbSize (RdbParser * p , void * userData , uint64_t db_size , uint64_t exp_size ) {
146
+ RdbxToJson * ctx = userData ;
147
+ UNUSED (p );
148
+
149
+ if (ctx -> state != R2J_IN_DB ) {
150
+ RDB_reportError (p , (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ,
151
+ "toJsonDbSize(): Invalid state value: %d" , ctx -> state );
152
+ return (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ;
153
+ }
154
+
155
+ /* output json part */
156
+ fprintf (ctx -> outfile , " \"%sdbSize\": {\n" , jsonMetaPrefix );
157
+ fprintf (ctx -> outfile , " \"size\": %lu,\n" , db_size );
158
+ fprintf (ctx -> outfile , " \"expires\": %lu\n" , exp_size );
159
+ fprintf (ctx -> outfile , " }%s\n" , (db_size ) ? "," : "" );
160
+
161
+ return RDB_OK ;
162
+ }
163
+
164
+ static RdbRes toJsonSlotInfo (RdbParser * p , void * userData , RdbSlotInfo * info ) {
165
+ RdbxToJson * ctx = userData ;
166
+ UNUSED (p , info );
167
+
168
+ if (ctx -> state != R2J_IN_DB ) {
169
+ RDB_reportError (p , (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ,
170
+ "toJsonSlotInfo(): Invalid state value: %d" , ctx -> state );
171
+ return (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ;
172
+ }
173
+
174
+ /* output json part */
175
+ fprintf (ctx -> outfile , " \"%sSlotInfo\": {\n" , jsonMetaPrefix );
176
+ fprintf (ctx -> outfile , " \"slotId\": %lu,\n" , info -> slot_id );
177
+ fprintf (ctx -> outfile , " \"slotSize\": %lu,\n" , info -> slot_size );
178
+ fprintf (ctx -> outfile , " \"slotSExpiresSize\": %lu\n" , info -> expires_slot_size );
179
+ fprintf (ctx -> outfile , " },\n" );
180
+ return RDB_OK ;
181
+ }
182
+
139
183
static RdbRes toJsonAuxField (RdbParser * p , void * userData , RdbBulk auxkey , RdbBulk auxval ) {
140
184
RdbxToJson * ctx = userData ;
141
185
UNUSED (p );
142
186
187
+ if (ctx -> state == R2J_IDLE ) {
188
+ ctx -> state = R2J_AUX_FIELDS ;
189
+ fprintf (ctx -> outfile , "{\n " ); /* group aux-fields with { ... } */
190
+ } else if (ctx -> state == R2J_AUX_FIELDS ) {
191
+ fprintf (ctx -> outfile , ",\n " );
192
+ } else {
193
+ RDB_reportError (p , (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ,
194
+ "toJsonAuxField(): Invalid state value: %d" , ctx -> state );
195
+ return (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ;
196
+ }
197
+
143
198
/* output json part */
144
199
outputQuotedEscaping (ctx , auxkey , RDB_bulkLen (p , auxkey ));
145
200
fprintf (ctx -> outfile , ":" );
146
201
outputQuotedEscaping (ctx , auxval , RDB_bulkLen (p , auxval ));
147
- fprintf (ctx -> outfile , ",\n" );
148
202
149
203
return RDB_OK ;
150
204
}
@@ -227,13 +281,17 @@ static RdbRes toJsonNewDb(RdbParser *p, void *userData, int db) {
227
281
RdbxToJson * ctx = userData ;
228
282
229
283
if (ctx -> state == R2J_IDLE ) {
284
+ /* old RDBs might not have aux-fields */
285
+ if (!ctx -> conf .flatten ) fprintf (ctx -> outfile , "{\n" );
286
+ } else if (ctx -> state == R2J_AUX_FIELDS || ctx -> state == R2J_FUNCTIONS ) {
287
+ fprintf (ctx -> outfile , "\n},\n" );
230
288
if (!ctx -> conf .flatten ) fprintf (ctx -> outfile , "{\n" );
231
289
} else if (ctx -> state == R2J_IN_DB ) {
232
290
/* output json part */
233
- if (!ctx -> conf .flatten ) {
234
- fprintf (ctx -> outfile , "\n},{\n" );
235
- } else {
291
+ if (ctx -> conf .flatten ) {
236
292
fprintf (ctx -> outfile , ",\n" );
293
+ } else {
294
+ fprintf (ctx -> outfile , "\n},{\n" );
237
295
}
238
296
} else {
239
297
RDB_reportError (p , (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ,
@@ -266,8 +324,10 @@ static RdbRes toJsonNewRdb(RdbParser *p, void *userData, int rdbVersion) {
266
324
static RdbRes toJsonEndRdb (RdbParser * p , void * userData ) {
267
325
RdbxToJson * ctx = userData ;
268
326
269
- if (ctx -> state == R2J_IDLE ) {
327
+ if (( ctx -> state == R2J_IDLE ) ) {
270
328
RDB_log (p , RDB_LOG_WRN , "RDB is empty." );
329
+ } else if (ctx -> state == R2J_AUX_FIELDS || ctx -> state == R2J_FUNCTIONS ) {
330
+ fprintf (ctx -> outfile , "\n},\n" );
271
331
} else if (ctx -> state == R2J_IN_DB ) {
272
332
if (!ctx -> conf .flatten ) fprintf (ctx -> outfile , "\n}" );
273
333
} else {
@@ -433,10 +493,24 @@ static RdbRes toJsonHash(RdbParser *p, void *userData, RdbBulk field, RdbBulk va
433
493
434
494
static RdbRes toJsonFunction (RdbParser * p , void * userData , RdbBulk func ) {
435
495
RdbxToJson * ctx = userData ;
496
+
497
+ if (ctx -> state == R2J_IDLE ) {
498
+ ctx -> state = R2J_FUNCTIONS ;
499
+ } else if (ctx -> state == R2J_AUX_FIELDS ) {
500
+ fprintf (ctx -> outfile , "\n},{\n" );
501
+ ctx -> state = R2J_FUNCTIONS ;
502
+ } else if (ctx -> state == R2J_FUNCTIONS ) {
503
+ fprintf (ctx -> outfile , ",\n" );
504
+ } else {
505
+ RDB_reportError (p , (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ,
506
+ "toJsonFunction(): Invalid state value: %d" , ctx -> state );
507
+ return (RdbRes ) RDBX_ERR_R2J_INVALID_STATE ;
508
+ }
509
+
436
510
/* output json part */
437
- fprintf (ctx -> outfile , " \"Function_% d\":" , ++ ctx -> count_functions );
511
+ fprintf (ctx -> outfile , " \"%sFunction_% d\":" , jsonMetaPrefix , ++ ctx -> count_functions );
438
512
outputQuotedEscaping ( (RdbxToJson * ) userData , func , RDB_bulkLen (p , func ));
439
- fprintf ( ctx -> outfile , ",\n" ) ;
513
+ ctx -> count_functions ++ ;
440
514
return RDB_OK ;
441
515
}
442
516
@@ -639,9 +713,9 @@ RdbxToJson *RDBX_createHandlersToJson(RdbParser *p, const char *filename, RdbxTo
639
713
toJsonNewRdb ,
640
714
toJsonEndRdb ,
641
715
toJsonNewDb ,
642
- NULL , /* handleResizeDb */
643
- NULL ,
644
- NULL ,
716
+ NULL , /*handleDbSize */
717
+ NULL , /*handleSlotInfo*/
718
+ NULL , /*handleAuxField*/
645
719
toJsonNewKey ,
646
720
toJsonEndKey ,
647
721
toJsonString ,
@@ -673,16 +747,21 @@ RdbxToJson *RDBX_createHandlersToJson(RdbParser *p, const char *filename, RdbxTo
673
747
dataCb .handleStreamConsumerPendingEntry = toJsonStreamConsumerPendingEntry ;
674
748
}
675
749
750
+ if (ctx -> conf .includeDbInfo ) {
751
+ dataCb .handleDbSize = toJsonDbSize ;
752
+ dataCb .handleSlotInfo = toJsonSlotInfo ;
753
+ }
754
+
676
755
RDB_createHandlersData (p , & dataCb , ctx , deleteRdbToJsonCtx );
677
756
678
757
} else if (ctx -> conf .level == RDB_LEVEL_STRUCT ) {
679
758
RdbHandlersStructCallbacks structCb = {
680
759
toJsonNewRdb ,
681
760
toJsonEndRdb ,
682
761
toJsonNewDb ,
683
- NULL , /* handleResizeDb */
684
- NULL ,
685
- NULL ,
762
+ NULL , /*handleDbSize */
763
+ NULL , /*handleSlotInfo*/
764
+ NULL , /*handleAuxField*/
686
765
toJsonNewKey ,
687
766
toJsonEndKey ,
688
767
toJsonString ,
@@ -724,9 +803,9 @@ RdbxToJson *RDBX_createHandlersToJson(RdbParser *p, const char *filename, RdbxTo
724
803
toJsonNewRdb ,
725
804
toJsonEndRdb ,
726
805
toJsonNewDb ,
727
- NULL , /* handleResizeDb */
728
- NULL ,
729
- NULL ,
806
+ NULL , /*handleDbSize */
807
+ NULL , /*handleSlotInfo*/
808
+ NULL , /*handleAuxField*/
730
809
toJsonNewKey ,
731
810
toJsonEndKey ,
732
811
NULL , /*handleBeginModuleAux*/
0 commit comments