Exemple #1
0
void init_kvstore_htable(){
    kvpair_size = destor.index_key_size + destor.index_value_length * 8;

    if(destor.index_key_size >=4)
    	htable = g_hash_table_new_full(g_int_hash, g_feature_equal,
			free_kvpair, NULL);
    else
    	htable = g_hash_table_new_full(g_feature_hash, g_feature_equal,
			free_kvpair, NULL);

	sds indexpath = sdsdup(destor.working_directory);
	indexpath = sdscat(indexpath, "index/htable");

	/* Initialize the feature index from the dump file. */
	FILE *fp;
	if ((fp = fopen(indexpath, "r"))) {
		/* The number of features */
		int key_num;
		fread(&key_num, sizeof(int), 1, fp);
		for (; key_num > 0; key_num--) {
			/* Read a feature */
			kvpair kv = new_kvpair();
			fread(get_key(kv), destor.index_key_size, 1, fp);

			/* The number of segments/containers the feature refers to. */
			int id_num, i;
			fread(&id_num, sizeof(int), 1, fp);
			assert(id_num <= destor.index_value_length);

			for (i = 0; i < id_num; i++)
				/* Read an ID */
				fread(&get_value(kv)[i], sizeof(int64_t), 1, fp);

			g_hash_table_insert(htable, get_key(kv), kv);
		}
		fclose(fp);
	}

	sdsfree(indexpath);
}
Exemple #2
0
S triefort_open(TF ** const fort, const HCFG * const hashcfg, const char * const path) {
  NULLCHK(fort);
  NULLCHK(hashcfg);
  NULLCHK(path);

  S s;

  sds fortpath = sdsnew(path);
  sds cfgpath = sdsdup(fortpath);
  cfgpath = sdscat(cfgpath, "/" CONFIG_FILE_NAME);

  if (!file_exists(cfgpath)) {
    s = triefort_err_not_a_triefort;
  } else {
    *fort = calloc(1, sizeof(**fort));
    TF * f = *fort;

    f->path = fortpath; // *fort takes ownership of `fortpath`
    f->hcfg = hashcfg;

    if (triefort_ok == (s = load_cfg(&f->cfg, cfgpath))) {
      if (!validate_cfg(&(*fort)->cfg)) {
        s = triefort_err_invalid_config;
      }

      if (0 != strncmp(hashcfg->fn_name, (*fort)->cfg.hash_name, MAX_LEN_HASH_NAME)) {
        s = triefort_err_hash_name_mismatch;
      }

      if (triefort_ok != s) {
        triefort_close(*fort);
        *fort = NULL;
      }
    }
  }

  sdsfree(cfgpath);

  return s;
}
static int process_command(sub_client *c)
{
    srv_log(LOG_DEBUG, "c->argv[0]: %s", c->argv[0]);
    sds name = sdsnew(c->argv[0]);
    sdstolower(name);

    sub_command *cmd = ght_get(server.sub_commands, sdslen(name), name);
    if (!cmd) {
        add_reply_error_fmt(c, "unknown command '%s'", name);
    } else if ((cmd->arity > 0 && cmd->arity != c->argc) ||
               (c->argc < -cmd->arity)) {
        add_reply_error_fmt(c, "wrong number of arguments for '%s' command",
                name);
    } else {
        srv_log(LOG_DEBUG, "cmd name: %s arity: %d", cmd->name, cmd->arity);
        cmd->proc(c);
    }

    sdsfree(name);

    return SUBCLI_OK;
}
Exemple #4
0
/* Try to encode a string object in order to save space */
robj *tryObjectEncoding(robj *o) {
    long value;
    sds s = o->ptr;

    if (o->encoding != REDIS_ENCODING_RAW)
        return o; /* Already encoded */

    /* It's not safe to encode shared objects: shared objects can be shared
     * everywhere in the "object space" of Redis. Encoded objects can only
     * appear as "values" (and not, for instance, as keys) */
     if (o->refcount > 1) return o;

    /* Currently we try to encode only strings */
    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);

    /* Check if we can represent this string as a long integer */
    if (!string2l(s,sdslen(s),&value)) return o;

    /* Ok, this object can be encoded...
     *
     * Can I use a shared object? Only if the object is inside a given
     * range and if the back end in use is in-memory. For disk store every
     * object in memory used as value should be independent.
     *
     * Note that we also avoid using shared integers when maxmemory is used
     * because every object needs to have a private LRU field for the LRU
     * algorithm to work well. */
    if (server.maxmemory == 0 && value >= 0 && value < REDIS_SHARED_INTEGERS) {
        decrRefCount(o);
        incrRefCount(shared.integers[value]);
        return shared.integers[value];
    } else {
        o->encoding = REDIS_ENCODING_INT;
        sdsfree(o->ptr);
        o->ptr = (void*) value;
        return o;
    }
}
Exemple #5
0
int  processLineBuffer(ugClient *c) {
    char *newline = strstr(c->querybuf, "\r\n");
    int argc, j;
    sds *argv;
    size_t querylen;

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

    /* Split the input buffer up to the \r\n */
    querylen = newline-(c->querybuf);
    argv = sdssplitlen(c->querybuf,(int)querylen," ",1,&argc);

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

    /* Setup argv array on client structure */
    if (c->argv) zfree(c->argv);
    c->argv = zmalloc(sizeof(robj *)*argc);

    /* Create redis objects for all arguments. */
    for (c->argc = 0, j = 0; j < argc; j++) {
        if (sdslen(argv[j])) {
            c->argv[c->argc] = createObject(UG_STRING,argv[j]);
            c->argc++;
        } else {
            sdsfree(argv[j]);
        }
    }
    zfree(argv);
    return UGOK;
}
Exemple #6
0
void parg_asset_preload(parg_token id)
{
    if (!_pngsuffix) {
        _pngsuffix = sdsnew(".png");
    }
    sds filename = parg_token_to_sds(id);
    parg_buffer* buf = parg_buffer_from_path(filename);
    parg_assert(buf, "Unable to load asset");
    if (sdslen(filename) > 4) {
        sds suffix = sdsdup(filename);
        sdsrange(suffix, -4, -1);
        if (!sdscmp(suffix, _pngsuffix)) {
            unsigned char* decoded;
            unsigned dims[3] = {0, 0, 4};
            unsigned char* filedata = parg_buffer_lock(buf, PARG_READ);
            unsigned err = lodepng_decode_memory(&decoded, &dims[0], &dims[1],
                    filedata, parg_buffer_length(buf), LCT_RGBA, 8);
            parg_assert(err == 0, "PNG decoding error");
            parg_buffer_free(buf);
            int nbytes = dims[0] * dims[1] * dims[2];
            buf = parg_buffer_alloc(nbytes + 12, PARG_CPU);
            int* ptr = parg_buffer_lock(buf, PARG_WRITE);
            *ptr++ = dims[0];
            *ptr++ = dims[1];
            *ptr++ = dims[2];
            memcpy(ptr, decoded, nbytes);
            free(decoded);
            parg_buffer_unlock(buf);
        }
        sdsfree(suffix);
    }
    if (!_asset_registry) {
        _asset_registry = kh_init(assmap);
    }
    int ret;
    int iter = kh_put(assmap, _asset_registry, id, &ret);
    kh_value(_asset_registry, iter) = buf;
}
Exemple #7
0
static int cliReadMultiBulkReply(int fd) {
    sds replylen = cliReadLine(fd);
    int elements, c = 1;
    int retval = 0;

    if (replylen == NULL) return 1;
    elements = atoi(replylen);
    if (elements == -1) {
        sdsfree(replylen);
        printf("(nil)\n");
        return 0;
    }
    if (elements == 0) {
        printf("(empty list or set)\n");
    }
    while(elements--) {
        if (config.tty) printf("%d. ", c);
        if (cliReadReply(fd)) retval = 1;
        if (elements) printf("%c",config.mb_sep);
        c++;
    }
    return retval;
}
Exemple #8
0
/* Write the output buffer to the socket.
 *
 * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
 * succesfully written to the socket. When the buffer is empty after the
 * write operation, "wdone" is set to 1 (if given).
 *
 * Returns REDIS_ERR if an error occured trying to write and sets
 * c->error to hold the appropriate error string.
 */
