Exemplo n.º 1
0
void addReply(client *c, const char *fmt, ...) {
    va_list ap;
    va_start(ap,fmt);
    sds s = sdscatvprintf(sdsempty(),fmt,ap);
    va_end(ap);
    addReplyString(c,s,sdslen(s));
    addReplyString(c,"\r\n",2);
    sdsfree(s);
}
Exemplo n.º 2
0
/* Add a long long as integer reply or bulk len / multi bulk count.
 * Basically this is used to output <prefix><long long><crlf>. */
void addReplyLongLongWithPrefix(client *c, long long ll, char prefix) {
    char buf[128];
    int len;

    buf[0] = prefix;
    len = ll2string(buf+1,sizeof(buf)-1,ll);
    buf[len+1] = '\r';
    buf[len+2] = '\n';
    addReplyString(c,buf,len+3);
}
Exemplo n.º 3
0
void mgetCommand(client *c) {
    counter *cntr;
    int j;

    addReplyMultiBulkLen(c,c->argc-1);
    for (j = 1; j < c->argc; j++) {
        cntr = counterLookup(c->argv[j]->ptr);

        if (cntr == NULL) {
            addReplyString(c,OBJ_SHARED_0STR,sizeof(OBJ_SHARED_0STR)-1);
        } else {
            /* Do we need to recalculate the cached response? */
            if (cntr->rlen == 0) {
                counterCacheResponse(cntr);
            }

            addReplyString(c,cntr->rbuf,cntr->rlen);
        }
    }
}
Exemplo n.º 4
0
/* Add a double as a bulk reply */
void addReplyDouble(client *c, double d) {
    char dbuf[128], sbuf[128];
    int dlen, slen;
    if (isinf(d)) {
        /* Libc in odd systems (Hi Solaris!) will format infinite in a
         * different way, so better to handle it in an explicit way. */
        addReplyBulkCString(c, d > 0 ? "inf" : "-inf");
    } else {
        dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d);
        slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf);
        addReplyString(c,sbuf,slen);
    }
}
Exemplo n.º 5
0
void genericIncrCommand(client *c, long double increment) {
    counter *cntr;

    cntr = counterLookup(c->argv[1]->ptr);
    if (cntr == NULL) {
        cntr = counterCreate(c->argv[1]->ptr);
    }

    if (cntr->myshard == NULL) {
        counterAddShard(cntr, myself, myself->name);
    }

    cntr->myshard->value += increment;
    cntr->value += increment;
    server.dirty++;
    counterCacheResponse(cntr);
    addReplyString(c,cntr->rbuf,cntr->rlen);
}
Exemplo n.º 6
0
void getCommand(client *c) {
    counter *cntr;

    cntr = counterLookup(c->argv[1]->ptr);
    if (cntr == NULL) {
        if (c->argc == 2) {
            addReplyString(c,OBJ_SHARED_0STR,sizeof(OBJ_SHARED_0STR)-1);
        } else if (!strcasecmp(c->argv[2]->ptr,"state")) {
            addReplyMultiBulkLen(c,2);
            addReplyString(c,OBJ_SHARED_0STR,sizeof(OBJ_SHARED_0STR)-1);
            if (server.cluster->failing_nodes_count > 0) {
                addReplyString(c, OBJ_SHARED_INCONSISTENT, sizeof(OBJ_SHARED_INCONSISTENT)-1);
            } else {
                addReplyString(c, OBJ_SHARED_CONSISTENT, sizeof(OBJ_SHARED_CONSISTENT)-1);
            }
        }
        return;
    }

    /* Do we need to recalculate the cached response? */
    if (cntr->rlen == 0) {
        counterCacheResponse(cntr);
    }

    if (c->argc == 2) {
        addReplyString(c,cntr->rbuf,cntr->rlen);
    } else if (!strcasecmp(c->argv[2]->ptr,"state")) {
        addReplyMultiBulkLen(c,2);
        addReplyString(c,cntr->rbuf,cntr->rlen);
        if (server.cluster->failing_nodes_count > 0) {
            addReplyString(c, OBJ_SHARED_INCONSISTENT, sizeof(OBJ_SHARED_INCONSISTENT)-1);
        } else {
            addReplyString(c, OBJ_SHARED_CONSISTENT, sizeof(OBJ_SHARED_CONSISTENT)-1);
        }
    } else {
        addReplyErrorFormat(c, "Unknown GET option '%s'",
            (char*)c->argv[2]->ptr);
    }
}
Exemplo n.º 7
0
void setCommand(client *c) {
    counter *cntr;
    long double value;
    unsigned int i;

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

    cntr = counterLookup(c->argv[1]->ptr);
    if (cntr == NULL) {
        cntr = counterCreate(c->argv[1]->ptr);
    }

    if (cntr->myshard == NULL) {
        counterAddShard(cntr,myself,myself->name);
    }

    /* myshard->value        = 4
     * cntr->value           = 10
     * value                 = 2
     * value in other shards = 6
     * new myshard->value    = 2 - (10 - 4) = -4
     */
    cntr->myshard->value = value - (cntr->value - cntr->myshard->value);

    /* Force a new prediction to be send. */
    cntr->myshard->predict_time = 0;

    /* Make sure the prediction is 0 so it doesn't change every second. */
    for (i = 0; i < server.history_size; i++) {
        cntr->history[i] = cntr->myshard->value;
    }

    cntr->value = value;
    server.dirty++;
    counterCacheResponse(cntr);
    addReplyString(c,cntr->rbuf,cntr->rlen);
}
Exemplo n.º 8
0
/* Add a C buffer as bulk reply */
void addReplyBulkCBuffer(client *c, const void *p, size_t len) {
    addReplyLongLongWithPrefix(c,len,'$');
    addReplyString(c,p,len);
    addReplyString(c,"\r\n",2);
}
Exemplo n.º 9
0
void addReplyStatusLength(client *c, const char *s, size_t len) {
    addReplyString(c,"+",1);
    addReplyString(c,s,len);
    addReplyString(c,"\r\n",2);
}
Exemplo n.º 10
0
void addReplyErrorLength(client *c, const char *s, size_t len) {
    addReplyString(c,"-ERR ",5);
    addReplyString(c,s,len);
    addReplyString(c,"\r\n",2);
}
Exemplo n.º 11
0
static bool sendRestAPIReply(cli *c, sds file) { //printf("sendRestAPIReply\n");
    int argc; bool ret = 0;
    sds pb  = c->http.post_body; //TODO cat [file,pb] is too much copying
    sds url = pb ? sdscatprintf(sdsempty(), "%s%s", file, pb) :
                   sdsdup(file);                                     //FREE 156
    sds       *argv  = sdssplitlen(url, sdslen(url), "/", 1, &argc); //FREE 157
    rcommand  *cmd   = lookupCommand(argv[0]);
    if (!cmd) goto send_rest_end;
    ret = 1;
    //printf("sendRestAPIReply: found cmd: %s\n", cmd->name);
    if ((cmd->arity > 0 && cmd->arity != argc) || (argc < -cmd->arity)) {
        addReplyErrorFormat(c,"wrong number of arguments for '%s' command",
            cmd->name);
        goto send_rest_end;
    }
    //NOTE: rest is copy of redis.c processCommand()
    if (server.maxmemory) freeMemoryIfNeeded();
    if (server.maxmemory && (cmd->flags & REDIS_CMD_DENYOOM) &&
        zmalloc_used_memory() > server.maxmemory) {
        addReplyError(c, "command not allowed when used memory > 'maxmemory'");
        goto send_rest_end;
    }
    if ((dictSize(c->pubsub_channels) > 0 || listLength(c->pubsub_patterns) > 0)
        &&
        cmd->proc != subscribeCommand && cmd->proc != unsubscribeCommand &&
        cmd->proc != psubscribeCommand && cmd->proc != punsubscribeCommand) {
        addReplyError(c, 
           "only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context");
        goto send_rest_end;
    }
    if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED &&
        server.repl_serve_stale_data == 0 &&
        cmd->proc != infoCommand && cmd->proc != slaveofCommand) {
        addReplyError(c,
            "link with MASTER is down and slave-serve-stale-data is set to no");
        goto send_rest_end;
    }
    if (server.loading && cmd->proc != infoCommand) {
        addReply(c, shared.loadingerr);
        goto send_rest_end;
    }
    if (c->flags & REDIS_MULTI &&
        cmd->proc != execCommand && cmd->proc != discardCommand &&
        cmd->proc != multiCommand && cmd->proc != watchCommand) {
        queueMultiCommand(c, cmd); addReply(c, shared.queued);
        goto send_rest_end;
    }
    listNode *ln; listIter *li; cli *restc = server.alc.RestClient;
    // 1.) call() cmd in RestClient
    { // REST CLIENT call
        robj **rargv = zmalloc(sizeof(robj *) * argc);
        for (int i = 0; i < argc; i++) {
            rargv[i] = createStringObject(argv[i], sdslen(argv[i]));
        }
        restc->argc = argc; restc->argv = rargv; call(restc, cmd);
        for (int i = 0; i < argc; i++) decrRefCount(rargv[i]);
        zfree(rargv);
    }
    // 2.) calculate Content-Length from RestClient's response
    ulong brlen = restc->bufpos; ulong trlen = brlen;
    if (restc->reply->len) {
        li = listGetIterator(restc->reply, AL_START_HEAD);
        while((ln = listNext(li))) {
            robj *r = ln->value; trlen += sdslen(r->ptr);
        } listReleaseIterator(li);
    }
    bool err = brlen && (*restc->buf == '-');
    //TODO check for "+OK" and return 201 w/ no body
    // 3.) create header w/ Content-Length
    sds   s  = err ? send_http404_reponse_header(c, trlen) :
                     send_http200_reponse_header(c, trlen);
    robj *ho = createObject(REDIS_STRING, s);
    addReply(c, ho); decrRefCount(ho);
    // 4.) tack on RestClient's response as HTTP Body
    if (brlen) { addReplyString(c, restc->buf, brlen); }
    if (restc->reply->len) {
        li = listGetIterator(restc->reply, AL_START_HEAD);
        while((ln = listNext(li))) {
            robj *r = ln->value; addReply(c, r);
        } listReleaseIterator(li);
    }
    // 5.) reset RestClient
    restc->bufpos = 0;
    while (restc->reply->len) {
        listDelNode(restc->reply, listFirst(restc->reply));
    }

send_rest_end:
    sdsfree(url);                                                 // FREE 156
    for (int i = 0; i < argc; i++) sdsfree(argv[i]); zfree(argv); // FREE 157
    return ret;
}