8 #include "solarisfixes.h"
21 #include "ae.h" /* Event driven programming library */
22 #include "sds.h" /* Dynamic safe strings */
23 #include "dict.h" /* Hash tables */
24 #include "adlist.h" /* Linked lists */
25 #include "zmalloc.h" /* total memory usage aware version of malloc/free */
26 #include "anet.h" /* Networking the easy way */
27 #include "zipmap.h" /* Compact string -> string data structure */
28 #include "ziplist.h" /* Compact list data structure */
29 #include "intset.h" /* Compact integer set structure */
36 /* Static server configuration */
37 #define REDIS_SERVERPORT 6379 /* TCP port */
38 #define REDIS_MAXIDLETIME (60*5) /* default client timeout */
39 #define REDIS_IOBUF_LEN 1024
40 #define REDIS_LOADBUF_LEN 1024
41 #define REDIS_STATIC_ARGS 8
42 #define REDIS_DEFAULT_DBNUM 16
43 #define REDIS_CONFIGLINE_MAX 1024
44 #define REDIS_OBJFREELIST_MAX 1000000 /* Max number of objects to cache */
45 #define REDIS_MAX_SYNC_TIME 60 /* Slave can't take more to sync */
46 #define REDIS_EXPIRELOOKUPS_PER_CRON 10 /* lookup 10 expires per loop */
47 #define REDIS_MAX_WRITE_PER_EVENT (1024*64)
48 #define REDIS_REQUEST_MAX_SIZE (1024*1024*256) /* max bytes in inline command */
49 #define REDIS_SHARED_INTEGERS 10000
51 /* If more then REDIS_WRITEV_THRESHOLD write packets are pending use writev */
52 #define REDIS_WRITEV_THRESHOLD 3
53 /* Max number of iovecs used for each writev call */
54 #define REDIS_WRITEV_IOVEC_COUNT 256
56 /* Hash table parameters */
57 #define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */
60 #define REDIS_CMD_BULK 1 /* Bulk write command */
61 #define REDIS_CMD_INLINE 2 /* Inline command */
62 /* REDIS_CMD_DENYOOM reserves a longer comment: all the commands marked with
63 this flags will return an error when the 'maxmemory' option is set in the
64 config file and the server is using more than maxmemory bytes of memory.
65 In short this commands are denied on low memory conditions. */
66 #define REDIS_CMD_DENYOOM 4
67 #define REDIS_CMD_FORCE_REPLICATION 8 /* Force replication even if dirty is 0 */
70 #define REDIS_STRING 0
75 #define REDIS_VMPOINTER 8
77 /* Objects encoding. Some kind of objects like Strings and Hashes can be
78 * internally represented in multiple ways. The 'encoding' field of the object
79 * is set to one of this fields for this object. */
80 #define REDIS_ENCODING_RAW 0 /* Raw representation */
81 #define REDIS_ENCODING_INT 1 /* Encoded as integer */
82 #define REDIS_ENCODING_HT 2 /* Encoded as hash table */
83 #define REDIS_ENCODING_ZIPMAP 3 /* Encoded as zipmap */
84 #define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
85 #define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
86 #define REDIS_ENCODING_INTSET 6 /* Encoded as intset */
88 /* Object types only used for dumping to disk */
89 #define REDIS_EXPIRETIME 253
90 #define REDIS_SELECTDB 254
93 /* Defines related to the dump file format. To store 32 bits lengths for short
94 * keys requires a lot of space, so we check the most significant 2 bits of
95 * the first byte to interpreter the length:
97 * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte
98 * 01|000000 00000000 => 01, the len is 14 byes, 6 bits + 8 bits of next byte
99 * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow
100 * 11|000000 this means: specially encoded object will follow. The six bits
101 * number specify the kind of object that follows.
102 * See the REDIS_RDB_ENC_* defines.
104 * Lenghts up to 63 are stored using a single byte, most DB keys, and may
105 * values, will fit inside. */
106 #define REDIS_RDB_6BITLEN 0
107 #define REDIS_RDB_14BITLEN 1
108 #define REDIS_RDB_32BITLEN 2
109 #define REDIS_RDB_ENCVAL 3
110 #define REDIS_RDB_LENERR UINT_MAX
112 /* When a length of a string object stored on disk has the first two bits
113 * set, the remaining two bits specify a special encoding for the object
114 * accordingly to the following defines: */
115 #define REDIS_RDB_ENC_INT8 0 /* 8 bit signed integer */
116 #define REDIS_RDB_ENC_INT16 1 /* 16 bit signed integer */
117 #define REDIS_RDB_ENC_INT32 2 /* 32 bit signed integer */
118 #define REDIS_RDB_ENC_LZF 3 /* string compressed with FASTLZ */
120 /* Virtual memory object->where field. */
121 #define REDIS_VM_MEMORY 0 /* The object is on memory */
122 #define REDIS_VM_SWAPPED 1 /* The object is on disk */
123 #define REDIS_VM_SWAPPING 2 /* Redis is swapping this object on disk */
124 #define REDIS_VM_LOADING 3 /* Redis is loading this object from disk */
126 /* Virtual memory static configuration stuff.
127 * Check vmFindContiguousPages() to know more about this magic numbers. */
128 #define REDIS_VM_MAX_NEAR_PAGES 65536
129 #define REDIS_VM_MAX_RANDOM_JUMP 4096
130 #define REDIS_VM_MAX_THREADS 32
131 #define REDIS_THREAD_STACK_SIZE (1024*1024*4)
132 /* The following is the *percentage* of completed I/O jobs to process when the
133 * handelr is called. While Virtual Memory I/O operations are performed by
134 * threads, this operations must be processed by the main thread when completed
135 * in order to take effect. */
136 #define REDIS_MAX_COMPLETED_JOBS_PROCESSED 1
139 #define REDIS_SLAVE 1 /* This client is a slave server */
140 #define REDIS_MASTER 2 /* This client is a master server */
141 #define REDIS_MONITOR 4 /* This client is a slave monitor, see MONITOR */
142 #define REDIS_MULTI 8 /* This client is in a MULTI context */
143 #define REDIS_BLOCKED 16 /* The client is waiting in a blocking operation */
144 #define REDIS_IO_WAIT 32 /* The client is waiting for Virtual Memory I/O */
145 #define REDIS_DIRTY_CAS 64 /* Watched keys modified. EXEC will fail. */
147 /* Slave replication state - slave side */
148 #define REDIS_REPL_NONE 0 /* No active replication */
149 #define REDIS_REPL_CONNECT 1 /* Must connect to master */
150 #define REDIS_REPL_CONNECTED 2 /* Connected to master */
152 /* Slave replication state - from the point of view of master
153 * Note that in SEND_BULK and ONLINE state the slave receives new updates
154 * in its output queue. In the WAIT_BGSAVE state instead the server is waiting
155 * to start the next background saving in order to send updates to it. */
156 #define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */
157 #define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */
158 #define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */
159 #define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */
161 /* List related stuff */
165 /* Sort operations */
166 #define REDIS_SORT_GET 0
167 #define REDIS_SORT_ASC 1
168 #define REDIS_SORT_DESC 2
169 #define REDIS_SORTKEY_MAX 1024
172 #define REDIS_DEBUG 0
173 #define REDIS_VERBOSE 1
174 #define REDIS_NOTICE 2
175 #define REDIS_WARNING 3
177 /* Anti-warning macro... */
178 #define REDIS_NOTUSED(V) ((void) V)
180 #define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */
181 #define ZSKIPLIST_P 0.25 /* Skiplist P = 1/4 */
183 /* Append only defines */
184 #define APPENDFSYNC_NO 0
185 #define APPENDFSYNC_ALWAYS 1
186 #define APPENDFSYNC_EVERYSEC 2
188 /* Zip structure related defaults */
189 #define REDIS_HASH_MAX_ZIPMAP_ENTRIES 64
190 #define REDIS_HASH_MAX_ZIPMAP_VALUE 512
191 #define REDIS_LIST_MAX_ZIPLIST_ENTRIES 1024
192 #define REDIS_LIST_MAX_ZIPLIST_VALUE 32
193 #define REDIS_SET_MAX_INTSET_ENTRIES 4096
195 /* Sets operations codes */
196 #define REDIS_OP_UNION 0
197 #define REDIS_OP_DIFF 1
198 #define REDIS_OP_INTER 2
200 /* We can print the stacktrace, so our assert is defined this way: */
201 #define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))
202 #define redisPanic(_e) _redisPanic(#_e,__FILE__,__LINE__),_exit(1)
203 void _redisAssert(char *estr
, char *file
, int line
);
204 void _redisPanic(char *msg
, char *file
, int line
);
206 /*-----------------------------------------------------------------------------
208 *----------------------------------------------------------------------------*/
210 /* A redis object, that is a type able to hold a string / list / set */
212 /* The actual Redis Object */
213 typedef struct redisObject
{
215 unsigned storage
:2; /* REDIS_VM_MEMORY or REDIS_VM_SWAPPING */
217 unsigned lru
:22; /* lru time (relative to server.lruclock) */
220 /* VM fields are only allocated if VM is active, otherwise the
221 * object allocation function will just allocate
222 * sizeof(redisObjct) minus sizeof(redisObjectVM), so using
223 * Redis without VM active will not have any overhead. */
226 /* The VM pointer structure - identifies an object in the swap file.
228 * This object is stored in place of the value
229 * object in the main key->value hash table representing a database.
230 * Note that the first fields (type, storage) are the same as the redisObject
231 * structure so that vmPointer strucuters can be accessed even when casted
232 * as redisObject structures.
234 * This is useful as we don't know if a value object is or not on disk, but we
235 * are always able to read obj->storage to check this. For vmPointer
236 * structures "type" is set to REDIS_VMPOINTER (even if without this field
237 * is still possible to check the kind of object from the value of 'storage').*/
238 typedef struct vmPointer
{
240 unsigned storage
:2; /* REDIS_VM_SWAPPED or REDIS_VM_LOADING */
242 unsigned int vtype
; /* type of the object stored in the swap file */
243 off_t page
; /* the page at witch the object is stored on disk */
244 off_t usedpages
; /* number of pages used on disk */
247 /* Macro used to initalize a Redis object allocated on the stack.
248 * Note that this macro is taken near the structure definition to make sure
249 * we'll update it when the structure is changed, to avoid bugs like
250 * bug #85 introduced exactly in this way. */
251 #define initStaticStringObject(_var,_ptr) do { \
253 _var.type = REDIS_STRING; \
254 _var.encoding = REDIS_ENCODING_RAW; \
256 _var.storage = REDIS_VM_MEMORY; \
259 typedef struct redisDb
{
260 dict
*dict
; /* The keyspace for this DB */
261 dict
*expires
; /* Timeout of keys with a timeout set */
262 dict
*blocking_keys
; /* Keys with clients waiting for data (BLPOP) */
263 dict
*io_keys
; /* Keys with clients waiting for VM I/O */
264 dict
*watched_keys
; /* WATCHED keys for MULTI/EXEC CAS */
268 /* Client MULTI/EXEC state */
269 typedef struct multiCmd
{
272 struct redisCommand
*cmd
;
275 typedef struct multiState
{
276 multiCmd
*commands
; /* Array of MULTI commands */
277 int count
; /* Total number of MULTI commands */
280 /* With multiplexing we need to take per-clinet state.
281 * Clients are taken in a liked list. */
282 typedef struct redisClient
{
287 robj
**argv
, **mbargv
;
289 long bulklen
; /* bulk read len. -1 if not in bulk read mode */
290 int multibulk
; /* multi bulk command format active */
293 time_t lastinteraction
; /* time of the last interaction, used for timeout */
294 int flags
; /* REDIS_SLAVE | REDIS_MONITOR | REDIS_MULTI ... */
295 int slaveseldb
; /* slave selected db, if this client is a slave */
296 int authenticated
; /* when requirepass is non-NULL */
297 int replstate
; /* replication state if this is a slave */
298 int repldbfd
; /* replication DB file descriptor */
299 long repldboff
; /* replication DB file offset */
300 off_t repldbsize
; /* replication DB file size */
301 multiState mstate
; /* MULTI/EXEC state */
302 robj
**blocking_keys
; /* The key we are waiting to terminate a blocking
303 * operation such as BLPOP. Otherwise NULL. */
304 int blocking_keys_num
; /* Number of blocking keys */
305 time_t blockingto
; /* Blocking operation timeout. If UNIX current time
306 * is >= blockingto then the operation timed out. */
307 list
*io_keys
; /* Keys this client is waiting to be loaded from the
308 * swap file in order to continue. */
309 list
*watched_keys
; /* Keys WATCHED for MULTI/EXEC CAS */
310 dict
*pubsub_channels
; /* channels a client is interested in (SUBSCRIBE) */
311 list
*pubsub_patterns
; /* patterns a client is interested in (SUBSCRIBE) */
319 struct sharedObjectsStruct
{
320 robj
*crlf
, *ok
, *err
, *emptybulk
, *czero
, *cone
, *cnegone
, *pong
, *space
,
321 *colon
, *nullbulk
, *nullmultibulk
, *queued
,
322 *emptymultibulk
, *wrongtypeerr
, *nokeyerr
, *syntaxerr
, *sameobjecterr
,
323 *outofrangeerr
, *plus
,
324 *select0
, *select1
, *select2
, *select3
, *select4
,
325 *select5
, *select6
, *select7
, *select8
, *select9
,
326 *messagebulk
, *pmessagebulk
, *subscribebulk
, *unsubscribebulk
, *mbulk3
,
327 *mbulk4
, *psubscribebulk
, *punsubscribebulk
,
328 *integers
[REDIS_SHARED_INTEGERS
];
331 /* Global server state structure */
333 pthread_t mainthread
;
337 long long dirty
; /* changes to DB from the last save */
339 list
*slaves
, *monitors
;
340 char neterr
[ANET_ERR_LEN
];
342 int cronloops
; /* number of times the cron function run */
343 list
*objfreelist
; /* A list of freed objects to avoid malloc() */
344 time_t lastsave
; /* Unix time of last save succeeede */
345 /* Fields used only for stats */
346 time_t stat_starttime
; /* server start time */
347 long long stat_numcommands
; /* number of processed commands */
348 long long stat_numconnections
; /* number of connections received */
349 long long stat_expiredkeys
; /* number of expired keys */
358 int no_appendfsync_on_rewrite
;
364 pid_t bgsavechildpid
;
365 pid_t bgrewritechildpid
;
366 sds bgrewritebuf
; /* buffer taken by parent during oppend only rewrite */
367 sds aofbuf
; /* AOF buffer, written before entering the event loop */
368 struct saveparam
*saveparams
;
373 char *appendfilename
;
377 /* Replication related */
382 redisClient
*master
; /* client that is master for this slave */
384 unsigned int maxclients
;
385 unsigned long long maxmemory
;
386 unsigned int blpop_blocked_clients
;
387 unsigned int vm_blocked_clients
;
388 /* Sort parameters - qsort_r() is only available under BSD so we
389 * have to take this state global, in order to pass it to sortCompare() */
393 /* Virtual memory configuration */
398 unsigned long long vm_max_memory
;
399 /* Zip structure config */
400 size_t hash_max_zipmap_entries
;
401 size_t hash_max_zipmap_value
;
402 size_t list_max_ziplist_entries
;
403 size_t list_max_ziplist_value
;
404 size_t set_max_intset_entries
;
405 /* Virtual memory state */
408 off_t vm_next_page
; /* Next probably empty page */
409 off_t vm_near_pages
; /* Number of pages allocated sequentially */
410 unsigned char *vm_bitmap
; /* Bitmap of free/used pages */
411 time_t unixtime
; /* Unix time sampled every second. */
412 /* Virtual memory I/O threads stuff */
413 /* An I/O thread process an element taken from the io_jobs queue and
414 * put the result of the operation in the io_done list. While the
415 * job is being processed, it's put on io_processing queue. */
416 list
*io_newjobs
; /* List of VM I/O jobs yet to be processed */
417 list
*io_processing
; /* List of VM I/O jobs being processed */
418 list
*io_processed
; /* List of VM I/O jobs already processed */
419 list
*io_ready_clients
; /* Clients ready to be unblocked. All keys loaded */
420 pthread_mutex_t io_mutex
; /* lock to access io_jobs/io_done/io_thread_job */
421 pthread_mutex_t obj_freelist_mutex
; /* safe redis objects creation/free */
422 pthread_mutex_t io_swapfile_mutex
; /* So we can lseek + write */
423 pthread_attr_t io_threads_attr
; /* attributes for threads creation */
424 int io_active_threads
; /* Number of running I/O threads */
425 int vm_max_threads
; /* Max number of I/O threads running at the same time */
426 /* Our main thread is blocked on the event loop, locking for sockets ready
427 * to be read or written, so when a threaded I/O operation is ready to be
428 * processed by the main thread, the I/O thread will use a unix pipe to
429 * awake the main thread. The followings are the two pipe FDs. */
430 int io_ready_pipe_read
;
431 int io_ready_pipe_write
;
432 /* Virtual memory stats */
433 unsigned long long vm_stats_used_pages
;
434 unsigned long long vm_stats_swapped_objects
;
435 unsigned long long vm_stats_swapouts
;
436 unsigned long long vm_stats_swapins
;
438 dict
*pubsub_channels
; /* Map channels to list of subscribed clients */
439 list
*pubsub_patterns
; /* A list of pubsub_patterns */
442 unsigned lruclock
:22; /* clock incrementing every minute, for LRU */
443 unsigned lruclock_padding
:10;
446 typedef struct pubsubPattern
{
451 typedef void redisCommandProc(redisClient
*c
);
452 typedef void redisVmPreloadProc(redisClient
*c
, struct redisCommand
*cmd
, int argc
, robj
**argv
);
453 struct redisCommand
{
455 redisCommandProc
*proc
;
458 /* Use a function to determine which keys need to be loaded
459 * in the background prior to executing this command. Takes precedence
460 * over vm_firstkey and others, ignored when NULL */
461 redisVmPreloadProc
*vm_preload_proc
;
462 /* What keys should be loaded in background when calling this command? */
463 int vm_firstkey
; /* The first argument that's a key (0 = no keys) */
464 int vm_lastkey
; /* THe last argument that's a key */
465 int vm_keystep
; /* The step between first and last key */
468 struct redisFunctionSym
{
470 unsigned long pointer
;
473 typedef struct _redisSortObject
{
481 typedef struct _redisSortOperation
{
484 } redisSortOperation
;
486 /* ZSETs use a specialized version of Skiplists */
488 typedef struct zskiplistNode
{
489 struct zskiplistNode
**forward
;
490 struct zskiplistNode
*backward
;
496 typedef struct zskiplist
{
497 struct zskiplistNode
*header
, *tail
;
498 unsigned long length
;
502 typedef struct zset
{
507 /* VM threaded I/O request message */
508 #define REDIS_IOJOB_LOAD 0 /* Load from disk to memory */
509 #define REDIS_IOJOB_PREPARE_SWAP 1 /* Compute needed pages */
510 #define REDIS_IOJOB_DO_SWAP 2 /* Swap from memory to disk */
511 typedef struct iojob
{
512 int type
; /* Request type, REDIS_IOJOB_* */
513 redisDb
*db
;/* Redis database */
514 robj
*key
; /* This I/O request is about swapping this key */
515 robj
*id
; /* Unique identifier of this job:
516 this is the object to swap for REDIS_IOREQ_*_SWAP, or the
517 vmpointer objct for REDIS_IOREQ_LOAD. */
518 robj
*val
; /* the value to swap for REDIS_IOREQ_*_SWAP, otherwise this
519 * field is populated by the I/O thread for REDIS_IOREQ_LOAD. */
520 off_t page
; /* Swap page where to read/write the object */
521 off_t pages
; /* Swap pages needed to save object. PREPARE_SWAP return val */
522 int canceled
; /* True if this command was canceled by blocking side of VM */
523 pthread_t thread
; /* ID of the thread processing this entry */
526 /* Structure to hold list iteration abstraction. */
529 unsigned char encoding
;
530 unsigned char direction
; /* Iteration direction */
535 /* Structure for an entry while iterating over a list. */
537 listTypeIterator
*li
;
538 unsigned char *zi
; /* Entry in ziplist */
539 listNode
*ln
; /* Entry in linked list */
542 /* Structure to hold set iteration abstraction. */
546 int ii
; /* intset iterator */
550 /* Structure to hold hash iteration abstration. Note that iteration over
551 * hashes involves both fields and values. Because it is possible that
552 * not both are required, store pointers in the iterator to avoid
553 * unnecessary memory allocation for fields/values. */
557 unsigned char *zk
, *zv
;
558 unsigned int zklen
, zvlen
;
564 #define REDIS_HASH_KEY 1
565 #define REDIS_HASH_VALUE 2
567 /*-----------------------------------------------------------------------------
568 * Extern declarations
569 *----------------------------------------------------------------------------*/
571 extern struct redisServer server
;
572 extern struct sharedObjectsStruct shared
;
573 extern dictType setDictType
;
574 extern dictType zsetDictType
;
575 extern double R_Zero
, R_PosInf
, R_NegInf
, R_Nan
;
576 dictType hashDictType
;
578 /*-----------------------------------------------------------------------------
579 * Functions prototypes
580 *----------------------------------------------------------------------------*/
582 /* networking.c -- Networking and Client related operations */
583 redisClient
*createClient(int fd
);
584 void closeTimedoutClients(void);
585 void freeClient(redisClient
*c
);
586 void resetClient(redisClient
*c
);
587 void sendReplyToClient(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
588 void sendReplyToClientWritev(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
589 void addReply(redisClient
*c
, robj
*obj
);
590 void addReplySds(redisClient
*c
, sds s
);
591 void processInputBuffer(redisClient
*c
);
592 void acceptHandler(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
593 void readQueryFromClient(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
594 void addReplyBulk(redisClient
*c
, robj
*obj
);
595 void addReplyBulkCString(redisClient
*c
, char *s
);
596 void acceptHandler(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
597 void addReply(redisClient
*c
, robj
*obj
);
598 void addReplySds(redisClient
*c
, sds s
);
599 void addReplyDouble(redisClient
*c
, double d
);
600 void addReplyLongLong(redisClient
*c
, long long ll
);
601 void addReplyUlong(redisClient
*c
, unsigned long ul
);
602 void *dupClientReplyValue(void *o
);
605 void listTypeTryConversion(robj
*subject
, robj
*value
);
606 void listTypePush(robj
*subject
, robj
*value
, int where
);
607 robj
*listTypePop(robj
*subject
, int where
);
608 unsigned long listTypeLength(robj
*subject
);
609 listTypeIterator
*listTypeInitIterator(robj
*subject
, int index
, unsigned char direction
);
610 void listTypeReleaseIterator(listTypeIterator
*li
);
611 int listTypeNext(listTypeIterator
*li
, listTypeEntry
*entry
);
612 robj
*listTypeGet(listTypeEntry
*entry
);
613 void listTypeInsert(listTypeEntry
*entry
, robj
*value
, int where
);
614 int listTypeEqual(listTypeEntry
*entry
, robj
*o
);
615 void listTypeDelete(listTypeEntry
*entry
);
616 void listTypeConvert(robj
*subject
, int enc
);
617 void unblockClientWaitingData(redisClient
*c
);
618 int handleClientsWaitingListPush(redisClient
*c
, robj
*key
, robj
*ele
);
619 void popGenericCommand(redisClient
*c
, int where
);
621 /* MULTI/EXEC/WATCH... */
622 void unwatchAllKeys(redisClient
*c
);
623 void initClientMultiState(redisClient
*c
);
624 void freeClientMultiState(redisClient
*c
);
625 void queueMultiCommand(redisClient
*c
, struct redisCommand
*cmd
);
626 void touchWatchedKey(redisDb
*db
, robj
*key
);
627 void touchWatchedKeysOnFlush(int dbid
);
629 /* Redis object implementation */
630 void decrRefCount(void *o
);
631 void incrRefCount(robj
*o
);
632 void freeStringObject(robj
*o
);
633 void freeListObject(robj
*o
);
634 void freeSetObject(robj
*o
);
635 void freeZsetObject(robj
*o
);
636 void freeHashObject(robj
*o
);
637 robj
*createObject(int type
, void *ptr
);
638 robj
*createStringObject(char *ptr
, size_t len
);
639 robj
*dupStringObject(robj
*o
);
640 robj
*tryObjectEncoding(robj
*o
);
641 robj
*getDecodedObject(robj
*o
);
642 size_t stringObjectLen(robj
*o
);
643 int tryFreeOneObjectFromFreelist(void);
644 robj
*createStringObjectFromLongLong(long long value
);
645 robj
*createListObject(void);
646 robj
*createZiplistObject(void);
647 robj
*createSetObject(void);
648 robj
*createIntsetObject(void);
649 robj
*createHashObject(void);
650 robj
*createZsetObject(void);
651 int getLongFromObjectOrReply(redisClient
*c
, robj
*o
, long *target
, const char *msg
);
652 int checkType(redisClient
*c
, robj
*o
, int type
);
653 int getLongLongFromObjectOrReply(redisClient
*c
, robj
*o
, long long *target
, const char *msg
);
654 int getDoubleFromObjectOrReply(redisClient
*c
, robj
*o
, double *target
, const char *msg
);
655 int getLongLongFromObject(robj
*o
, long long *target
);
656 char *strEncoding(int encoding
);
657 int compareStringObjects(robj
*a
, robj
*b
);
658 int equalStringObjects(robj
*a
, robj
*b
);
661 void replicationFeedSlaves(list
*slaves
, int dictid
, robj
**argv
, int argc
);
662 void replicationFeedMonitors(list
*monitors
, int dictid
, robj
**argv
, int argc
);
663 int syncWithMaster(void);
664 void updateSlavesWaitingBgsave(int bgsaveerr
);
666 /* RDB persistence */
667 int rdbLoad(char *filename
);
668 int rdbSaveBackground(char *filename
);
669 void rdbRemoveTempFile(pid_t childpid
);
670 int rdbSave(char *filename
);
671 int rdbSaveObject(FILE *fp
, robj
*o
);
672 off_t
rdbSavedObjectPages(robj
*o
, FILE *fp
);
673 off_t
rdbSavedObjectLen(robj
*o
, FILE *fp
);
674 robj
*rdbLoadObject(int type
, FILE *fp
);
675 void backgroundSaveDoneHandler(int statloc
);
677 /* AOF persistence */
678 void flushAppendOnlyFile(void);
679 void feedAppendOnlyFile(struct redisCommand
*cmd
, int dictid
, robj
**argv
, int argc
);
680 void aofRemoveTempFile(pid_t childpid
);
681 int rewriteAppendOnlyFileBackground(void);
682 int loadAppendOnlyFile(char *filename
);
683 void stopAppendOnly(void);
684 int startAppendOnly(void);
685 void backgroundRewriteDoneHandler(int statloc
);
687 /* Sorted sets data type */
688 zskiplist
*zslCreate(void);
689 void zslFree(zskiplist
*zsl
);
690 void zslInsert(zskiplist
*zsl
, double score
, robj
*obj
);
693 void freeMemoryIfNeeded(void);
694 int processCommand(redisClient
*c
);
695 void setupSigSegvAction(void);
696 struct redisCommand
*lookupCommand(char *name
);
697 void call(redisClient
*c
, struct redisCommand
*cmd
);
698 int prepareForShutdown();
699 void redisLog(int level
, const char *fmt
, ...);
701 void updateDictResizePolicy(void);
702 int htNeedsResize(dict
*dict
);
703 void oom(const char *msg
);
707 void vmMarkPagesFree(off_t page
, off_t count
);
708 robj
*vmLoadObject(robj
*o
);
709 robj
*vmPreviewObject(robj
*o
);
710 int vmSwapOneObjectBlocking(void);
711 int vmSwapOneObjectThreaded(void);
712 int vmCanSwapOut(void);
713 void vmThreadedIOCompletedJob(aeEventLoop
*el
, int fd
, void *privdata
, int mask
);
714 void vmCancelThreadedIOJob(robj
*o
);
715 void lockThreadedIO(void);
716 void unlockThreadedIO(void);
717 int vmSwapObjectThreaded(robj
*key
, robj
*val
, redisDb
*db
);
718 void freeIOJob(iojob
*j
);
719 void queueIOJob(iojob
*j
);
720 int vmWriteObjectOnSwap(robj
*o
, off_t page
);
721 robj
*vmReadObjectFromSwap(off_t page
, int type
);
722 void waitEmptyIOJobsQueue(void);
723 void vmReopenSwapFile(void);
724 int vmFreePage(off_t page
);
725 void zunionInterBlockClientOnSwappedKeys(redisClient
*c
, struct redisCommand
*cmd
, int argc
, robj
**argv
);
726 void execBlockClientOnSwappedKeys(redisClient
*c
, struct redisCommand
*cmd
, int argc
, robj
**argv
);
727 int blockClientOnSwappedKeys(redisClient
*c
, struct redisCommand
*cmd
);
728 int dontWaitForSwappedKey(redisClient
*c
, robj
*key
);
729 void handleClientsBlockedOnSwappedKey(redisDb
*db
, robj
*key
);
730 vmpointer
*vmSwapObjectBlocking(robj
*val
);
733 robj
*setTypeCreate(robj
*value
);
734 int setTypeAdd(robj
*subject
, robj
*value
);
735 int setTypeRemove(robj
*subject
, robj
*value
);
736 int setTypeIsMember(robj
*subject
, robj
*value
);
737 setTypeIterator
*setTypeInitIterator(robj
*subject
);
738 void setTypeReleaseIterator(setTypeIterator
*si
);
739 robj
*setTypeNext(setTypeIterator
*si
);
740 robj
*setTypeRandomElement(robj
*subject
);
741 unsigned long setTypeSize(robj
*subject
);
742 void setTypeConvert(robj
*subject
, int enc
);
745 void convertToRealHash(robj
*o
);
746 void hashTypeTryConversion(robj
*subject
, robj
**argv
, int start
, int end
);
747 void hashTypeTryObjectEncoding(robj
*subject
, robj
**o1
, robj
**o2
);
748 robj
*hashTypeGet(robj
*o
, robj
*key
);
749 int hashTypeExists(robj
*o
, robj
*key
);
750 int hashTypeSet(robj
*o
, robj
*key
, robj
*value
);
751 int hashTypeDelete(robj
*o
, robj
*key
);
752 unsigned long hashTypeLength(robj
*o
);
753 hashTypeIterator
*hashTypeInitIterator(robj
*subject
);
754 void hashTypeReleaseIterator(hashTypeIterator
*hi
);
755 int hashTypeNext(hashTypeIterator
*hi
);
756 robj
*hashTypeCurrent(hashTypeIterator
*hi
, int what
);
757 robj
*hashTypeLookupWriteOrCreate(redisClient
*c
, robj
*key
);
760 int pubsubUnsubscribeAllChannels(redisClient
*c
, int notify
);
761 int pubsubUnsubscribeAllPatterns(redisClient
*c
, int notify
);
762 void freePubsubPattern(void *p
);
763 int listMatchPubsubPattern(void *a
, void *b
);
765 /* Utility functions */
766 int stringmatchlen(const char *pattern
, int patternLen
,
767 const char *string
, int stringLen
, int nocase
);
768 int stringmatch(const char *pattern
, const char *string
, int nocase
);
769 long long memtoll(const char *p
, int *err
);
770 int ll2string(char *s
, size_t len
, long long value
);
771 int isStringRepresentableAsLong(sds s
, long *longval
);
772 int isStringRepresentableAsLongLong(sds s
, long long *longval
);
773 int isObjectRepresentableAsLongLong(robj
*o
, long long *llongval
);
776 void loadServerConfig(char *filename
);
777 void appendServerSaveParams(time_t seconds
, int changes
);
778 void resetServerSaveParams();
780 /* db.c -- Keyspace access API */
781 int removeExpire(redisDb
*db
, robj
*key
);
782 void propagateExpire(redisDb
*db
, robj
*key
);
783 int expireIfNeeded(redisDb
*db
, robj
*key
);
784 time_t getExpire(redisDb
*db
, robj
*key
);
785 void setExpire(redisDb
*db
, robj
*key
, time_t when
);
786 robj
*lookupKey(redisDb
*db
, robj
*key
);
787 robj
*lookupKeyRead(redisDb
*db
, robj
*key
);
788 robj
*lookupKeyWrite(redisDb
*db
, robj
*key
);
789 robj
*lookupKeyReadOrReply(redisClient
*c
, robj
*key
, robj
*reply
);
790 robj
*lookupKeyWriteOrReply(redisClient
*c
, robj
*key
, robj
*reply
);
791 int dbAdd(redisDb
*db
, robj
*key
, robj
*val
);
792 int dbReplace(redisDb
*db
, robj
*key
, robj
*val
);
793 int dbExists(redisDb
*db
, robj
*key
);
794 robj
*dbRandomKey(redisDb
*db
);
795 int dbDelete(redisDb
*db
, robj
*key
);
797 int selectDb(redisClient
*c
, int id
);
800 char *redisGitSHA1(void);
801 char *redisGitDirty(void);
803 /* Commands prototypes */
804 void authCommand(redisClient
*c
);
805 void pingCommand(redisClient
*c
);
806 void echoCommand(redisClient
*c
);
807 void setCommand(redisClient
*c
);
808 void setnxCommand(redisClient
*c
);
809 void setexCommand(redisClient
*c
);
810 void getCommand(redisClient
*c
);
811 void delCommand(redisClient
*c
);
812 void existsCommand(redisClient
*c
);
813 void incrCommand(redisClient
*c
);
814 void decrCommand(redisClient
*c
);
815 void incrbyCommand(redisClient
*c
);
816 void decrbyCommand(redisClient
*c
);
817 void selectCommand(redisClient
*c
);
818 void randomkeyCommand(redisClient
*c
);
819 void keysCommand(redisClient
*c
);
820 void dbsizeCommand(redisClient
*c
);
821 void lastsaveCommand(redisClient
*c
);
822 void saveCommand(redisClient
*c
);
823 void bgsaveCommand(redisClient
*c
);
824 void bgrewriteaofCommand(redisClient
*c
);
825 void shutdownCommand(redisClient
*c
);
826 void moveCommand(redisClient
*c
);
827 void renameCommand(redisClient
*c
);
828 void renamenxCommand(redisClient
*c
);
829 void lpushCommand(redisClient
*c
);
830 void rpushCommand(redisClient
*c
);
831 void lpushxCommand(redisClient
*c
);
832 void rpushxCommand(redisClient
*c
);
833 void linsertCommand(redisClient
*c
);
834 void lpopCommand(redisClient
*c
);
835 void rpopCommand(redisClient
*c
);
836 void llenCommand(redisClient
*c
);
837 void lindexCommand(redisClient
*c
);
838 void lrangeCommand(redisClient
*c
);
839 void ltrimCommand(redisClient
*c
);
840 void typeCommand(redisClient
*c
);
841 void lsetCommand(redisClient
*c
);
842 void saddCommand(redisClient
*c
);
843 void sremCommand(redisClient
*c
);
844 void smoveCommand(redisClient
*c
);
845 void sismemberCommand(redisClient
*c
);
846 void scardCommand(redisClient
*c
);
847 void spopCommand(redisClient
*c
);
848 void srandmemberCommand(redisClient
*c
);
849 void sinterCommand(redisClient
*c
);
850 void sinterstoreCommand(redisClient
*c
);
851 void sunionCommand(redisClient
*c
);
852 void sunionstoreCommand(redisClient
*c
);
853 void sdiffCommand(redisClient
*c
);
854 void sdiffstoreCommand(redisClient
*c
);
855 void syncCommand(redisClient
*c
);
856 void flushdbCommand(redisClient
*c
);
857 void flushallCommand(redisClient
*c
);
858 void sortCommand(redisClient
*c
);
859 void lremCommand(redisClient
*c
);
860 void rpoplpushcommand(redisClient
*c
);
861 void infoCommand(redisClient
*c
);
862 void mgetCommand(redisClient
*c
);
863 void monitorCommand(redisClient
*c
);
864 void expireCommand(redisClient
*c
);
865 void expireatCommand(redisClient
*c
);
866 void getsetCommand(redisClient
*c
);
867 void ttlCommand(redisClient
*c
);
868 void persistCommand(redisClient
*c
);
869 void slaveofCommand(redisClient
*c
);
870 void debugCommand(redisClient
*c
);
871 void msetCommand(redisClient
*c
);
872 void msetnxCommand(redisClient
*c
);
873 void zaddCommand(redisClient
*c
);
874 void zincrbyCommand(redisClient
*c
);
875 void zrangeCommand(redisClient
*c
);
876 void zrangebyscoreCommand(redisClient
*c
);
877 void zcountCommand(redisClient
*c
);
878 void zrevrangeCommand(redisClient
*c
);
879 void zcardCommand(redisClient
*c
);
880 void zremCommand(redisClient
*c
);
881 void zscoreCommand(redisClient
*c
);
882 void zremrangebyscoreCommand(redisClient
*c
);
883 void multiCommand(redisClient
*c
);
884 void execCommand(redisClient
*c
);
885 void discardCommand(redisClient
*c
);
886 void blpopCommand(redisClient
*c
);
887 void brpopCommand(redisClient
*c
);
888 void appendCommand(redisClient
*c
);
889 void substrCommand(redisClient
*c
);
890 void strlenCommand(redisClient
*c
);
891 void zrankCommand(redisClient
*c
);
892 void zrevrankCommand(redisClient
*c
);
893 void hsetCommand(redisClient
*c
);
894 void hsetnxCommand(redisClient
*c
);
895 void hgetCommand(redisClient
*c
);
896 void hmsetCommand(redisClient
*c
);
897 void hmgetCommand(redisClient
*c
);
898 void hdelCommand(redisClient
*c
);
899 void hlenCommand(redisClient
*c
);
900 void zremrangebyrankCommand(redisClient
*c
);
901 void zunionstoreCommand(redisClient
*c
);
902 void zinterstoreCommand(redisClient
*c
);
903 void hkeysCommand(redisClient
*c
);
904 void hvalsCommand(redisClient
*c
);
905 void hgetallCommand(redisClient
*c
);
906 void hexistsCommand(redisClient
*c
);
907 void configCommand(redisClient
*c
);
908 void hincrbyCommand(redisClient
*c
);
909 void subscribeCommand(redisClient
*c
);
910 void unsubscribeCommand(redisClient
*c
);
911 void psubscribeCommand(redisClient
*c
);
912 void punsubscribeCommand(redisClient
*c
);
913 void publishCommand(redisClient
*c
);
914 void watchCommand(redisClient
*c
);
915 void unwatchCommand(redisClient
*c
);
917 #if defined(__GNUC__)
918 void *calloc(size_t count
, size_t size
) __attribute__ ((deprecated
));
919 void free(void *ptr
) __attribute__ ((deprecated
));
920 void *malloc(size_t size
) __attribute__ ((deprecated
));
921 void *realloc(void *ptr
, size_t size
) __attribute__ ((deprecated
));