Пример #1
0
/* Duplicate the whole list. On out of memory NULL is returned.
 * On success a copy of the original list is returned.
 *
 * The 'Dup' method set with listSetDupMethod() function is used
 * to copy the node value. Otherwise the same pointer value of
 * the original node is used as value of the copied node.
 *
 * The original list both on success or error is never modified. */
list *listDup(list *orig)
{
    list *copy;
    listIter *iter;
    listNode *node;

    if ((copy = listCreate()) == NULL)
        return NULL;
    copy->dup = orig->dup;
    copy->free = orig->free;
    copy->match = orig->match;
    iter = listGetIterator(orig, AL_START_HEAD);
    while((node = listNext(iter)) != NULL) {
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {
                listRelease(copy);
                listReleaseIterator(iter);
                return NULL;
            }
        } else
            value = node->value;
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            listReleaseIterator(iter);
            return NULL;
        }
    }
    listReleaseIterator(iter);
    return copy;
}
Пример #2
0
/*
 * 订阅一个频道,订阅成功返回 1, 如果返回 0, 则客户端已经订阅过这个频道
 */
int pubsubSubscribeChannel(redisClient *c, robj *channel) {
    dictEntry *de;
    list *clients = NULL;
    int retval = 0;

    /* Add the channel to the client -> channels hash table */
    if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) {
        retval = 1;
        incrRefCount(channel);
        /* Add the client to the channel -> list of clients hash table */
        de = dictFind(server.pubsub_channels,channel);
        if (de == NULL) {
            clients = listCreate();
            dictAdd(server.pubsub_channels,channel,clients);
            incrRefCount(channel);
        } else {
            clients = dictGetVal(de);
        }
        listAddNodeTail(clients,c);
    }
    /* Notify the client */
    addReply(c,shared.mbulkhdr[3]);
    addReply(c,shared.subscribebulk);
    addReplyBulk(c,channel);
    addReplyLongLong(c,clientSubscriptionsCount(c));
    return retval;
}
/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. 
 *
 * 设置客户端 c 订阅模式 pattern 。
 *
 * 订阅成功返回 1 ,如果客户端已经订阅了该模式,那么返回 0 。
 */
