sds sdsgrowzero(sds s, size_t len) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    size_t totlen, curlen = sh->len;

    // 如果 len 比字符串的现有长度小,
    // 那么直接返回,不做动作
    if (len <= curlen) return s;

    // 扩展 sds
    // T = O(N)
    s = sdsMakeRoomFor(s,len-curlen);
    // 如果内存不足,直接返回
    if (s == NULL) return NULL;

    /* Make sure added region doesn't contain garbage */
    // 将新分配的空间用 0 填充,防止出现垃圾内容
    // T = O(N)
    sh = (void*)(s-(sizeof(struct sdshdr)));
    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */

    // 更新属性
    totlen = sh->len+sh->free;
    sh->len = len;
    sh->free = totlen-sh->len;

    // 返回新的 sds
    return s;
}
Example #2
0
/* copy len elements of t to s*/
sds sdscpylen(sds s, char *t, size_t len) {
    /* @sh -> struct which contains s */
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
    /* @totlen -> total length of sh */
    size_t totlen = sh->free+sh->len;

    /* doesn't have enough space */
    if (totlen < len) {
        /* make room for the new string */
        s = sdsMakeRoomFor(s,len-totlen);
        /* failed to make more room */
        if (s == NULL) return NULL;
        /*update sh and totlen */
        sh = (void*) (s-(sizeof(struct sdshdr)));
        totlen = sh->free+sh->len;
    }
    /* copy the contents */
    memcpy(s, t, len);
    /* add '\0' to the end of the string */
    s[len] = '\0';
    /* update sh->len and sh->free */
    sh->len = len;
    sh->free = totlen-len;
    /* return s */
    return s;
}
Example #3
0
static void pub_ev_handler(evutil_socket_t fd, short event, void *args)
{
    if (!(event & EV_READ)) {
        srv_log(LOG_WARN, "publisher [fd %d] invalid event: %d", event);
        return;
    }

    pub_client *c = (pub_client *) args;

    c->read_buf = sdsMakeRoomFor(c->read_buf, PUB_READ_BUF_LEN);
    size_t cur_len = sdslen(c->read_buf);
    int nread = read(fd, c->read_buf + cur_len, PUB_READ_BUF_LEN);
    if (nread == -1) {
        if (errno == EAGAIN || errno == EINTR) {
            /* temporary unavailable */
        } else {
            srv_log(LOG_ERROR, "[fd %d] failed to read from publisher: %s",
                    fd, strerror(errno));
            pub_cli_release(c);
        }
    } else if (nread == 0) {
        srv_log(LOG_INFO, "[fd %d] publisher detached", fd);
        pub_cli_release(c);
    } else {
        /*
        chunk[n] = '\0';
        srv_log(LOG_INFO, "[fd %d] publisher send: %s", fd, chunk);
        write(fd, "hello", 5);
        */
        /* data process */
        sdsIncrLen(c->read_buf, nread);
        process_pub_read_buf(c);
        /*process_publish(c, chunk, nread);*/
    }
}
Example #4
0
void sub_ev_handler(evutil_socket_t fd, short event, void *args)
{
    sub_client *c = (sub_client *) args;

    if (event & EV_READ) {
        c->read_buf = sdsMakeRoomFor(c->read_buf, SUB_READ_BUF_LEN);
        size_t cur_len = sdslen(c->read_buf);
        int n = read(fd, c->read_buf + cur_len, SUB_READ_BUF_LEN);
        if (n == -1) {
            if (errno == EAGAIN || errno == EINTR) {
                /* temporary unavailable */
                return;
            } else {
                srv_log(LOG_ERROR, "[fd %d] failed to read from sublisher: %s",
                        fd, strerror(errno));
                sub_cli_release(c);
                return;
            }
        } else if (n == 0) {
            srv_log(LOG_INFO, "[fd %d] sublisher detached", fd);
            sub_cli_release(c);
            return;
        } else {
            sdsIncrLen(c->read_buf, n);
        }
        process_sub_read_buf(c);
    } else if (event & EV_WRITE) {
        send_reply_to_subcli(c);
    }
}
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
 * end of the specified sds string 's'.
 *
 * After the call, the passed sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscatlen(sds s, const void *t, size_t len) {
    
    struct sdshdr *sh;
    
    // 原有字符串长度
    size_t curlen = sdslen(s);

    // 扩展 sds 空间
    // T = O(N)
    s = sdsMakeRoomFor(s,len);

    // 内存不足?直接返回
    if (s == NULL) return NULL;

    // 复制 t 中的内容到字符串后部
    // T = O(N)
    sh = (void*) (s-(sizeof(struct sdshdr)));
    memcpy(s+curlen, t, len);

    // 更新属性
    sh->len = curlen+len;
    sh->free = sh->free-len;

    // 添加新结尾符号
    s[curlen+len] = '\0';

    // 返回新 sds
    return s;
}
 // 将给定的 C 字符串复制到 SDS 里面, 覆盖 SDS 原有的字符串。              O(N) , N 为被复制 C 字符串的长度。 
