Ejemplo n.º 1
0
Archivo: db.c Proyecto: Xwuming/misc
/* This callback is used by scanGenericCommand in order to collect elements
 * returned by the dictionary iterator into a list. */
void scanCallback(void *privdata, const dictEntry *de) {
    void **pd = (void**) privdata;
    list *keys = pd[0];
    robj *o = pd[1];
    robj *key, *val = NULL;

    if (o == NULL) {
        sds sdskey = dictGetKey(de);
        key = createStringObject(sdskey, sdslen(sdskey));
    } else if (o->type == OBJ_SET) {
        sds keysds = dictGetKey(de);
        key = createStringObject(keysds,sdslen(keysds));
    } else if (o->type == OBJ_HASH) {
        sds sdskey = dictGetKey(de);
        sds sdsval = dictGetVal(de);
        key = createStringObject(sdskey,sdslen(sdskey));
        val = createStringObject(sdsval,sdslen(sdsval));
    } else if (o->type == OBJ_ZSET) {
        sds sdskey = dictGetKey(de);
        key = createStringObject(sdskey,sdslen(sdskey));
        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de),0);
    } else {
        serverPanic("Type not handled in SCAN callback.");
    }

    listAddNodeTail(keys, key);
    if (val) listAddNodeTail(keys, val);
}
Ejemplo n.º 2
0
int z_incr_key(void *cptr, char *arg) {
	redisClient *c = (redisClient *)cptr;
	robj *argv[2], *cmd, *key;
	int i, increment_max = 1000;

	printf("z_incr_key: %s\n", arg);

	z_set(c, "incr", "1");

	cmd = createStringObject("INCR", 4);
	key = createStringObject("incr", 4);

	argv[0] = cmd;
	argv[1] = key;
	
	c->argv = argv;
	c->argc = 2;

	if(arg) {
		increment_max = atoi(arg);
	}

	for(i = 0; i < increment_max; i++) {
		incrDecrCommand(c, 1);
	}

	freeStringObject(cmd);
	freeStringObject(key);

	c->argv = NULL;
	c->argc = 0;

	return 0;
}
Ejemplo n.º 3
0
int z_sadd(void *cptr, char * name, char * val) {
	redisClient *c = (redisClient *)cptr;
	robj *argv[10], *sadd, *rkey, *rval;

	sadd = createStringObject("SADD", 4);
	rkey = createStringObject(name, strlen(name));
	rval = createStringObject(val, strlen(val));

	argv[0] = sadd;
	argv[1] = rkey;
	argv[2] = rval;

	c->argv = argv;
	c->argc = 3;

	saddCommand(c);

	c->argv = NULL;
	c->argc = 0;

	freeStringObject(sadd);
	freeStringObject(rkey);
	// FAILS! tryObjectEncoding() in t_set.c .. freeStringObject(rval);

	return 0;
}
Ejemplo n.º 4
0
void rpoplpushHandlePush(redisClient *origclient, redisClient *c, robj *dstkey, robj *dstobj, robj *value) {
    robj *aux;

    if (!handleClientsWaitingListPush(c,dstkey,value)) {
        /* Create the list if the key does not exist */
        if (!dstobj) {
            dstobj = createZiplistObject();
            dbAdd(c->db,dstkey,dstobj);
        } else {
            signalModifiedKey(c->db,dstkey);
        }
        listTypePush(dstobj,value,REDIS_HEAD);
        /* If we are pushing as a result of LPUSH against a key
         * watched by BLPOPLPUSH, we need to rewrite the command vector.
         * But if this is called directly by RPOPLPUSH (either directly
         * or via a BRPOPLPUSH where the popped list exists)
         * we should replicate the BRPOPLPUSH command itself. */
        if (c != origclient) {
            aux = createStringObject("LPUSH",5);
            rewriteClientCommandVector(origclient,3,aux,dstkey,value);
            decrRefCount(aux);
        } else {
            /* Make sure to always use RPOPLPUSH in the replication / AOF,
             * even if the original command was BRPOPLPUSH. */
            aux = createStringObject("RPOPLPUSH",9);
            rewriteClientCommandVector(origclient,3,aux,c->argv[1],c->argv[2]);
            decrRefCount(aux);
        }
        server.dirty++;
    }

    /* Always send the pushed value to the client. */
    addReplyBulk(c,value);
}
Ejemplo n.º 5
0
int z_keys_star(void *cptr, char *arg) {
	redisClient *c = (redisClient *)cptr;
	robj *argv[2], *keys, *star;

	printf("z_keys_star: %s\n", arg);

	keys = createStringObject("KEYS", 4);
	star = createStringObject("*", 1);

	argv[0] = keys;
	argv[1] = star;

	c->argv = argv;
	c->argc = 2;

	keysCommand(c);

	freeStringObject(keys);
	freeStringObject(star);

	c->argv = NULL;
	c->argc = 0;

	return 0;
}
Ejemplo n.º 6
0
void spopCommand(client *c) {
    robj *set, *ele, *aux;
    sds sdsele;
    int64_t llele;
    int encoding;

    if (c->argc == 3) {
        spopWithCountCommand(c);
        return;
    } else if (c->argc > 3) {
        addReply(c,shared.syntaxerr);
        return;
    }

    /* Make sure a key with the name inputted exists, and that it's type is
     * indeed a set */
    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
        checkType(c,set,OBJ_SET)) return;

    /* Get a random element from the set */
    encoding = setTypeRandomElement(set,&sdsele,&llele);

    /* Remove the element from the set */
    if (encoding == OBJ_ENCODING_INTSET) {
        ele = createStringObjectFromLongLong(llele);
        set->ptr = intsetRemove(set->ptr,llele,NULL);
    } else {
        ele = createStringObject(sdsele,sdslen(sdsele));
        setTypeRemove(set,ele->ptr);
    }

    notifyKeyspaceEvent(NOTIFY_SET,"spop",c->argv[1],c->db->id);

    /* Replicate/AOF this command as an SREM operation */
    aux = createStringObject("SREM",4);
    rewriteClientCommandVector(c,3,aux,c->argv[1],ele);
    decrRefCount(aux);

    /* Add the element to the reply */
    addReplyBulk(c,ele);
    decrRefCount(ele);

    /* Delete the set if it's empty */
    if (setTypeSize(set) == 0) {
        dbDelete(c->db,c->argv[1]);
        notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
    }

    /* Set has been modified */
    signalModifiedKey(c->db,c->argv[1]);
    server.dirty++;
}
Ejemplo n.º 7
0
int z_set(void *cptr, char * key, char * val) {
	redisClient *c = (redisClient *) cptr;
	robj *rkey, *rval;
	rkey = createStringObject(key, strlen(key));
	rval = createStringObject(val, strlen(val));

	setGenericCommand(c, 0, rkey, rval, NULL, 0, NULL, NULL);

	freeStringObject(rkey);
	freeStringObject(rval);

	return 0;
}
Ejemplo n.º 8
0
void keysCommand(redisClient *c) {
    dictIterator *di;
    dictEntry *de;
    sds pattern = c->argv[1]->ptr;
    int plen = sdslen(pattern);
    unsigned long numkeys = 0;
    robj *lenobj = createObject(REDIS_STRING,NULL);

    di = dictGetIterator(c->db->dict);
    addReply(c,lenobj);
    decrRefCount(lenobj);
    while((de = dictNext(di)) != NULL) {
        sds key = dictGetEntryKey(de);
        robj *keyobj;

        if ((pattern[0] == '*' && pattern[1] == '\0') ||
            stringmatchlen(pattern,plen,key,sdslen(key),0)) {
            keyobj = createStringObject(key,sdslen(key));
            if (expireIfNeeded(c->db,keyobj) == 0) {
                addReplyBulk(c,keyobj);
                numkeys++;
            }
            decrRefCount(keyobj);
        }
    }
    dictReleaseIterator(di);
    lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",numkeys);
}
Ejemplo n.º 9
0
/* Create the sds representation of an PEXPIREAT command, using
 * 'seconds' as time to live and 'cmd' to understand what command
 * we are translating into a PEXPIREAT.
 *
 * This command is used in order to translate EXPIRE and PEXPIRE commands
 * into PEXPIREAT command so that we retain precision in the append only
 * file, and the time is always absolute and not relative. */
