}
if (aeCreateFileEvent(server.el, server.cfd, AE_READABLE,
clusterAcceptHandler, NULL) == AE_ERR) oom("creating file event");
+ server.cluster.slots_to_keys = zslCreate();
}
/* -----------------------------------------------------------------------------
#include <signal.h>
+void SlotToKeyAdd(robj *key);
+void SlotToKeyDel(robj *key);
+
/*-----------------------------------------------------------------------------
* C-level DB API
*----------------------------------------------------------------------------*/
sds copy = sdsdup(key->ptr);
dictAdd(db->dict, copy, val);
if (server.ds_enabled) cacheSetKeyMayExist(db,key);
+ if (server.cluster_enabled) SlotToKeyAdd(key);
return REDIS_OK;
}
}
if ((oldval = dictFetchValue(db->dict,key->ptr)) == NULL) {
sds copy = sdsdup(key->ptr);
dictAdd(db->dict, copy, val);
+ if (server.cluster_enabled) SlotToKeyAdd(key);
retval = 1;
} else {
dictReplace(db->dict, key->ptr, val);
/* Deleting an entry from the expires dict will not free the sds of
* the key, because it is shared with the main dictionary. */
if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);
- return dictDelete(db->dict,key->ptr) == DICT_OK;
+ if (dictDelete(db->dict,key->ptr) == DICT_OK) {
+ if (server.cluster_enabled) SlotToKeyDel(key);
+ return 1;
+ } else {
+ return 0;
+ }
}
/* Empty the whole database.
*numkeys = num;
return keys;
}
+
+/* Slot to Key API. This is used by Redis Cluster in order to obtain in
+ * a fast way a key that belongs to a specified hash slot. This is useful
+ * while rehashing the cluster. */
+void SlotToKeyAdd(robj *key) {
+ unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));
+
+ zslInsert(server.cluster.slots_to_keys,hashslot,key);
+ incrRefCount(key);
+}
+
+void SlotToKeyDel(robj *key) {
+ unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));
+
+ zslDelete(server.cluster.slots_to_keys,hashslot,key);
+}
+
+robj *GetKeyInSlot(unsigned int hashslot) {
+ zskiplistNode *n;
+ zrangespec range;
+
+ range.min = range.max = hashslot;
+ range.minex = range.maxex = 0;
+
+ n = zslFirstInRange(server.cluster.slots_to_keys, range);
+ if (!n) return NULL;
+ return n->obj;
+}
*integers[REDIS_SHARED_INTEGERS];
};
+/* ZSETs use a specialized version of Skiplists */
+typedef struct zskiplistNode {
+ robj *obj;
+ double score;
+ struct zskiplistNode *backward;
+ struct zskiplistLevel {
+ struct zskiplistNode *forward;
+ unsigned int span;
+ } level[];
+} zskiplistNode;
+
+typedef struct zskiplist {
+ struct zskiplistNode *header, *tail;
+ unsigned long length;
+ int level;
+} zskiplist;
+
+typedef struct zset {
+ dict *dict;
+ zskiplist *zsl;
+} zset;
+
/*-----------------------------------------------------------------------------
* Redis cluster data structures
*----------------------------------------------------------------------------*/
clusterNode *migrating_slots_to[REDIS_CLUSTER_SLOTS];
clusterNode *importing_slots_from[REDIS_CLUSTER_SLOTS];
clusterNode *slots[REDIS_CLUSTER_SLOTS];
+ zskiplist *slots_to_keys;
} clusterState;
/* Redis cluster messages header */
/* Misc */
unsigned lruclock:22; /* clock incrementing every minute, for LRU */
unsigned lruclock_padding:10;
+ /* Cluster */
int cluster_enabled;
clusterState cluster;
};
robj *pattern;
} redisSortOperation;
-/* ZSETs use a specialized version of Skiplists */
-typedef struct zskiplistNode {
- robj *obj;
- double score;
- struct zskiplistNode *backward;
- struct zskiplistLevel {
- struct zskiplistNode *forward;
- unsigned int span;
- } level[];
-} zskiplistNode;
-
-typedef struct zskiplist {
- struct zskiplistNode *header, *tail;
- unsigned long length;
- int level;
-} zskiplist;
-
-typedef struct zset {
- dict *dict;
- zskiplist *zsl;
-} zset;
-
/* DIsk store threaded I/O request message */
#define REDIS_IOJOB_LOAD 0
#define REDIS_IOJOB_SAVE 1
void backgroundRewriteDoneHandler(int exitcode, int bysignal);
/* Sorted sets data type */
+
+/* Struct to hold a inclusive/exclusive range spec. */
+typedef struct {
+ double min, max;
+ int minex, maxex; /* are min or max exclusive? */
+} zrangespec;
+
zskiplist *zslCreate(void);
void zslFree(zskiplist *zsl);
zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj);
unsigned char *zzlInsert(unsigned char *zl, robj *ele, double score);
+int zslDelete(zskiplist *zsl, double score, robj *obj);
+zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec range);
double zzlGetScore(unsigned char *sptr);
void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);
void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);
return 0; /* not found */
}
-/* Struct to hold a inclusive/exclusive range spec. */
-typedef struct {
- double min, max;
- int minex, maxex; /* are min or max exclusive? */
-} zrangespec;
-
static int zslValueGteMin(double value, zrangespec *spec) {
return spec->minex ? (value > spec->min) : (value >= spec->min);
}