sds sdscpylen(sds s, const char *t, size_t len) {

    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));

    // sds 现有 buf 的长度
    size_t totlen = sh->free+sh->len;

    // 如果 s 的 buf 长度不满足 len ,那么扩展它
    if (totlen < len) {
        // T = O(N)
        s = sdsMakeRoomFor(s,len-sh->len);
        if (s == NULL) return NULL;
        sh = (void*) (s-(sizeof(struct sdshdr)));
        totlen = sh->free+sh->len;
    }

    // 复制内容
    // T = O(N)
    memcpy(s, t, len);

    // 添加终结符号
    s[len] = '\0';

    // 更新属性
    sh->len = len;
    sh->free = totlen-len;

    // 返回新的 sds
    return s;
}
Example #7
0
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
 * end of the specified sds string 's'.
 *
 * After the call, the passed sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscatlen(sds s, const void *t, size_t len) {
    size_t curlen = sdslen(s);

    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    memcpy(s+curlen, t, len);
    sdssetlen(s, curlen+len);
    s[curlen+len] = '\0';
    return s;
}
Example #8
0
/* Destructively modify the sds string 's' to hold the specified binary
 * safe string pointed by 't' of length 'len' bytes. */
sds sdscpylen(sds s, const char *t, size_t len) {
    if (sdsalloc(s) < len) {
        s = sdsMakeRoomFor(s,len-sdslen(s));
        if (s == NULL) return NULL;
    }
    memcpy(s, t, len);
    s[len] = '\0';
    sdssetlen(s, len);
    return s;
}
Example #9
0
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
    client *c = (client*) privdata;
    int nread, readlen;
    size_t qblen;
    UNUSED(el);
    UNUSED(mask);

    readlen = PROTO_IOBUF_LEN;
    /* If this is a multi bulk request, and we are processing a bulk reply
     * that is large enough, try to maximize the probability that the query
     * buffer contains exactly the SDS string representing the object, even
     * at the risk of requiring more read(2) calls. This way the function
     * processMultiBulkBuffer() can avoid copying buffers to create the
     * Redis Object representing the argument. */
    if (c->reqtype == PROTO_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1
        && c->bulklen >= PROTO_MBULK_BIG_ARG)
    {
        int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf);

        if (remaining < readlen) readlen = remaining;
    }

    qblen = sdslen(c->querybuf);
    if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;
    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
    nread = read(fd, c->querybuf+qblen, readlen);
    if (nread == -1) {
        if (errno == EAGAIN) {
            return;
        } else {
            Log(LL_VERBOSE, "Reading from client: %s",strerror(errno));
            freeClient(c);
            return;
        }
    } else if (nread == 0) {
        Log(LL_VERBOSE, "Client closed connection");
        freeClient(c);
        return;
    }

    sdsIncrLen(c->querybuf,nread);
    c->lastinteraction = server.unixtime;
    server.stat_net_input_bytes += nread;
    if (sdslen(c->querybuf) > server.client_max_querybuf_len) {
        sds ci = catClientInfoString(sdsempty(),c), bytes = sdsempty();

        bytes = sdscatrepr(bytes,c->querybuf,64);
        Log(LL_WARNING,"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)", ci, bytes);
        sdsfree(ci);
        sdsfree(bytes);
        freeClient(c);
        return;
    }
    processInputBuffer(c);
}
Example #10
0
sds sdscatlen(sds s, const void* t, size_t len) {
	size_t curlen = sdslen(s);
	s = sdsMakeRoomFor(s, len);
	if (s == NULL) return NULL;
	struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr)));
	memcpy(s + curlen, t, len);
	sh->len = curlen + len;
	sh->free = sh->free - len;
	s[curlen + len] = '\0';
	return s;
}
Example #11
0
/* Grow the sds to have the specified length. Bytes that were not part of
 * the original length of the sds will be set to zero.
 *
 * if the specified length is smaller than the current length, no operation
 * is performed. */
sds sdsgrowzero(sds s, size_t len) {
    size_t curlen = sdslen(s);

    if (len <= curlen) return s;
    s = sdsMakeRoomFor(s,len-curlen);
    if (s == NULL) return NULL;

    /* Make sure added region doesn't contain garbage */
    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
    sdssetlen(s, len);
    return s;
}
Example #12
0
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
 * end of the specified sds string 's'.
 *
 * After the call, the passed sds string is no longer valid and all the
 * references must be substituted with the new pointer returned by the call. */
