variadic command support in hiredis

869 views
Skip to first unread message

Birdy

unread,
Dec 9, 2011, 12:01:17 AM12/9/11
to Redis DB
Hi,

Does Redis client 'hiredis' supports variadic commands (specially
variadic rpush)?
If yes, can you please tell me the usage.

Thanks,
Anurag Berdia

Didier Spezia

unread,
Dec 9, 2011, 4:29:29 AM12/9/11
to redi...@googlegroups.com

Hi,

hiredis allows you to run arbitrary commands on Redis
including the variadic ones.

redisContext *c = redisConnectUnix("/tmp/redis.sock");
...
redisReply *reply = redisCommand(c,"RPUSH key%d %s %s %s %s", key, item1, item2, item3, item4 );
...
freeReplyObject(reply);

(error handling code ommitted)

Regards,
Didier.

Birdy

unread,
Dec 10, 2011, 4:46:45 AM12/10/11
to Redis DB
Hi Didier,

Thanks for reply.
In the given case, how can we add N number of items at run time.
I mean in first call i want to push 3 elements, then in seconds 10 and
in third 2 and so on
How can we implement this using hiredis?

Thanks,
Anurag Berdia

Didier Spezia

unread,
Dec 10, 2011, 7:51:05 AM12/10/11
to redi...@googlegroups.com

Hi,

you could use the following function:

/* Issue a command to Redis. This function takes the
 * number of arguments, an array with arguments and an array with their
 * lengths. If the latter is set to NULL, strlen will be used to compute the
 * argument lengths.
 */
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);

Here is an example in old-school C++:

If you plan to push a large number of items, consider splitting the operation in smaller
commands, and pipeline them using redisAppendCommandArgv (i.e. grouping 20 by 20
for instance).

Regards,
Didier.

George Coles

unread,
Mar 4, 2013, 3:24:18 PM3/4/13
to redi...@googlegroups.com
Hello again,
  I wrote some C++ code that takes matlab strings and tries to send them using redisCommandArgv. But in redisFormatCommandArg, assert(pos == totlen) fails. pos is always two greater than totlen.

This function populates the args and arg lengths:

void send( redisReply** reply, redisContext* ctx, int nprhs, int startIndex, const mxArray** prhs  ){
    
int numArgs = nprhs-startIndex;
vector<const char *> argv( numArgs );
    vector<size_t> argvlen( numArgs );
    size_t m,n;
    int argIndex = 0;
    
    mwSize index = 0;
    for ( index = startIndex; index < nprhs; index++ ){
        const mxArray* mx;
mx = prhs[index];
m = mxGetM( mx );
        n = mxGetN( mx );
        char* str;
        mxArray2Char( &str, m,n, prhs[index] );
        const char* c = str;
argv[argIndex] = c;
        argvlen[argIndex] = strlen(c);
        argIndex++;
    }
    *reply = (redisReply*)redisCommandArgv(ctx,argv.size(),&(argv[0]),&(argvlen[0]) );

}

This function is called to create a char* from each matlab string:

void mxArray2Char( char** str,  mwSize m,mwSize n, const  mxArray* mx ){
    
    *str = mxArrayToString( mx );
}

I am trying to pass the command strings "SET" "FOO" "abcdefghijklmnopqrstuvwxyz"


On Sunday, March 3, 2013 7:11:21 PM UTC-5, George Coles wrote:
I know this is old, but it is the only post on the redis forum that deals with this issue. 

I am writing a matlab interface to redis in C. I am not good at C, but I am worse at C++. I need to use redisCommandArgv, because I need to transform the args list from matlab MxArrays to char arrays, and then pass those to redisCommand. So variadic args list a la C will not work. 

I have an embarrassing question - how would you write an example that uses redisCommandArgv in C? I understand the semantics, but I am a bit confused about how to iteratively construct the char **argv. Why not just make it char* ? 

thx
George 

George Coles

unread,
Mar 15, 2013, 9:46:20 AM3/15/13
to redi...@googlegroups.com
I want to thank everyone for their help on this. I found an answer to my problem. 

I am using the hiredis-win project so that I can use redis on windows or other platforms. The author of that project neglected to touch the redisFormatCommandArgv function with his tests. On windows, as far as I can tell, the following format string does not work as intended:

pos += sprintf(cmd+pos,"$%zu\r\n",len);

This is on line 968 of hiredis.c. If you use the "%lu" format on Windows, it is fixed. I thought this would be of mild interest because while I know that WIndows is not the intended home for Redis, there many hardworking people out there who have to use it for part fo their computing life. 

I wrote my argv handling code in c++ instead of c, and it was just a matter of adapting the example code to be generic to any command not just RPUSH.

Thanks,
George
Reply all
Reply to author
Forward
0 new messages