sds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, robj *seconds) {
    long long when;
    robj *argv[3];

    /* Make sure we can use strtol */
    seconds = getDecodedObject(seconds);
    when = strtoll(seconds->ptr,NULL,10);
    /* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */
    if (cmd->proc == expireCommand || cmd->proc == setexCommand ||
        cmd->proc == expireatCommand)
    {
        when *= 1000;
    }
    /* Convert into absolute time for EXPIRE, PEXPIRE, SETEX, PSETEX */
    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||
        cmd->proc == setexCommand || cmd->proc == psetexCommand)
    {
        when += mstime();
    }
    decrRefCount(seconds);

    argv[0] = createStringObject("PEXPIREAT",9);
    argv[1] = key;
    argv[2] = createStringObjectFromLongLong(when);
    buf = catAppendOnlyGenericCommand(buf, 3, argv);
    decrRefCount(argv[0]);
    decrRefCount(argv[2]);
    return buf;
}
Ejemplo n.º 10
0
// LINDEX key index
// LINDEX命令的实现
void lindexCommand(client *c) {
    //以读操作取出key对象的value值
    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk);
    //如果key没找到或value对象不是列表类型则直接返回
    if (o == NULL || checkType(c,o,OBJ_LIST)) return;
    long index;
    robj *value = NULL;

    //将index参数转换为long类型的整数,保存在index中
    if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != C_OK))
        return;

    //只对编码为quicklist类型的value对象操作
    if (o->encoding == OBJ_ENCODING_QUICKLIST) {
        quicklistEntry entry;
        //将下标为index的entry节点保存到entry中
        if (quicklistIndex(o->ptr, index, &entry)) {
            if (entry.value) {  //如果vlaue是字符串类型
                //创建一个字符串类型的对象,保存value值
                value = createStringObject((char*)entry.value,entry.sz);
            } else {
                //将整型的value值转换为字符串类型并创建字符串类型的对象
                value = createStringObjectFromLongLong(entry.longval);
            }
            addReplyBulk(c,value);  //发送value对象
            decrRefCount(value);    //释放value对象
        } else {
            addReply(c,shared.nullbulk);    //如果下标为index没找到,则发送空信息
        }
    } else {
        serverPanic("Unknown list encoding");   //发送未知的列表编码类型
    }
}
Ejemplo n.º 11
0
Archivo: db.c Proyecto: Elbandi/redis
void delkeysCommand(redisClient *c) {
    dictIterator *di;
    dictEntry *de;
    sds pattern = c->argv[1]->ptr;
    int plen = sdslen(pattern), allkeys;
    unsigned long deleted = 0;

    di = dictGetIterator(c->db->dict);
    allkeys = (pattern[0] == '*' && pattern[1] == '\0');
    while((de = dictNext(di)) != NULL) {
        sds key = dictGetEntryKey(de);
        robj *keyobj;

        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
            keyobj = createStringObject(key,sdslen(key));
            if (dbDelete(c->db,keyobj)) {
                touchWatchedKey(c->db,keyobj);
                server.dirty++;
                deleted++;
            }
            decrRefCount(keyobj);
        }
    }
    dictReleaseIterator(di);
    addReplyLongLong(c,deleted);
}
Ejemplo n.º 12
0
/* Note: this function is defined into object.c since here it is where it
 * belongs but it is actually designed to be used just for INCRBYFLOAT */