sds sdscatlen(sds s, const void *t, size_t len) {
    sdshdr *sh;
    size_t curlen = sdslen(s);

    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    sh = sds_start(s);
    memcpy(s+curlen, t, len);
    sh->len = curlen+len;
    sh->free = sh->free-len;
    s[curlen+len] = '\0';
    return s;
}
Example #13
0
sds sdsgrowzero(sds s, size_t len) {
	struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr)));
	size_t totlen, curlen = sh->len;
	if (len <= curlen) return s;
	s = sdsMakeRoomFor(s, len - curlen);
	if (s == NULL) return NULL;
	sh = (void*)(s - (sizeof(struct sdshdr)));
	memset(s + curlen, 0, (len - curlen + 1));
	totlen = sh->len + sh->free;
	sh->len = len;
	sh->free = totlen - sh->len;
	return s;
}
Example #14
0
sds sdscpylen(sds s, const char *t, size_t len) {
	struct sdshdr *sh = (void*)(s - (sizeof(struct sdshdr)));
	size_t totlen = sh->free + sh->len;
	if (totlen < len) {
		s = sdsMakeRoomFor(s, len - sh->len);
		if (s == NULL) return NULL;
		sh = (void*)(s - (sizeof(struct sdshdr)));
		totlen = sh->free + sh->len;
	}
	memcpy(s, t, len);
	s[len] = len;
	sh->free = totlen - len;
	return s;
}
Example #15
0
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
    vuiClient *c = (vuiClient *) privdata;
    int nread, readlen;
    size_t qblen;

    /* If this is a multi bulk request, and we are processing a bulk reply
     * that is large enough, try to maximize the probability that the query
     * buffer contains exactly the SDS string representing the object, even
     * at the risk of requiring more read(2) calls. This way the function
     * processMultiBulkBuffer() can avoid copying buffers to create the
     * Redis Object representing the argument. */
    if (c->prot.waiting)
    {
        readlen = c->prot.waiting;
    }
    else
    {
        readlen = 1024 * 2;
    }

    qblen = sdslen(c->querybuf);
    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
    nread = read(fd, c->querybuf+qblen, readlen);

    if (nread == -1) {
        if (errno == EAGAIN) {
            nread = 0;
        } else {
            LogInfo("Reading from client: %s",strerror(errno));
            freeClient(c);
            return;
        }
    } else if (nread == 0) {
        LogInfo("Client closed connection");
        freeClient(c);
        return;
    }
    if (nread) {
        sdsIncrLen(c->querybuf,nread);
    } 
    //TODO
    if (sdslen(c->querybuf) > 1024 * 1024) {
        LogWarn("Closing client that reached max query buffer length");
        sdsclear(c->querybuf);
        freeClient(c);
        return;
    }
    processInputBuffer(c);
}
Example #16
0
sds getAllClientsInfoString(void) {
    listNode *ln;
    listIter li;
    client *client;
    sds o = sdsempty();

    o = sdsMakeRoomFor(o,200*listLength(server.clients));
    listRewind(server.clients,&li);
    while ((ln = listNext(&li)) != NULL) {
        client = listNodeValue(ln);
        o = catClientInfoString(o,client);
        o = sdscatlen(o,"\n",1);
    }
    return o;
}
Example #17
0
File: sds.c Project: freb/rules
/* Grow the sds to have the specified length. Bytes that were not part of
 * the original length of the sds will be set to zero.
 *
 * if the specified length is smaller than the current length, no operation
 * is performed. */
sds sdsgrowzero(sds s, size_t len) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    size_t totlen, curlen = sh->len;

    if (len <= curlen) return s;
    s = sdsMakeRoomFor(s,len-curlen);
    if (s == NULL) return NULL;

    /* Make sure added region doesn't contain garbage */
    sh = (void*)(s-(sizeof(struct sdshdr)));
    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
    totlen = sh->len+sh->free;
    sh->len = (int)len;
    sh->free = (int)(totlen-sh->len);
    return s;
}
Example #18
0
/* 以t作为新添加的len长度buf的数据,实现追加操作 */
sds sdscatlen(sds s, const void *t, size_t len) {
    struct sdshdr *sh;
    size_t curlen = sdslen(s);
	
	//为原字符串扩展len长度空间
    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    sh = (void*) (s-(sizeof(struct sdshdr)));
    //多余的数据以t作初始化
    memcpy(s+curlen, t, len);
    //更改相应的len,free值
    sh->len = curlen+len;
    sh->free = sh->free-len;
    s[curlen+len] = '\0';
    return s;
}
Example #19
0
/* concate len elements of t at the end of s */
sds sdscatlen(sds s, void *t, size_t len) {
    /* @sh -> struct contains s */
    struct sdshdr *sh;
    size_t curlen = sdslen(s);
    /* make enough room */
    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    sh = (void*) (s-(sizeof(struct sdshdr)));
    /* copy the len elements after s */
    memcpy(s+curlen, t, len);
    /* update sh->len and sh->free */
    sh->len = curlen+len;
    sh->free = sh->free-len;
    /* add '\0' at the end of the string */
    s[curlen+len] = '\0';
    return s;
}
Example #20
0
/* Destructively modify the sds string 's' to hold the specified binary
 * safe string pointed by 't' of length 'len' bytes. */
sds sdscpylen(sds s, const char *t, size_t len) {
    if (s == NULL) return NULL;

    sdshdr *sh = sds_start(s);
    size_t totlen = sh->free+sh->len;

    if (totlen < len) {
        s = sdsMakeRoomFor(s,len-sh->len);
        if (s == NULL) return NULL;
        sh = sds_start(s);
        totlen = sh->free+sh->len;
    }
    memcpy(s, t, len);
    s[len] = '\0';
    sh->len = len;
    sh->free = totlen-len;
    return s;
}
Example #21
0
/* Grow the sds to have the specified length. Bytes that were not part of
 * the original length of the sds will be set to zero.
 *
 * if the specified length is smaller than the current length, no operation
 * is performed. */
sds sdsgrowzero(sds s, size_t len) {
    if (s == NULL) return NULL;

    sdshdr *sh = sds_start(s);
    size_t totlen, curlen = sh->len;

    if (len <= curlen) return s;
    s = sdsMakeRoomFor(s,len-curlen);
    if (s == NULL) return NULL;

    /* Make sure added region doesn't contain garbage */
    sh = sds_start(s);
    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
    totlen = sh->len+sh->free;
    sh->len = len;
    sh->free = totlen-sh->len;
    return s;
}
Example #22
0
/* Format a command according to the Redis protocol using an sds string and
 * sdscatfmt for the processing of arguments. This function takes the
 * number of arguments, an array with arguments and an array with their
 * lengths. If the latter is set to NULL, strlen will be used to compute the
 * argument lengths.
 */