int pubsubSubscribePattern(redisClient *c, robj *pattern) {
    int retval = 0;

    // 在链表中查找模式,看客户端是否已经订阅了这个模式
    // 这里为什么不像 channel 那样,用字典来进行检测呢?
    // 虽然 pattern 的数量一般来说并不多
    if (listSearchKey(c->pubsub_patterns,pattern) == NULL) {
        
        // 如果没有的话,执行以下代码

        retval = 1;

        pubsubPattern *pat;

        // 将 pattern 添加到 c->pubsub_patterns 链表中
        listAddNodeTail(c->pubsub_patterns,pattern);

        incrRefCount(pattern);

        // 创建并设置新的 pubsubPattern 结构
        pat = zmalloc(sizeof(*pat));
        pat->pattern = getDecodedObject(pattern);
        pat->client = c;

        // 添加到末尾
        listAddNodeTail(server.pubsub_patterns,pat);
    }

    /* Notify the client */
    // 回复客户端。
    // 示例:
    // redis 127.0.0.1:6379> PSUBSCRIBE xxx*
    // Reading messages... (press Ctrl-C to quit)
    // 1) "psubscribe"
    // 2) "xxx*"
    // 3) (integer) 1
    addReply(c,shared.mbulkhdr[3]);
    // 回复 "psubscribe" 字符串
    addReply(c,shared.psubscribebulk);
    // 回复被订阅的模式
    addReplyBulk(c,pattern);
    // 回复客户端订阅的频道和模式的总数
    addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns));

    return retval;
}
Пример #4
0
redisClient *createClient(int fd) {
    redisClient *c = zmalloc(sizeof(redisClient));

    /* passing -1 as fd it is possible to create a non connected client.
     * This is useful since all the Redis commands needs to be executed
     * in the context of a client. When commands are executed in other
     * contexts (for instance a Lua script) we need a non connected client. */
    if (fd != -1) {
        anetNonBlock(NULL,fd);
        anetEnableTcpNoDelay(NULL,fd);
        if (server.tcpkeepalive)
            anetKeepAlive(NULL,fd,server.tcpkeepalive);
        if (aeCreateFileEvent(server.el,fd,AE_READABLE,
            readQueryFromClient, c) == AE_ERR)
        {
            close(fd);
            zfree(c);
            return NULL;
        }
    }

    selectDb(c,0);
    c->fd = fd;
    c->name = NULL;
    c->bufpos = 0;
    c->querybuf = sdsempty();
    c->querybuf_peak = 0;
    c->reqtype = 0;
    c->argc = 0;
    c->argv = NULL;
    c->cmd = c->lastcmd = NULL;
    c->multibulklen = 0;
    c->bulklen = -1;
    c->sentlen = 0;
    c->flags = 0;
    c->ctime = c->lastinteraction = server.unixtime;
    c->authenticated = 0;
    c->replstate = REDIS_REPL_NONE;
    c->slave_listening_port = 0;
    c->reply = listCreate();
    c->reply_bytes = 0;
    c->obuf_soft_limit_reached_time = 0;
    listSetFreeMethod(c->reply,decrRefCount);
    listSetDupMethod(c->reply,dupClientReplyValue);
    c->bpop.keys = dictCreate(&setDictType,NULL);
    c->bpop.timeout = 0;
    c->bpop.target = NULL;
    c->io_keys = listCreate();
    c->watched_keys = listCreate();
    listSetFreeMethod(c->io_keys,decrRefCount);
    c->pubsub_channels = dictCreate(&setDictType,NULL);
    c->pubsub_patterns = listCreate();
    listSetFreeMethod(c->pubsub_patterns,decrRefCount);
    listSetMatchMethod(c->pubsub_patterns,listMatchObjects);
    if (fd != -1) listAddNodeTail(server.clients,c);
    initClientMultiState(c);
    return c;
}
Пример #5
0
// HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS
static void addHttpResponseHeader(sds name, sds value) {
    if (!server.alc.CurrClient->http.resp_hdr) {
        server.alc.CurrClient->http.resp_hdr       = listCreate(); 
        server.alc.CurrClient->http.resp_hdr->free = free_two_sds;
    }
    two_sds *ss = init_two_sds(name, value);
    // Store RESP Headers in List
    listAddNodeTail(server.alc.CurrClient->http.resp_hdr, ss);
}
/* Subscribe a client to a channel. Returns 1 if the operation succeeded, or
 * 0 if the client was already subscribed to that channel. 
 *
 * 设置客户端 c 订阅频道 channel 。
 *
 * 订阅成功返回 1 ,如果客户端已经订阅了该频道,那么返回 0 。
 */