robj *createStringObjectFromLongDouble(long double value) {
    char buf[256];
    int len;

    /* We use 17 digits precision since with 128 bit floats that precision
     * after rounding is able to represent most small decimal numbers in a way
     * that is "non surprising" for the user (that is, most small decimal
     * numbers will be represented in a way that when converted back into
     * a string are exactly the same as what the user typed.) */
#ifdef _WIN32
    /* on Windows the magic number is 15 */
    len = snprintf(buf,sizeof(buf),"%.15Lf", value);
#else
    len = snprintf(buf,sizeof(buf),"%.17Lf", value);
#endif
    /* Now remove trailing zeroes after the '.' */
    if (strchr(buf,'.') != NULL) {
        char *p = buf+len-1;
        while(*p == '0') {
            p--;
            len--;
        }
        if (*p == '.') len--;
    }
    return createStringObject(buf,len);
}
Ejemplo n.º 13
0
void lindexCommand(redisClient *c) {
    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk);
    if (o == NULL || checkType(c,o,REDIS_LIST)) return;
    int index = atoi(c->argv[2]->ptr);
    robj *value = NULL;

    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *p;
        unsigned char *vstr;
        unsigned int vlen;
        long long vlong;
        p = ziplistIndex(o->ptr,index);
        if (ziplistGet(p,&vstr,&vlen,&vlong)) {
            if (vstr) {
                value = createStringObject((char*)vstr,vlen);
            } else {
                value = createStringObjectFromLongLong(vlong);
            }
            addReplyBulk(c,value);
            decrRefCount(value);
        } else {
            addReply(c,shared.nullbulk);
        }
    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
        listNode *ln = listIndex(o->ptr,index);
        if (ln != NULL) {
            value = listNodeValue(ln);
            addReplyBulk(c,value);
        } else {
            addReply(c,shared.nullbulk);
        }
    } else {
        redisPanic("Unknown list encoding");
    }
}
Ejemplo n.º 14
0
/* Send a MULTI command to all the slaves and AOF file. Check the execCommand
 * implementation for more information. */