int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv,
                              const size_t *argvlen)
{
    sds cmd;
    unsigned long long totlen;
    int j;
    size_t len;

    /* Abort on a NULL target */
    if (target == NULL)
        return -1;

    /* Calculate our total size */
    totlen = 1+countDigits(argc)+2;
    for (j = 0; j < argc; j++) {
        len = argvlen ? argvlen[j] : strlen(argv[j]);
        totlen += bulklen(len);
    }

    /* Use an SDS string for command construction */
    cmd = sdsempty();
    if (cmd == NULL)
        return -1;

    /* We already know how much storage we need */
    cmd = sdsMakeRoomFor(cmd, totlen);
    if (cmd == NULL)
        return -1;

    /* Construct command */
    cmd = sdscatfmt(cmd, "*%i\r\n", argc);
    for (j=0; j < argc; j++) {
        len = argvlen ? argvlen[j] : strlen(argv[j]);
        cmd = sdscatfmt(cmd, "$%T\r\n", len);
        cmd = sdscatlen(cmd, argv[j], len);
        cmd = sdscatlen(cmd, "\r\n", sizeof("\r\n")-1);
    }

    assert(sdslen(cmd)==totlen);

    *target = cmd;
    return totlen;
}
Example #23
0
/* 扩展字符串到指定的长度 */
sds sdsgrowzero(sds s, size_t len) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    size_t totlen, curlen = sh->len;

	//如果当前长度已经大于要求长度,直接返回
    if (len <= curlen) return s;
    //如果小于,则重新为此字符串分配新空间,得到新字符串
    s = sdsMakeRoomFor(s,len-curlen);
    if (s == NULL) return NULL;

    /* Make sure added region doesn't contain garbage */
    //确保多余的字符串不包含垃圾数据,置空处理
    sh = (void*)(s-(sizeof(struct sdshdr)));
    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
    totlen = sh->len+sh->free;
    sh->len = len;
    sh->free = totlen-sh->len;
    return s;
}
Example #24
0
/* This function is similar to sdscatprintf, but much faster as it does
 * not rely on sprintf() family functions implemented by the libc that
 * are often very slow. Moreover directly handling the sds string as
 * new data is concatenated provides a performance improvement.
 *
 * However this function only handles an incompatible subset of printf-alike
 * format specifiers:
 *
 * %s - C String
 * %S - SDS string
 * %i - signed int
 * %I - 64 bit signed integer (long long, int64_t)
 * %u - unsigned int
 * %U - 64 bit unsigned integer (unsigned long long, uint64_t)
 * %% - Verbatim "%" character.
 */