int redisBufferWrite(redisContext *c, int *done) {
    int nwritten;
    if (sdslen(c->obuf) > 0) {
        nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
        if (nwritten == -1) {
            if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
                /* Try again later */
            } else {
                __redisSetError(c,REDIS_ERR_IO,NULL);
                return REDIS_ERR;
            }
        } else if (nwritten > 0) {
            if (nwritten == (signed)sdslen(c->obuf)) {
                sdsfree(c->obuf);
                c->obuf = sdsempty();
            } else {
                c->obuf = sdsrange(c->obuf,nwritten,-1);
            }
        }
    }
    if (done != NULL) *done = (sdslen(c->obuf) == 0);
    return REDIS_OK;
}
Exemple #9
0
void server_accept_log_client(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr)
{
    int nlen = len - offsetof(struct sockaddr_un, sun_path);
    struct sockaddr_un caddr;
    caddr.sun_path[nlen] = '\0';

    server.log_client_connected++;

    log_info("Accepted log client, current[%d] max[%d] total[%"PRIu64"]", server.rlc_list->count + 1, ZR_MAX_LOG_CONN, server.log_client_connected);
    if(server.rlc_list->count >= ZR_MAX_LOG_CONN)
    {
        ssize_t wl;
        log_warn("Reached max log client connection: %d, current client will be closed.", server.rlc_list->count + 1);
        sds msg = sdscatprintf(sdsempty(), "%s 1%sMax log client connection error. [%d]", ZR_CMD_REP_ERR, ZR_MSG_NL, server.rlc_list->count);
        wl = write(sock, msg, sdslen(msg));
        sdsfree(msg);
        close(sock);
        return;
    }

    rlclient_alloc(sock, &caddr);

}
Exemple #10
0
void server_accept_client(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr)
{
    int port = ntohs(((struct sockaddr_in*)addr)->sin_port);
    sds ip = sdsnew(inet_ntoa(((struct sockaddr_in*)addr)->sin_addr));

    server.client_connected++;

    log_info("Accepted client socket from %s:%d, current[%d], max[%d], total[%"PRIu64"]", ip, port, server.client_current + 1, server.client_max, server.client_connected);
    if(server.client_current >= server.client_max)
    {
        ssize_t wl;
        log_warn("Reached max connection: %d, client will be closed.", server.client_current + 1);
        sds msg = sdscatprintf(sdsempty(), "%s 1%sMax connection error.", ZR_CMD_REP_ERR, ZR_MSG_NL);
        wl = write(sock, msg, sdslen(msg));
        sdsfree(msg);
        close(sock);
        return;
    }


    //struct client *c = client_alloc(sock, (struct sockaddr_in*)addr);
    client_alloc(sock, (struct sockaddr_in*)addr);
}
Exemple #11
0
void prezLogObjectDebugInfo(robj *o) {
    prezLog(PREZ_WARNING,"Object type: %d", o->type);
    prezLog(PREZ_WARNING,"Object encoding: %d", o->encoding);
    prezLog(PREZ_WARNING,"Object refcount: %d", o->refcount);
    if (o->type == PREZ_STRING && sdsEncodedObject(o)) {
        prezLog(PREZ_WARNING,"Object raw string len: %zu", sdslen(o->ptr));
        if (sdslen(o->ptr) < 4096) {
            sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));
            prezLog(PREZ_WARNING,"Object raw string content: %s", repr);
            sdsfree(repr);
        }
    } /*else if (o->type == PREZ_LIST) {
        prezLog(PREZ_WARNING,"List length: %d", (int) listTypeLength(o));
    } else if (o->type == PREZ_SET) {
        prezLog(PREZ_WARNING,"Set size: %d", (int) setTypeSize(o));
    } else if (o->type == PREZ_HASH) {
        prezLog(PREZ_WARNING,"Hash size: %d", (int) hashTypeLength(o));
    } else if (o->type == PREZ_ZSET) {
        prezLog(PREZ_WARNING,"Sorted set size: %d", (int) zsetLength(o));
        if (o->encoding == PREZ_ENCODING_SKIPLIST)
            prezLog(PREZ_WARNING,"Skiplist level: %d", (int) ((zset*)o->ptr)->zsl->level);
    } */
}
Exemple #12
0
void init_container_store() {

	sds containerfile = sdsdup(destor.working_directory);
	containerfile = sdscat(containerfile, "/container.pool");

	if ((fp = fopen(containerfile, "r+"))) {
		fread(&container_count, 8, 1, fp);
	} else if (!(fp = fopen(containerfile, "w+"))) {
		perror(
				"Can not create container.pool for read and write because");
		exit(1);
	}

	sdsfree(containerfile);

	container_buffer = sync_queue_new(25);

	pthread_mutex_init(&mutex, NULL);

	pthread_create(&append_t, NULL, append_thread, NULL);

    NOTICE("Init container store successfully");
}
static void parseMarks(json_value *_marks, subtable_gpos_mark_to_ligature *subtable,
                       classname_hash **h) {
	NEW(subtable->marks);
	subtable->marks->numGlyphs = _marks->u.object.length;
	NEW_N(subtable->marks->glyphs, subtable->marks->numGlyphs);
	NEW(subtable->markArray);
	subtable->markArray->markCount = _marks->u.object.length;
	NEW_N(subtable->markArray->records, subtable->markArray->markCount);
	for (uint16_t j = 0; j < _marks->u.object.length; j++) {
		char *gname = _marks->u.object.values[j].name;
		json_value *anchorRecord = _marks->u.object.values[j].value;
		subtable->marks->glyphs[j].name = sdsnewlen(gname, _marks->u.object.values[j].name_length);

		subtable->markArray->records[j].markClass = 0;
		subtable->markArray->records[j].anchor = otl_anchor_absent();

		if (!anchorRecord || anchorRecord->type != json_object) continue;
		json_value *_className = json_obj_get_type(anchorRecord, "class", json_string);
		if (!_className) continue;

		sds className = sdsnewlen(_className->u.string.ptr, _className->u.string.length);
		classname_hash *s;
		HASH_FIND_STR(*h, className, s);
		if (!s) {
			NEW(s);
			s->className = className;
			s->classID = HASH_COUNT(*h);
			HASH_ADD_STR(*h, className, s);
		} else {
			sdsfree(className);
		}
		subtable->markArray->records[j].markClass = s->classID;
		subtable->markArray->records[j].anchor.present = true;
		subtable->markArray->records[j].anchor.x = json_obj_getnum(anchorRecord, "x");
		subtable->markArray->records[j].anchor.y = json_obj_getnum(anchorRecord, "y");
	}
}
Exemple #14
0
bool consolidate_gsub_multi(otfcc_Font *font, table_OTL *table, otl_Subtable *_subtable, const otfcc_Options *options) {
	subtable_gsub_multi *subtable = &(_subtable->gsub_multi);
	gsub_multi_hash *h = NULL;

	for (glyphid_t k = 0; k < subtable->length; k++) {
		if (!GlyphOrder.consolidateHandle(font->glyph_order, &subtable->items[k].from)) {
			logWarning("[Consolidate] Ignored missing glyph /%s.\n", subtable->items[k].from.name);
			continue;
		}
		fontop_consolidateCoverage(font, subtable->items[k].to, options);
		Coverage.shrink(subtable->items[k].to, false);

		gsub_multi_hash *s;
		int fromid = subtable->items[k].from.index;
		HASH_FIND_INT(h, &fromid, s);
		if (!s) {
			NEW(s);
			s->fromid = subtable->items[k].from.index;
			s->fromname = sdsdup(subtable->items[k].from.name);
			s->to = subtable->items[k].to;
			subtable->items[k].to = NULL; // Transfer ownership
			HASH_ADD_INT(h, fromid, s);
		}
	}
	HASH_SORT(h, by_from_id_multi);
	iSubtable_gsub_multi.clear(subtable);
	{
		gsub_multi_hash *s, *tmp;
		HASH_ITER(hh, h, s, tmp) {
			iSubtable_gsub_multi.push(subtable,
			                          ((otl_GsubMultiEntry){
			                              .from = Handle.fromConsolidated(s->fromid, s->fromname), .to = s->to,
			                          }));
			sdsfree(s->fromname);
			HASH_DEL(h, s);
			FREE(s);
		}
Exemple #15
0
/* Try to encode a string object in order to save space */
robj *tryObjectEncoding(robj *o) {
    long value;
    sds s = o->ptr;

    if (o->encoding != REDIS_ENCODING_RAW)
        return o; /* Already encoded */

    /* It's not safe to encode shared objects: shared objects can be shared
     * everywhere in the "object space" of Redis. Encoded objects can only
     * appear as "values" (and not, for instance, as keys) */
     if (o->refcount > 1) return o;

    /* Currently we try to encode only strings */
    redisAssert(o->type == REDIS_STRING);

    /* Check if we can represent this string as a long integer */
    if (isStringRepresentableAsLong(s,&value) == REDIS_ERR) return o;

    /* Ok, this object can be encoded...
     *
     * Can I use a shared object? Only if the object is inside a given
     * range and if this is the main thread, since when VM is enabled we
     * have the constraint that I/O thread should only handle non-shared
     * objects, in order to avoid race conditions (we don't have per-object
     * locking). */
    if (value >= 0 && value < REDIS_SHARED_INTEGERS &&
        pthread_equal(pthread_self(),server.mainthread)) {
        decrRefCount(o);
        incrRefCount(shared.integers[value]);
        return shared.integers[value];
    } else {
        o->encoding = REDIS_ENCODING_INT;
        sdsfree(o->ptr);
        o->ptr = (void*) value;
        return o;
    }
}
Exemple #16
0
static int cliReadReply(int output_raw_strings) {
    void *_reply;
    redisReply *reply;
    sds out;

    if (redisGetReply(context,&_reply) != REDIS_OK) {
        if (config.shutdown)
            return REDIS_OK;
        if (config.interactive) {
            /* Filter cases where we should reconnect */
            if (context->err == REDIS_ERR_IO && errno == ECONNRESET)
                return REDIS_ERR;
            if (context->err == REDIS_ERR_EOF)
                return REDIS_ERR;
        }
        cliPrintContextError();
        exit(1);
        return REDIS_ERR; /* avoid compiler warning */
    }

    reply = (redisReply*)_reply;
    if (output_raw_strings) {
        out = cliFormatReplyRaw(reply);
    } else {
        if (config.raw_output) {
            out = cliFormatReplyRaw(reply);
            out = sdscat(out,"\n");
        } else {
            out = cliFormatReplyTTY(reply,"");
        }
    }
    fwrite(out,sdslen(out),1,stdout);
    sdsfree(out);
    freeReplyObject(reply);
    return REDIS_OK;
}
static int cliReadBulkReply(int fd) {
    sds replylen = cliReadLine(fd);
    char *reply, crlf[2];
    int bulklen;

    if (replylen == NULL) return 1;
    bulklen = atoi(replylen);
    if (bulklen == -1) {
        sdsfree(replylen);
        printf("(nil)\n");
        return 0;
    }
    reply = zmalloc(bulklen);
    anetRead(fd,reply,bulklen);
    anetRead(fd,crlf,2);
    if (bulklen && fwrite(reply,bulklen,1,stdout) == 0) {
        zfree(reply);
        return 1;
    }
    if (isatty(fileno(stdout)) && reply[bulklen-1] != '\n')
        printf("\n");
    zfree(reply);
    return 0;
}
Exemple #18
0
void lsCommand(redisClient* c)
{
    DIR* pstDir = opendir((const char*)c->argv[1]->ptr);
    if (pstDir == NULL) {
        addReplyErrorFormat(c, "opendir fail, %s", strerror(errno));
        return;
    }

    list* dir = listCreate();
    struct dirent* pstDirent = NULL;
    while ((pstDirent = readdir(pstDir)) != NULL) {

        if(strcmp(pstDirent->d_name, ".") == 0 ||
            strcmp(pstDirent->d_name, "..") == 0)
            continue;

        sds path = sdsdup(c->argv[1]->ptr);
        size_t len = sdslen(path);
        if (path[len - 1] != '/')
            path = sdscat(path, "/");

        path = sdscat(path, pstDirent->d_name);
        listAddNodeTail(dir, path);
    }
    closedir(pstDir);

    addReplyMultiBulkLen(c, listLength(dir));
    listIter* iter = listGetIterator(dir, AL_START_HEAD);
    listNode* node = NULL;
    while ((node = listNext(iter))) {
        addReplyBulkCString(c, node->value);
        sdsfree(node->value);
        listDelNode(dir, node);
    }
    listRelease(dir);
}
Exemple #19
0
/* Try to encode a string object in order to save space */
static int tryObjectEncoding(robj *o) {
    long value;
    sds s = o->ptr;

    if (o->encoding != REDIS_ENCODING_RAW)
        return REDIS_ERR; /* Already encoded */

    /* It's not save to encode shared objects: shared objects can be shared
     * everywhere in the "object space" of Redis. Encoded objects can only
     * appear as "values" (and not, for instance, as keys) */
     if (o->refcount > 1) return REDIS_ERR;

    /* Currently we try to encode only strings */
    redisAssert(o->type == REDIS_STRING);

    /* Check if we can represent this string as a long integer */
    if (isStringRepresentableAsLong(s,&value) == REDIS_ERR) return REDIS_ERR;

    /* Ok, this object can be encoded */
    o->encoding = REDIS_ENCODING_INT;
    sdsfree(o->ptr);
    o->ptr = (void*) value;
    return REDIS_OK;
}
Exemple #20
0
static void listDeleteClientObjects(void *cl) {
    ugClient *c = (ugClient *) cl;
    resetClient(c);
    if (c->querybuf) sdsfree(c->querybuf);

    if (c->reply) {
        LOG_TRACE("reply size :%d", listLength(c->reply));
        listRelease(c->reply);
    }

    pubsubUnsubscribeAllChannels(c, 0);
    if (c->pubsub_channels) dictRelease(c->pubsub_channels);
    if (c->pubsub_patterns) listRelease(c->pubsub_patterns);

    aeDeleteFileEvent(server.el, c->fd, AE_READABLE);
    aeDeleteFileEvent(server.el, c->fd, AE_WRITABLE);
#ifdef _WIN32
    aeWinCloseSocket(c->fd);
#else
    close(c->fd);
#endif
    zfree(c);
    c = NULL;
}
Exemple #21
0
void luaReplyToRedisReply(redisClient *c, lua_State *lua) {
    int t = lua_type(lua,-1);

    switch(t) {
    case LUA_TSTRING:
        addReplyBulkCBuffer(c,(char*)lua_tostring(lua,-1),lua_strlen(lua,-1));
        break;
    case LUA_TBOOLEAN:
        addReply(c,lua_toboolean(lua,-1) ? shared.cone : shared.nullbulk);
        break;
    case LUA_TNUMBER:
        addReplyLongLong(c,(long long)lua_tonumber(lua,-1));
        break;
    case LUA_TTABLE:
        /* We need to check if it is an array, an error, or a status reply.
         * Error are returned as a single element table with 'err' field.
         * Status replies are returned as single element table with 'ok' field */
        lua_pushstring(lua,"err");
        lua_gettable(lua,-2);
        t = lua_type(lua,-1);
        if (t == LUA_TSTRING) {
            sds err = sdsnew(lua_tostring(lua,-1));
            sdsmapchars(err,"\r\n","  ",2);
            addReplySds(c,sdscatprintf(sdsempty(),"-%s\r\n",err));
            sdsfree(err);
            lua_pop(lua,2);
            return;
        }

        lua_pop(lua,1);
        lua_pushstring(lua,"ok");
        lua_gettable(lua,-2);
        t = lua_type(lua,-1);
        if (t == LUA_TSTRING) {
            sds ok = sdsnew(lua_tostring(lua,-1));
            sdsmapchars(ok,"\r\n","  ",2);
            addReplySds(c,sdscatprintf(sdsempty(),"+%s\r\n",ok));
            sdsfree(ok);
            lua_pop(lua,1);
        } else {
            void *replylen = addDeferredMultiBulkLength(c);
            int j = 1, mbulklen = 0;

            lua_pop(lua,1); /* Discard the 'ok' field value we popped */
            while(1) {
                lua_pushnumber(lua,j++);
                lua_gettable(lua,-2);
                t = lua_type(lua,-1);
                if (t == LUA_TNIL) {
                    lua_pop(lua,1);
                    break;
                }
                luaReplyToRedisReply(c, lua);
                mbulklen++;
            }
            setDeferredMultiBulkLength(c,replylen,mbulklen);
        }
        break;
    default:
        addReply(c,shared.nullbulk);
    }
    lua_pop(lua,1);
}
Exemple #22
0
static void callbackKeyDestructor(void *privdata, void *key) {
    ((void) privdata);
    sdsfree((sds)key);
}
Exemple #23
0
int luaRedisGenericCommand(lua_State *lua, int raise_error) {
    int j, argc = lua_gettop(lua);
    struct redisCommand *cmd;
    robj **argv;
    redisClient *c = server.lua_client;
    sds reply;

    /* 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 */
    argv = zmalloc(sizeof(robj*)*argc);
    for (j = 0; j < argc; j++) {
        if (!lua_isstring(lua,j+1)) break;
        argv[j] = createStringObject((char*)lua_tostring(lua,j+1),
                                     lua_strlen(lua,j+1));
    }
    
    /* 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--;
        }
        zfree(argv);
        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. */
    reply = sdsempty();
    if (c->bufpos) {
        reply = sdscatlen(reply,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);
    }
    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++)
        decrRefCount(c->argv[j]);
    zfree(c->argv);

    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;
}
Exemple #24
0
TEST(sds, sds)
{
    // struct sdshdr *sh;
    sds x = sdsnew("foo"), y;

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

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

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

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

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

    sdsfree(x);

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

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

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

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

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

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

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

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

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

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

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

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

#if 0
    {
        int oldfree;

        sdsfree(x);
        x = sdsnew("0");
        sh = (void*) (x-(sizeof(struct sdshdr)));
        TEST_ASSERT_TRUE( sh->len == 1 && sh->free == 0);
        x = sdsMakeRoomFor(x,1);
        sh = (void*) (x-(sizeof(struct sdshdr)));
        TEST_ASSERT_TRUE( sh->len == 1 && sh->free > 0);
        oldfree = sh->free;
        x[1] = '1';
        sdsIncrLen(x,1);
        TEST_ASSERT_TRUE( x[0] == '0' && x[1] == '1');
        TEST_ASSERT_TRUE( sh->len == 2);
        TEST_ASSERT_TRUE( sh->free == oldfree-1);
    }
#endif
}
Exemple #25
0
void freeClient(redisClient *c) {
    listNode *ln;

    /* Note that if the client we are freeing is blocked into a blocking
     * call, we have to set querybuf to NULL *before* to call
     * unblockClientWaitingData() to avoid processInputBuffer() will get
     * called. Also it is important to remove the file events after
     * this, because this call adds the READABLE event. */
    sdsfree(c->querybuf);
    c->querybuf = NULL;
    if (c->flags & REDIS_BLOCKED)
        unblockClientWaitingData(c);

    /* UNWATCH all the keys */
    unwatchAllKeys(c);
    listRelease(c->watched_keys);
    /* Unsubscribe from all the pubsub channels */
    pubsubUnsubscribeAllChannels(c,0);
    pubsubUnsubscribeAllPatterns(c,0);
    dictRelease(c->pubsub_channels);
    listRelease(c->pubsub_patterns);
    /* Obvious cleanup */
    aeDeleteFileEvent(server.el,c->fd,AE_READABLE);
    aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
    listRelease(c->reply);
    freeClientArgv(c);
    close(c->fd);
    /* Remove from the list of clients */
    ln = listSearchKey(server.clients,c);
    redisAssert(ln != NULL);
    listDelNode(server.clients,ln);
    /* Remove from the list of clients waiting for swapped keys, or ready
     * to be restarted, but not yet woken up again. */
    if (c->flags & REDIS_IO_WAIT) {
        redisAssert(server.vm_enabled);
        if (listLength(c->io_keys) == 0) {
            ln = listSearchKey(server.io_ready_clients,c);

            /* When this client is waiting to be woken up (REDIS_IO_WAIT),
             * it should be present in the list io_ready_clients */
            redisAssert(ln != NULL);
            listDelNode(server.io_ready_clients,ln);
        } else {
            while (listLength(c->io_keys)) {
                ln = listFirst(c->io_keys);
                dontWaitForSwappedKey(c,ln->value);
            }
        }
        server.vm_blocked_clients--;
    }
    listRelease(c->io_keys);
    /* Master/slave cleanup.
     * Case 1: we lost the connection with a slave. */
    if (c->flags & REDIS_SLAVE) {
        if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1)
            close(c->repldbfd);
        list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves;
        ln = listSearchKey(l,c);
        redisAssert(ln != NULL);
        listDelNode(l,ln);
    }

    /* Case 2: we lost the connection with the master. */
    if (c->flags & REDIS_MASTER) {
        server.master = NULL;
        server.replstate = REDIS_REPL_CONNECT;
        /* Since we lost the connection with the master, we should also
         * close the connection with all our slaves if we have any, so
         * when we'll resync with the master the other slaves will sync again
         * with us as well. Note that also when the slave is not connected
         * to the master it will keep refusing connections by other slaves. */
        while (listLength(server.slaves)) {
            ln = listFirst(server.slaves);
            freeClient((redisClient*)ln->value);
        }
    }
    /* Release memory */
    zfree(c->argv);
    zfree(c->mbargv);
    freeClientMultiState(c);
    zfree(c);
}
Exemple #26
0
int redisvFormatCommand(char **target, const char *format, va_list ap) {
    const char *c = format;
    char *cmd = NULL; /* final command */
    int pos; /* position in final command */
    sds curarg, newarg; /* current argument */
    int touched = 0; /* was the current argument touched? */
    char **curargv = NULL, **newargv = NULL;
    int argc = 0;
    int totlen = 0;
    int j;

    /* Abort if there is not target to set */
    if (target == NULL)
        return -1;

    /* Build the command string accordingly to protocol */
    curarg = sdsempty();
    if (curarg == NULL)
        return -1;

    while(*c != '\0') {
        if (*c != '%' || c[1] == '\0') {
            if (*c == ' ') {
                if (touched) {
                    newargv = realloc(curargv,sizeof(char*)*(argc+1));
                    if (newargv == NULL) goto err;
                    curargv = newargv;
                    curargv[argc++] = curarg;
                    totlen += bulklen(sdslen(curarg));

                    /* curarg is put in argv so it can be overwritten. */
                    curarg = sdsempty();
                    if (curarg == NULL) goto err;
                    touched = 0;
                }
            } else {
                newarg = sdscatlen(curarg,c,1);
                if (newarg == NULL) goto err;
                curarg = newarg;
                touched = 1;
            }
        } else {
            char *arg;
            size_t size;

            /* Set newarg so it can be checked even if it is not touched. */
            newarg = curarg;

            switch(c[1]) {
            case 's':
                arg = va_arg(ap,char*);
                size = strlen(arg);
                if (size > 0)
                    newarg = sdscatlen(curarg,arg,size);
                break;
            case 'b':
                arg = va_arg(ap,char*);
                size = va_arg(ap,size_t);
                if (size > 0)
                    newarg = sdscatlen(curarg,arg,size);
                break;
            case '%':
                newarg = sdscat(curarg,"%");
                break;
            default:
                /* Try to detect printf format */
                {
                    char _format[16];
                    const char *_p = c+1;
                    size_t _l = 0;
                    va_list _cpy;

                    /* Flags */
                    if (*_p != '\0' && *_p == '#') _p++;
                    if (*_p != '\0' && *_p == '0') _p++;
                    if (*_p != '\0' && *_p == '-') _p++;
                    if (*_p != '\0' && *_p == ' ') _p++;
                    if (*_p != '\0' && *_p == '+') _p++;

                    /* Field width */
                    while (*_p != '\0' && isdigit(*_p)) _p++;

                    /* Precision */
                    if (*_p == '.') {
                        _p++;
                        while (*_p != '\0' && isdigit(*_p)) _p++;
                    }

                    /* Copy va_list before consuming with va_arg */
                    va_copy(_cpy,ap);

                    /* Integer conversion (without modifiers) */
                    if (strchr("diouxX",*_p) != NULL) {
                        va_arg(ap,int);
                        goto fmt_valid;
                    }

                    /* Double conversion (without modifiers) */
                    if (strchr("eEfFgGaA",*_p) != NULL) {
                        va_arg(ap,double);
                        goto fmt_valid;
                    }

                    /* Size: char */
                    if (_p[0] == 'h' && _p[1] == 'h') {
                        _p += 2;
                        if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
                            va_arg(ap,int); /* char gets promoted to int */
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: short */
                    if (_p[0] == 'h') {
                        _p += 1;
                        if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
                            va_arg(ap,int); /* short gets promoted to int */
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: long long */
                    if (_p[0] == 'l' && _p[1] == 'l') {
                        _p += 2;
                        if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
                            va_arg(ap,long long);
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: long */
                    if (_p[0] == 'l') {
                        _p += 1;
                        if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
                            va_arg(ap,long);
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                fmt_invalid:
                    va_end(_cpy);
                    goto err;

                fmt_valid:
                    _l = (_p+1)-c;
                    if (_l < sizeof(_format)-2) {
                        memcpy(_format,c,_l);
                        _format[_l] = '\0';
                        newarg = sdscatvprintf(curarg,_format,_cpy);

                        /* Update current position (note: outer blocks
                         * increment c twice so compensate here) */
                        c = _p-1;
                    }

                    va_end(_cpy);
                    break;
                }
            }

            if (newarg == NULL) goto err;
            curarg = newarg;

            touched = 1;
            c++;
        }
        c++;
    }

    /* Add the last argument if needed */
    if (touched) {
        newargv = realloc(curargv,sizeof(char*)*(argc+1));
        if (newargv == NULL) goto err;
        curargv = newargv;
        curargv[argc++] = curarg;
        totlen += bulklen(sdslen(curarg));
    } else {
        sdsfree(curarg);
    }

    /* Clear curarg because it was put in curargv or was free'd. */
    curarg = NULL;

    /* Add bytes needed to hold multi bulk count */
    totlen += 1+intlen(argc)+2;

    /* Build the command at protocol level */
    cmd = malloc(totlen+1);
    if (cmd == NULL) goto err;

    pos = sprintf(cmd,"*%d\r\n",argc);
    for (j = 0; j < argc; j++) {
        pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j]));
        memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));
        pos += sdslen(curargv[j]);
        sdsfree(curargv[j]);
        cmd[pos++] = '\r';
        cmd[pos++] = '\n';
    }
    assert(pos == totlen);
    cmd[pos] = '\0';

    free(curargv);
    *target = cmd;
    return totlen;