void execCommandPropagateMulti(client *c) {
    robj *multistring = createStringObject("MULTI",5);

    propagate(server.multiCommand,c->db->id,&multistring,1,
              PROPAGATE_AOF|PROPAGATE_REPL);
    decrRefCount(multistring);
}
Ejemplo n.º 15
0
void lindexCommand(client *c) {
    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk);
    if (o == NULL || checkType(c,o,OBJ_LIST)) return;
    long index;
    robj *value = NULL;

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

    if (o->encoding == OBJ_ENCODING_QUICKLIST) {
        quicklistEntry entry;
        if (quicklistIndex(o->ptr, index, &entry)) {
            if (entry.value) {
                value = createStringObject((char*)entry.value,entry.sz);
            } else {
                value = createStringObjectFromLongLong(entry.longval);
            }
            addReplyBulk(c,value);
            decrRefCount(value);
        } else {
            addReply(c,shared.nullbulk);
        }
    } else {
        serverPanic("Unknown list encoding");
    }
}
Ejemplo n.º 16
0
void scriptCommand(rliteClient *c) {
	if (c->argc == 2 && !strcasecmp(c->argv[1],"flush")) {
		scriptingReset();
		c->reply = createStatusObject(RLITE_STR_OK);
	} else if (c->argc >= 2 && !strcasecmp(c->argv[1],"exists")) {
		int j;

		c->reply = createArrayObject(c->argc - 2);
		for (j = 2; j < c->argc; j++) {
			c->reply->element[j - 2] = createLongLongObject(getScript(c, c->argv[j], NULL, NULL) == RL_OK ? 1 : 0);
		}
	} else if (c->argc == 3 && !strcasecmp(c->argv[1],"load")) {
		char sha[41];

		sha1hex(sha,c->argv[2],c->argvlen[2]);
		setScript(c, c->argv[2], c->argvlen[2]);
		c->reply = createStringObject(sha,40);
	} else if (c->argc == 2 && !strcasecmp(c->argv[1],"kill")) {
		if (lua_caller == NULL) {
			c->reply = createCStringObject("NOTBUSY No scripts in execution right now.\r\n");
		} else if (lua_write_dirty) {
			c->reply = createCStringObject("UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.\r\n");
		} else {
			lua_kill = 1;
			c->reply = createStatusObject(RLITE_STR_OK);
		}
	} else {
		c->reply = createErrorObject("ERR Unknown SCRIPT subcommand or wrong # of args.");
	}
}
Ejemplo n.º 17
0
void evalName(redisClient *c, char *name) {
    sds hash;
    robj *sha;

    /* if len(name) == 40, then this *could* be a script hash.
     * Try to look it up as a hash first. */
    if (sdslen(name) == 40 && dictFind(server.lua_scripts, name)) {
        hash = name;
    } else {
        hash = dictFetchValue(g.names, name);
        /* If we didn't find it, or if we did find it but for some
         * reason the len(hash) != 40, ... */
        if (!hash || sdslen(hash) != 40) {
            addReply(c, g.err.nosha);
            return;
        }
    }

    /* the redisClient object uses robj * for fields,
     * so here we convert the sds hash into an robj of
     * an sds */
    sha = createStringObject(hash, sdslen(hash));
    rewriteClientCommandArgument(c, 1, sha);
    decrRefCount(sha); /* No leaking memory from our created robj */

    /* Now run the script as normal, just like we never existed. *poof* */
    evalGenericCommand(c, 1);
}
Ejemplo n.º 18
0
void spopCommand(redisClient *c) {
    robj *set, *ele, *aux;
    int64_t llele;
    int encoding;

    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
        checkType(c,set,REDIS_SET)) return;

    encoding = setTypeRandomElement(set,&ele,&llele);
    if (encoding == REDIS_ENCODING_INTSET) {
        ele = createStringObjectFromLongLong(llele);
        set->ptr = intsetRemove(set->ptr,llele,NULL);
    } else {
        incrRefCount(ele);
        setTypeRemove(set,ele);
    }
    notifyKeyspaceEvent(REDIS_NOTIFY_SET,"spop",c->argv[1],c->db->id);

    /* Replicate/AOF this command as an SREM operation */
    aux = createStringObject("SREM",4);
    rewriteClientCommandVector(c,3,aux,c->argv[1],ele);
    decrRefCount(ele);
    decrRefCount(aux);

    addReplyBulk(c,ele);
    if (setTypeSize(set) == 0) {
        dbDelete(c->db,c->argv[1]);
        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
    }
    signalModifiedKey(c->db,c->argv[1]);
    server.dirty++;
}
Ejemplo n.º 19
0
/* Higher level function of hashTypeGet*() that always returns a Redis
 * object (either new or with refcount incremented), so that the caller
 * can retain a reference or call decrRefCount after the usage.
 *
 * The lower level function can prevent copy on write so it is
 * the preferred way of doing read operations. */