int pubsubSubscribeChannel(redisClient *c, robj *channel) {
    dictEntry *de;
    list *clients = NULL;
    int retval = 0;

    /* Add the channel to the client -> channels hash table */
    // 将 channels 填接到 c->pubsub_channels 的集合中(值为 NULL 的字典视为集合)
    if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) {
        retval = 1;
        incrRefCount(channel);

        // 关联示意图
        // {
        //  频道名        订阅频道的客户端
        //  'channel-a' : [c1, c2, c3],
        //  'channel-b' : [c5, c2, c1],
        //  'channel-c' : [c10, c2, c1]
        // }
        /* Add the client to the channel -> list of clients hash table */
        // 从 pubsub_channels 字典中取出保存着所有订阅了 channel 的客户端的链表
        // 如果 channel 不存在于字典,那么添加进去
        de = dictFind(server.pubsub_channels,channel);
        if (de == NULL) {
            clients = listCreate();
            dictAdd(server.pubsub_channels,channel,clients);
            incrRefCount(channel);
        } else {
            clients = dictGetVal(de);
        }

        // before:
        // 'channel' : [c1, c2]
        // after:
        // 'channel' : [c1, c2, c3]
        // 将客户端添加到链表的末尾
        listAddNodeTail(clients,c);
    }

    /* Notify the client */
    // 回复客户端。
    // 示例:
    // redis 127.0.0.1:6379> SUBSCRIBE xxx
    // Reading messages... (press Ctrl-C to quit)
    // 1) "subscribe"
    // 2) "xxx"
    // 3) (integer) 1
    addReply(c,shared.mbulkhdr[3]);
    // "subscribe\n" 字符串
    addReply(c,shared.subscribebulk);
    // 被订阅的客户端
    addReplyBulk(c,channel);
    // 客户端订阅的频道和模式总数
    addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns));

    return retval;
}
Пример #7
0
static void unmapFDToIndex(aeEventLoop *eventLoop, socket_t s)
{
    fdi_t fdi = lookupFDI(eventLoop, s);
    if (fdi == INVALID_FDI)
    {
        return;
    }
    dictDelete(eventLoop->fdiMap->map, (void *)s);
    listAddNodeTail(eventLoop->fdiMap->recycle_pool, (void *)fdi);
}
Пример #8
0
void create_list()
{
    int		 n,i;
    int		*elem;
    list	*ll;
    ll=listCreate();
    printf("给你的链表起个名字吧:(限于字母)");
    scanf("%s",ll->name);
    printf("输入初始化时候链表需要插入多少元素:");
    scanf("%d",&n);
    printf("依次输入插入的元素:");
    for(i=0;i<n;i++){
	elem=(int*)malloc(sizeof(int));
	scanf("%d",elem);
	ll=listAddNodeTail(ll,elem);
    }
    listall=listAddNodeTail(listall,ll);
    printf("创建完毕!\n");
}
Пример #9
0
robj *rdbLoadNRL(FILE *fp) {
    robj         *iname;
    unsigned int  u;
    d_l_t *nrlind  = malloc(sizeof(d_l_t));
    nrlind->l1     = listCreate();
    list  *nrltoks = nrlind->l1;
    nrlind->l2     = listCreate();
    list  *nrlcols = nrlind->l2;

    if ((u = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL;
    nrlind->num = (int)u;
    int imatch  = nrlind->num;
    if (!(iname = rdbLoadStringObject(fp))) return NULL;
    if ((u = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL;
    int tmatch  = (int)u;

    unsigned int ssize;
    if ((ssize = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL;
    for (uint32 i = 0; i < ssize; i++) {
        robj *r;
        if (!(r = rdbLoadStringObject(fp))) return NULL;
        listAddNodeTail(nrltoks, sdsdup(r->ptr));
        decrRefCount(r);
    }

    if ((ssize = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL;
    for (uint32 i = 0; i < ssize; i++) {
        uint32 col;
        if ((col = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL;
        listAddNodeTail(nrlcols, (void *)(long)col);
    }
    Index[server.dbid][imatch].obj     = iname;
    Index[server.dbid][imatch].table   = tmatch;
    Index[server.dbid][imatch].column  = -1;
    Index[server.dbid][imatch].type    = COL_TYPE_NONE;
    Index[server.dbid][imatch].virt    = 0;
    Index[server.dbid][imatch].nrl     = 1;
    int dbid = server.dbid;
    if (Num_indx[dbid] < (imatch + 1)) Num_indx[dbid] = imatch + 1;

    return createObject(REDIS_NRL_INDEX, nrlind);
}
Пример #10
0
/*
 * 监视给定 key
 *
 * T = O(N)
 */
void watchForKey(redisClient *c, robj *key)
{
    list *clients = NULL;
    listIter li;
    listNode *ln;
    watchedKey *wk;

    /* Check if we are already watching for this key */
    // 检查该 key 是否已经被 WATCH
    // (出现在 WATCH 命令调用时一个 key 被输入多次的情况)
    // 如果是的话,直接返回
    // O(N)
    listRewind(c->watched_keys,&li);
    while((ln = listNext(&li)))
    {
        wk = listNodeValue(ln);
        if (wk->db == c->db && equalStringObjects(key,wk->key))
            return; /* Key already watched */
    }

    // key 未被监视
    // 根据 key ,将客户端加入到 DB 的监视 key 字典中
    /* This key is not already watched in this DB. Let's add it */
    // O(1)
    clients = dictFetchValue(c->db->watched_keys,key);
    if (!clients)
    {
        clients = listCreate();
        dictAdd(c->db->watched_keys,key,clients);
        incrRefCount(key);
    }
    listAddNodeTail(clients,c);

    // 将 key 添加到客户端的监视列表中
    /* Add the new key to the lits of keys watched by this client */
    // O(1)
    wk = zmalloc(sizeof(*wk));
    wk->key = key;
    wk->db = c->db;
    incrRefCount(key);
    listAddNodeTail(c->watched_keys,wk);
}
Пример #11
0
/* node can be NULL so node_name is a seperate parameter. */
shard *counterAddShard(counter *cntr, clusterNode* node, const char *node_name) {
    shard *shrd = zcalloc(sizeof(shard));
    shrd->node = node;
    memcpy(shrd->node_name,node_name,CLUSTER_NAMELEN);
    if (node == myself) {
        serverAssert(cntr->myshard == NULL);
        cntr->myshard = shrd;
    }
    listAddNodeTail(cntr->shards, shrd);
    return shrd;
}
Пример #12
0
/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. */
int pubsubSubscribePattern(redisClient *c, robj *pattern) {
    int retval = 0;

    if (listSearchKey(c->pubsub_patterns,pattern) == NULL) {
        retval = 1;
        pubsubPattern *pat;
        listAddNodeTail(c->pubsub_patterns,pattern);
        incrRefCount(pattern);
        pat = zmalloc(sizeof(*pat));
        pat->pattern = getDecodedObject(pattern);
        pat->client = c;
        listAddNodeTail(server.pubsub_patterns,pat);
    }
    /* Notify the client */
    addReply(c,shared.mbulkhdr[3]);
    addReply(c,shared.psubscribebulk);
    addReplyBulk(c,pattern);
    addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns));
    return retval;
}
Пример #13
0
void addReply(redisClient *c, robj *obj) {
    if (listLength(c->reply) == 0 &&
        (c->replstate == REDIS_REPL_NONE ||
         c->replstate == REDIS_REPL_ONLINE) &&
        aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,
        sendReplyToClient, c) == AE_ERR) return;

    if (server.vm_enabled && obj->storage != REDIS_VM_MEMORY) {
        obj = dupStringObject(obj);
        obj->refcount = 0; /* getDecodedObject() will increment the refcount */
    }
    listAddNodeTail(c->reply,getDecodedObject(obj));
}
Пример #14
0
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
    struct bio_job *job = zmalloc(sizeof(*job));

    job->time = time(NULL);
    job->arg1 = arg1;
    job->arg2 = arg2;
    job->arg3 = arg3;
    pthread_mutex_lock(&bio_mutex[type]);
    listAddNodeTail(bio_jobs[type],job);
    bio_pending[type]++;
    pthread_cond_signal(&bio_condvar[type]);
    pthread_mutex_unlock(&bio_mutex[type]);
}
Пример #15
0
// WATCH 某个 KEY
void watchForKey(redisClient *c, robj *key) {
    list *clients = NULL;
    listIter li;
    listNode *ln;
    watchedKey *wk;

    /* Check if we are already watching for this key */
    // 所有被 WATCHED 的 KEY 都被放在 redisClient.watched_keys 链表中
    // 遍历这个链表,查看这个 KEY 是否已经处于监视状态(WATCHED)
    listRewind(c->watched_keys,&li);
    while((ln = listNext(&li))) {
        wk = listNodeValue(ln);
        if (wk->db == c->db && equalStringObjects(key,wk->key))
            return; /* Key already watched */
    }

    /* This key is not already watched in this DB. Let's add it */
    // 如果 KEY 还没有被 WATCH 过,那么对它进行 WATCH
    clients = dictFetchValue(c->db->watched_keys,key);
    if (!clients) { 
        // 如果 clients 链表不存在
        // 说明这个客户端是第一个监视这个 DB 的这个 KEY 的客户端
        // 那么 clients 创建链表,并将它添加到 c->db->watched_keys 字典中
        clients = listCreate();
        dictAdd(c->db->watched_keys,key,clients);
        incrRefCount(key);
    }
    // 将客户端添加到 clients 链表
    listAddNodeTail(clients,c); 

    /* Add the new key to the lits of keys watched by this client */
    // 除了 c->db->watched_keys 之外
    // 还要将被 WATCH 的 KEY 添加到 c->watched_keys
    wk = zmalloc(sizeof(*wk));
    wk->key = key;
    wk->db = c->db;
    incrRefCount(key);
    listAddNodeTail(c->watched_keys,wk);
}
Пример #16
0
redisClient *createClient(int fd) {
    redisClient *c = zmalloc(sizeof(redisClient));
    c->bufpos = 0;

    anetNonBlock(NULL,fd);
    anetTcpNoDelay(NULL,fd);
    if (!c) return NULL;
    if (aeCreateFileEvent(server.el,fd,AE_READABLE,
                          readQueryFromClient, c) == AE_ERR)
    {
#ifdef _WIN32
        closesocket(fd);
#else
        close(fd);
#endif
        zfree(c);
        return NULL;
    }

    selectDb(c,0);
    c->fd = fd;
    c->querybuf = sdsempty();
    c->reqtype = 0;
    c->argc = 0;
    c->argv = NULL;
    c->multibulklen = 0;
    c->bulklen = -1;
    c->sentlen = 0;
    c->flags = 0;
    c->lastinteraction = time(NULL);
    c->authenticated = 0;
    c->replstate = REDIS_REPL_NONE;
    c->reply = listCreate();
    listSetFreeMethod(c->reply,decrRefCount);
    listSetDupMethod(c->reply,dupClientReplyValue);
    c->bpop.keys = NULL;
    c->bpop.count = 0;
    c->bpop.timeout = 0;
    c->bpop.target = NULL;
    c->io_keys = listCreate();
    c->watched_keys = listCreate();
    listSetFreeMethod(c->io_keys,decrRefCount);
    c->pubsub_channels = dictCreate(&setDictType,NULL);
    c->pubsub_patterns = listCreate();
    listSetFreeMethod(c->pubsub_patterns,decrRefCount);
    listSetMatchMethod(c->pubsub_patterns,listMatchObjects);
    listAddNodeTail(server.clients,c);
    initClientMultiState(c);
    return c;
}
Пример #17
0
ugClient *createClient(int fd) {
    ugClient *c = zmalloc(sizeof(ugClient));
    memset(c,0,sizeof(ugClient));
    if (fd != -1) {
        anetNonBlock(NULL,fd);
        anetEnableTcpNoDelay(NULL,fd);
        if (server.tcpkeepalive)
            anetKeepAlive(NULL, fd, server.tcpkeepalive);
        if (aeCreateFileEvent(server.el, fd, AE_READABLE,
                              readQueryFromClient, c) == AE_ERR) {
#ifdef _WIN32
            aeWinCloseSocket(fd);
#else
            close(fd);
#endif
            zfree(c);
            return NULL;
        }
    }

    if (server.config->password == NULL) {
        c->authenticated = 1;
    }
    c->querybuf = sdsempty();
    c->fd = fd;
    c->ctime = c->lastinteraction = time(NULL);
    c->multibulklen = 0;
    c->bulklen = -1;
    c->reply = listCreate();

    c->reply_bytes = 0;
    c->bufpos = 0;
    c->sentlen = 0;
    /* listSetDupMethod(c->reply, listDupReplyObjects); */
    listSetFreeMethod(c->reply, listFreeReplyObjects);

    c->pubsub_channels = dictCreate(&callbackDict, NULL);
    c->pubsub_patterns = listCreate();
    listSetMatchMethod(c->pubsub_patterns, listMatchPubsubPattern);
    listSetFreeMethod(c->pubsub_patterns, listFreePubsubPattern);
    /* c->pubsub_patterns = listCreate(); */
    if (!server.clients) {
        server.clients = createClientlist();
    }

    listAddNodeTail(server.clients, c);

    return c;
}
Пример #18
0
void dup_list()
{
    listNode	*node;
    list	*orig=found_list(&node);
    list	*ll;
    if(orig){
	ll=listDup(orig);
	printf("输入复制过后的链表名称:");
	scanf("%s",(ll->name));
	listall=listAddNodeTail(listall,ll);
	printf("复制成功\n");
    }else{
	printf("没有这个链表\n");
    }
}
Пример #19
0
/* Watch for the specified key */
void watchForKey(redisClient *c, robj *key) {
    list *clients = NULL;
    listIter li;
    listNode *ln;
    watchedKey *wk;

    // 是否已经监视该键值
    /* Check if we are already watching for this key */
    listRewind(c->watched_keys,&li);
    while((ln = listNext(&li))) {
        wk = listNodeValue(ln);
        if (wk->db == c->db && equalStringObjects(key,wk->key))
            return; /* Key already watched */
    }

    // 获取监视该键值的客户端链表
    /* This key is not already watched in this DB. Let's add it */
    clients = dictFetchValue(c->db->watched_keys,key);
    // 如果不存在链表,需要新建一个
    if (!clients) {
        clients = listCreate();
        dictAdd(c->db->watched_keys,key,clients);
        incrRefCount(key);
    }

    // 尾插法。将客户端添加到链表尾部
    listAddNodeTail(clients,c);

    // 将监视键添加到 redisClient.watched_keys 的尾部
    /* Add the new key to the list of keys watched by this client */
    wk = zmalloc(sizeof(*wk));
    wk->key = key;
    wk->db = c->db;
    incrRefCount(key);
    listAddNodeTail(c->watched_keys,wk);
}
Пример #20
0
/* Parses "xxx$col1 yyy$col2 zzz" -> "xxx[col1] yyy[col2] zzz" */
bool parseNRLcmd(char *o_s, list *nrltoks, list *nrlcols, int tmatch) {
    char *s   = strchr(o_s, '$');
    if (!s) {
       listAddNodeTail(nrltoks, sdsdup(o_s)); /* freed in freeNrlIndexObject */
    } else {
        while (1) {
            s++; /* advance past "$" */
            char *nxo  = s;
            while (isalnum(*nxo) || *nxo == '_') nxo++; /* col must be alpnum */
            int   cmatch = find_column_n(tmatch, s, nxo - s);
            if (cmatch == -1) return 0;
            listAddNodeTail(nrlcols, (void *)(long)(cmatch + 1)); /* 0!=NULL */
            listAddNodeTail(nrltoks, sdsnewlen(o_s, (s - 1) - o_s)); /*no "$"*/
            char *nexts  = strchr(s, '$');              /* var is '$' delimed */
            if (!nexts) { /* no more vars */
                if (*nxo) listAddNodeTail(nrltoks, sdsnewlen(nxo, strlen(nxo)));
                break;
            }
            o_s = nxo;
            s   = nexts;
        }
    }
    return 1;
}
Пример #21
0
// 让client监视所有的指定的key
void watchForKey(client *c, robj *key) {
    list *clients = NULL;
    listIter li;
    listNode *ln;
    watchedKey *wk;

    /* Check if we are already watching for this key */
    listRewind(c->watched_keys,&li);
    // 遍历客户端监视的键的链表,检查是否已经监视了指定的键
    while((ln = listNext(&li))) {
        wk = listNodeValue(ln);
        // 如果键已经被监视,则直接返回
        if (wk->db == c->db && equalStringObjects(key,wk->key))
            return; /* Key already watched */
    }
    /* This key is not already watched in this DB. Let's add it */
    // 如果数据库中该键没有被client监视则添加它
    clients = dictFetchValue(c->db->watched_keys,key);
    // 没有被client监视
    if (!clients) {
        // 创建一个空链表
        clients = listCreate();
        // 值是被client监控的key,键是client,添加到数据库的watched_keys字典中
        dictAdd(c->db->watched_keys,key,clients);
        incrRefCount(key);
    }
    // 将当前client添加到监视该key的client链表的尾部
    listAddNodeTail(clients,c);
    /* Add the new key to the list of keys watched by this client */
    // 将新的被监视的key和与该key关联的数据库加入到客户端的watched_keys中
    wk = zmalloc(sizeof(*wk));
    wk->key = key;
    wk->db = c->db;
    incrRefCount(key);
    listAddNodeTail(c->watched_keys,wk);
}
Пример #22
0
//创建一个后台任务
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
    struct bio_job *job = zmalloc(sizeof(*job));

    //初始化变量
    job->time = time(NULL);
    job->arg1 = arg1;
    job->arg2 = arg2;
    job->arg3 = arg3;
    //多线程环境,操作任务队列时,需要使用mutex防止冲突
    pthread_mutex_lock(&bio_mutex[type]);
    listAddNodeTail(bio_jobs[type],job);
    bio_pending[type]++;
    //通知操作线程有新任务添加
    pthread_cond_signal(&bio_condvar[type]);
    pthread_mutex_unlock(&bio_mutex[type]);
}
Пример #23
0
static client createClient(void) {
    client c = zmalloc(sizeof(struct _client));

    c->context = redisAsyncConnect(config.hostip,config.hostport);
    c->context->data = c;
    redisAsyncSetDisconnectCallback(c->context,clientDisconnected);
    if (c->context->err) {
        fprintf(stderr,"Connect: %s\n",c->context->errstr);
        exit(1);
    }

    redisAeAttach(config.el,c->context);
    listAddNodeTail(config.clients,c);
    issueRequest(c);
    return c;
}
Пример #24
0
/* Unblock a client calling the right function depending on the kind
 * of operation the client is blocking for.
 * 不阻塞客户端
 * 取消给定的客户端的阻塞状态*/
void unblockClient(redisClient *c) {
    if (c->btype == REDIS_BLOCKED_LIST) {
        unblockClientWaitingData(c);
    } else if (c->btype == REDIS_BLOCKED_WAIT) {
        unblockClientWaitingReplicas(c);
    } else {
        redisPanic("Unknown btype in unblockClient().");
    }
    /* Clear the flags, and put the client in the unblocked list so that
     * we'll process new commands in its query buffer ASAP. */
    c->flags &= ~REDIS_BLOCKED;
    c->flags |= REDIS_UNBLOCKED;
    c->btype = REDIS_BLOCKED_NONE;
    server.bpop_blocked_clients--;
    listAddNodeTail(server.unblocked_clients,c);
}
Пример #25
0
list *listDup(list *orign)
/*{{{*/
{
    list *cpy;
    listIter *iter;
    listNode *node;

    if((cpy = listCreate()) == NULL)
    {
        return NULL;
    }

    cpy->free = orign->free;
    cpy->dup = orign->dup;
    cpy->match = orign->match;

    iter = listGetIterator(orign, AL_START_HEAD);
    while((node = listNext(iter)) != NULL)
    {
        void *value;
        if(cpy->dup)
        {
            value = cpy->dup(node->value);
            if(value == NULL)
            {
                listRelease(cpy);
                listReleaseIterator(iter);
                return NULL;
            }
        }
        else
        {
            value = node->value;
        }

        //出错只有一种情况,就是malloc失败了,return NULL;
        if(listAddNodeTail(cpy, value) == NULL)
        {
            listRelease(cpy);
            listReleaseIterator(iter);
            return NULL;
        }
    }
    listReleaseIterator(iter);
    return cpy;
}
Пример #26
0
/**
 *创建后台作业部分 只对aof部分
 */
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {
    struct bio_job *job = zmalloc(sizeof(*job));

    job->time = time(NULL);
    job->arg1 = arg1;
    job->arg2 = arg2;
    job->arg3 = arg3;
    pthread_mutex_lock(&bio_mutex[type]);
    listAddNodeTail(bio_jobs[type],job);
    bio_pending[type]++;
    /**
    pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。
但使用pthread_cond_signal不会有“惊群现象”产生,他最多只给一个线程发信号。假如有多个线程正在阻塞等待着这个条件变量的话,那么是根据各等待线程优先级的高低确定哪个线程接收到信号开始继续执行。如果各线程优先级相同,则根据等待时间的长短来确定哪个线程获得信号。但无论如何一个pthread_cond_signal调用最多发信一次。
另外,互斥量的作用一般是用于对某个资源进行互斥性的存取,很多时候是用来保证操作是一个原子性的操作,是不可中断的。
     */
    pthread_cond_signal(&bio_condvar[type]);
    pthread_mutex_unlock(&bio_mutex[type]);
}
Пример #27
0
/* monitor state changes for a socket */
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
    aeApiState *state = (aeApiState *)eventLoop->apidata;
    aeSockState *sockstate = aeGetSockState(state, fd);
    if (sockstate == NULL) {
        errno = WSAEINVAL;
        return -1;
    }

    if (mask & AE_READABLE) {
        sockstate->masks |= AE_READABLE;
        if ((sockstate->masks & CONNECT_PENDING) == 0) {
            if (sockstate->masks & LISTEN_SOCK) {
                /* actually a listen. Do not treat as read */
            } else {
                if ((sockstate->masks & READ_QUEUED) == 0) {
                    // queue up a 0 byte read
                    aeWinReceiveDone(fd);
                }
            }
        }
    }
    if (mask & AE_WRITABLE) {
        sockstate->masks |= AE_WRITABLE;
        if ((sockstate->masks & CONNECT_PENDING) == 0) {
            // if no write active, then need to queue write ready
            if (sockstate->wreqs == 0) {
                asendreq *areq = (asendreq *)zmalloc(sizeof(asendreq));
                memset(areq, 0, sizeof(asendreq));
                if (PostQueuedCompletionStatus(state->iocp,
                                            0,
                                            fd,
                                            &areq->ov) == 0) {
                    errno = GetLastError();
                    zfree(areq);
                    return -1;
                }
                sockstate->wreqs++;
                listAddNodeTail(&sockstate->wreqlist, areq);
            }
        }
    }
    return 0;
}
Пример #28
0
int continue_http_session(cli *c) {
    if (c->argc < 2) return 1; // IGNORE Headers w/ no values
    if (!strcasecmp(c->argv[0]->ptr, "Connection:")) {
        if (!strcasecmp(c->argv[1]->ptr, "Keep-Alive")) c->http.ka = 1;
        if (!strcasecmp(c->argv[1]->ptr, "Close"))      c->http.ka = 0;
    }
    if (!strcasecmp(c->argv[0]->ptr, "Content-Length:")) {
      c->http.req_clen = atoi(c->argv[1]->ptr);
    }
    sds hval = sdsdup(c->argv[1]->ptr);                  // DESTROY ME 084
    for (int i = 2; i < c->argc; i++) {
        hval = sdscatlen(hval, " ", 1); //TODO this assumes single space
        hval = sdscatlen(hval, c->argv[i]->ptr, sdslen(c->argv[i]->ptr));
    }
    two_sds *ss = init_two_sds(c->argv[0]->ptr, hval);
    sdsfree(hval);                                       // DESTROYED 084
    listAddNodeTail(c->http.req_hdr, ss); // Store REQ Headers in List
    return 1;
}
Пример #29
0
void insert_list()
{
    listNode	*node;
    list	*ll=found_list(&node);
    int		*elem;

    if(ll){
	elem=(int*)malloc(sizeof(int));
	printf("输入要插入的元素:");
	scanf("%d",elem);
	if((listAddNodeTail(ll,elem))!=NULL){
	    printf("插入成功\n");
	}else{
	    printf("插入失败\n");
	}
    }else{
	printf("没有这个链表\n");
    }
}
Пример #30
0
static client createClient(char *cmd, size_t len) {
    int j;
    client c = zmalloc(sizeof(struct _client));

    if (config.hostsocket == NULL) {
        c->context = redisConnectNonBlock(config.hostip,config.hostport);
    } else {
        c->context = redisConnectUnixNonBlock(config.hostsocket);
    }
    if (c->context->err) {
        fprintf(stderr,"Could not connect to Redis at ");
        if (config.hostsocket == NULL)
            fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,c->context->errstr);
        else
            fprintf(stderr,"%s: %s\n",config.hostsocket,c->context->errstr);
        exit(1);
    }
    /* Suppress hiredis cleanup of unused buffers for max speed. */
    c->context->reader->maxbuf = 0;
    /* Queue N requests accordingly to the pipeline size. */
    c->obuf = sdsempty();
    for (j = 0; j < config.pipeline; j++)
        c->obuf = sdscatlen(c->obuf,cmd,len);
    c->randlen = 0;
    c->written = 0;
    c->pending = config.pipeline;

    /* Find substrings in the output buffer that need to be randomized. */
    if (config.randomkeys) {
        char *p = c->obuf;
        while ((p = strstr(p,":rand:")) != NULL) {
            assert(c->randlen < (signed)(sizeof(c->randptr)/sizeof(char*)));
            c->randptr[c->randlen++] = p+6;
            p += 6;
        }
    }

/*    redisSetReplyObjectFunctions(c->context,NULL); */
    aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);
    listAddNodeTail(config.clients,c);
    config.liveclients++;
    return c;
}