X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/f00b0844c9d825bd19597e214ef8169333684810..4468ba231785fe9fda26f2d05181f91342d91c2d:/src/redis.h?ds=inline diff --git a/src/redis.h b/src/redis.h index a64b4fd7..071cb534 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2009-2012, Salvatore Sanfilippo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef __REDIS_H #define __REDIS_H @@ -57,10 +86,9 @@ #define REDIS_SLOWLOG_MAX_LEN 128 #define REDIS_MAX_CLIENTS 10000 #define REDIS_AUTHPASS_MAX_LEN 512 - +#define REDIS_DEFAULT_SLAVE_PRIORITY 100 #define REDIS_REPL_TIMEOUT 60 #define REDIS_REPL_PING_SLAVE_PERIOD 10 - #define REDIS_RUN_ID_SIZE 40 #define REDIS_OPS_SEC_SAMPLES 16 @@ -87,6 +115,7 @@ #define REDIS_CMD_SORT_FOR_SCRIPT 256 /* "S" flag */ #define REDIS_CMD_LOADING 512 /* "l" flag */ #define REDIS_CMD_STALE 1024 /* "t" flag */ +#define REDIS_CMD_SKIP_MONITOR 2048 /* "M" flag */ /* Object types */ #define REDIS_STRING 0 @@ -140,18 +169,20 @@ #define REDIS_AOF_WAIT_REWRITE 2 /* AOF waits rewrite to start appending */ /* Client flags */ -#define REDIS_SLAVE 1 /* This client is a slave server */ -#define REDIS_MASTER 2 /* This client is a master server */ -#define REDIS_MONITOR 4 /* This client is a slave monitor, see MONITOR */ -#define REDIS_MULTI 8 /* This client is in a MULTI context */ -#define REDIS_BLOCKED 16 /* The client is waiting in a blocking operation */ -#define REDIS_DIRTY_CAS 64 /* Watched keys modified. EXEC will fail. */ -#define REDIS_CLOSE_AFTER_REPLY 128 /* Close after writing entire reply. */ -#define REDIS_UNBLOCKED 256 /* This client was unblocked and is stored in - server.unblocked_clients */ -#define REDIS_LUA_CLIENT 512 /* This is a non connected client used by Lua */ -#define REDIS_ASKING 1024 /* Client issued the ASKING command */ -#define REDIS_CLOSE_ASAP 2048 /* Close this client ASAP */ +#define REDIS_SLAVE (1<<0) /* This client is a slave server */ +#define REDIS_MASTER (1<<1) /* This client is a master server */ +#define REDIS_MONITOR (1<<2) /* This client is a slave monitor, see MONITOR */ +#define REDIS_MULTI (1<<3) /* This client is in a MULTI context */ +#define REDIS_BLOCKED (1<<4) /* The client is waiting in a blocking operation */ +#define REDIS_DIRTY_CAS (1<<5) /* Watched keys modified. EXEC will fail. */ +#define REDIS_CLOSE_AFTER_REPLY (1<<6) /* Close after writing entire reply. */ +#define REDIS_UNBLOCKED (1<<7) /* This client was unblocked and is stored in + server.unblocked_clients */ +#define REDIS_LUA_CLIENT (1<<8) /* This is a non connected client used by Lua */ +#define REDIS_ASKING (1<<9) /* Client issued the ASKING command */ +#define REDIS_CLOSE_ASAP (1<<10)/* Close this client ASAP */ +#define REDIS_UNIX_SOCKET (1<<11) /* Client connected via Unix domain socket */ +#define REDIS_DIRTY_EXEC (1<<12) /* EXEC will fail for errors while queueing */ /* Client request types */ #define REDIS_REQ_INLINE 1 @@ -168,8 +199,9 @@ #define REDIS_REPL_NONE 0 /* No active replication */ #define REDIS_REPL_CONNECT 1 /* Must connect to master */ #define REDIS_REPL_CONNECTING 2 /* Connecting to master */ -#define REDIS_REPL_TRANSFER 3 /* Receiving .rdb from master */ -#define REDIS_REPL_CONNECTED 4 /* Connected to master */ +#define REDIS_REPL_RECEIVE_PONG 3 /* Wait for PING reply */ +#define REDIS_REPL_TRANSFER 4 /* Receiving .rdb from master */ +#define REDIS_REPL_CONNECTED 5 /* Connected to master */ /* Synchronous read timeout - slave side */ #define REDIS_REPL_SYNCIO_TIMEOUT 5 @@ -257,6 +289,11 @@ #define REDIS_PROPAGATE_AOF 1 #define REDIS_PROPAGATE_REPL 2 +/* Using the following macro you can run code inside serverCron() with the + * specified period, specified in milliseconds. + * The actual resolution depends on REDIS_HZ. */ +#define run_with_period(_ms_) if (!(server.cronloops%((_ms_)/(1000/REDIS_HZ)))) + /* We can print the stacktrace, so our assert is defined this way: */ #define redisAssertWithInfo(_c,_o,_e) ((_e)?(void)0 : (_redisAssertWithInfo(_c,_o,#_e,__FILE__,__LINE__),_exit(1))) #define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1))) @@ -295,6 +332,7 @@ typedef struct redisDb { dict *dict; /* The keyspace for this DB */ dict *expires; /* Timeout of keys with a timeout set */ dict *blocking_keys; /* Keys with clients waiting for data (BLPOP) */ + dict *ready_keys; /* Blocked keys that received a PUSH */ dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */ int id; } redisDb; @@ -312,15 +350,30 @@ typedef struct multiState { } multiState; typedef struct blockingState { - robj **keys; /* The key we are waiting to terminate a blocking + dict *keys; /* The keys we are waiting to terminate a blocking * operation such as BLPOP. Otherwise NULL. */ - int count; /* Number of blocking keys */ time_t timeout; /* Blocking operation timeout. If UNIX current time * is >= timeout then the operation timed out. */ robj *target; /* The key that should receive the element, * for BRPOPLPUSH. */ } blockingState; +/* The following structure represents a node in the server.ready_keys list, + * where we accumulate all the keys that had clients blocked with a blocking + * operation such as B[LR]POP, but received new data in the context of the + * last executed command. + * + * After the execution of every command or script, we run this list to check + * if as a result we should serve data to clients blocked, unblocking them. + * Note that server.ready_keys will not have duplicates as there dictionary + * also called ready_keys in every structure representing a Redis database, + * where we make sure to remember if a given key was already added in the + * server.ready_keys list. */ +typedef struct readyList { + redisDb *db; + robj *key; +} readyList; + /* With multiplexing we need to take per-clinet state. * Clients are taken in a liked list. */ typedef struct redisClient { @@ -372,9 +425,10 @@ struct sharedObjectsStruct { *colon, *nullbulk, *nullmultibulk, *queued, *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr, *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr, - *masterdownerr, *roslaveerr, + *masterdownerr, *roslaveerr, *execaborterr, *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk, *unsubscribebulk, *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop, + *lpush, *select[REDIS_SHARED_SELECT_CMDS], *integers[REDIS_SHARED_INTEGERS], *mbulkhdr[REDIS_SHARED_BULKHDR_LEN], /* "*\r\n" */ @@ -440,7 +494,7 @@ typedef struct redisOpArray { struct redisServer { /* General */ redisDb *db; - dict *commands; /* Command table hahs table */ + dict *commands; /* Command table hash table */ aeEventLoop *el; unsigned lruclock:22; /* Clock incrementing every minute, for LRU */ unsigned lruclock_padding:10; @@ -451,6 +505,7 @@ struct redisServer { int arch_bits; /* 32 or 64 depending on sizeof(long) */ int cronloops; /* Number of times the cron function run */ char runid[REDIS_RUN_ID_SIZE+1]; /* ID always different at every exec. */ + int sentinel_mode; /* True if this instance is a Sentinel. */ /* Networking */ int port; /* TCP listening port */ char *bindaddr; /* Bind address or NULL */ @@ -469,7 +524,8 @@ struct redisServer { off_t loading_loaded_bytes; time_t loading_start_time; /* Fast pointers to often looked up command */ - struct redisCommand *delCommand, *multiCommand, *lpushCommand; + struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand, + *rpopCommand; /* Fields used only for stats */ time_t stat_starttime; /* Server start time */ long long stat_numcommands; /* Number of processed commands */ @@ -544,12 +600,14 @@ struct redisServer { char *masterauth; /* AUTH with this password with master */ char *masterhost; /* Hostname of master */ int masterport; /* Port of master */ - int repl_ping_slave_period; /* Master pings the salve every N seconds */ + int repl_ping_slave_period; /* Master pings the slave every N seconds */ int repl_timeout; /* Timeout after N seconds of master idle */ redisClient *master; /* Client that is master for this slave */ int repl_syncio_timeout; /* Timeout for synchronous I/O calls */ int repl_state; /* Replication status if the instance is a slave */ - off_t repl_transfer_left; /* Bytes left reading .rdb */ + off_t repl_transfer_size; /* Size of RDB to read from master during sync. */ + off_t repl_transfer_read; /* Amount of RDB read from master during sync. */ + off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */ int repl_transfer_s; /* Slave -> Master SYNC socket */ int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */ char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */ @@ -557,6 +615,7 @@ struct redisServer { int repl_serve_stale_data; /* Serve stale data when link is down? */ int repl_slave_ro; /* Slave is read only? */ time_t repl_down_since; /* Unix time at which link with master went down */ + int slave_priority; /* Reported in INFO and used by Sentinel. */ /* Limits */ unsigned int maxclients; /* Max number of simultaneous clients */ unsigned long long maxmemory; /* Max number of memory bytes to use */ @@ -565,9 +624,9 @@ struct redisServer { /* Blocked clients */ unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */ list *unblocked_clients; /* list of clients to unblock before next loop */ + list *ready_keys; /* List of readyList structures for BLPOP & co */ /* Sort parameters - qsort_r() is only available under BSD so we * have to take this state global, in order to pass it to sortCompare() */ - int sort_dontsort; int sort_desc; int sort_alpha; int sort_bypattern; @@ -695,6 +754,7 @@ extern struct sharedObjectsStruct shared; extern dictType setDictType; extern dictType zsetDictType; extern dictType dbDictType; +extern dictType shaScriptObjectDictType; extern double R_Zero, R_PosInf, R_NegInf, R_Nan; extern dictType hashDictType; @@ -775,7 +835,7 @@ int listTypeEqual(listTypeEntry *entry, robj *o); void listTypeDelete(listTypeEntry *entry); void listTypeConvert(robj *subject, int enc); void unblockClientWaitingData(redisClient *c); -int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele); +void handleClientsBlockedOnLists(void); void popGenericCommand(redisClient *c, int where); /* MULTI/EXEC/WATCH... */ @@ -786,6 +846,7 @@ void queueMultiCommand(redisClient *c); void touchWatchedKey(redisDb *db, robj *key); void touchWatchedKeysOnFlush(int dbid); void discardTransaction(redisClient *c); +void flagTransaction(redisClient *c); /* Redis object implementation */ void decrRefCount(void *o); @@ -972,6 +1033,12 @@ int *noPreloadGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numke int *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags); int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags); +/* Sentinel */ +void initSentinelConfig(void); +void initSentinel(void); +void sentinelTimer(void); +char *sentinelHandleConfiguration(char **argv, int argc); + /* Scripting */ void scriptingInit(void); @@ -1135,4 +1202,10 @@ void enableWatchdog(int period); void disableWatchdog(void); void watchdogScheduleSignal(int period); void redisLogHexDump(int level, char *descr, void *value, size_t len); + +#define redisDebug(fmt, ...) \ + printf("DEBUG %s:%d > " fmt "\n", __FILE__, __LINE__, __VA_ARGS__) +#define redisDebugMark() \ + printf("-- MARK %s:%d --\n", __FILE__, __LINE__) + #endif