robj *hashTypeGetObject(robj *o, robj *field) {
    robj *value = NULL;

    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *vstr = NULL;
        unsigned int vlen = UINT_MAX;
        long long vll = LLONG_MAX;

        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) {
            if (vstr) {
                value = createStringObject((char*)vstr, vlen);
            } else {
                value = createStringObjectFromLongLong(vll);
            }
        }

    } else if (o->encoding == REDIS_ENCODING_HT) {
        robj *aux;

        if (hashTypeGetFromHashTable(o, field, &aux) == 0) {
            incrRefCount(aux);
            value = aux;
        }
    } else {
        logicError("Unknown hash encoding");
    }
    return value;
}
Ejemplo n.º 20
0
static void
slotsremove(redisClient *c, robj **keys, int n, int rewrite) {
    for (int i = 0; i < n; i ++) {
        dbDelete(c->db, keys[i]);
        signalModifiedKey(c->db, keys[i]);
        server.dirty ++;
    }
    if (!rewrite) {
        return;
    }
    for (int i = 0; i < n; i ++) {
        incrRefCount(keys[i]);
    }
    for (int i = 0; i < c->argc; i ++) {
        decrRefCount(c->argv[i]);
    }
    zfree(c->argv);
    c->argc = n + 1;
    c->argv = zmalloc(sizeof(robj *) * c->argc);
    c->argv[0] = createStringObject("DEL", 3);
    for (int i = 0; i < n; i ++) {
        c->argv[i + 1] = keys[i];
    }
    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);
    redisAssertWithInfo(c, NULL, c->cmd != NULL);
}
Ejemplo n.º 21
0
/* *
 * slotsmgrttagslot host port timeout slot
 * */
