示例#1
0
static int
processMultiBulk (client_t * c)
{
  char *newline = NULL;
  int pos = 0, ok;
  long long ll;

  if (c->multibulklen == 0)
    {
      newline = strchr (c->querybuf, '\r');
      if (newline == NULL)
	{
	  if (sdslen (c->querybuf) > REDIS_INLINE_MAX_SIZE)
	    {
	      addReplyStr (c,
			   "-ERR Protocol error: too big mbulk count string\r\n");
	      c->flags |= REDIS_CLOSE_AFTER_REPLY;
	    }
	  return -1;
	}
      if (newline - c->querybuf > sdslen (c->querybuf) - 2)
	return -1;

      ok = string2ll (c->querybuf + 1, newline - (c->querybuf + 1), &ll);
      if (!ok || ll > 1024 * 1024)
	{
	  addReplyStr (c,
		       "-ERR Protocol error: invalid multibulk length\r\n");
	  c->flags |= REDIS_CLOSE_AFTER_REPLY;
	  return -1;
	}
      c->multibulklen = ll;
      c->argv = malloc (sizeof (sds) * c->multibulklen);
      c->argvlen = malloc (sizeof (size_t) * c->multibulklen);
      pos = (newline - c->querybuf) + 2;
      if (ll <= 0)
	{
	  sdsrange (c->querybuf, pos, -1);
	  return 0;
	}
    }

  while (c->multibulklen)
    {
      if (c->bulklen == -1)
	{
	  newline = strchr (c->querybuf + pos, '\r');
	  if (newline == NULL)
	    {
	      if (sdslen (c->querybuf) > REDIS_INLINE_MAX_SIZE)
		{
		  addReplyStr (c,
			       "-ERR Protocol error: too big bulk count string\r\n");
		  c->flags |= REDIS_CLOSE_AFTER_REPLY;
		}
	      break;
	    }
	  if (newline - (c->querybuf) > (sdslen (c->querybuf) - 2))
	    break;

	  if (c->querybuf[pos] != '$')
	    {
	      addReplyStr (c, "-ERR Protocol error: expected '$', got '");
	      addReplyStrLen (c, c->querybuf + pos, 1);
	      addReplyStr (c, "'\r\n");
	      c->flags |= REDIS_CLOSE_AFTER_REPLY;
	      return -1;
	    }

	  ok =
	    string2ll (c->querybuf + pos + 1,
		       newline - (c->querybuf + pos + 1), &ll);
	  if (!ok || ll < 0 || ll > 512 * 1024 * 1024)
	    {
	      addReplyStr (c, "-ERR Protocol error: invalid bulk length\r\n");
	      c->flags |= REDIS_CLOSE_AFTER_REPLY;
	      return -1;
	    }

	  pos += newline - (c->querybuf + pos) + 2;
	  c->bulklen = ll;
	}

      if (sdslen (c->querybuf) - pos < (unsigned) (c->bulklen + 2))
	break;
      c->argvlen[c->argc] = c->bulklen;
      c->argv[c->argc++] = sdsnewlen (c->querybuf + pos, c->bulklen);
      pos += c->bulklen + 2;
      c->bulklen = -1;
      c->multibulklen--;
    }

  if (pos)
    sdsrange (c->querybuf, pos, -1);
  if (c->multibulklen)
    return -1;

  if (c->argc == 1 && sdslen (c->argv[0]) == 4
      && !strcasecmp (c->argv[0], "quit"))
    {
      addReplyStrLen (c, "+OK\r\n", 5);
      c->flags |= REDIS_CLOSE_AFTER_REPLY;
      return -1;
    }
  arc_append_commandcv (c->rqst, c->argc, (const char **) c->argv,
			c->argvlen);
  c->total_append_command++;
  return 0;
}
示例#2
0
文件: sds.c 项目: wangxuemin/coding
/* Create an empty (zero length) sds string. Even in this case the string
 * always has an implicit null term. */
