-
Notifications
You must be signed in to change notification settings - Fork 8
/
librdb-api.h
643 lines (561 loc) · 29.1 KB
/
librdb-api.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
#ifndef LIBRDB_API_H
#define LIBRDB_API_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _LIBRDB_API
#define _LIBRDB_API __attribute__((visibility("default")))
#endif
typedef char *RdbBulk;
typedef char *RdbBulkCopy;
/****************************************************************
* Incomplete structures for compiler checks but opaque access
****************************************************************/
typedef struct RdbReader RdbReader;
typedef struct RdbParser RdbParser;
typedef struct RdbHandlers RdbHandlers;
typedef struct RdbMemAlloc RdbMemAlloc;
/****************************************************************
* Enums & Typedefs
****************************************************************/
typedef enum RdbRes {
RDB_OK=0,
/* RDB_OK_DONT_PROPAGATE - allowed to be returned only by handlers
* callbacks to prevent propagation of the data to the next
* Handlers in-line (of the same callback type). It can be useful to
* implement sets of Handlers as Filters. As reference, see
* implementation RDBX_createHandlersFilterKey */
RDB_OK_DONT_PROPAGATE,
/* Handlers callbacks can indicate to cancel parsing immediately */
RDB_ERR_CANCEL_PARSING,
/*** error codes - reported by parser's blocks ***/
RDB_ERR_GENERAL,
RDB_ERR_FAIL_ALLOC,
RDB_ERR_FAILED_OPEN_FILE,
RDB_ERR_INVALID_CONFIGURATION,
RDB_ERR_FAILED_CREATE_PARSER,
RDB_ERR_FAILED_OPEN_LOG_FILE,
RDB_ERR_FAILED_GET_FD_FLAGS,
RDB_ERR_NONBLOCKING_FD,
RDB_ERR_NONBLOCKING_READ_FD,
RDB_ERR_FAILED_READ_RDB_FILE,
RDB_ERR_FAILED_OPEN_RDB_FILE,
RDB_ERR_WRONG_FILE_SIGNATURE,
RDB_ERR_UNSUPPORTED_RDB_VERSION,
RDB_ERR_FAILED_PARTIAL_READ_RDB_FILE,
RDB_ERR_PARSER_RETURNED_INVALID_LIBRDB_STATUS,
RDB_ERR_INVALID_LEN_ENCODING,
RDB_ERR_INVALID_INT_ENCODING,
RDB_ERR_STRING_INVALID_LZF_COMPRESSED,
RDB_ERR_STRING_UNKNOWN_ENCODING_TYPE,
RDB_ERR_NOT_SUPPORTED_RDB_ENCODING_TYPE,
RDB_ERR_PRERELEASE_FUNC_FORMAT_NOT_SUPPORTED,
RDB_ERR_UNKNOWN_RDB_ENCODING_TYPE,
RDB_ERR_QUICK_LIST_INTEG_CHECK,
RDB_ERR_LIST_ZL_INTEG_CHECK,
RDB_ERR_SET_IS_INTEG_CHECK,
RDB_ERR_SET_LP_INTEG_CHECK,
RDB_ERR_ZSET_ZL_INTEG_CHECK,
RDB_ERR_ZSET_LP_INTEG_CHECK,
RDB_ERR_HASH_LP_INTEG_CHECK,
RDB_ERR_HASH_ZM_INTEG_CHECK,
RDB_ERR_STREAM_LP_INTEG_CHECK,
RDB_ERR_SSTYPE_INTEG_CHECK,
RDB_ERR_STRING_INVALID_STATE,
RDB_ERR_PLAIN_HASH_INVALID_STATE,
RDB_ERR_PLAIN_LIST_INVALID_STATE,
RDB_ERR_PLAIN_SET_INVALID_STATE,
RDB_ERR_PLAIN_ZSET_INVALID_STATE,
RDB_ERR_QUICK_LIST_INVALID_STATE,
RDB_ERR_SSTYPE_INVALID_STATE,
RDB_ERR_MODULE_INVALID_STATE,
RDB_ERR_STREAM_INVALID_STATE,
RDB_ERR_INVALID_BULK_ALLOC_TYPE,
RDB_ERR_INVALID_BULK_CLONE_REQUEST,
RDB_ERR_INVALID_BULK_LENGTH_REQUEST,
RDB_ERR_BULK_ALLOC_INVALID_TYPE,
RDB_ERR_INVALID_IS_REF_BULK,
RDB_ERR_EXP_EOF_BUT_PARSER_WAIT_MORE_DATA,
RDB_ERR_EXP_WAIT_MORE_DATA_BUT_PARSER_EOF,
RDB_ERR_CHECKSUM_FAILURE,
RDB_ERR_PARSEBUF_AFTER_PAUSE_NOT_SAME_BUFF,
RDB_ERR_MAX_RAW_LEN_EXCEEDED_FOR_KEY,
RDB_ERR_EXCLUSIVE_RAW_HANDLERS,
RDB_ERR_MODULE_INVALID_WHEN_OPCODE,
/*** api-ext error codes (see file: rp-ext-api.h) ***/
_RDB_ERR_EXTENSION_FIRST = 0x1000,
/*** user-defined error codes - reported by user-defined handlers or reader ***/
_RDB_ERR_USER_DEFINED_FIRST = 0x2000,
} RdbRes;
typedef enum RdbState {
RDB_STATE_CONFIGURING=0,
RDB_STATE_RUNNING,
RDB_STATE_PAUSED,
RDB_STATE_ENDED,
RDB_STATE_ERROR,
} RdbState;
typedef enum RdbStatus {
RDB_STATUS_OK = 0,
RDB_STATUS_WAIT_MORE_DATA,
RDB_STATUS_PAUSED,
RDB_STATUS_ERROR
} RdbStatus;
typedef enum RdbHandlersLevel {
RDB_LEVEL_RAW=0, /* A set of handlers that get raw data */
RDB_LEVEL_STRUCT, /* A set of handlers that get "low level" RDB data structures */
RDB_LEVEL_DATA, /* A set of handlers that get "high level" Redis data types */
RDB_LEVEL_MAX,
} RdbHandlersLevel;
typedef enum RdbLogLevel {
RDB_LOG_ERR,
RDB_LOG_WRN,
RDB_LOG_INF,
RDB_LOG_DBG
} RdbLogLevel;
/* for explanation, read "Memory management" section below */
typedef enum RdbBulkAllocType {
RDB_BULK_ALLOC_STACK,
RDB_BULK_ALLOC_HEAP,
RDB_BULK_ALLOC_EXTERN,
RDB_BULK_ALLOC_EXTERN_OPT,
RDB_BULK_ALLOC_MAX,
} RdbBulkAllocType;
typedef struct RdbKeyInfo {
long long expiretime; /* -1 if not set */
long long lruIdle; /* -1 if not set */
int lfuFreq; /* -1 if not set */
int opcode;
int dataType; /* See enum RdbDataType */
} RdbKeyInfo;
typedef struct RdbSlotInfo {
uint64_t slot_id;
uint64_t slot_size;
uint64_t expires_slot_size;
} RdbSlotInfo;
typedef struct RdbStreamID {
uint64_t ms; /* Unix time in milliseconds. */
uint64_t seq; /* sequence number */
} RdbStreamID;
typedef struct RdbStreamMeta {
uint64_t length; /* Current number of elements inside this stream. */
uint64_t entriesAdded; /* All time count of elements added. */
RdbStreamID firstID;
RdbStreamID lastID;
RdbStreamID maxDelEntryID; /* maximum deleted entry id */
} RdbStreamMeta;
typedef struct RdbStreamPendingEntry {
RdbStreamID id;
uint64_t deliveryTime;
uint64_t deliveryCount;
} RdbStreamPendingEntry;
typedef struct RdbStreamGroupMeta {
RdbStreamID lastId;
int64_t entriesRead;
} RdbStreamGroupMeta;
typedef struct RdbStreamConsumerMeta {
long long activeTime;
long long seenTime;
} RdbStreamConsumerMeta;
/* misc function pointer typedefs */
typedef RdbStatus (*RdbReaderFunc) (void *readerData, void *buf, size_t len);
typedef void (*RdbFreeFunc) (RdbParser *p, void *obj);
typedef void (*RdbLoggerCB) (RdbLogLevel l, const char *msg);
/****************************************************************
* Common Callbacks for Registration (handlers Level 0/1/2)
*
* Common Callbacks to all levels. If registered at different levels then all
* of them will be called, one by one, starting from handlers that are
* registered at the lowest level.
****************************************************************/
/* Definition of the common callback functions for handling various RDB parsing events */
#define HANDLERS_COMMON_CALLBACKS \
/* Callback once RDB header was parsed */ \
RdbRes (*handleStartRdb)(RdbParser *p, void *userData, int rdbVersion); \
/* Callback to indicate the completion of the parsing process for the dump file */ \
RdbRes (*handleEndRdb)(RdbParser *p, void *userData); \
/* Callback to indicate start parsing of database `dbnum` */ \
RdbRes (*handleNewDb)(RdbParser *p, void *userData, int dbnum); \
/* Callback per db before the keys, with the key count and the total voletaile key count */ \
RdbRes (*handleDbSize)(RdbParser *p, void *userData, uint64_t db_size, uint64_t exp_size); \
/* Callback per cluster slot with related info */ \
RdbRes (*handleSlotInfo)(RdbParser *p, void *userData, RdbSlotInfo *info); \
/* Callback in the beginning of the RDB with various keys and values. exists since redis 3.2 (RDB v7) */ \
RdbRes (*handleAuxField)(RdbParser *p, void *userData, RdbBulk auxkey, RdbBulk auxval); \
/* Callback on each new key along with additional info, such as, expire-time, LRU, etc. */ \
RdbRes (*handleNewKey)(RdbParser *p, void *userData, RdbBulk key, RdbKeyInfo *info); \
/* Callback on each completion of a key. Useful To finalize handled key. */ \
RdbRes (*handleEndKey)(RdbParser *p, void *userData);
/****************************************************************
* Rdb raw Callbacks for Registration (handlers Level 0)
*
* This level of callback registration is adequate mainly when it is required
* to RESTORE from RDB source and play it against live Redis server.
****************************************************************/
typedef struct RdbHandlersRawCallbacks {
HANDLERS_COMMON_CALLBACKS
/* Callback on start of serializing module aux data (alternative to handleBegin) */
RdbRes (*handleBeginModuleAux)(RdbParser *p, void *userData, RdbBulk name, int encver, int when, size_t size);
/* Callback on start of serializing value of a new key */
RdbRes (*handleBegin)(RdbParser *p, void *userData, size_t size);
/* Callback on one or more chunks of serialized value of a key */
RdbRes (*handleFrag)(RdbParser *p, void *userData, RdbBulk frag);
/* Callback on end of serializing value of a key */
RdbRes (*handleEnd)(RdbParser *p, void *userData);
} RdbHandlersRawCallbacks;
/****************************************************************
* Rdb data-structures Callbacks for Registration (handlers Level 1)
*
* This level of callback registration is adequate mainly when it is required to
* analyze memory consumption, or other reason for inspection of "low-level"
* data structures of RDB file.
****************************************************************/
typedef struct RdbHandlersStructCallbacks {
HANDLERS_COMMON_CALLBACKS
/* Callback to handle a string value of a key */
RdbRes (*handleString)(RdbParser *p, void *userData, RdbBulk str);
/* Callback to handle an item from a plain-list. Or plain node of RDB_TYPE_LIST_QUICKLIST_2 */
RdbRes (*handleListPlain)(RdbParser *p, void *userData, RdbBulk node);
/* Callback to handle a ziplist-based list value */
RdbRes (*handleListZL)(RdbParser *p, void *userData, RdbBulk ziplist);
/* Callback to handle a listpack-based list value */
RdbRes (*handleListLP)(RdbParser *p, void *userData, RdbBulk listpack);
/* Callback to handle a field-value pair within a plain-hash. expireAt -1 if not set. */
RdbRes (*handleHashPlain)(RdbParser *p, void *userData, RdbBulk field, RdbBulk value, int64_t expireAt);
/* Callback to handle a ziplist-based hash value */
RdbRes (*handleHashZL)(RdbParser *p, void *userData, RdbBulk ziplist);
/* Callback to handle a listpack-based hash value */
RdbRes (*handleHashLP)(RdbParser *p, void *userData, RdbBulk listpack);
/* Callback to handle a listpackex-based hash (with expiry on fields) */
RdbRes (*handleHashLPEx)(RdbParser *p, void *userData, RdbBulk listpackEx);
/* Callback to handle a zipmap-based hash value */
RdbRes (*handleHashZM)(RdbParser *p, void *userData, RdbBulk zipmap);
/* Callback to handle an item from a plain-set */
RdbRes (*handleSetPlain)(RdbParser *p, void *userData, RdbBulk item);
/* Callback to handle an intset-based set value */
RdbRes (*handleSetIS)(RdbParser *p, void *userData, RdbBulk intset);
/* Callback to handle a listpack-based set value */
RdbRes (*handleSetLP)(RdbParser *p, void *userData, RdbBulk listpack);
/* Callback to handle an item from a plain sorted set */
RdbRes (*handleZsetPlain)(RdbParser *p, void *userData, RdbBulk item, double score);
/* Callback to handle a ziplist-based sorted set value */
RdbRes (*handleZsetZL)(RdbParser *p, void *userData, RdbBulk ziplist);
/* Callback to handle a listpack-based sorted set value */
RdbRes (*handleZsetLP)(RdbParser *p, void *userData, RdbBulk listpack);
/* Callback to handle function code */
RdbRes (*handleFunction)(RdbParser *p, void *userData, RdbBulk func);
/* Callback to handle module. Currently only reports about the name & size. */
RdbRes (*handleModule)(RdbParser *p, void *userData, RdbBulk moduleName, size_t serializedSize);
/* Callback to handle a stream key with listpack value */
RdbRes (*handleStreamLP)(RdbParser *p, void *userData, RdbBulk nodekey, RdbBulk streamLP);
} RdbHandlersStructCallbacks;
/****************************************************************
* Redis Data Type Callbacks for Registration (handlers Level 2)
*
* This level of callback registration is adequate when the focus is solely on
* the logical data types within the database, such as to export the data to
* another framework or investigate the content of the data.
****************************************************************/
typedef struct RdbHandlersDataCallbacks {
HANDLERS_COMMON_CALLBACKS
/* Callback to handle the value of a string key */
RdbRes (*handleStringValue)(RdbParser *p, void *userData, RdbBulk str);
/* Callback to handle an item from a list */
RdbRes (*handleListItem)(RdbParser *p, void *userData, RdbBulk item);
/* Callback to handle a field-value pair within a hash */
RdbRes (*handleHashField)(RdbParser *p, void *userData, RdbBulk field, RdbBulk value, int64_t expireAt);
/* Callback to handle a member within a set */
RdbRes (*handleSetMember)(RdbParser *p, void *userData, RdbBulk member);
/* Callback to handle a member within a sorted set along with its score */
RdbRes (*handleZsetMember)(RdbParser *p, void *userData, RdbBulk member, double score);
/* Callback to handle function code */
RdbRes (*handleFunction)(RdbParser *p, void *userData, RdbBulk func);
/* Callback to handle module. Currently only reports about the name & size */
RdbRes (*handleModule)(RdbParser *p, void *userData, RdbBulk moduleName, size_t serializedSize);
/* Callback to handle metadata associated with a stream */
RdbRes (*handleStreamMetadata)(RdbParser *p, void *userData, RdbStreamMeta *meta);
/* Callback to handle an item within a stream along with its field and value */
RdbRes (*handleStreamItem)(RdbParser *p, void *userData, RdbStreamID *id, RdbBulk field, RdbBulk value, int64_t itemsLeft);
/* Callback to handle the creation of a new consumer group within a stream */
RdbRes (*handleStreamNewCGroup)(RdbParser *p, void *userData, RdbBulk grpName, RdbStreamGroupMeta *meta);
/* Callback to handle a pending entry within a consumer group */
RdbRes (*handleStreamCGroupPendingEntry)(RdbParser *p, void *userData, RdbStreamPendingEntry *pendingEntry);
/* Callback to handle the creation of a new consumer within a stream */
RdbRes (*handleStreamNewConsumer)(RdbParser *p, void *userData, RdbBulk consName, RdbStreamConsumerMeta *meta);
/* Callback to handle a pending entry within a consumer */
RdbRes (*handleStreamConsumerPendingEntry)(RdbParser *p, void *userData, RdbStreamID *streamId);
} RdbHandlersDataCallbacks;
/****************************************************************
* Parser creation and deletion
****************************************************************/
_LIBRDB_API RdbParser *RDB_createParserRdb(RdbMemAlloc *memAlloc);
_LIBRDB_API void RDB_deleteParser(RdbParser *p);
/****************************************************************
* Execute parser
****************************************************************/
_LIBRDB_API RdbStatus RDB_parse(RdbParser *p);
/* parse in mem buffers without a reader */
_LIBRDB_API RdbStatus RDB_parseBuff(RdbParser *p,
unsigned char *buff,
size_t size, int isEOF);
/****************************************************************
* Create Reader
*
* The built-in readers should be sufficient for most purposes. However, if they
* do not meet your specific needs, you can use the `RDB_createReaderRdb()`
* helper function to create a custom reader with its own reader function. The
* built-in reader file (readerFile.c) can serve as a code reference for this
* purpose.
*
* Used by: RDBX_createReaderFile
* <user-defined-reader>
*
* TODO: The parser only supports reading asynchrnously (non-blocking)
* through RDB_parseBuff() API. It is required to Extend parser for
* readers to support non-blocking mode as well. Currently the provided
* reader-function (RdbReaderFunc) can only:
* - Read the entire request and return RDB_STATUS_OK
* - Or, read none and return RDB_STATUS_WAIT_MORE_DATA
* - Or, return RDB_STATUS_ERROR
****************************************************************/
_LIBRDB_API RdbReader *RDB_createReaderRdb(RdbParser *p,
RdbReaderFunc r,
void *readerData,
RdbFreeFunc freeReaderData);
/****************************************************************
* Create Handlers
*
* Create set of handlers, at requested level (lvl), to be filled up with
* callback handlers.
*
* Used by: RDBX_createHandlersToJson
* RDBX_createHandlersFilterKey
* <user-defined-handlers>
****************************************************************/
_LIBRDB_API RdbHandlers *RDB_createHandlersRaw(RdbParser *p,
RdbHandlersRawCallbacks *callbacks,
void *userData,
RdbFreeFunc freeUserData);
_LIBRDB_API RdbHandlers *RDB_createHandlersStruct(RdbParser *p,
RdbHandlersStructCallbacks *callbacks,
void *userData,
RdbFreeFunc freeUserData);
_LIBRDB_API RdbHandlers *RDB_createHandlersData(RdbParser *p,
RdbHandlersDataCallbacks *callbacks,
void *userData,
RdbFreeFunc freeUserData);
/****************************************************************
* Handlers prevent data propagation
*
* When Handlers is being called by the parser, it can decide not to propagate
* the data to the next Handlers in-line. It can be useful to implement sets of
* Handlers as Filters. Use this function only from inside Handlers callbacks.
* As reference, see implementation of RDBX_createHandlersFilterKey
****************************************************************/
_LIBRDB_API void RDB_dontPropagate(RdbParser *p);
/****************************************************************
* Parser setters & getters
****************************************************************/
/* set deep integrity check */
_LIBRDB_API void RDB_setDeepIntegCheck(RdbParser *p, int deep);
/* get number of bytes processed so far */
_LIBRDB_API size_t RDB_getBytesProcessed(RdbParser *p);
/* get current state of the parser */
_LIBRDB_API RdbState RDB_getState(RdbParser *p);
/* get number of handlers registered at given level */
_LIBRDB_API int RDB_getNumHandlers(RdbParser *p, RdbHandlersLevel lvl);
/* To ignore on checksum error. Else parser return RDB_ERR_CHECKSUM_FAILURE */
_LIBRDB_API void RDB_IgnoreChecksum(RdbParser *p);
/* There could be relatively large strings stored within Redis, which are
* subsequently also present in the RDB. This is especially true for collections
* of strings. In situations like this, if the parser is configured to read
* raw data (using RDB_createHandlersRaw), it could potentially lead to memory
* problems in data path. By establishing a MaxRawSize threshold, the size of
* raw data can be restricted, and if this threshold is exceeded, the parser will
* terminate its operation. The default threshold is unlimited. */
_LIBRDB_API void RDB_setMaxRawSize(RdbParser *p, size_t maxSize);
/* logger */
_LIBRDB_API void RDB_setLogLevel(RdbParser *p, RdbLogLevel l);
_LIBRDB_API void RDB_setLogger(RdbParser *p, RdbLoggerCB f);
#ifdef __GNUC__
_LIBRDB_API void RDB_log(RdbParser *p, RdbLogLevel lvl, const char *format, ...)
__attribute__((format(printf, 3, 4)));
#else
_LIBRDB_API void RDB_log(RdbParser *p, RdbLogLevel lvl, const char *format, ...);
#endif
/* Following function returns a hint for the total number of items in the current
* parsed key context - to assist with memory allocation or other optimizations.
* If hint is not available, then return -1. */
_LIBRDB_API int64_t RDB_getNumItemsHint(RdbParser *p);
/****************************************************************
* Pause the Parser
*
* the parser can be configured with a pause interval that specifies the number
* of bytes to be processed before pausing. This means that each time the parser
* is invoked, it will continue parsing until it has processed a number of bytes
* equal to or greater than the configured interval, at which point it will
* automatically pause and return 'RDB_STATUS_PAUSED' in order to allow the
* application to perform other tasks. It is also possible to pause the parser
* by the callbacks by calling RDB_pauseParser()
****************************************************************/
_LIBRDB_API void RDB_setPauseInterval(RdbParser *p, size_t interval);
_LIBRDB_API void RDB_pauseParser(RdbParser *p);
/****************************************************************
* Error Handling
*
* If the parser, or attached built-in handlers or reader got failed, they will
* make an internal call to `RDB_reportError` to keep the error. The way to the
* app to retrieve the error is via `RDB_getErrorCode` and `RDB_getErrorMessage`.
*
* Likewise, if one of the app's callback handlers got failed, it should report
* the error to the parser by function `RDB_reportError` and also can provide
* description to the error. Either way, app's callbaack must return the error
* code. (See RdbRes enum for valid range of user-defined error-code to app to
* report).
****************************************************************/
_LIBRDB_API RdbRes RDB_getErrorCode(RdbParser *p);
_LIBRDB_API const char *RDB_getErrorMessage(RdbParser *p);
#ifdef __GNUC__
_LIBRDB_API void RDB_reportError(RdbParser *p, RdbRes e, const char *msg, ...)
__attribute__((format(printf, 3, 4)));
#else
_LIBRDB_API void RDB_reportError(RdbParser *p, RdbRes e, const char *msg, ...);
#endif
/****************************************************************
* Memory management
*
* User can configure his own set of malloc/free functions via structure
* RdbMemAlloc
*
* If library is used in a multi-threaded application, then functions must be
* thread safe. In that case, library is thread-safe as well.
*
* When functions are not set or set to NULL then, they are set to internal
* routines that use the standard library functions malloc() and free()
*
* Optimizing Bulk Allocation
*
* On callback, sometimes the client application need to receive the processed
* payload wrapped in specific structure, such as, with additional header. To
* save the extra copy, the app can provide the parser its own allocator only
* for RdbBulk (and specify that bulkAllocType is of type RDB_BULK_ALLOC_EXTERN).
* In that case the parser will allocate with provided allocation function and
* copy the plain payload along with '\0' termination (without any headers or
* trailers). Note that actual allocation sometimes might be larger than than
* RDB_bulkLen + 1 (Plus one for the termination character).
*
* On the other hand, if the parser heap allocation is sufficient, and the
* client application doesn't care about the wrapping structure of RdbBulk,
* then set bulkAllocType to RDB_BULK_ALLOC_HEAP. Note that `RDB_bulkClone` in
* that case will only increment refcount.
*
* If the client app not going to use too much `RDB_bulkClone` (cloning bulks.
* See below.) then it is better to set RDB_BULK_ALLOC_STACK, such that, when
* possible allocation quickly be made on internal stack.
*
* As mentioned above, RDB_BULK_ALLOC_EXTERN can help to avoid redundant copies
* of bulks. Yet, there are some cases that the parser can avoid bulk allocation
* of any type because the data is already available in memory, either because
* data prefetched, preceding in-memory decompress chunk of data, etc. If the
* application wants to optimize those cases as well along with external
* allocator, it can configure bulkAllocType to RDB_BULK_ALLOC_EXTERN_OPT. But
* then not all the given RdbBulk to callbacks will be allocated by provided
* allocation function and the app's callback cannot make any assumption about
* RdbBulk allocation. To decide in this case if given RdbBulk is actually
* allocated by configured external allocator or only reference another section
* of memory, the callback will need to assist function `RDB_isRefBulk`.
****************************************************************/
struct RdbMemAlloc {
void *(*malloc)(size_t size);
void *(*realloc)(void *ptr, size_t size);
void (*free)(void *ptr);
RdbBulkAllocType bulkAllocType;
/* appBulk is relevant only if bulkAllocType equals RDB_BULK_ALLOC_EXTERN or
* RDB_BULK_ALLOC_EXTERN_OPT */
struct {
void *(*alloc)(size_t size);
void *(*clone)(void *ptr, size_t size); /* prefer refcount than actual copy */
void (*free)(void *ptr);
} appBulk;
};
/* Memory allocation functions to be used by Reader & Handlers extensions */
void *RDB_alloc(RdbParser *p, size_t size);
void *RDB_realloc(RdbParser *p, void *ptr, size_t size);
void RDB_free(RdbParser *p, void *ptr);
/****************************************************************
* RdbBulk - native c-string alike
*
* The purpose of RdbBulk is to give native c-string feeling, yet hiding whether
* it actually allocated behind on stack, heap, reference another memory, or
* externally allocated by user supplied RdbBulk allocation function.
*
* You can print RdbBulk with printf() as there is an implicit \0 at the
* end of the string. However the string is binary safe and can contain
* \0 characters in the middle. The length is stored out of bound and can be
* queried by function RDB_bulkLen() only from the handlers callbacks.
*
* In order to process the string behind the current call-stack, function
* `RDB_bulkClone()` is the way to clone a string, within callback context only!
* If bulk allocated on stack (default of bulkAllocType) or reference another
* memory, then the function will malloc memory on heap and return a copy to the
* user. If allocated on heap, then just a refcount will be incremented.
*
* IF configured external allocator, then corresponding clone callback will be
* made, giving the opportunity to the application client to clone in its own
* way. In that mode the parser will only copy afterward the plain payload along
* with '\0' termination (It might seem like redundant to application to clone
* something that it knows to work with natively, but it is still required for
* 3rd party handlers that only familiar with the parser API).
*
* Note that the returned value of RDB_bulkClone has a distinct typedef, called
* RdbBulkCopy, in order to differentiate the functions that are allowed to apply
* on RdbBulk than the one allowed to apply on RdbBulkCopy.
****************************************************************/
_LIBRDB_API RdbBulkCopy RDB_bulkClone(RdbParser *p, RdbBulk b);
_LIBRDB_API RdbBulkCopy RDB_bulkCopyClone(RdbParser *p, RdbBulkCopy b, size_t len);
_LIBRDB_API void RDB_bulkCopyFree(RdbParser *p, RdbBulkCopy b);
_LIBRDB_API size_t RDB_bulkLen(RdbParser *p, RdbBulk b);
int RDB_isRefBulk(RdbParser *p, RdbBulk b);
/****************************************************************
* Multiple levels registration
* Some of the more advanced configuration might require parsing different data
* types at different levels of the parser.
*
* The callbacks that are common to all levels (lookup HANDLERS_COMMON_CALLBACKS),
* if registered at different levels then all of them will be called, one by one,
* starting from level 0.
*
* As for the callbacks of RDB object types, each level has its own way to
* handle the data with distinct set of callbacks interfaces. In case of multiple
* levels registration, the application should configure for each RDB data type
* at what level it is needed to get parsed by calling `RDB_handleByLevel()`.
* Otherwise, the parser will resolve it by parsing and calling handlers that are
* registered at lowest level.
*****************************************************************/
typedef enum RdbDataType {
RDB_DATA_TYPE_STRING=0,
RDB_DATA_TYPE_LIST,
RDB_DATA_TYPE_SET,
RDB_DATA_TYPE_ZSET,
RDB_DATA_TYPE_HASH,
RDB_DATA_TYPE_MODULE,
RDB_DATA_TYPE_STREAM,
RDB_DATA_TYPE_FUNCTION,
RDB_DATA_TYPE_MAX
} RdbDataType;
/* Return 0 on success, 1 otherwise. Can be called at any point along parsing
* (Useful after parsing source rdb version) */
_LIBRDB_API int RDB_handleByLevel(RdbParser *p,
RdbDataType t,
RdbHandlersLevel lvl);
/*****************************************************************
* LIBRDB Versioning
*
* Follows the semantic semver versioning convention
*****************************************************************/
_LIBRDB_API const char* RDB_getLibVersion(int* major, int* minor, int* patch);
_LIBRDB_API int RDB_getMaxSuppportRdbVersion(void);
#ifdef __cplusplus
}
#endif
#endif //LIBRDB_API_H