void
slotsmgrttagslotCommand(redisClient *c) {
    sds host = c->argv[1]->ptr;
    sds port = c->argv[2]->ptr;
    int timeout, slot;
    if (parse_timeout(c, c->argv[3], &timeout) != 0) {
        return;
    }
    if (parse_slot(c, c->argv[4], &slot) != 0) {
        return;
    }

    dict *d = c->db->hash_slots[slot];
    int succ = 0;
    do {
        const dictEntry *de = dictGetRandomKey(d);
        if (de == NULL) {
            break;
        }
        sds skey = dictGetKey(de);
        robj *key = createStringObject(skey, sdslen(skey));
        succ = slotsmgrttag_command(c, host, port, timeout, key);
        decrRefCount(key);
        if (succ < 0) {
            return;
        }
    } while (0);
    addReplyMultiBulkLen(c, 2);
    addReplyLongLong(c, succ);
    addReplyLongLong(c, dictSize(d));
}
Ejemplo n.º 22
0
static void
slotsScanSdsKeyTagCallback(void *privdata, const dictEntry *de) {
    void **args = (void **)privdata;
    list *l = (list *)args[0];
    void *tag1 = args[1];
    int taglen1 = *(int *)args[2];
    void *vcrc = args[3];

    if (vcrc != dictGetVal(de)) {
        return;
    }
    sds skey = dictGetKey(de);

    int taglen2;
    void *tag2 = slots_tag(skey, &taglen2);
    if (tag2 == NULL) {
        return;
    }
    if (taglen2 != taglen1) {
        return;
    }
    if (strncmp(tag1, tag2, taglen1) != 0) {
        return;
    }

    robj *key = createStringObject(skey, sdslen(skey));
    listAddNodeTail(l, key);
}
Ejemplo n.º 23
0
static bool jRowReply(jrow_reply_t *r, int lvl) {
    int cnt = 0;
    for (int i = 0; i <= lvl; i++) { /* sort columns back to queried-order */
        for (int j = 0; j < r->jind_ncols[i]; j++) {
            int n       = r->reordered ? r->csort_order[cnt].n : cnt;
            Jrcols[n]   = Rcols[i][j];
            Jrc_lens[n] = Rc_lens[i][j];
            cnt++;
        }
    }

    if (!Order_by && r->cstar) return 1; /* NOOP just count */
    int slot = 0;
    for (int i = 0; i < cnt; i++) {
        char *s   = *Jrcols[i];
        int rlen  = Jrc_lens[i];
        memcpy(r->reply + slot, s, rlen);
        slot     += rlen;
        memcpy(r->reply + slot, OUTPUT_DELIM, 1);
        slot++;
    }
    robj *resp = createStringObject(r->reply, slot -1);

    if (Order_by) {
        addJoinOutputRowToList(r, resp);
    } else {
        addReplyBulk(r->c, resp);
        decrRefCount(resp);
    }
    return 1;
}
Ejemplo n.º 24
0
void rpoplpushHandlePush(redisClient *origclient, redisClient *c, robj *dstkey, robj *dstobj, robj *value) {
    if (!handleClientsWaitingListPush(origclient,dstkey,value)) {
        /* Create the list if the key does not exist */
        if (!dstobj) {
            dstobj = createZiplistObject();
            dbAdd(c->db,dstkey,dstobj);
        } else {
            signalModifiedKey(c->db,dstkey);
        }
        listTypePush(dstobj,value,REDIS_HEAD);
        /* Additionally propagate this PUSH operation together with
         * the operation performed by the command. */
        {
            robj **argv = zmalloc(sizeof(robj*)*3);
            argv[0] = createStringObject("LPUSH",5);
            argv[1] = dstkey;
            argv[2] = value;
            incrRefCount(argv[1]);
            incrRefCount(argv[2]);
            alsoPropagate(server.lpushCommand,c->db->id,argv,3,
                          REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);
        }
    }
    /* Always send the pushed value to the client. */
    addReplyBulk(c,value);
}
Ejemplo n.º 25
0
int rdbSaveNRL(FILE *fp, robj *o) {
    listNode *ln;
    d_l_t    *nrlind  = o->ptr;
    list     *nrltoks = nrlind->l1;

    int imatch = nrlind->num;
    if (rdbSaveLen(fp, imatch) == -1) return -1;
    robj *iname  = Index[server.dbid][imatch].obj;
    if (rdbSaveStringObject(fp, iname) == -1) return -1;
    int   tmatch = Index[server.dbid][imatch].table;
    if (rdbSaveLen(fp, tmatch) == -1) return -1;

    if (rdbSaveLen(fp, listLength(nrltoks)) == -1) return -1;
    listIter    *li = listGetIterator(nrltoks, AL_START_HEAD);
    while((ln = listNext(li)) != NULL) {
        sds   s = ln->value;
        robj *r = createStringObject(s, sdslen(s));
        if (rdbSaveStringObject(fp, r) == -1) return -1;
        decrRefCount(r);
    }
    listReleaseIterator(li);

    list  *nrlcols = nrlind->l2;
    if (rdbSaveLen(fp, listLength(nrlcols)) == -1) return -1;
    li = listGetIterator(nrlcols, AL_START_HEAD);
    while((ln = listNext(li)) != NULL) {
        uint32 i = (uint32)(long)ln->value;
        if (rdbSaveLen(fp, i) == -1) return -1;
    }
    listReleaseIterator(li);

    return 0;
}
Ejemplo n.º 26
0
void keysCommand(redisClient *c) {
    dictIterator *di;
    dictEntry *de;
    sds pattern = c->argv[1]->ptr;
    int plen = sdslen(pattern), allkeys;
    unsigned long numkeys = 0;
    void *replylen = addDeferredMultiBulkLength(c);

    di = dictGetSafeIterator(c->db->dict);
    allkeys = (pattern[0] == '*' && pattern[1] == '\0');
    while((de = dictNext(di)) != NULL) {
        sds key = dictGetKey(de);
        robj *keyobj;

        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
            keyobj = createStringObject(key,sdslen(key));
            if (expireIfNeeded(c->db,keyobj) == 0) {
                addReplyBulk(c,keyobj);
                numkeys++;
            }
            decrRefCount(keyobj);
        }
    }
    dictReleaseIterator(di);
    setDeferredMultiBulkLength(c,replylen,numkeys);
}
/*
 * 根据传入的 long double 值,为它创建一个字符串对象
 *
 * 对象将 long double 转换为字符串来保存
 */