sds sdsempty(void) {
    return sdsnewlen("",0);
}
示例#3
0
文件: sds.c 项目: wangxuemin/coding
/* Duplicate an sds string. */
sds sdsdup(const sds s) {
    return sdsnewlen(s, sdslen(s));
}
示例#4
0
/* Create a new sds string starting from a null terminated C string. */
sds sdsnew(const char *init) {
    // 申请一个sds空间,只需要init
    size_t initlen = (init == NULL) ? 0 : strlen(init);
    return sdsnewlen(init, initlen);
}
示例#5
0
robj *createStringObject(char *ptr, size_t len) {
    return createObject(REDIS_STRING,sdsnewlen(ptr,len));
}
示例#6
0
文件: dict_ex.c 项目: skypacer210/Ex
int main(int argc, char *argv[])
{
	sds ex_1 = sdsnewlen("zhangjie", 8);
	sds ex_2 = sdsnewlen("zhbngjie", 8);
	sds ex_3 = sdsnewlen("zhcngjie", 8);
	sds ex_4 = sdsnewlen("zhengjie", 8);
	sds ex_5 = sdsnewlen("zh3ngjie", 8);
	sds ex_6 = sdsnewlen("zhrngjie", 8);
	sds ex_7 = sdsnewlen("zhfngjie", 8);
	sds ex_8 = sdsnewlen("zhgngjie", 8);
	sds ex_9 = sdsnewlen("zhingjie", 8);
	sds ex_10= sdsnewlen("zhajgjie", 8);
	sds ex_11= sdsnewlen("zhkngjie", 8);
	sds ex_12= sdsnewlen("zhjngjie", 8);
	sds ex_13= sdsnewlen("zhakgjie", 8);
	sds ex_14= sdsnewlen("zhtngjie", 8);
	sds ex_15= sdsnewlen("zhvngjie", 8);
	sds ex_16= sdsnewlen("zhyngjie", 8);
	sds ex_17= sdsnewlen("zhaqgjie", 8);
	sds ex_18= sdsnewlen("shangjie", 8);
	sds ex_19= sdsnewlen("zdangjie", 8);
	sds ex_20= sdsnewlen("shangjie", 8);
	sds ex_21= sdsnewlen("zhfngjie", 8);

	sds v_1 = sdsnewlen("zhangjie", 8);
	sds v_2 = sdsnewlen("zhangjie", 8);
	sds v_3 = sdsnewlen("zhangjie", 8);
	sds v_4 = sdsnewlen("zhangjie", 8);
	sds v_5 = sdsnewlen("zhangjie", 8);
	sds v_6 = sdsnewlen("zhangjie", 8);
	sds v_7 = sdsnewlen("zhangjie", 8);
	sds v_8 = sdsnewlen("zhangjie", 8);
	sds v_9 = sdsnewlen("zhangjie", 8);
	sds v_10= sdsnewlen("zhangjie", 8);
	sds v_11= sdsnewlen("zhangjie", 8);
	sds v_12= sdsnewlen("zhangjie", 8);
	sds v_13= sdsnewlen("zhangjie", 8);
	sds v_14= sdsnewlen("zhangjie", 8);
	sds v_15= sdsnewlen("zhangjie", 8);
	sds v_16= sdsnewlen("zhangjie", 8);
	sds v_17= sdsnewlen("zhangjie", 8);
	sds v_18= sdsnewlen("zhangjie", 8);
	sds v_19= sdsnewlen("zhangjie", 8);
	sds v_20= sdsnewlen("zhangjie", 8);
	sds v_21= sdsnewlen("zhangjie", 8);

	dict *d = dictCreate(&strTableDictType, NULL);
	dictAdd(d, (void *)ex_1, (void *)v_1);
	dictAdd(d, (void *)ex_2, (void *)v_2);
	dictAdd(d, (void *)ex_3, (void *)v_3);
	dictAdd(d, (void *)ex_4, (void *)v_4);
	dictAdd(d, (void *)ex_5, (void *)v_5);
	dictAdd(d, (void *)ex_6, (void *)v_6);
	dictAdd(d, (void *)ex_7, (void *)v_7);
	dictAdd(d, (void *)ex_8, (void *)v_8);
	dictAdd(d, (void *)ex_9, (void *)v_9);
	dictAdd(d, (void *)ex_10,(void *)v_10);
	dictAdd(d, (void *)ex_11,(void *)v_11);
	dictAdd(d, (void *)ex_12,(void *)v_12);
	dictAdd(d, (void *)ex_13,(void *)v_13);
	dictAdd(d, (void *)ex_14,(void *)v_14);
	dictAdd(d, (void *)ex_15,(void *)v_15);
	dictAdd(d, (void *)ex_16,(void *)v_16);
	dictAdd(d, (void *)ex_17,(void *)v_17);
	dictAdd(d, (void *)ex_18,(void *)v_18);
	dictAdd(d, (void *)ex_19,(void *)v_19);
	dictAdd(d, (void *)ex_20,(void *)v_20);
	dictAdd(d, (void *)ex_21,(void *)v_21);
	
		
	return 0;
}
示例#7
0
int main(void) {
    {
        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 = sdstrim(sdsnew("xxciaoyyy"),"xy");
        test_cond("sdstrim() correctly trims characters",
            sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0)

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

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

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

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

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

        sdsfree(y);
        y = sdsrange(sdsdup(x),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)
    }
    test_report()
}
示例#8
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;
}
示例#9
0
void scriptCommand(redisClient *c)
{
    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"flush"))
    {
        scriptingReset();
        addReply(c,shared.ok);
        server.dirty++; /* Replicating this command is a good idea. */
    }
    else if (c->argc >= 2 && !strcasecmp(c->argv[1]->ptr,"exists"))
    {
        int j;

        addReplyMultiBulkLen(c, c->argc-2);
        for (j = 2; j < c->argc; j++)
        {
            if (dictFind(server.lua_scripts,c->argv[j]->ptr))
                addReply(c,shared.cone);
            else
                addReply(c,shared.czero);
        }
    }
    else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,"load"))
    {
        char funcname[43];
        sds sha;

        // 生成函数名
        funcname[0] = 'f';
        funcname[1] = '_';
        // 计算脚本的 SHA1 值
        sha1hex(funcname+2,c->argv[2]->ptr,sdslen(c->argv[2]->ptr));
        sha = sdsnewlen(funcname+2,40);
        // 根据 SHA1 值,在字典中查找脚本
        if (dictFind(server.lua_scripts,sha) == NULL)
        {
            // 如果脚本未定义,在 Lua 中创建新函数
            if (luaCreateFunction(c,server.lua,funcname,c->argv[2])
                    == REDIS_ERR)
            {
                sdsfree(sha);
                return;
            }
        }
        // 返回脚本的 SHA1 值
        addReplyBulkCBuffer(c,funcname+2,40);
        sdsfree(sha);
    }
    else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"kill"))
    {
        if (server.lua_caller == NULL)
        {
            addReplySds(c,sdsnew("-NOTBUSY No scripts in execution right now.\r\n"));
        }
        else if (server.lua_write_dirty)
        {
            addReplySds(c,sdsnew("-UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in an hard way using the SHUTDOWN NOSAVE command.\r\n"));
        }
        else
        {
            server.lua_kill = 1;
            addReply(c,shared.ok);
        }
    }
    else
    {
        addReplyError(c, "Unknown SCRIPT subcommand or wrong # of args.");
    }
}
示例#10
0
文件: aof.c 项目: kamparo/tweet
/* Replay the append log file. On error REDIS_OK is returned. On non fatal
 * error (the append only file is zero-length) REDIS_ERR is returned. On
 * fatal error an error message is logged and the program exists. */
int loadAppendOnlyFile(char *filename) {
    struct redisClient *fakeClient;
    FILE *fp = fopen(filename,"r");
    struct redis_stat sb;
    int old_aof_state = server.aof_state;
    long loops = 0;

    if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
        server.aof_current_size = 0;
        fclose(fp);
        return REDIS_ERR;
    }

    if (fp == NULL) {
        redisLog(REDIS_WARNING,"Fatal error: can't open the append log file for reading: %s",strerror(errno));
        exit(1);
    }

    /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI
     * to the same file we're about to read. */
    server.aof_state = REDIS_AOF_OFF;

    fakeClient = createFakeClient();
    startLoading(fp);

    while(1) {
        int argc, j;
        unsigned long len;
        robj **argv;
        char buf[128];
        sds argsds;
        struct redisCommand *cmd;

        /* Serve the clients from time to time */
        if (!(loops++ % 1000)) {
            loadingProgress(ftello(fp));
            processEventsWhileBlocked();
        }

        if (fgets(buf,sizeof(buf),fp) == NULL) {
            if (feof(fp))
                break;
            else
                goto readerr;
        }
        if (buf[0] != '*') goto fmterr;
        if (buf[1] == '\0') goto readerr;
        argc = atoi(buf+1);
        if (argc < 1) goto fmterr;

        argv = zmalloc(sizeof(robj*)*argc);
        fakeClient->argc = argc;
        fakeClient->argv = argv;

        for (j = 0; j < argc; j++) {
            if (fgets(buf,sizeof(buf),fp) == NULL) {
                fakeClient->argc = j; /* Free up to j-1. */
                freeFakeClientArgv(fakeClient);
                goto readerr;
            }
            if (buf[0] != '$') goto fmterr;
            len = strtol(buf+1,NULL,10);
            argsds = sdsnewlen(NULL,len);
            if (len && fread(argsds,len,1,fp) == 0) {
                sdsfree(argsds);
                fakeClient->argc = j; /* Free up to j-1. */
                freeFakeClientArgv(fakeClient);
                goto readerr;
            }
            argv[j] = createObject(REDIS_STRING,argsds);
            if (fread(buf,2,1,fp) == 0) {
                fakeClient->argc = j+1; /* Free up to j. */
                freeFakeClientArgv(fakeClient);
                goto readerr; /* discard CRLF */
            }
        }

        /* Command lookup */
        cmd = lookupCommand(argv[0]->ptr);
        if (!cmd) {
            redisLog(REDIS_WARNING,"Unknown command '%s' reading the append only file", (char*)argv[0]->ptr);
            exit(1);
        }

        /* Run the command in the context of a fake client */
        cmd->proc(fakeClient);

        /* The fake client should not have a reply */
        redisAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);
        /* The fake client should never get blocked */
        redisAssert((fakeClient->flags & REDIS_BLOCKED) == 0);

        /* Clean up. Command code may have changed argv/argc so we use the
         * argv/argc of the client instead of the local variables. */
        freeFakeClientArgv(fakeClient);
    }

    /* This point can only be reached when EOF is reached without errors.
     * If the client is in the middle of a MULTI/EXEC, log error and quit. */
    if (fakeClient->flags & REDIS_MULTI) goto uxeof;

loaded_ok: /* DB loaded, cleanup and return REDIS_OK to the caller. */
    fclose(fp);
    freeFakeClient(fakeClient);
    server.aof_state = old_aof_state;
    stopLoading();
    aofUpdateCurrentSize();
    server.aof_rewrite_base_size = server.aof_current_size;
    return REDIS_OK;

readerr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */
    if (!feof(fp)) {
        redisLog(REDIS_WARNING,"Unrecoverable error reading the append only file: %s", strerror(errno));
        exit(1);
    }