sds sdscatfmt(sds s, char const *fmt, ...) {
    size_t initlen = sdslen(s);
    const char *f = fmt;
    int i;
    va_list ap;

    va_start(ap,fmt);
    f = fmt;    /* Next format specifier byte to process. */
    i = initlen; /* Position of the next byte to write to dest str. */
    while(*f) {
        char next, *str;
        size_t l;
        long long num;
        unsigned long long unum;

        /* Make sure there is always space for at least 1 char. */
        if (sdsavail(s)==0) {
            s = sdsMakeRoomFor(s,1);
        }

        switch(*f) {
        case '%':
            next = *(f+1);
            f++;
            switch(next) {
            case 's':
            case 'S':
                str = va_arg(ap,char*);
                l = (next == 's') ? strlen(str) : sdslen(str);
                if (sdsavail(s) < l) {
                    s = sdsMakeRoomFor(s,l);
                }
                memcpy(s+i,str,l);
                sdsinclen(s,l);
                i += l;
                break;
            case 'i':
            case 'I':
                if (next == 'i')
                    num = va_arg(ap,int);
                else
                    num = va_arg(ap,long long);
                {
                    char buf[SDS_LLSTR_SIZE];
                    l = sdsll2str(buf,num);
                    if (sdsavail(s) < l) {
                        s = sdsMakeRoomFor(s,l);
                    }
                    memcpy(s+i,buf,l);
                    sdsinclen(s,l);
                    i += l;
                }
                break;
            case 'u':
            case 'U':
                if (next == 'u')
                    unum = va_arg(ap,unsigned int);
                else
                    unum = va_arg(ap,unsigned long long);
                {
                    char buf[SDS_LLSTR_SIZE];
                    l = sdsull2str(buf,unum);
                    if (sdsavail(s) < l) {
                        s = sdsMakeRoomFor(s,l);
                    }
                    memcpy(s+i,buf,l);
                    sdsinclen(s,l);
                    i += l;
                }
                break;
            default: /* Handle %% and generally %<unknown>. */
                s[i++] = next;
                sdsinclen(s,1);
                break;
            }
            break;
        default:
            s[i++] = *f;
            sdsinclen(s,1);
            break;
        }
Example #25
0
static void redis_test_read_handler(aeEventLoop *el, int fd, void *privdata, int mask)
{
	redis_test_client *c = (redis_test_client*) privdata;
    UNUSED(el);
    UNUSED(mask);		
	static char buf[1024];
	int ret = recv(fd, buf, 1024, 0);
	if (ret == 0) {
		serverLog(LL_WARNING, "%s %d %d: recv ret [%d] err [%d]", __FUNCTION__, __LINE__, fd, ret, errno);
		free_redis_test_client(c);		
		return;
	}
	else if (ret < 0) {
		if (errno != EAGAIN && errno != EINTR) {
			serverLog(LL_WARNING, "%s %d %d: recv ret [%d] err [%d]", __FUNCTION__, __LINE__, fd, ret, errno);
			free_redis_test_client(c);					
			return;
		}
		else {
			return;
		}
	}
	if (ret != send(fd, buf, ret, 0)) {
		serverLog(LL_WARNING, "%s %d %d: recv ret [%d] err [%d]", __FUNCTION__, __LINE__, fd, ret, errno);
		free_redis_test_client(c);		
	}
	return;
	
#if 0
	
	redis_test_client *c = (redis_test_client*) privdata;
    int nread, readlen;
    size_t qblen;
    UNUSED(el);
    UNUSED(mask);

    readlen = PROTO_IOBUF_LEN;
    qblen = sdslen(c->querybuf);
//    if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;
    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
    nread = read(fd, c->querybuf+qblen, readlen);
    if (nread == -1) {
        if (errno == EAGAIN) {
            return;
        } else {
            serverLog(LL_VERBOSE, "Reading from client: %s",strerror(errno));
            free_redis_test_client(c);
            return;
        }
    } else if (nread == 0) {
        serverLog(LL_VERBOSE, "Client closed connection");
		free_redis_test_client(c);
        return;
    }

    sdsIncrLen(c->querybuf,nread);
    c->lastinteraction = server.unixtime;

	printf("%s %d: len = %zd, nread = %d, buf = %s\n", __FUNCTION__, __LINE__,
		sdslen(c->querybuf), nread, c->querybuf);	
	
//    processInputBuffer(c);
#endif	
}
Example #26
0
int processMultibulkBuffer(client *c) {
    char *newline = NULL;
    int pos = 0, ok;
    long long ll;

    if (c->multibulklen == 0) {
        /* The client should have been reset */
        serverAssertWithInfo(c,NULL,c->argc == 0);

        /* Multi bulk length cannot be read without a \r\n */
        newline = strchr(c->querybuf,'\r');
        if (newline == NULL) {
            if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {
                addReplyError(c,"Protocol error: too big mbulk count string");
                setProtocolError(c,0);
            }
            return C_ERR;
        }

        /* Buffer should also contain \n */
        if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))
            return C_ERR;

        /* We know for sure there is a whole line since newline != NULL,
         * so go ahead and find out the multi bulk length. */
        serverAssertWithInfo(c,NULL,c->querybuf[0] == '*');
        ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll);
        if (!ok || ll > 1024*1024) {
            addReplyError(c,"Protocol error: invalid multibulk length");
            setProtocolError(c,pos);
            return C_ERR;
        }

        pos = (newline-c->querybuf)+2;
        if (ll <= 0) {
            sdsrange(c->querybuf,pos,-1);
            return C_OK;
        }

        c->multibulklen = ll;

        /* Setup argv array on client structure */
        if (c->argv) free(c->argv);
        c->argv = malloc(sizeof(sds*)*c->multibulklen);
    }

    serverAssertWithInfo(c,NULL,c->multibulklen > 0);
    while(c->multibulklen) {
        /* Read bulk length if unknown */
        if (c->bulklen == -1) {
            newline = strchr(c->querybuf+pos,'\r');
            if (newline == NULL) {
                if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {
                    addReplyError(c,
                        "Protocol error: too big bulk count string");
                    setProtocolError(c,0);
                    return C_ERR;
                }
                break;
            }

            /* Buffer should also contain \n */
            if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))
                break;

            if (c->querybuf[pos] != '$') {
                addReplyErrorFormat(c,
                    "Protocol error: expected '$', got '%c'",
                    c->querybuf[pos]);
                setProtocolError(c,pos);
                return C_ERR;
            }

            ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll);
            if (!ok || ll < 0 || ll > 512*1024*1024) {
                addReplyError(c,"Protocol error: invalid bulk length");
                setProtocolError(c,pos);
                return C_ERR;
            }

            pos += newline-(c->querybuf+pos)+2;
            if (ll >= PROTO_MBULK_BIG_ARG) {
                size_t qblen;

                /* If we are going to read a large object from network
                 * try to make it likely that it will start at c->querybuf
                 * boundary so that we can optimize object creation
                 * avoiding a large copy of data. */
                sdsrange(c->querybuf,pos,-1);
                pos = 0;
                qblen = sdslen(c->querybuf);
                /* Hint the sds library about the amount of bytes this string is
                 * going to contain. */
                if (qblen < (size_t)ll+2)
                    c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen);
            }
            c->bulklen = ll;
        }

        /* Read bulk argument */
        if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) {
            /* Not enough data (+2 == trailing \r\n) */
            break;
        } else {
            /* Optimization: if the buffer contains JUST our bulk element
             * instead of creating a new object by *copying* the sds we
             * just use the current sds string. */
            if (pos == 0 &&
                c->bulklen >= PROTO_MBULK_BIG_ARG &&
                (signed) sdslen(c->querybuf) == c->bulklen+2)
            {
                c->argv[c->argc++] = c->querybuf;
                sdsIncrLen(c->querybuf,-2); /* remove CRLF */
                c->querybuf = sdsempty();
                /* Assume that if we saw a fat argument we'll see another one
                 * likely... */
                c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2);
                pos = 0;
            } else {
                c->argv[c->argc++] = sdsnewlen(c->querybuf+pos,c->bulklen);
                pos += c->bulklen+2;
            }
            c->bulklen = -1;
            c->multibulklen--;
        }
    }

    /* Trim to pos */
    if (pos) sdsrange(c->querybuf,pos,-1);

    /* We're done when c->multibulk == 0 */
    if (c->multibulklen == 0) return C_OK;

    /* Still not read to process the command */
    return C_ERR;
}
Example #27
0
/* sid = |flags(4byte)|client fd(4byte)| */
static int
smrCbData (void *arg, long long seq, long long timestamp,
	   short nid, int sid, int hash, smrData * smr_data, int size)
{
  char *data = smr_data_get_data (smr_data);
  redisClient *c;
  short cmdflags;
  dlisth *node;

  /* Special commands */
  if (size == 1 && data[0] == REDIS_SMR_CMD_CATCHUP_CHECK)
    {
      if (nid == smr_get_nid (server.smr_conn)
	  && (server.smr_init_flags & SMR_INIT_CATCHUP_PHASE2))
	checkSmrCatchup ();
      goto release_seq;
    }
  else if (size == 1 && data[0] == REDIS_SMR_CMD_DELIVER_OOM)
    {
      server.smr_oom_until = timestamp + REDIS_OOM_DURATION_MS;
      goto release_seq;
    }

  /* Normal command */
  server.smr_mstime = timestamp;
  cmdflags = (0xFFFF0000 & sid) >> 16;

  /* Because we fixed the bug that causes timestamp be 0, 
   * this warning log is not necessary and just an assert statement is enough after all.
   * But currently, there are nbase-arc clusters which have the bug.
   * So, we don't assert for now. */
  if (timestamp == 0)
    {
      redisLog (REDIS_WARNING, "Timestamp of SMR callback is 0,"
		"seq:%lld, nid:%d, sid:%d, hash:%d, size:%d",
		seq, nid, sid, hash, size);
    }

  if ((server.smr_init_flags & SMR_INIT_DONE)
      && nid == smr_get_nid (server.smr_conn))
    {
      callbackInfo *cb;
      /* query from this server. get client from global callback list */
      assert (!dlisth_is_empty (&server.global_callbacks));	/* global callback list shouldn't be empty */
      node = server.global_callbacks.next;
      cb = (callbackInfo *) node;
      dlisth_delete (&cb->global_head);
      dlisth_delete (&cb->client_head);
      c = cb->client;
      assert (cb->hash == hash);
      assert (c->fd == -1 || c->fd == (0X0000FFFF & sid));

      /* We already parsed querybuf because the query is requested from this 
       * server before smr callback*/
      c->argc = cb->argc;
      c->argv = cb->argv;
      cb->argc = 0;
      cb->argv = NULL;
      zfree (cb);

      server.current_client = c;

      /* fake client doesn't need to execute non-write query(read-only or admin) */
      if (c->fd != -1 || cmdflags & REDIS_CMD_WRITE)
	{
	  assert (!(c->flags & REDIS_CLOSE_AFTER_REPLY));
	  processCommand (c);
	}
    }
  else
    {
      /* replicated query from other servers, or catchup query during initialize */
      c = server.smrlog_client;
      server.current_client = c;

      /* fake client doesn't need to execute non-write query(read-only or admin) */
      if (cmdflags & REDIS_CMD_WRITE)
	{
	  /* We need to parse querybuf because the query is from different server 
	   * or we are recovering without client */
	  sdsclear (c->querybuf);
	  c->querybuf = sdsMakeRoomFor (c->querybuf, size);
	  memcpy (c->querybuf, data, size);
	  sdsIncrLen (c->querybuf, size);
	  if (c->querybuf_peak < size)
	    c->querybuf_peak = size;
	  processInputBuffer (c);
	}
    }

  resetClient (c);
  zfree (c->argv);
  c->argv = NULL;
  server.current_client = NULL;

release_seq:
  if (smr_release_seq_upto (server.smr_conn, seq + size) == -1)
    {
      redisLog (REDIS_WARNING, "smr_release_seq_upto error");
      redisAssert (0);
      return REDIS_ERR;
    }
  server.smr_seqnum = seq + size;

  return REDIS_OK;
}
Example #28
0
int main(void) {
    {
        sdshdr *sh;
        sds x = sdsnew("foo"), y;

        test_cond("Create a string and obtain the length",
            sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0)

        sdsfree(x);
        x = sdsnewlen("foo",2);
        test_cond("Create a string with specified length",
            sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0)

        x = sdscat(x,"bar");
        test_cond("Strings concatenation",
            sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0);

        x = sdscpy(x,"a");
        test_cond("sdscpy() against an originally longer string",
            sdslen(x) == 1 && memcmp(x,"a\0",2) == 0)

        x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk");
        test_cond("sdscpy() against an originally shorter string",
            sdslen(x) == 33 &&
            memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0)

        sdsfree(x);
        x = sdscatprintf(sdsempty(),"%d",123);
        test_cond("sdscatprintf() seems working in the base case",
            sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)

        sdsfree(x);
        x = sdsnew("xxciaoyyy");
        sdstrim(x,"xy");
        test_cond("sdstrim() correctly trims characters",
            sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)

        y = sdsdup(x);
        sdsrange(y,1,1);
        test_cond("sdsrange(...,1,1)",
            sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)

        sdsfree(y);
        y = sdsdup(x);
        sdsrange(y,1,-1);
        test_cond("sdsrange(...,1,-1)",
            sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)

        sdsfree(y);
        y = sdsdup(x);
        sdsrange(y,-2,-1);
        test_cond("sdsrange(...,-2,-1)",
            sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)

        sdsfree(y);
        y = sdsdup(x);
        sdsrange(y,2,1);
        test_cond("sdsrange(...,2,1)",
            sdslen(y) == 0 && memcmp(y,"\0",1) == 0)

        sdsfree(y);
        y = sdsdup(x);
        sdsrange(y,1,100);
        test_cond("sdsrange(...,1,100)",
            sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)

        sdsfree(y);
        y = sdsdup(x);
        sdsrange(y,100,100);
        test_cond("sdsrange(...,100,100)",
            sdslen(y) == 0 && memcmp(y,"\0",1) == 0)

        sdsfree(y);
        sdsfree(x);
        x = sdsnew("foo");
        y = sdsnew("foa");
        test_cond("sdscmp(foo,foa)", sdscmp(x,y) > 0)

        sdsfree(y);
        sdsfree(x);
        x = sdsnew("bar");
        y = sdsnew("bar");
        test_cond("sdscmp(bar,bar)", sdscmp(x,y) == 0)

        sdsfree(y);
        sdsfree(x);
        x = sdsnew("aar");
        y = sdsnew("bar");
        test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)

        sdsfree(y);
        sdsfree(x);
        x = sdsnewlen("\a\n\0foo\r",7);
        y = sdscatrepr(sdsempty(),x,sdslen(x));
        test_cond("sdscatrepr(...data...)",
            memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0)
	sdsfree(y);

        {
            size_t oldfree;

            sdsfree(x);
            x = sdsnew("0");
            sh = sds_start(x);
            test_cond("sdsnew() free/len buffers", sh->len == 1 && sh->free == 0);
            x = sdsMakeRoomFor(x,1);
            sh = sds_start(x);
            test_cond("sdsMakeRoomFor()", sh->len == 1 && sh->free > 0);
            oldfree = sh->free;
            x[1] = '1';
            sdsIncrLen(x,1);
            test_cond("sdsIncrLen() -- content", x[0] == '0' && x[1] == '1');
            test_cond("sdsIncrLen() -- len", sh->len == 2);
            test_cond("sdsIncrLen() -- free", sh->free == oldfree-1);
	    sdsfree(x);
        }

        x = sdsnew("0FoO1bar\n");
        sdstolower(x);
        test_cond("sdstolower(...)",
            memcmp(x,"0foo1bar\n\0",10) == 0)

        sdsfree(x);

        x = sdsnew("0FoO1bar\n");
        sdstoupper(x);
        test_cond("sdstoupper(...)",
            memcmp(x,"0FOO1BAR\n\0",10) == 0)

        sdsfree(x);
    }
    test_report()
    return 0;
}
Example #29
0
TEST(sds, sds)
{
    // struct sdshdr *sh;
    sds x = sdsnew("foo"), y;

    TEST_ASSERT_TRUE(
        sdslen(x) == 3 && memcmp(x,"foo\0",4) == 0)

    sdsfree(x);
    x = sdsnewlen("foo",2);
    TEST_ASSERT_TRUE(
        sdslen(x) == 2 && memcmp(x,"fo\0",3) == 0)

    x = sdscat(x,"bar");
    TEST_ASSERT_TRUE(
        sdslen(x) == 5 && memcmp(x,"fobar\0",6) == 0);

    x = sdscpy(x,"a");
    TEST_ASSERT_TRUE(
        sdslen(x) == 1 && memcmp(x,"a\0",2) == 0)

    x = sdscpy(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk");
    TEST_ASSERT_TRUE(
        sdslen(x) == 33 &&
        memcmp(x,"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\0",33) == 0)

    sdsfree(x);

    x = sdscatprintf(sdsempty(),"%d",123);
    TEST_ASSERT_TRUE(
        sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)

    sdsfree(x);
    x = sdsnew("xxciaoyyy");
    sdstrim(x,"xy");
    TEST_ASSERT_TRUE(
        sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)

    y = sdsdup(x);
    sdsrange(y,1,1);
    TEST_ASSERT_TRUE(
        sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)

    sdsfree(y);
    y = sdsdup(x);
    sdsrange(y,1,-1);
    TEST_ASSERT_TRUE(
        sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)

    sdsfree(y);
    y = sdsdup(x);
    sdsrange(y,-2,-1);
    TEST_ASSERT_TRUE(
        sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)

    sdsfree(y);
    y = sdsdup(x);
    sdsrange(y,2,1);
    TEST_ASSERT_TRUE(
        sdslen(y) == 0 && memcmp(y,"\0",1) == 0)

    sdsfree(y);
    y = sdsdup(x);
    sdsrange(y,1,100);
    TEST_ASSERT_TRUE(
        sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)

    sdsfree(y);
    y = sdsdup(x);
    sdsrange(y,100,100);
    TEST_ASSERT_TRUE(
        sdslen(y) == 0 && memcmp(y,"\0",1) == 0)

    sdsfree(y);
    sdsfree(x);
    x = sdsnew("foo");
    y = sdsnew("foa");
    TEST_ASSERT_TRUE( sdscmp(x,y) > 0)

    sdsfree(y);
    sdsfree(x);
    x = sdsnew("bar");
    y = sdsnew("bar");
    TEST_ASSERT_TRUE( sdscmp(x,y) == 0)

    sdsfree(y);
    sdsfree(x);
    x = sdsnew("aar");
    y = sdsnew("bar");
    TEST_ASSERT_TRUE( sdscmp(x,y) < 0)

    sdsfree(y);
    sdsfree(x);
    // x = sdsnewlen("\a\n\0foo\r",7);
    // y = sdscatrepr(sdsempty(),x,sdslen(x));
    // TEST_ASSERT_TRUE(
    //     memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0)

#if 0
    {
        int oldfree;

        sdsfree(x);
        x = sdsnew("0");
        sh = (void*) (x-(sizeof(struct sdshdr)));
        TEST_ASSERT_TRUE( sh->len == 1 && sh->free == 0);
        x = sdsMakeRoomFor(x,1);
        sh = (void*) (x-(sizeof(struct sdshdr)));
        TEST_ASSERT_TRUE( sh->len == 1 && sh->free > 0);
        oldfree = sh->free;
        x[1] = '1';
        sdsIncrLen(x,1);
        TEST_ASSERT_TRUE( x[0] == '0' && x[1] == '1');
        TEST_ASSERT_TRUE( sh->len == 2);
        TEST_ASSERT_TRUE( sh->free == oldfree-1);
    }
#endif
}
Example #30
0
File: sds.c Project: bugou/test
/* This function is similar to sdscatprintf, but much faster as it does
 * not rely on sprintf() family functions implemented by the libc that
 * are often very slow. Moreover directly handling the sds string as
 * new data is concatenated provides a performance improvement.
 *
 * However this function only handles an incompatible subset of printf-alike
 * format specifiers:
 *
 * %s - C String
 * %S - SDS string
 * %i - signed int
 * %I - 64 bit signed integer (PORT_LONGLONG, int64_t)
 * %u - unsigned int
 * %U - 64 bit unsigned integer (PORT_ULONGLONG, uint64_t)
 * %% - Verbatim "%" character.
 */
sds sdscatfmt(sds s, char const *fmt, ...) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
    size_t initlen = sdslen(s);
    const char *f = fmt;
    int i;
    va_list ap;

    va_start(ap,fmt);
    f = fmt;    /* Next format specifier byte to process. */
    i = (int)initlen; /* Position of the next byte to write to dest str. */
    while(*f) {
        char next, *str;
        unsigned int l;
        PORT_LONGLONG num;
        PORT_ULONGLONG unum;

        /* Make sure there is always space for at least 1 char. */
        if (sh->free == 0) {
            s = sdsMakeRoomFor(s,1);
            sh = (void*) (s-(sizeof(struct sdshdr)));
        }

        switch(*f) {
        case '%':
            next = *(f+1);
            f++;
            switch(next) {
            case 's':
            case 'S':
                str = va_arg(ap,char*);
                l = (int)((next == 's') ? strlen(str) : sdslen(str));
                if (sh->free < l) {
                    s = sdsMakeRoomFor(s,l);
                    sh = (void*) (s-(sizeof(struct sdshdr)));
                }
                memcpy(s+i,str,l);
                sh->len += l;
                sh->free -= l;
                i += l;
                break;
            case 'i':
            case 'I':
                if (next == 'i')
                    num = va_arg(ap,int);
                else
                    num = va_arg(ap,PORT_LONGLONG);
                {
                    char buf[SDS_LLSTR_SIZE];
                    l = sdsll2str(buf,num);
                    if (sh->free < l) {
                        s = sdsMakeRoomFor(s,l);
                        sh = (void*) (s-(sizeof(struct sdshdr)));
                    }
                    memcpy(s+i,buf,l);
                    sh->len += l;
                    sh->free -= l;
                    i += l;
                }
                break;
            case 'u':
            case 'U':
                if (next == 'u')
                    unum = va_arg(ap,unsigned int);
                else
                    unum = va_arg(ap,PORT_ULONGLONG);
                {
                    char buf[SDS_LLSTR_SIZE];
                    l = sdsull2str(buf,unum);
                    if (sh->free < l) {
                        s = sdsMakeRoomFor(s,l);
                        sh = (void*) (s-(sizeof(struct sdshdr)));
                    }
                    memcpy(s+i,buf,l);
                    sh->len += l;
                    sh->free -= l;
                    i += l;
                }
                break;
            default: /* Handle %% and generally %<unknown>. */
                s[i++] = next;
                sh->len += 1;
                sh->free -= 1;
                break;
            }
            break;
        default:
            s[i++] = *f;
            sh->len += 1;
            sh->free -= 1;
            break;
        }