Beispiel #1
0
int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg) {
    long long value;

    if (getLongLongFromObjectOrReply(c, o, &value, msg) != REDIS_OK) return REDIS_ERR;
    if (value < LONG_MIN || value > LONG_MAX) {
        if (msg != NULL) {
            addReplyError(c,(char*)msg);
        } else {
            addReplyError(c,"value is out of range");
        }
        return REDIS_ERR;
    }

    *target = value;
    return REDIS_OK;
}
void setrangeCommand(redisClient *c) {
    robj *o;
    long offset;
    sds value = c->argv[3]->ptr;

    if (getLongFromObjectOrReply(c,c->argv[2],&offset,NULL) != REDIS_OK)
        return;

    if (offset < 0) {
        addReplyError(c,"offset is out of range");
        return;
    }

    o = lookupKeyWrite(c->db,c->argv[1]);
    if (o == NULL) {
        /* Return 0 when setting nothing on a non-existing string */
        if (sdslen(value) == 0) {
            addReply(c,shared.czero);
            return;
        }

        /* Return when the resulting string exceeds allowed size */
        if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK)
            return;

        o = createObject(REDIS_STRING,sdsempty());
        dbAdd(c->db,c->argv[1],o);
    } else {
        size_t olen;

        /* Key exists, check type */
        if (checkType(c,o,REDIS_STRING))
            return;

        /* Return existing string length when setting nothing */
        olen = stringObjectLen(o);
        if (sdslen(value) == 0) {
            addReplyLongLong(c,olen);
            return;
        }

        /* Return when the resulting string exceeds allowed size */
        if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK)
            return;

        /* Create a copy when the object is shared or encoded. */
        o = dbUnshareStringValue(c->db,c->argv[1],o);
    }

    if (sdslen(value) > 0) {
        o->ptr = sdsgrowzero(o->ptr,offset+sdslen(value));
        memcpy((char*)o->ptr+offset,value,sdslen(value));
        signalModifiedKey(c->db,c->argv[1]);
        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,
            "setrange",c->argv[1],c->db->id);
        server.dirty++;
    }
    addReplyLongLong(c,sdslen(o->ptr));
}
Beispiel #3
0
void discardCommand(client *c) {
    if (!(c->flags & CLIENT_MULTI)) {
        addReplyError(c,"DISCARD without MULTI");
        return;
    }
    discardTransaction(c);
    addReply(c,shared.ok);
}
Beispiel #4
0
void selectCommand(redisClient *c) {
    long id;

    if (getLongFromObjectOrReply(c, c->argv[1], &id,
        "invalid DB index") != REDIS_OK)
        return;

    if (server.cluster_enabled && id != 0) {
        addReplyError(c,"SELECT is not allowed in cluster mode");
        return;
    }
    if (selectDb(c,id) == REDIS_ERR) {
        addReplyError(c,"invalid DB index");
    } else {
        addReply(c,shared.ok);
    }
}
Beispiel #5
0
void multiCommand(redisClient *c) {
    if (c->flags & REDIS_MULTI) {
        addReplyError(c,"MULTI calls can not be nested");
        return;
    }
    c->flags |= REDIS_MULTI;
    addReply(c,shared.ok);
}
// Utility commands
void MZHappy(client *c, int argc, sds *argv)
{
  // Set for 1e9 pulses. Should renew this in the status readout.
  int ret= Pulser(1,0.5,1e9,MappedHappyBaseAddress);

  if(ret == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #7
0
int processInlineBuffer(client *c) {
    char *newline;
    int argc;
    sds *argv, aux;
    size_t querylen;

    /* Search for end of line */
    newline = strchr(c->querybuf,'\n');

    /* Nothing to do without a \r\n */
    if (newline == NULL) {
        if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {
            addReplyError(c,"Protocol error: too big inline request");
            setProtocolError(c,0);
        }
        return C_ERR;
    }

    /* Handle the \r\n case. */
    if (newline && newline != c->querybuf && *(newline-1) == '\r')
        newline--;

    /* Split the input buffer up to the \r\n */
    querylen = newline-(c->querybuf);
    aux = sdsnewlen(c->querybuf,querylen);
    argv = sdssplitargs(aux,&argc);
    sdsfree(aux);
    if (argv == NULL) {
        addReplyError(c,"Protocol error: unbalanced quotes in request");
        setProtocolError(c,0);
        return C_ERR;
    }

    /* Leave data after the first line of the query in the buffer */
    sdsrange(c->querybuf,querylen+2,-1);

    /* Setup argv array on client structure */
    if (argc) {
        if (c->argv) free(c->argv);
        c->argv = argv;
    }

    c->argc = argc;

    return C_OK;
}
Beispiel #8
0
/* scriptNameCommand() has compound sub-arguments, so it looks slightly more
 * convoluted than it actually is.  Just read each if/else branch as
 * if it were an individual command. */
void scriptNameCommand(redisClient *c) {
    char *req = c->argv[1]->ptr;
    sds script_name = c->argv[2]->ptr;

    if (c->argc == 4 && !strcasecmp(req, "set")) {
        sds target_sha = c->argv[3]->ptr;

        if (sdslen(target_sha) != 40 ||
            dictFind(server.lua_scripts,target_sha) == NULL) {
            addReply(c, g.err.nosha);
            return;
        }

        /* If name doesn't exist, dictReplace == dictAdd */
        dictReplace(g.names, script_name, target_sha);

        addReplyBulkCBuffer(c, script_name, sdslen(script_name));
    } else if (c->argc == 3 && !strcasecmp(req, "get")) {
        sds found;
        if ((found = dictFetchValue(g.names, script_name))) {
            addReplyBulkCBuffer(c, found, sdslen(found));
        } else {
            addReply(c, g.err.noname);
        }
    } else if (c->argc == 2 && !strcasecmp(req, "getall")) {
        dictIterator *di;
        dictEntry *de;

        unsigned long sz = dictSize(g.names);

        if (!sz) {
            addReply(c, shared.emptymultibulk);
            return;
        }

        /* Multiply by 2 because the size of the dict is the number of keys.
         * We are returning keys *and* values, so length is dictSize * 2 */
        addReplyMultiBulkLen(c, sz * 2);

        di = dictGetIterator(g.names);
        while ((de = dictNext(di))) {
            addReplyBulkCString(c, dictGetKey(de));
            addReplyBulkCString(c, dictGetVal(de));
        }
        dictReleaseIterator(di);
    } else if (c->argc == 3 && !strcasecmp(req, "del")) {
        sds deleted;

        if ((deleted = dictFetchValue(g.names, script_name))) {
            dictDelete(g.names, script_name);
            addReplyBulkCBuffer(c, deleted, sdslen(deleted));
        } else {
            addReply(c, g.err.noname);
        }
    } else {
        addReplyError(c, "Unknown scriptName subcommand or arg count");
    }
}
int do_delete_event(struct redisClient *c,sds funcname)
{

    redisSrand48(0);
    server.lua_random_dirty = 0;
    server.lua_write_dirty = 0;
    lua_getglobal(server.lua,(char *)funcname);



    if (lua_isnil(server.lua,1)) {
        addReplyError(c,"no funcname triggle_scipts in lua");
        return 0;
    }
    luaTriggleSetGlobalArray(server.lua,"KEYS",c->argv+1,c->argc-1);

    redisLog(REDIS_NOTICE,"stack: %d",lua_gettop(server.lua));


#ifdef BRIDGE_DEBUG
    for(int i=0;i<c->argc-1;i++){
        redisLog(REDIS_NOTICE,"%s",(c->argv+1)[i]->ptr);
    }
#endif


    selectDb(server.lua_client,c->db->id);


    server.lua_time_start = ustime()/1000;
    server.lua_kill = 0;

    if (server.lua_time_limit > 0) {
        lua_sethook(server.lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
        server.lua_time_start = ustime()/1000;
    } else {
        lua_sethook(server.lua,luaMaskCountHook,0,0);
    }

    if (lua_pcall(server.lua,0,1,0)) {
        selectDb(c,server.lua_client->db->id); 
        addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
                (char*)funcname, lua_tostring(server.lua,-1));
        lua_pop(server.lua,1);
        lua_gc(server.lua,LUA_GCCOLLECT,0);
        return -1;
    }
    selectDb(c,server.lua_client->db->id); 
    // luaReplyToRedisReply(c,server.lua);
    server.lua_timedout = 0;
    server.lua_caller = NULL;
    lua_gc(server.lua,LUA_GCSTEP,1);

    //for slaves
    //

    return 0; 
}
Beispiel #10
0
Datei: db.c Projekt: andmej/redis
void selectCommand(redisClient *c) {
    int id = atoi(c->argv[1]->ptr);

    if (selectDb(c,id) == REDIS_ERR) {
        addReplyError(c,"invalid DB index");
    } else {
        addReply(c,shared.ok);
    }
}
int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg) {

    long long value;

    // T = O(N)
    if (getLongLongFromObject(o, &value) != REDIS_OK) {
        if (msg != NULL) {
            addReplyError(c,(char*)msg);
        } else {
            addReplyError(c,"value is not an integer or out of range");
        }
        return REDIS_ERR;
    }

    *target = value;

    return REDIS_OK;
}
Beispiel #12
0
// Clock commands
void clockreset(client *c, int argc, sds *argv)
{
  int ret= clockReset(1);
  usleep(1000);
  ret= clockReset(0);

  if(ret != 0) addReplyError(c, tubii_err);
  else addReplyStatus(c, "+OK");
}
Beispiel #13
0
void loadShift(client *c, int argc, sds *argv)
{
  uint32_t lShift;
  safe_strtoul(argv[1],&lShift);
  int ret= LoadShift(lShift);

  if(ret == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #14
0
//// Shift Register commands
//   Low level stuff
void dataready(client *c, int argc, sds *argv)
{
  uint32_t dReady;
  safe_strtoul(argv[1],&dReady);
  int ret= DataReady(dReady);

  if(ret==0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #15
0
void muxer(client *c, int argc, sds *argv)
{
  uint32_t mux;
  safe_strtoul(argv[1],&mux);
  int ret= Muxer(mux);

  if(ret == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #16
0
void SetComboTrigger(client *c, int argc, sds *argv)
{
  u32 enableMask, logicMask;
  safe_strtoul(argv[1],&enableMask);
  safe_strtoul(argv[2],&logicMask);

  if(comboTrig(enableMask,logicMask) == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #17
0
void execCommand(redisClient *c) {
    int j;
    robj **orig_argv;
    int orig_argc;
    struct redisCommand *orig_cmd;

    if (!(c->flags & REDIS_MULTI)) {
        addReplyError(c,"EXEC without MULTI");
        return;
    }

    /* Check if we need to abort the EXEC if some WATCHed key was touched.
     * A failed EXEC will return a multi bulk nil object. */
    if (c->flags & REDIS_DIRTY_CAS) {
        freeClientMultiState(c);
        initClientMultiState(c);
        c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS);
        unwatchAllKeys(c);
        addReply(c,shared.nullmultibulk);
        return;
    }

    /* Replicate a MULTI request now that we are sure the block is executed.
     * This way we'll deliver the MULTI/..../EXEC block as a whole and
     * both the AOF and the replication link will have the same consistency
     * and atomicity guarantees. */
    execCommandReplicateMulti(c);

    /* Exec all the queued commands */
    unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */
    orig_argv = c->argv;
    orig_argc = c->argc;
    orig_cmd = c->cmd;
    addReplyMultiBulkLen(c,c->mstate.count);
    for (j = 0; j < c->mstate.count; j++) {
        c->argc = c->mstate.commands[j].argc;
        c->argv = c->mstate.commands[j].argv;
        c->cmd = c->mstate.commands[j].cmd;
        call(c);

        /* Commands may alter argc/argv, restore mstate. */
        c->mstate.commands[j].argc = c->argc;
        c->mstate.commands[j].argv = c->argv;
        c->mstate.commands[j].cmd = c->cmd;
    }
    c->argv = orig_argv;
    c->argc = orig_argc;
    c->cmd = orig_cmd;
    freeClientMultiState(c);
    initClientMultiState(c);
    c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS);
    /* Make sure the EXEC command is always replicated / AOF, since we
     * always send the MULTI command (we can't know beforehand if the
     * next operations will contain at least a modification to the DB). */
    server.dirty++;
}
Beispiel #18
0
/* 事务起始指令multi的执行函数 */
void multiCommand(client *c) {
    /* 事务不能嵌套 */
    if (c->flags & CLIENT_MULTI) {
        addReplyError(c,"MULTI calls can not be nested");
        return;
    }
    /* 设置标识 */
    c->flags |= CLIENT_MULTI;
    addReply(c,shared.ok);
}
Beispiel #19
0
void gtdelay(client *c, int argc, sds *argv)
{
  float length=0;
  safe_strtof(argv[1],&length);
  u32 delay = length*ns;
  int ret= Delay(delay,MappedGTDelayBaseAddress);

  if(ret == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
Beispiel #20
0
void SetPrescaleTrigger(client *c, int argc, sds *argv)
{
  float rate;
  uint32_t bit;
  safe_strtof(argv[1],&rate);
  safe_strtoul(argv[2],&bit);

  if(prescaleTrig(rate,bit) == 0) addReplyStatus(c, "+OK");
  else addReplyError(c, tubii_err);
}
// 放弃执行事务(命令)
void discardCommand(redisClient *c) {
    // 如果没有调用过 MULTI ,报错
    if (!(c->flags & REDIS_MULTI)) {
        addReplyError(c,"DISCARD without MULTI");
        return;
    }

    discardTransaction(c);
    addReply(c,shared.ok);
}
Beispiel #22
0
void triggleDelCommand(struct redisClient *c)
{
    int id = atoi(c->argv[1]->ptr);
    if(id<0||id>server.dbnum)
    {
        addReplyError(c,"wrong dbid for triggle");
        return;
    }
    if(	dictDelete(server.bridge_db.triggle_scipts[id],c->argv[2]->ptr)==DICT_OK)
    {
        addReply(c,  shared.ok);

    }
    else
    {
        addReplyError(c,"delete unknow error");
    }

}
Beispiel #23
0
/* The SLOWLOG command. Implements all the subcommands needed to handle the
 * Redis slow log.
 *
 * SLOWLOG 命令的实现,支持 GET / RESET 和 LEN 参数
 */
void slowlogCommand(redisClient *c)
{

    // 重置
    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"reset"))
    {
        slowlogReset();
        addReply(c,shared.ok);

        // 返回长度
    }
    else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"len"))
    {
        addReplyLongLong(c,listLength(server.slowlog));

        // 获取某条或者全部日志
    }
    else if ((c->argc == 2 || c->argc == 3) &&
             !strcasecmp(c->argv[1]->ptr,"get"))
    {
        long count = 10, sent = 0;
        listIter li;
        void *totentries;
        listNode *ln;
        slowlogEntry *se;

        if (c->argc == 3 &&
                getLongFromObjectOrReply(c,c->argv[2],&count,NULL) != REDIS_OK)
            return;

        // 遍历日志,取出指定数量的日志
        listRewind(server.slowlog,&li);
        totentries = addDeferredMultiBulkLength(c);
        while(count-- && (ln = listNext(&li)))
        {
            int j;

            se = ln->value;
            addReplyMultiBulkLen(c,4);
            addReplyLongLong(c,se->id);
            addReplyLongLong(c,se->time);
            addReplyLongLong(c,se->duration);
            addReplyMultiBulkLen(c,se->argc);
            for (j = 0; j < se->argc; j++)
                addReplyBulk(c,se->argv[j]);
            sent++;
        }
        setDeferredMultiBulkLength(c,totentries,sent);
    }
    else
    {
        addReplyError(c,
                      "Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.");
    }
}
Beispiel #24
0
/* COMMAND <subcommand> <args> */
void commandCommand(client *c) {
    dictIterator *di;
    dictEntry *de;

    if (c->argc == 1) {
        addReplyMultiBulkLen(c, dictSize(server.commands));
        di = dictGetIterator(server.commands);
        while ((de = dictNext(di)) != NULL) {
            addReplyCommand(c, dictGetVal(de));
        }
        dictReleaseIterator(di);
    } else if (!strcasecmp(c->argv[1]->ptr, "info")) {
        int i;
        addReplyMultiBulkLen(c, c->argc-2);
        for (i = 2; i < c->argc; i++) {
            addReplyCommand(c, dictFetchValue(server.commands, c->argv[i]->ptr));
        }
    } else if (!strcasecmp(c->argv[1]->ptr, "count") && c->argc == 2) {
        addReplyLongLong(c, dictSize(server.commands));
    } else if (!strcasecmp(c->argv[1]->ptr,"getkeys") && c->argc >= 3) {
        struct redisCommand *cmd = lookupCommand(c->argv[2]->ptr);
        int *keys, numkeys, j;

        if (!cmd) {
            addReplyErrorFormat(c,"Invalid command specified");
            return;
        } else if ((cmd->arity > 0 && cmd->arity != c->argc-2) ||
                   ((c->argc-2) < -cmd->arity))
        {
            addReplyError(c,"Invalid number of arguments specified for command");
            return;
        }

        keys = getKeysFromCommand(cmd,c->argv+2,c->argc-2,&numkeys);
        addReplyMultiBulkLen(c,numkeys);
        for (j = 0; j < numkeys; j++) addReplyBulk(c,c->argv[keys[j]+2]);
        getKeysFreeResult(keys);
    } else {
        addReplyError(c, "Unknown subcommand or wrong number of arguments.");
        return;
    }
}
// MULTI命令的实现,标记一个事务的开始
void multiCommand(client *c) {
    // 客户端已经处于事务状态,回复错误后返回
    if (c->flags & CLIENT_MULTI) {
        addReplyError(c,"MULTI calls can not be nested");
        return;
    }
    // 打开客户的的事务状态标识
    c->flags |= CLIENT_MULTI;
    // 回复OK
    addReply(c,shared.ok);
}
Beispiel #26
0
void bgsaveCommand(redisClient *c) {
    if (server.bgsavechildpid != -1) {
        addReplyError(c,"Background save already in progress");
        return;
    }
    if (rdbSaveBackground(server.dbfilename) == REDIS_OK) {
        addReplyStatus(c,"Background saving started");
    } else {
        addReply(c,shared.err);
    }
}
// DISCARD取消事务的命令实现
void discardCommand(client *c) {
    // 客户端当前不处于事务状态,回复错误后返回
    if (!(c->flags & CLIENT_MULTI)) {
        addReplyError(c,"DISCARD without MULTI");
        return;
    }
    // 取消事务
    discardTransaction(c);
    // 回复OK
    addReply(c,shared.ok);
}
Beispiel #28
0
void moveCommand(client *c) {
    robj *o;
    redisDb *src, *dst;
    int srcid;
    long long dbid, expire;

    if (server.cluster_enabled) {
        addReplyError(c,"MOVE is not allowed in cluster mode");
        return;
    }

    /* Obtain source and target DB pointers */
    src = c->db;
    srcid = c->db->id;

    if (getLongLongFromObject(c->argv[2],&dbid) == C_ERR ||
        dbid < INT_MIN || dbid > INT_MAX ||
        selectDb(c,dbid) == C_ERR)
    {
        addReply(c,shared.outofrangeerr);
        return;
    }
    dst = c->db;
    selectDb(c,srcid); /* Back to the source DB */

    /* If the user is moving using as target the same
     * DB as the source DB it is probably an error. */
    if (src == dst) {
        addReply(c,shared.sameobjecterr);
        return;
    }

    /* Check if the element exists and get a reference */
    o = lookupKeyWrite(c->db,c->argv[1]);
    if (!o) {
        addReply(c,shared.czero);
        return;
    }
    expire = getExpire(c->db,c->argv[1]);

    /* Return zero if the key already exists in the target DB */
    if (lookupKeyWrite(dst,c->argv[1]) != NULL) {
        addReply(c,shared.czero);
        return;
    }
    dbAdd(dst,c->argv[1],o);
    if (expire != -1) setExpire(dst,c->argv[1],expire);
    incrRefCount(o);

    /* OK! key moved, free the entry in the source DB */
    dbDelete(src,c->argv[1]);
    server.dirty++;
    addReply(c,shared.cone);
}
Beispiel #29
0
void bgrewriteaofCommand(redisClient *c) {
    if (server.bgrewritechildpid != -1) {
        addReplyError(c,"Background append only file rewriting already in progress");
        return;
    }
    if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
        addReplyStatus(c,"Background append only file rewriting started");
    } else {
        addReply(c,shared.err);
    }
}
Beispiel #30
0
void watchCommand(redisClient *c) {
    int j;

    if (c->flags & REDIS_MULTI) {
        addReplyError(c,"WATCH inside MULTI is not allowed");
        return;
    }
    for (j = 1; j < c->argc; j++)
        watchForKey(c,c->argv[j]);
    addReply(c,shared.ok);
}