robj *createStringObjectFromLongDouble(long double value) {
    char buf[256];
    int len;

    /* We use 17 digits precision since with 128 bit floats that precision
     * after rounding is able to represent most small decimal numbers in a way
     * that is "non surprising" for the user (that is, most small decimal
     * numbers will be represented in a way that when converted back into
     * a string are exactly the same as what the user typed.) */
    // 使用 17 位小数精度,这种精度可以在大部分机器上被 rounding 而不改变
    len = snprintf(buf,sizeof(buf),"%.17Lf", value);

    /* Now remove trailing zeroes after the '.' */
    // 移除尾部的 0 
    // 比如 3.1400000 将变成 3.14
    // 而 3.00000 将变成 3
    if (strchr(buf,'.') != NULL) {
        char *p = buf+len-1;
        while(*p == '0') {
            p--;
            len--;
        }
        // 如果不需要小数点,那么移除它
        if (*p == '.') len--;
    }

    // 创建对象
    return createStringObject(buf,len);
}
Ejemplo n.º 28
0
void call_expire_delete_event(void *pdb,void *pkeyobj)
{
    redisDb *db=(redisDb *)pdb;
    robj *myobj=(robj *)pkeyobj;
    robj *keyobj = createStringObject(myobj->ptr,sdslen(myobj->ptr));

    struct dictIterator *iter=dictGetIterator(server.bridge_db.triggle_scipts[db->id]);
    dictEntry *trigs;
    do{
        trigs=dictNext(iter);
        if(trigs!=NULL)
        {
            struct bridge_db_triggle_t * tmptrg=dictGetVal(trigs);
            //add func str check for the function only the key satisfy the funcname:XXXX can call the event 
            if(tmptrg->event==DELETE_EXPIRE&&strncmp(keyobj->ptr,dictGetKey(trigs),sdslen(dictGetKey(trigs)))==0){ //找到指定的类型事件
                redisLog(REDIS_NOTICE,"triggle_event:%d,%s",DELETE_EXPIRE,(char *)dictGetKey(trigs));
                triggle_expire_event(db,dictGetKey(trigs),keyobj);
            }
        }
    }while(trigs!=NULL);
    dictReleaseIterator(iter);

    decrRefCount(keyobj);  

}
Ejemplo n.º 29
0
/* Create a string object from a long double. If humanfriendly is non-zero
 * it does not use exponential format and trims trailing zeroes at the end,
 * however this results in loss of precision. Otherwise exp format is used
 * and the output of snprintf() is not modified.
 *
 * The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */
robj *createStringObjectFromLongDouble(long double value, int humanfriendly) {
    char buf[256];
    int len;

    if (isinf(value)) {
        /* Libc in odd systems (Hi Solaris!) will format infinite in a
         * different way, so better to handle it in an explicit way. */
        if (value > 0) {
            memcpy(buf,"inf",3);
            len = 3;
        } else {
            memcpy(buf,"-inf",4);
            len = 4;
        }
    } else if (humanfriendly) {
        /* We use 17 digits precision since with 128 bit floats that precision
         * after rounding is able to represent most small decimal numbers in a
         * way that is "non surprising" for the user (that is, most small
         * decimal numbers will be represented in a way that when converted
         * back into a string are exactly the same as what the user typed.) */
        len = snprintf(buf,sizeof(buf),"%.17Lf", value);
        /* Now remove trailing zeroes after the '.' */
        if (strchr(buf,'.') != NULL) {
            char *p = buf+len-1;
            while(*p == '0') {
                p--;
                len--;
            }
            if (*p == '.') len--;
        }
    } else {
        len = snprintf(buf,sizeof(buf),"%.17Lg", value);
    }
    return createStringObject(buf,len);
}
Ejemplo n.º 30
0
static void runCmdInFakeClient(sds s) {
    //RL4 "runCmdInFakeClient: %s", s);
    int           argc;
    sds          *argv = sdssplitlen(s, sdslen(s), " ", 1, &argc); // FREEME 017
    if (!argv)    return;
    if (argc < 1) goto run_cmd_end;
    redisCommand *cmd  = lookupCommand(argv[0]);
    if (!cmd)     goto run_cmd_end;
    if ((cmd->arity > 0 && cmd->arity > argc) || (argc < -cmd->arity))
                  goto run_cmd_end;
    int    arity;
    robj **rargv;
    if (cmd->arity > 0 || cmd->proc == insertCommand    ||
                          cmd->proc == sqlSelectCommand ||
                          cmd->proc == tscanCommand)       {
        arity = abs(cmd->arity);
        rargv = zmalloc(sizeof(robj *) * arity);         /* ZFREE ME 018 */
        for (int j = 0; j < arity - 1; j++) {
            rargv[j] = createStringObject(argv[j], sdslen(argv[j])); // FREE 019
        }
        sds lastarg = sdsempty();
        for (int j = arity - 1; j < argc; j++) {
            if (j != (arity - 1)) lastarg = sdscatlen(lastarg, " ", 1);
            lastarg = sdscatlen(lastarg, argv[j], sdslen(argv[j]));
        }
        rargv[arity - 1] = createObject(REDIS_STRING, lastarg); // FREE 019
    } else {
        arity = argc;
        rargv = zmalloc(sizeof(robj *) * arity);         /* ZFREE ME 018 */
        for (int j = 0; j < arity; j++) {
            rargv[j] = createStringObject(argv[j], sdslen(argv[j])); // FREE 019
        }
    }
    redisClient *c  = CurrClient;
    redisClient *fc = rsql_createFakeClient();           /* DESTROY ME 020 */
    fc->argv        = rargv;
    fc->argc        = arity;
    fakeClientPipe(c, fc, NULL, 0, &NriFlag,
                   nonRelIndRespHandler, emptyNonRelIndRespHandler);
    rsql_freeFakeClient(fc);                             /* DESTROYED 020 */
    for (int j = 0; j < arity; j++) decrRefCount(rargv[j]); /* FREED 019 */
    zfree(rargv);                                        /* ZFREED 018 */

run_cmd_end:
    for (int j = 0; j < argc; j++) sdsfree(argv[j]);     /* FREED 017 */
    zfree(argv);                                         /* FREED 017 */
}