err:
    while(argc--)
        sdsfree(curargv[argc]);
    free(curargv);

    if (curarg != NULL)
        sdsfree(curarg);

    /* No need to check cmd since it is the last statement that can fail,
     * but do it anyway to be as defensive as possible. */
    if (cmd != NULL)
        free(cmd);

    return -1;
}
Exemple #27
0
/* dictionary types */
static void dictSdsDestructor(void *privdata, void *val)
{
    DICT_NOTUSED(privdata);

    sdsfree((sds)val);
}
Exemple #28
0
void processInputBuffer(redisClient *c) {
again:
    /* Before to process the input buffer, make sure the client is not
     * waitig for a blocking operation such as BLPOP. Note that the first
     * iteration the client is never blocked, otherwise the processInputBuffer
     * would not be called at all, but after the execution of the first commands
     * in the input buffer the client may be blocked, and the "goto again"
     * will try to reiterate. The following line will make it return asap. */
    if (c->flags & REDIS_BLOCKED || c->flags & REDIS_IO_WAIT) return;
    if (c->bulklen == -1) {
        /* Read the first line of the query */
        char *p = strchr(c->querybuf,'\n');
        size_t querylen;

        if (p) {
            sds query, *argv;
            int argc, j;

            query = c->querybuf;
            c->querybuf = sdsempty();
            querylen = 1+(p-(query));
            if (sdslen(query) > querylen) {
                /* leave data after the first line of the query in the buffer */
                c->querybuf = sdscatlen(c->querybuf,query+querylen,sdslen(query)-querylen);
            }
            *p = '\0'; /* remove "\n" */
            if (*(p-1) == '\r') *(p-1) = '\0'; /* and "\r" if any */
            sdsupdatelen(query);

            /* Now we can split the query in arguments */
            argv = sdssplitlen(query,sdslen(query)," ",1,&argc);
            sdsfree(query);

            if (c->argv) zfree(c->argv);
            c->argv = zmalloc(sizeof(robj*)*argc);

            for (j = 0; j < argc; j++) {
                if (sdslen(argv[j])) {
                    c->argv[c->argc] = createObject(REDIS_STRING,argv[j]);
                    c->argc++;
                } else {
                    sdsfree(argv[j]);
                }
            }
            zfree(argv);
            if (c->argc) {
                /* Execute the command. If the client is still valid
                 * after processCommand() return and there is something
                 * on the query buffer try to process the next command. */
                if (processCommand(c) && sdslen(c->querybuf)) goto again;
            } else {
                /* Nothing to process, argc == 0. Just process the query
                 * buffer if it's not empty or return to the caller */
                if (sdslen(c->querybuf)) goto again;
            }
            return;
        } else if (sdslen(c->querybuf) >= REDIS_REQUEST_MAX_SIZE) {
            redisLog(REDIS_VERBOSE, "Client protocol error");
            freeClient(c);
            return;
        }
    } else {
        /* Bulk read handling. Note that if we are at this point
           the client already sent a command terminated with a newline,
           we are reading the bulk data that is actually the last
           argument of the command. */
        int qbl = sdslen(c->querybuf);

        if (c->bulklen <= qbl) {
            /* Copy everything but the final CRLF as final argument */
            c->argv[c->argc] = createStringObject(c->querybuf,c->bulklen-2);
            c->argc++;
            c->querybuf = sdsrange(c->querybuf,c->bulklen,-1);
            /* Process the command. If the client is still valid after
             * the processing and there is more data in the buffer
             * try to parse it. */
            if (processCommand(c) && sdslen(c->querybuf)) goto again;
            return;
        }
    }
}
Exemple #29
0
int redisvFormatCommand(char **target, const char *format, va_list ap) {
    size_t size;
    const char *arg, *c = format;
    char *cmd = NULL; /* final command */
    int pos; /* position in final command */
    sds current; /* current argument */
    int touched = 0; /* was the current argument touched? */
    char **argv = NULL;
    int argc = 0, j;
    int totlen = 0;

    /* Abort if there is not target to set */
    if (target == NULL)
        return -1;

    /* Build the command string accordingly to protocol */
    current = sdsempty();
    while(*c != '\0') {
        if (*c != '%' || c[1] == '\0') {
            if (*c == ' ') {
                if (touched) {
                    addArgument(current, &argv, &argc, &totlen);
                    current = sdsempty();
                    touched = 0;
                }
            } else {
                current = sdscatlen(current,c,1);
                touched = 1;
            }
        } else {
            switch(c[1]) {
            case 's':
                arg = va_arg(ap,char*);
                size = strlen(arg);
                if (size > 0)
                    current = sdscatlen(current,arg,size);
                break;
            case 'b':
                arg = va_arg(ap,char*);
                size = va_arg(ap,size_t);
                if (size > 0)
                    current = sdscatlen(current,arg,size);
                break;
            case '%':
                current = sdscat(current,"%");
                break;
            default:
                /* Try to detect printf format */
                {
                    char _format[16];
                    const char *_p = c+1;
                    size_t _l = 0;
                    va_list _cpy;

                    /* Flags */
                    if (*_p != '\0' && *_p == '#') _p++;
                    if (*_p != '\0' && *_p == '0') _p++;
                    if (*_p != '\0' && *_p == '-') _p++;
                    if (*_p != '\0' && *_p == ' ') _p++;
                    if (*_p != '\0' && *_p == '+') _p++;

                    /* Field width */
                    while (*_p != '\0' && isdigit(*_p)) _p++;

                    /* Precision */
                    if (*_p == '.') {
                        _p++;
                        while (*_p != '\0' && isdigit(*_p)) _p++;
                    }

                    /* Modifiers */
                    if (*_p != '\0') {
                        if (*_p == 'h' || *_p == 'l') {
                            /* Allow a single repetition for these modifiers */
                            if (_p[0] == _p[1]) _p++;
                            _p++;
                        }
                    }

                    /* Conversion specifier */
                    if (*_p != '\0' && strchr("diouxXeEfFgGaA",*_p) != NULL) {
                        _l = (_p+1)-c;
                        if (_l < sizeof(_format)-2) {
                            memcpy(_format,c,_l);
                            _format[_l] = '\0';
                            va_copy(_cpy,ap);
                            current = sdscatvprintf(current,_format,_cpy);
                            va_end(_cpy);

                            /* Update current position (note: outer blocks
                             * increment c twice so compensate here) */
                            c = _p-1;
                        }
                    }

                    /* Consume and discard vararg */
                    va_arg(ap,void);
                }
            }
            touched = 1;
            c++;
        }
        c++;
    }

    /* Add the last argument if needed */
    if (touched) {
        addArgument(current, &argv, &argc, &totlen);
    } else {
        sdsfree(current);
    }

    /* Add bytes needed to hold multi bulk count */
    totlen += 1+intlen(argc)+2;

    /* Build the command at protocol level */
    cmd = malloc(totlen+1);
    if (!cmd) redisOOM();
    pos = sprintf(cmd,"*%d\r\n",argc);
    for (j = 0; j < argc; j++) {
        pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(argv[j]));
        memcpy(cmd+pos,argv[j],sdslen(argv[j]));
        pos += sdslen(argv[j]);
        sdsfree(argv[j]);
        cmd[pos++] = '\r';
        cmd[pos++] = '\n';
    }
    assert(pos == totlen);
    free(argv);
    cmd[totlen] = '\0';
    *target = cmd;
    return totlen;
}
Exemple #30
0
Fichier : db.c Projet : yuyang0/mdb
void freeValue(value_t *val) {
	if (val->encoding == ENCODING_RAW) {
		sdsfree(val->ptr);
	}
	zfree(val);
}