Ejemplo n.º 1
0
/* Set a client in blocking mode for the specified key, with the specified
 * timeout */
void blockForKeys(redisClient *c, robj **keys, int numkeys, mstime_t timeout, robj *target) {
    dictEntry *de;
    list *l;
    int j;

    c->bpop.timeout = timeout;
    c->bpop.target = target;

    if (target != NULL) incrRefCount(target);

    for (j = 0; j < numkeys; j++) {
        /* If the key already exists in the dict ignore it. */
        if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;
        incrRefCount(keys[j]);

		redisDb *db = &(c->db)[keyHashSlot(keys[j]->ptr, sdslen(keys[j]->ptr))];
        /* And in the other "side", to map keys -> clients */
        de = dictFind(db->blocking_keys,keys[j]);
        if (de == NULL) {
            int retval;

            /* For every key we take a list of clients blocked for it */
            l = listCreate();
            retval = dictAdd(db->blocking_keys,keys[j],l);
            incrRefCount(keys[j]);
            redisAssertWithInfo(c,keys[j],retval == DICT_OK);
        } else {
            l = dictGetVal(de);
        }
        listAddNodeTail(l,c);
    }
    blockClient(c,REDIS_BLOCKED_LIST);
}
Ejemplo n.º 2
0
void readQueryFromClient(aeEventLoop *el, int fd, httpClient *c) {
    char buf[CCACHE_IOBUF_LEN];
    int nread;
    nread = read(fd, buf, CCACHE_IOBUF_LEN);
    if (nread == -1) {
        if (errno == EAGAIN) { /* try again */
            nread = 0;
        } else {
            ulog(CCACHE_VERBOSE, "Reading from client: %s",strerror(errno));
            freeClient(c);
            return;
        }
    } else if (nread == 0) {
        ulog(CCACHE_VERBOSE, "End of client request");
        freeClient(c);
        return;
    }
    if (nread>0) {
        printf("Read Request: %.2lf \n", (double)(clock()));
        c->lastinteraction = time(NULL);
        listMoveNodeToTail(el->clients,c->elNode);
        /* NOTICE: nread or nread-1 */
        switch(requestParse(c->req,buf,buf+nread)){
        case parse_not_completed:
            break;
        case parse_completed:
        {            
            int handle_result = requestHandle(c->req,c->rep,el->cache,c);
            if(handle_result == HANDLER_BLOCK){
                blockClient(el,c);
            }
            else {
                if (_installWriteEvent(el, c) != CCACHE_OK) return;
                printf("Install Write: %.2lf\n", (double)(clock()));
                /* For HANDLE_OK there is nothing to do */
                if(handle_result == HANDLER_ERR) requestHandleError(c->req,c->rep);
            }
                break;
        }
        case parse_error:
            if (_installWriteEvent(el, c) != CCACHE_OK) {
                return;
            }
            requestHandleError(c->req,c->rep);
            break;
        default:
            break;
        };
    }
}
Ejemplo n.º 3
0
/* Set a client in blocking mode for the specified key (list or stream), with
 * the specified timeout. The 'type' argument is BLOCKED_LIST or BLOCKED_STREAM
 * depending on the kind of operation we are waiting for an empty key in
 * order to awake the client. The client is blocked for all the 'numkeys'
 * keys as in the 'keys' argument. When we block for stream keys, we also
 * provide an array of streamID structures: clients will be unblocked only
 * when items with an ID greater or equal to the specified one is appended
 * to the stream. */
void blockForKeys(client *c, int btype, robj **keys, int numkeys, mstime_t timeout, robj *target, streamID *ids) {
    dictEntry *de;
    list *l;
    int j;

    c->bpop.timeout = timeout;
    c->bpop.target = target;

    if (target != NULL) incrRefCount(target);

    for (j = 0; j < numkeys; j++) {
        /* The value associated with the key name in the bpop.keys dictionary
         * is NULL for lists, or the stream ID for streams. */
        void *key_data = NULL;
        if (btype == BLOCKED_STREAM) {
            key_data = zmalloc(sizeof(streamID));
            memcpy(key_data,ids+j,sizeof(streamID));
        }

        /* If the key already exists in the dictionary ignore it. */
        if (dictAdd(c->bpop.keys,keys[j],key_data) != DICT_OK) {
            zfree(key_data);
            continue;
        }
        incrRefCount(keys[j]);

        /* And in the other "side", to map keys -> clients */
        de = dictFind(c->db->blocking_keys,keys[j]);
        if (de == NULL) {
            int retval;

            /* For every key we take a list of clients blocked for it */
            l = listCreate();
            retval = dictAdd(c->db->blocking_keys,keys[j],l);
            incrRefCount(keys[j]);
            serverAssertWithInfo(c,keys[j],retval == DICT_OK);
        } else {
            l = dictGetVal(de);
        }
        listAddNodeTail(l,c);
    }
    blockClient(c,btype);
}
Ejemplo n.º 4
0
// keys是一个key的数组,个数为numkeys个
// timeout保存超时时间
// target保存解除阻塞时的key对象,用于BRPOPLPUSH函数
// 根据给定的key将client阻塞
void blockForKeys(client *c, robj **keys, int numkeys, mstime_t timeout, robj *target) {
    dictEntry *de;
    list *l;
    int j;

    //设置超时时间和target
    c->bpop.timeout = timeout;
    c->bpop.target = target;

    //增加target的引用计数
    if (target != NULL) incrRefCount(target);

    //将当前client的numkeys个key设置为阻塞
    for (j = 0; j < numkeys; j++) {
        /* If the key already exists in the dict ignore it. */
        //bpop.keys记录所有造成client阻塞的键
        //将要阻塞的键放入bpop.keys字典中
        if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;
        //当前的key引用计数加1
        incrRefCount(keys[j]);

        /* And in the other "side", to map keys -> clients */
        //db->blocking_keys是一个字典,字典的键为bpop.keys中的一个键,值是一个列表,保存着所有被该键阻塞的client
        //当前造成client被阻塞的键有没有当前的key
        de = dictFind(c->db->blocking_keys,keys[j]);
        if (de == NULL) {   //没有当前的key,添加进去
            int retval;

            /* For every key we take a list of clients blocked for it */
            //创建一个列表
            l = listCreate();
            //将造成阻塞的键和列表添加到db->blocking_keys字典中
            retval = dictAdd(c->db->blocking_keys,keys[j],l);
            incrRefCount(keys[j]);
            serverAssertWithInfo(c,keys[j],retval == DICT_OK);
        } else {    //如果已经有了,则当前key的值保存起来,值是一个列表
            l = dictGetVal(de);
        }
        listAddNodeTail(l,c);   //将当前client加入到阻塞的client的列表
    }
    blockClient(c,BLOCKED_LIST);    //阻塞client
}