uxeof: /* Unexpected AOF end of file. */
    if (server.aof_load_truncated) {
        redisLog(REDIS_WARNING,"!!! Warning: short read while loading the AOF file !!!");
        redisLog(REDIS_WARNING,
            "AOF loaded anyway because aof-load-truncated is enabled");
        goto loaded_ok;
    }
    redisLog(REDIS_WARNING,"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.");
    exit(1);

fmterr: /* Format error. */
    redisLog(REDIS_WARNING,"Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>");
    exit(1);
}
示例#11
0
/* Create a new slowlog entry.
 *
 * 创建一条新的慢查询日志
 *
 * Incrementing the ref count of all the objects retained is up to
 * this function.
 *
 * 函数负责增加所有记录对象的引用计数
 */
slowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration)
{
    slowlogEntry *se = zmalloc(sizeof(*se));
    int j, slargc = argc;

    // 如果参数过多,那么只记录服务器允许的最大参数数量
    if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;

    // 记录参数数量
    se->argc = slargc;

    // 遍历并记录命令的参数
    se->argv = zmalloc(sizeof(robj*)*slargc);
    for (j = 0; j < slargc; j++)
    {
        /* Logging too many arguments is a useless memory waste, so we stop
         * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify
         * how many remaining arguments there were in the original command. */
        // 当参数的数量超过服务器允许的最大参数数量时,
        // 用最后一个参数记录省略提示
        if (slargc != argc && j == slargc-1)
        {
            se->argv[j] = createObject(REDIS_STRING,
                                       sdscatprintf(sdsempty(),"... (%d more arguments)",
                                                    argc-slargc+1));
        }
        else
        {
            /* Trim too long strings as well... */
            // 如果参数太长,那么进行截断
            if (argv[j]->type == REDIS_STRING &&
                    sdsEncodedObject(argv[j]) &&
                    sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)
            {
                sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING);

                s = sdscatprintf(s,"... (%lu more bytes)",
                                 (unsigned long)
                                 sdslen(argv[j]->ptr) - SLOWLOG_ENTRY_MAX_STRING);

                se->argv[j] = createObject(REDIS_STRING,s);
            }
            else
            {
                se->argv[j] = argv[j];
                incrRefCount(argv[j]);
            }
        }
    }

    // 命令的执行时间
    se->time = time(NULL);

    // 执行命令耗费的时间
    se->duration = duration;

    // 设置慢查询 id
    se->id = server.slowlog_entry_id++;

    return se;
}
示例#12
0
static void* rdbLoadValueObject(FILE *fp, int type, unsigned int *rlen) {
    unsigned int i, j, len;
    int buf_len;
    sds ele;
    sds *results = NULL;
    char buf[128];

    if(type == REDIS_STRING) {
        /* value type is string. */
        parser_stats.parse_num[STRING] += 1;
        ele = rdbLoadEncodedStringObject(fp);
        *rlen = sdslen(ele);
        return ele;

    } else if(type == REDIS_LIST) {
        /* value type is list. */
        parser_stats.parse_num[LIST] += 1;
        if ((len = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL;
        j = 0;
        *rlen = len;
        results = zmalloc(len * sizeof(*results));
        while(len--) {
            if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
            results[j++] = ele;
        }
        return results;

    } else if(type == REDIS_SET) {
        /* value type is set. */
        parser_stats.parse_num[SET] += 1;
        if ((len = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL;
        *rlen = len;
        results = zmalloc(len * sizeof(*results));
        for (i = 0; i < len; i++) {
            if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
            results[i] = ele; 
        }
        return results;

    } else if (type == REDIS_ZSET) {
        /* value type is zset */
        parser_stats.parse_num[ZSET] += 1;
        size_t zsetlen;
        double score;
        j = 0;    
        if ((zsetlen = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL;

        if(rdb_version < 2) {
            *rlen = zsetlen * 2;
        } else {
            *rlen = zsetlen;
        }
        results = zmalloc( *rlen * sizeof(*results));
        while(zsetlen--) {
            if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
            if (rdbLoadDoubleValue(fp,&score) == -1) return NULL;
            buf_len = snprintf(buf, 128, "%f", score);
            results[j] = ele;
            results[j+1] = sdsnewlen(buf, buf_len);
            j += 2;
        }
        return results;

    } else if (type == REDIS_HASH) {
        /* value type is hash */
        parser_stats.parse_num[HASH] += 1;
        size_t hashlen;
        if ((hashlen = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL;
        sds key, val;
        j = 0;
        *rlen = hashlen * 2;
        results = zmalloc(*rlen * sizeof(*results));
        while(hashlen--) {
            if ((key = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
            if ((val = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
            results[j] = key;
            results[j + 1] = val;
            j += 2;
        }
        return results;

    } else if(type == REDIS_HASH_ZIPMAP || 
            type == REDIS_LIST_ZIPLIST ||
            type == REDIS_SET_INTSET ||
            type == REDIS_ZSET_ZIPLIST ||
            type == REDIS_LSET) {
        sds aux = rdbLoadStringObject(fp); 
        switch(type) {
            case REDIS_HASH_ZIPMAP:
                parser_stats.parse_num[HASH] += 1;
                results = loadHashZipMapObject((unsigned char*)aux, rlen);
                break;
            case REDIS_LIST_ZIPLIST:
                parser_stats.parse_num[LIST] += 1;
                results = loadListZiplistObject((unsigned char *)aux, rlen);
                break;
            case REDIS_SET_INTSET:
                parser_stats.parse_num[SET] += 1;
                results = loadSetIntsetObject((unsigned char *)aux, rlen);
                break;
            case REDIS_ZSET_ZIPLIST:
                parser_stats.parse_num[ZSET] += 1;
                results = loadZsetZiplistObject((unsigned char *)aux, rlen);
                break;
        }
        sdsfree(aux);
        return results;
    } else {
        parsePanic("Unknown object type");
    }
}
示例#13
0
/* Create a string object with encoding OBJ_ENCODING_RAW, that is a plain
 * string object where o->ptr points to a proper sds string. */
robj *createRawStringObject(const char *ptr, size_t len) {
    return createObject(OBJ_STRING,sdsnewlen(ptr,len));
}
示例#14
0
文件: se_core.c 项目: itgb/ap_apps
static int se_try_read(lua_State *L, int fd, int size, sds *pcache)
{
	char sbuf[4 << 10];
	char *cache = *pcache;
	char *buf;
	int bufsize;
	int nread;

	if (cache) {
		bufsize = sdsavail(cache);
		buf = cache + sdslen(cache);
		printf("continue try read: %d / %d\n", bufsize, size);
	} else { // first try
		bufsize = size > 0 ? size : size < 0 ? -size : sizeof(sbuf);
		if (bufsize <= sizeof(sbuf)) {
			buf = sbuf;
		} else {
			cache = sdsnewlen(NULL, bufsize);
			oom_check(cache);
			sdsclear(cache);
			*pcache = cache;
			buf = cache;
		}
		printf("try read: %d / %d\n", bufsize, size);
	}

	nread = read(fd, buf, bufsize);
	if (nread > 0) {
		if (size <= 0 || nread == bufsize) { // done
			if (cache) {
				lua_pushlstring(L, cache, sdslen(cache) + nread);
				sdsfree(cache);
				*pcache = NULL;
			} else {
				lua_pushlstring(L, buf, nread);
			}
			printf("read done: %d / %d / %d\n", nread, bufsize, size);
			return 1;
		}
		// partial read
		if (!cache) {
			cache = sdsnewlen(NULL, bufsize);
			oom_check(cache);
			sdsclear(cache);
			*pcache = cache;
			memcpy(cache, buf, nread);
		}
		sdsIncrLen(cache, nread);
		printf("partial read: %d / %d / %d\n", nread, bufsize, size);
		return -1;
	}

	if (nread == 0)
		return se_read_error(L, pcache, "EOF");

	if (errno == EAGAIN || errno == EWOULDBLOCK)
		return -1;

	se_assert(L, errno != EBADF, "read(%d) error", fd);
	return se_read_error(L, pcache, strerror(errno));
}
示例#15
0
/**
 * make a new string with content of *init
 */
sds sdsnew(const char *init) {
    /* calculate the length of new string */
    size_t initlen = (init == NULL) ? 0 : strlen(init);
    /* call sdsnewlen(const void *, size_t) to new a string */
    return sdsnewlen(init, initlen);
}
示例#16
0
void createTableAsObject(redisClient *c) {
    robj *axs_type = c->argv[4];
    int   axs      = -1;
    for (int i = 0; i < NUM_ACCESS_TYPES; i++) {
        if (!strcasecmp(axs_type->ptr, AccessCommands[i].name)) {
            axs = i;
            break;
        }
    }
  
    if (axs != -1) {
        if (c->argc < (4 + AccessCommands[axs].argc)) {
            addReply(c, shared.create_table_as_access_num_args);
            return;
        }
    } else {
        if (strcasecmp(axs_type->ptr, DUMP)) {
            addReply(c, shared.create_table_as_function_not_found);
            return;
        }
        if (c->argc < 6) {
            addReply(c, shared.create_table_as_dump_num_args);
            return;
        }
    }

    robj *cdef;
    bool  single;
    robj *o  = NULL;
    if (axs == ACCESS_SELECT_COMMAND_NUM) {
        uchar sop   = 0; /*used in ARGN_OVERFLOW() */
        int   argn  = 5;
        sds   clist = sdsempty();

        parseSelectColumnList(c, &clist, &argn);
        /* parseSelectColumnList edits the cargv ----------------\/           */
        sdsfree(c->argv[5]->ptr);                             /* so free it   */
        c->argv[5]->ptr = sdsnewlen(clist, sdslen(clist));;   /* and recr8 it */
        ARGN_OVERFLOW()                      /* skip SQL keyword"FROM" */

        robj               *argv[3];
        bool                ret   = 0;
        int                 qcols = 0;
        uchar               where = 0;
        struct redisClient *rfc   = rsql_createFakeClient();
        rfc->argv                 = argv;
        rfc->argv[1]              = c->argv[2];
        if (strchr(clist, '.')) { /* CREATE TABLE AS SELECT JOIN */
            int   j_indxs[MAX_JOIN_INDXS];
            int   j_tbls [MAX_JOIN_INDXS], j_cols [MAX_JOIN_INDXS];
            int   idum;
            bool  bdum;
            robj *range = NULL;
            robj *nname = NULL;
            list *inl   = NULL;
            /* check WHERE clause for syntax */
            where = joinParseReply(c, clist, argn, j_indxs, j_tbls, j_cols,
                                   &qcols, &idum, &nname, &range, &idum,
                                   &idum, &idum, &bdum, &idum, &inl);
            if (inl)   listRelease(inl);
            if (range) decrRefCount(range);
            if (where && qcols)
                ret = createTableFromJoin(c, rfc, qcols, j_tbls, j_cols);
        } else {
            TABLE_CHECK_OR_REPLY(c->argv[argn]->ptr,);
            int cmatchs[MAX_COLUMN_PER_TABLE];
            qcols = parseColListOrReply(c, tmatch, clist, cmatchs);
            if (qcols) { /* check WHERE clause for syntax */
                bool  bdum;
                int   obc = -1; /* ORDER BY col */
                bool  asc = 1;
                int   lim = -1;
                list *inl = NULL;
                ARGN_OVERFLOW()
                where = checkSQLWhereClauseReply(c, NULL, NULL, NULL, NULL,
                                                 &argn, tmatch, 0, 1,
                                                 &obc, &asc, &lim, &bdum, &inl);
                if (inl) listRelease(inl);
                if (where)
                    ret = internalCreateTable(c, rfc, qcols, cmatchs, tmatch);
            }
        }
        rsql_freeFakeClient(rfc);
        if (!ret || !where || !qcols) return;

        createTableAsObjectOperation(c, 1);

        addReply(c, shared.ok);
        return;
    }
示例#17
0
static int process_multibulk_buffer(sub_client *c)
{
    char *newline = NULL;
    int pos = 0, ok;
    long long ll;

    if (c->multi_bulk_len == 0) {
        /* Multi bulk length cannot be read without a \r\n */
        newline = strchr(c->read_buf, '\r');
        if (newline == NULL) {
            if (sdslen(c->read_buf) > MAX_INLINE_READ) {
                srv_log(LOG_ERROR, "protocol error: too big mbulk string");
                set_protocol_err(c, 0);
            }
            return SUBCLI_ERR;
        }

        /* Buffer should also contain \n */
        if (newline-(c->read_buf) > ((signed)sdslen(c->read_buf)-2)) {
            return SUBCLI_ERR;
        }

        ok = string2ll(c->read_buf+1, newline-(c->read_buf+1), &ll);
        if (!ok || ll > SUB_READ_BUF_LEN) {
            srv_log(LOG_ERROR, "protocol error: invalid multibulk length");
            set_protocol_err(c, pos);
            return SUBCLI_ERR;
        }

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

        c->multi_bulk_len = ll;
        c->argv = malloc(sizeof(sds) * c->multi_bulk_len);
    }

    while (c->multi_bulk_len) {
        /* Read bulk length if unknown */
        if (c->bulk_len == -1) {
            newline = strchr(c->read_buf + pos, '\r');
            if (newline == NULL) {
                if (sdslen(c->read_buf) > MAX_INLINE_READ) {
                    srv_log(LOG_ERROR, "protocol error: too big bulk count string");
                    set_protocol_err(c, 0);
                    return SUBCLI_ERR;
                }
                break;
            }

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

            if (c->read_buf[pos] != '$') {
                srv_log(LOG_ERROR, "Protocol error: expected '$', got '%c'",
                        c->read_buf[pos]);
                set_protocol_err(c, pos);
                return SUBCLI_ERR;
            }

            ok = string2ll(c->read_buf+pos+1, newline-(c->read_buf+pos+1), &ll);
            if (!ok || ll < 0 || ll > MAX_BULK_LEN) {
                srv_log(LOG_ERROR, "Protocol error: invalid bulk length");
                set_protocol_err(c, pos);
                return SUBCLI_ERR;
            }

            pos += newline - (c->read_buf + pos) + 2;
            c->bulk_len = ll;
        }

        /* Read bulk argument */
        if (sdslen(c->read_buf) - pos < (unsigned)(c->bulk_len + 2)) {
            /* Not enough data (+2 == trailing \r\n) */
            break;
        } else {
            /*c->argv[c->argc++] = create_string_obj(c->read_buf+pos, c->bulk_len);*/
            c->argv[c->argc++] = sdsnewlen(c->read_buf+pos, c->bulk_len);
            pos += c->bulk_len + 2;
        }
        c->bulk_len = -1;
        c->multi_bulk_len--;
    }

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

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

    /* Still not read to process the command */
    return SUBCLI_ERR;
}
示例#18
0
vr_listen *
vr_listen_create(sds listen_str)
{
    rstatus_t status;
    vr_listen *vlisten;
    uint8_t *p, *name;
    uint32_t namelen;

    if (listen_str == NULL) {
        return NULL;
    }

    vlisten = vr_alloc(sizeof(struct vr_listen));
    if (vlisten == NULL) {
        return NULL;
    }

    vlisten->name = NULL;
    vlisten->port = 0;
    memset(&vlisten->info, 0, sizeof(vlisten->info));
    vlisten->sd = -1;
    
    if (listen_str == '/') {
        uint8_t *q, *start, *perm;
        uint32_t permlen;

        /* parse "socket_path permissions" from the end */
        p = listen_str + sdslen(listen_str) - 1;
        start = listen_str;
        q = vr_strrchr(p, start, ' ');
        if (q == NULL) {
            /* no permissions field, so use defaults */
            name = listen_str;
            namelen = sdslen(listen_str);
        } else {
            perm = q + 1;
            permlen = (uint32_t)(p - perm + 1);

            p = q - 1;
            name = start;
            namelen = (uint32_t)(p - start + 1);

            errno = 0;
            vlisten->perm = (mode_t)strtol((char *)perm, NULL, 8);
            if (errno || vlisten->perm > 0777) {
                log_error("config file has an invalid file permission in \"socket_path permission\" format string");
                vr_listen_destroy(vlisten);
                return NULL;
            }
        }
    } else {
        uint8_t *q, *start, *port;
        uint32_t portlen;

        /* parse "hostname:port" from the end */
        p = listen_str + sdslen(listen_str) - 1;
        start = listen_str;
        q = vr_strrchr(p, start, ':');
        if (q == NULL) {
            log_error("config file has an invalid \"hostname:port\" format string");
            vr_listen_destroy(vlisten);
            return NULL;
        }

        port = q + 1;
        portlen = (uint32_t)(p - port + 1);

        p = q - 1;

        name = start;
        namelen = (uint32_t)(p - start + 1);

        vlisten->port = vr_atoi(port, portlen);
        if (vlisten->port < 0 || !vr_valid_port(vlisten->port)) {
            log_error("config file has an invalid port in \"hostname:port\" format string");
            vr_listen_destroy(vlisten);
            return NULL;
        }
    }

    vlisten->name = sdsnewlen(name, namelen);
    if (vlisten->name == NULL) {
        log_error("create a sds string failed: out of memory.");
        vr_listen_destroy(vlisten);
        return NULL;
    }

    status = vr_resolve(vlisten->name, vlisten->port, &vlisten->info);
    if (status != VR_OK) {
        vr_listen_destroy(vlisten);
        return NULL;
    }

    return vlisten;
}
示例#19
0
/* Split 's' with separator in 'sep'. An array
 * of sds strings is returned. *count will be set
 * by reference to the number of tokens returned.
 *
 * On out of memory, zero length string, zero length
 * separator, NULL is returned.
 *
 * Note that 'sep' is able to split a string using
 * a multi-character separator. For example
 * sdssplit("foo_-_bar","_-_"); will return two
 * elements "foo" and "bar".
 *
 * This version of the function is binary-safe but
 * requires length arguments. sdssplit() is just the
 * same function but for zero-terminated strings.
 */
sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
    int elements = 0, slots = 5, start = 0, j;

    sds *tokens = malloc(sizeof(sds)*slots);
#ifdef SDS_ABORT_ON_OOM
    if (tokens == NULL) sdsOomAbort();
#endif
    if (seplen < 1 || len < 0 || tokens == NULL) return NULL;
    if (len == 0) {
        *count = 0;
        return tokens;
    }
    for (j = 0; j < (len-(seplen-1)); j++) {
        /* make sure there is room for the next element and the final one */
        if (slots < elements+2) {
            sds *newtokens;

            slots *= 2;
            newtokens = realloc(tokens,sizeof(sds)*slots);
            if (newtokens == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
            }
            tokens = newtokens;
        }
        /* search the separator */
        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {
            tokens[elements] = sdsnewlen(s+start,j-start);
            if (tokens[elements] == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
            }
            elements++;
            start = j+seplen;
            j = j+seplen-1; /* skip the separator */
        }
    }
    /* Add the final element. We are sure there is room in the tokens array. */
    tokens[elements] = sdsnewlen(s+start,len-start);
    if (tokens[elements] == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
    }
    elements++;
    *count = elements;
    return tokens;

#ifndef SDS_ABORT_ON_OOM
cleanup:
    {
        int i;
        for (i = 0; i < elements; i++) sdsfree(tokens[i]);
        free(tokens);
        return NULL;
    }
#endif
}
示例#20
0
文件: cetcd.c 项目: Huang-lin/cetcd
size_t cetcd_parse_response(char *ptr, size_t size, size_t nmemb, void *userdata) {
    int len, i;
    char *key, *val;
    cetcd_response_parser *parser;
    yajl_status status;
    cetcd_response *resp = NULL;
    cetcd_array *addrs = NULL;

    enum resp_parser_st {
        request_line_start_st,
        request_line_end_st,
        request_line_http_status_start_st,
        request_line_http_status_st,
        request_line_http_status_end_st,
        header_key_start_st,
        header_key_st,
        header_key_end_st,
        header_val_start_st,
        header_val_st,
        header_val_end_st,
        blank_line_st,
        json_start_st,
        json_end_st,
        response_discard_st
    };
    /* Headers we are interested in:
     * X-Etcd-Index: 14695
     * X-Raft-Index: 672930
     * X-Raft-Term: 12
     * */
    parser = userdata;
    if (parser->api_type == ETCD_MEMBERS) {
        addrs = parser->resp;
    } else {
        resp = parser->resp;
    }
    len = size * nmemb;
    for (i = 0; i < len; ++i) {
        if (parser->st == request_line_start_st) {
            if (ptr[i] == ' ') {
                parser->st = request_line_http_status_start_st;
            }
            continue;
        }
        if (parser->st == request_line_end_st) {
            if (ptr[i] == '\n') {
                parser->st = header_key_start_st;
            }
            continue;
        }
        if (parser->st == request_line_http_status_start_st) {
            parser->buf = sdscatlen(parser->buf, ptr+i, 1);
            parser->st = request_line_http_status_st;
            continue;
        }
        if (parser->st == request_line_http_status_st) {
            if (ptr[i] == ' ') {
                parser->st = request_line_http_status_end_st;
            } else {
                parser->buf = sdscatlen(parser->buf, ptr+i, 1);
                continue;
            }
        }
        if (parser->st == request_line_http_status_end_st) {
            val = parser->buf;
            parser->http_status = atoi(val);
            sdsclear(parser->buf);
            parser->st = request_line_end_st;
            if (parser->api_type == ETCD_MEMBERS && parser->http_status != 200) {
                parser->st = response_discard_st;
            }
            continue;
        }
        if (parser->st == header_key_start_st) {
            if (ptr[i] == '\r') {
                ++i;
            }
            if (ptr[i] == '\n') {
                parser->st = blank_line_st;
                if (parser->http_status >= 300 && parser->http_status < 400) {
                    /*this is a redirection, restart the state machine*/
                    parser->st = request_line_start_st;
                    break;
                }
                continue;
            }
            parser->st = header_key_st;
        }
        if (parser->st == header_key_st) {
            parser->buf = sdscatlen(parser->buf, ptr+i, 1);
            if (ptr[i] == ':') {
                parser->st = header_key_end_st;
            } else {
                continue;
            }
        }
        if (parser->st == header_key_end_st) {
            parser->st = header_val_start_st;
            continue;
        }
        if (parser->st == header_val_start_st) {
            if (ptr[i] == ' ') {
                continue;
            }
            parser->st = header_val_st;
        }
        if (parser->st == header_val_st) {
            if (ptr[i] == '\r') {
                ++i;
            }
            if (ptr[i] == '\n') {
                parser->st = header_val_end_st;
            } else {
                parser->buf = sdscatlen(parser->buf, ptr+i, 1);
                continue;
            }
        }
        if (parser->st == header_val_end_st) {
            parser->st = header_key_start_st;
            if (parser->api_type == ETCD_MEMBERS) {
                continue;
            }
            int count = 0;
            sds *kvs = sdssplitlen(parser->buf, sdslen(parser->buf), ":", 1, &count);
            sdsclear(parser->buf);
            if (count < 2) {
                sdsfreesplitres(kvs, count);
                continue;
            }
            key = kvs[0];
            val = kvs[1];
            if (strncmp(key, "X-Etcd-Index", sizeof("X-Etcd-Index")-1) == 0) {
                resp->etcd_index = atoi(val);
            } else if (strncmp(key, "X-Raft-Index", sizeof("X-Raft-Index")-1) == 0) {
                resp->raft_index = atoi(val);
            } else if (strncmp(key, "X-Raft-Term", sizeof("X-Raft-Term")-1) == 0) {
                resp->raft_term = atoi(val);
            }
            sdsfreesplitres(kvs, count);
            continue;
        }
        if (parser->st == blank_line_st) {
            if (ptr[i] != '{') {
                /*not a json response, discard*/
                parser->st = response_discard_st;
                if (resp->err == NULL && parser->api_type == ETCD_KEYS) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    resp->err->ecode = error_response_parsed_failed;
                    resp->err->message = sdsnew("not a json response");
                    resp->err->cause = sdsnewlen(ptr, len);
                }
                continue;
            }
            parser->st = json_start_st;
            cetcd_array_init(&parser->ctx.keystack, 10);
            cetcd_array_init(&parser->ctx.nodestack, 10);
            if (parser->api_type == ETCD_MEMBERS) {
                parser->ctx.userdata = addrs;
                parser->json = yajl_alloc(&sync_callbacks, 0, &parser->ctx);
            }
            else {
                if (parser->http_status != 200 && parser->http_status != 201) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    parser->ctx.userdata = resp->err;
                    parser->json = yajl_alloc(&error_callbacks, 0, &parser->ctx);
                } else {
                    parser->ctx.userdata = resp;
                    parser->json = yajl_alloc(&callbacks, 0, &parser->ctx);
                }
            }
        }
        if (parser->st == json_start_st) {
            if (yajl_status_ok != yajl_parse(parser->json, (const unsigned char *)ptr + i, len - i)) {
                parser->st = json_end_st;
            } else {
                parser->st = response_discard_st;
                yajl_free(parser->json);
                cetcd_array_destroy(&parser->ctx.keystack);
                cetcd_array_destroy(&parser->ctx.nodestack);
            }
        }
        if (parser->st == json_end_st) {
            status = yajl_complete_parse(parser->json);
            yajl_free(parser->json);
            cetcd_array_destroy(&parser->ctx.keystack);
            cetcd_array_destroy(&parser->ctx.nodestack);
            /*parse failed, TODO set error message*/
            if (status != yajl_status_ok) {
                if ( parser->api_type == ETCD_KEYS && resp->err == NULL) {
                    resp->err = calloc(1, sizeof(cetcd_error));
                    resp->err->ecode = error_response_parsed_failed;
                    resp->err->message = sdsnew("http response is invalid json format");
                    resp->err->cause = sdsnewlen(ptr, len);
                }
                return 0;
            }
            break;
        }
        if (parser->st == response_discard_st) {
            return len;
        }
    }
    return len;
}
示例#21
0
/* Create an empty (zero length) sds string. Even in this case the string
 * always has an implicit null term. */
sds sdsempty(void) {
    // 创建一个空的sds
    return sdsnewlen("",0);
}
示例#22
0
文件: lexer.c 项目: t3rm1n4l/alloy
sds extractToken(Lexer *self, int start, int length) {
	return sdsnewlen(&self->input[start], length);
}
示例#23
0
/* Duplicate an sds string. */
sds sdsdup(const sds s) {
    // copy new sds
    return sdsnewlen(s, sdslen(s));
}
示例#24
0
/* Replay the append log file. On error REDIS_OK is returned. On non fatal
 * error (the append only file is zero-length) REDIS_ERR is returned. On
 * fatal error an error message is logged and the program exists. */
int loadAppendOnlyFile(char *filename) {
    struct redisClient *fakeClient;
    FILE *fp = fopen(filename,"r");
    struct redis_stat sb;
    int old_aof_state = server.aof_state;
    long loops = 0;

    if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
        server.aof_current_size = 0;
        fclose(fp);
        return REDIS_ERR;
    }

    if (fp == NULL) {
        redisLog(REDIS_WARNING,"Fatal error: can't open the append log file for reading: %s",strerror(errno));
        exit(1);
    }

    /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI
     * to the same file we're about to read. */
    server.aof_state = REDIS_AOF_OFF;

    fakeClient = createFakeClient();
    startLoading(fp);

    while(1) {
        int argc, j;
        unsigned long len;
        robj **argv;
        char buf[128];
        sds argsds;
        struct redisCommand *cmd;

        /* Serve the clients from time to time */
        if (!(loops++ % 1000)) {
            loadingProgress(ftello(fp));
            aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);
        }

        if (fgets(buf,sizeof(buf),fp) == NULL) {
            if (feof(fp))
                break;
            else
                goto readerr;
        }
        if (buf[0] != '*') goto fmterr;
        argc = atoi(buf+1);
        if (argc < 1) goto fmterr;

        argv = zmalloc(sizeof(robj*)*argc);
        for (j = 0; j < argc; j++) {
            if (fgets(buf,sizeof(buf),fp) == NULL) goto readerr;
            if (buf[0] != '$') goto fmterr;
            len = strtol(buf+1,NULL,10);
            argsds = sdsnewlen(NULL,len);
            if (len && fread(argsds,len,1,fp) == 0) goto fmterr;
            argv[j] = createObject(REDIS_STRING,argsds);
            if (fread(buf,2,1,fp) == 0) goto fmterr; /* discard CRLF */
        }

        /* Command lookup */
        cmd = lookupCommand(argv[0]->ptr);
        if (!cmd) {
            redisLog(REDIS_WARNING,"Unknown command '%s' reading the append only file", (char*)argv[0]->ptr);
            exit(1);
        }
        /* Run the command in the context of a fake client */
        fakeClient->argc = argc;
        fakeClient->argv = argv;
        cmd->proc(fakeClient);

        /* The fake client should not have a reply */
        redisAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);
        /* The fake client should never get blocked */
        redisAssert((fakeClient->flags & REDIS_BLOCKED) == 0);

        /* Clean up. Command code may have changed argv/argc so we use the
         * argv/argc of the client instead of the local variables. */
        for (j = 0; j < fakeClient->argc; j++)
            decrRefCount(fakeClient->argv[j]);
        zfree(fakeClient->argv);
    }

    /* This point can only be reached when EOF is reached without errors.
     * If the client is in the middle of a MULTI/EXEC, log error and quit. */
    if (fakeClient->flags & REDIS_MULTI) goto readerr;

    fclose(fp);
    freeFakeClient(fakeClient);
    server.aof_state = old_aof_state;
    stopLoading();
    aofUpdateCurrentSize();
    server.aof_rewrite_base_size = server.aof_current_size;
    return REDIS_OK;

readerr:
    if (feof(fp)) {
        redisLog(REDIS_WARNING,"Unexpected end of file reading the append only file");
    } else {
        redisLog(REDIS_WARNING,"Unrecoverable error reading the append only file: %s", strerror(errno));
    }
    exit(1);
fmterr:
    redisLog(REDIS_WARNING,"Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>");
    exit(1);
}
示例#25
0
文件: sds.c 项目: wangxuemin/coding
/* Create an sds string from a long long value. It is much faster than:
 *
 * sdscatprintf(sdsempty(),"%lld\n", value);
 */
sds sdsfromlonglong(long long value) {
    char buf[SDS_LLSTR_SIZE];
    int len = sdsll2str(buf,value);

    return sdsnewlen(buf,len);
}
示例#26
0
int luaRedisGenericCommand(lua_State *lua, int raise_error) {
    int j, argc = lua_gettop(lua);
    struct redisCommand *cmd;
    redisClient *c = server.lua_client;
    sds reply;

    /* Cached across calls. */
    static robj **argv = NULL;
    static int argv_size = 0;
    static robj *cached_objects[LUA_CMD_OBJCACHE_SIZE];
    static int cached_objects_len[LUA_CMD_OBJCACHE_SIZE];

    /* Require at least one argument */
    if (argc == 0) {
        luaPushError(lua,
            "Please specify at least one argument for redis.call()");
        return 1;
    }

    /* Build the arguments vector */
    if (!argv) {
        argv = zmalloc(sizeof(robj*)*argc);
    } else if (argv_size < argc) {
        argv = zrealloc(argv,sizeof(robj*)*argc);
        argv_size = argc;
    }

    for (j = 0; j < argc; j++) {
        char *obj_s;
        size_t obj_len;
        char dbuf[64];

        if (lua_type(lua,j+1) == LUA_TNUMBER) {
            /* We can't use lua_tolstring() for number -> string conversion
             * since Lua uses a format specifier that loses precision. */
            lua_Number num = lua_tonumber(lua,j+1);

            obj_len = snprintf(dbuf,sizeof(dbuf),"%.17g",(double)num);
            obj_s = dbuf;
        } else {
            obj_s = (char*)lua_tolstring(lua,j+1,&obj_len);
            if (obj_s == NULL) break; /* Not a string. */
        }

        /* Try to use a cached object. */
        if (j < LUA_CMD_OBJCACHE_SIZE && cached_objects[j] &&
            cached_objects_len[j] >= obj_len)
        {
            char *s = cached_objects[j]->ptr;
            struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));

            argv[j] = cached_objects[j];
            cached_objects[j] = NULL;
            memcpy(s,obj_s,obj_len+1);
            sh->free += (int)(sh->len - obj_len);
            sh->len = (int)obj_len;
        } else {
            argv[j] = createStringObject(obj_s, obj_len);
        }
    }

    /* Check if one of the arguments passed by the Lua script
     * is not a string or an integer (lua_isstring() return true for
     * integers as well). */
    if (j != argc) {
        j--;
        while (j >= 0) {
            decrRefCount(argv[j]);
            j--;
        }
        luaPushError(lua,
            "Lua redis() command arguments must be strings or integers");
        return 1;
    }

    /* Setup our fake client for command execution */
    c->argv = argv;
    c->argc = argc;

    /* Command lookup */
    cmd = lookupCommand(argv[0]->ptr);
    if (!cmd || ((cmd->arity > 0 && cmd->arity != argc) ||
                   (argc < -cmd->arity)))
    {
        if (cmd)
            luaPushError(lua,
                "Wrong number of args calling Redis command From Lua script");
        else
            luaPushError(lua,"Unknown Redis command called from Lua script");
        goto cleanup;
    }

    /* There are commands that are not allowed inside scripts. */
    if (cmd->flags & REDIS_CMD_NOSCRIPT) {
        luaPushError(lua, "This Redis command is not allowed from scripts");
        goto cleanup;
    }

    /* Write commands are forbidden against read-only slaves, or if a
     * command marked as non-deterministic was already called in the context
     * of this script. */
    if (cmd->flags & REDIS_CMD_WRITE) {
        if (server.lua_random_dirty) {
            luaPushError(lua,
                "Write commands not allowed after non deterministic commands");
            goto cleanup;
        } else if (server.masterhost && server.repl_slave_ro &&
                   !server.loading &&
                   !(server.lua_caller->flags & REDIS_MASTER))
        {
            luaPushError(lua, shared.roslaveerr->ptr);
            goto cleanup;
        } else if (server.stop_writes_on_bgsave_err &&
                   server.saveparamslen > 0 &&
                   server.lastbgsave_status == REDIS_ERR)
        {
            luaPushError(lua, shared.bgsaveerr->ptr);
            goto cleanup;
        }
    }

    /* If we reached the memory limit configured via maxmemory, commands that
     * could enlarge the memory usage are not allowed, but only if this is the
     * first write in the context of this script, otherwise we can't stop
     * in the middle. */
    if (server.maxmemory && server.lua_write_dirty == 0 &&
        (cmd->flags & REDIS_CMD_DENYOOM))
    {
        if (freeMemoryIfNeeded() == REDIS_ERR) {
            luaPushError(lua, shared.oomerr->ptr);
            goto cleanup;
        }
    }

    if (cmd->flags & REDIS_CMD_RANDOM) server.lua_random_dirty = 1;
    if (cmd->flags & REDIS_CMD_WRITE) server.lua_write_dirty = 1;

    /* Run the command */
    c->cmd = cmd;
    call(c,REDIS_CALL_SLOWLOG | REDIS_CALL_STATS);

    /* Convert the result of the Redis command into a suitable Lua type.
     * The first thing we need is to create a single string from the client
     * output buffers. */
    if (listLength(c->reply) == 0 && c->bufpos < REDIS_REPLY_CHUNK_BYTES) {
        /* This is a fast path for the common case of a reply inside the
         * client static buffer. Don't create an SDS string but just use
         * the client buffer directly. */
        c->buf[c->bufpos] = '\0';
        reply = c->buf;
        c->bufpos = 0;
    } else {
        reply = sdsnewlen(c->buf,c->bufpos);
        c->bufpos = 0;
        while(listLength(c->reply)) {
            robj *o = listNodeValue(listFirst(c->reply));

            reply = sdscatlen(reply,o->ptr,sdslen(o->ptr));
            listDelNode(c->reply,listFirst(c->reply));
        }
    }
    if (raise_error && reply[0] != '-') raise_error = 0;
    redisProtocolToLuaType(lua,reply);
    /* Sort the output array if needed, assuming it is a non-null multi bulk
     * reply as expected. */
    if ((cmd->flags & REDIS_CMD_SORT_FOR_SCRIPT) &&
        (reply[0] == '*' && reply[1] != '-')) {
            luaSortArray(lua);
    }
    if (reply != c->buf) sdsfree(reply);
    c->reply_bytes = 0;

cleanup:
    /* Clean up. Command code may have changed argv/argc so we use the
     * argv/argc of the client instead of the local variables. */
    for (j = 0; j < c->argc; j++) {
        robj *o = c->argv[j];

        /* Try to cache the object in the cached_objects array.
         * The object must be small, SDS-encoded, and with refcount = 1
         * (we must be the only owner) for us to cache it. */
        if (j < LUA_CMD_OBJCACHE_SIZE &&
            o->refcount == 1 &&
            o->encoding == REDIS_ENCODING_RAW &&
            sdslen(o->ptr) <= LUA_CMD_OBJCACHE_MAX_LEN)
        {
            struct sdshdr *sh = (void*)(((char*)(o->ptr))-(sizeof(struct sdshdr)));

            if (cached_objects[j]) decrRefCount(cached_objects[j]);
            cached_objects[j] = o;
            cached_objects_len[j] = sh->free + sh->len;
        } else {
            decrRefCount(o);
        }
    }

    if (c->argv != argv) {
        zfree(c->argv);
        argv = NULL;
    }

    if (raise_error) {
        /* If we are here we should have an error in the stack, in the
         * form of a table with an "err" field. Extract the string to
         * return the plain error. */
        lua_pushstring(lua,"err");
        lua_gettable(lua,-2);
        return lua_error(lua);
    }
    return 1;
}
示例#27
0
文件: sds.c 项目: wangxuemin/coding
/* Create a new sds string starting from a null terminated C string. */
sds sdsnew(const char *init) {
    size_t initlen = (init == NULL) ? 0 : strlen(init);
    return sdsnewlen(init, initlen);
}
示例#28
0
/* Split 's' with separator in 'sep'. An array
 * of sds strings is returned. *count will be set
 * by reference to the number of tokens returned.
 *
 * On out of memory, zero length string, zero length
 * separator, NULL is returned.
 *
 * Note that 'sep' is able to split a string using
 * a multi-character separator. For example
 * sdssplit("foo_-_bar","_-_"); will return two
 * elements "foo" and "bar".
 *
 * This version of the function is binary-safe but
 * requires length arguments. sdssplit() is just the
 * same function but for zero-terminated strings.
 */
sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
    /**
     * @elements : count of split string
     * @slots : count of split string we could have *at most*, used for allocating memory
     * @start : the start position of next split string
     * @j : the current index of s
     */
    int elements = 0, slots = 5, start = 0, j;
    /**
     * @tokens : store the split string
     */
    sds *tokens = zmalloc(sizeof(sds)*slots);
#ifdef SDS_ABORT_ON_OOM
    if (tokens == NULL) sdsOomAbort();
#endif
    /* empty sep, empty s or can't out of memory */
    if (seplen < 1 || len < 0 || tokens == NULL) return NULL;
    /* split the string */
    for (j = 0; j < (len-(seplen-1)); j++) {
        /* make sure there is room for the next element and the final one */
        if (slots < elements+2) {
            sds *newtokens;

            /* double slots */
            slots *= 2;
            /* realloct new room */
            newtokens = zrealloc(tokens,sizeof(sds)*slots);
            if (newtokens == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
            }
            tokens = newtokens;
        }
        /* search the separator */
        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {
            /* make a new sdshdr to hold new string */
            tokens[elements] = sdsnewlen(s+start,j-start);
            if (tokens[elements] == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
            }
            /* update elements, start and j */
            elements++;
            start = j+seplen;
            j = j+seplen-1; /* skip the separator */
        }
    }
    /* Add the final element. We are sure there is room in the tokens array. */
    tokens[elements] = sdsnewlen(s+start,len-start);
    if (tokens[elements] == NULL) {
#ifdef SDS_ABORT_ON_OOM
                sdsOomAbort();
#else
                goto cleanup;
#endif
    }
    /* update info, and return */
    elements++;
    *count = elements;
    return tokens;

#ifndef SDS_ABORT_ON_OOM
cleanup: /* cleanup */
    {
        int i;
        for (i = 0; i < elements; i++) sdsfree(tokens[i]);
        zfree(tokens);
        return NULL;
    }
#endif
}
示例#29
0
文件: async.c 项目: bugou/test
/* Helper function for the redisAsyncCommand* family of functions. Writes a
 * formatted command to the output buffer and registers the provided callback
 * function with the context. */
static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, char *cmd, size_t len) {
    redisContext *c = &(ac->c);
    redisCallback cb;
    int pvariant, hasnext;
    char *cstr, *astr;
    size_t clen, alen;
    char *p;
    sds sname;

    /* Don't accept new commands when the connection is about to be closed. */
    if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR;

    /* Setup callback */
    cb.fn = fn;
    cb.privdata = privdata;

    /* Find out which command will be appended. */
    p = nextArgument(cmd,&cstr,&clen);
    assert(p != NULL);
    hasnext = (p[0] == '$');
    pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0;
    cstr += pvariant;
    clen -= pvariant;

    if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) {
        c->flags |= REDIS_SUBSCRIBED;

        /* Add every channel/pattern to the list of subscription callbacks. */
        while ((p = nextArgument(p,&astr,&alen)) != NULL) {
            sname = sdsnewlen(astr,alen);
            if (pvariant)
                dictReplace(ac->sub.patterns,sname,&cb);
            else
                dictReplace(ac->sub.channels,sname,&cb);
        }
    } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) {
        /* It is only useful to call (P)UNSUBSCRIBE when the context is
         * subscribed to one or more channels or patterns. */
        if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR;

        /* (P)UNSUBSCRIBE does not have its own response: every channel or
         * pattern that is unsubscribed will receive a message. This means we
         * should not append a callback function for this command. */
     } else if(strncasecmp(cstr,"monitor\r\n",9) == 0) {
         /* Set monitor flag and push callback */
         c->flags |= REDIS_MONITORING;
         __redisPushCallback(&ac->replies,&cb);
    } else {
        if (c->flags & REDIS_SUBSCRIBED)
            /* This will likely result in an error reply, but it needs to be
             * received and passed to the callback. */
            __redisPushCallback(&ac->sub.invalid,&cb);
        else
            __redisPushCallback(&ac->replies,&cb);
    }

    __redisAppendCommand(c,cmd,len);

    /* Always schedule a write when the write buffer is non-empty */
    // _EL_ADD_WRITE(ac);
    redisAsyncHandleWrite(ac);

    return REDIS_OK;
}
示例#30
0
/* Replay the append log file. On error REDIS_OK is returned. On non fatal
 * error (the append only file is zero-length) REDIS_ERR is returned. On
 * fatal error an error message is logged and the program exists. */
int loadAppendOnlyFile(char *filename) {
    struct redisClient *fakeClient;
    FILE *fp = fopen(filename,"r");
    struct redis_stat sb;
    unsigned long long loadedkeys = 0;

    if (redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0)
        return REDIS_ERR;

    fakeClient = createFakeClient();
    while(1) {
        int argc, j;
        unsigned long len;
        robj **argv;
        char buf[128];
        sds argsds;
        struct redisCommand *cmd;

        if (fgets(buf,sizeof(buf),fp) == NULL) {
            if (feof(fp))
                break;
            else
                goto readerr;
        }
        if (buf[0] != '*') goto fmterr;
        argc = atoi(buf+1);
        argv = zmalloc(sizeof(robj*)*argc);
        for (j = 0; j < argc; j++) {
            if (fgets(buf,sizeof(buf),fp) == NULL) goto readerr;
            if (buf[0] != '$') goto fmterr;
            len = strtol(buf+1,NULL,10);
            argsds = sdsnewlen(NULL,len);
            if (len && fread(argsds,len,1,fp) == 0) goto fmterr;
            argv[j] = createObject(REDIS_STRING,argsds);
            if (fread(buf,2,1,fp) == 0) goto fmterr; /* discard CRLF */
        }

        /* Command lookup */
        cmd = lookupCommand(argv[0]->ptr);

        /* Try object sharing and encoding */
        if (server.shareobjects) {
            int j;
            for(j = 1; j < argc; j++)
                argv[j] = tryObjectSharing(argv[j]);
        }
        if (cmd->flags & REDIS_CMD_BULK)
            tryObjectEncoding(argv[argc-1]);
        /* Run the command in the context of a fake client */
        fakeClient->argc = argc;
        fakeClient->argv = argv;
        cmd->proc(fakeClient);
        /* Discard the reply objects list from the fake client */
        while(listLength(fakeClient->reply))
            listDelNode(fakeClient->reply,listFirst(fakeClient->reply));
        /* Clean up, ready for the next command */
        for (j = 0; j < argc; j++) decrRefCount(argv[j]);
        zfree(argv);
        /* Handle swapping while loading big datasets when VM is on */
        loadedkeys++;
        if (server.vm_enabled && (loadedkeys % 5000) == 0) {
            while (zmalloc_used_memory() > server.vm_max_memory) {
                if (vmSwapOneObjectBlocking() == REDIS_ERR) break;
            }
        }
    }
    fclose(fp);
    freeFakeClient(fakeClient);
    return REDIS_OK;
}