diff --git a/src/replication.c b/src/replication.c index 8a15c01a7..4977bba42 100644 --- a/src/replication.c +++ b/src/replication.c @@ -1827,72 +1827,94 @@ error: return; } -/* Send a synchronous command to the master. Used to send AUTH and - * REPLCONF commands before starting the replication with SYNC. +char *receiveSynchronousResponse(connection *conn) { + char buf[256]; + /* Read the reply from the server. */ + if (connSyncReadLine(conn,buf,sizeof(buf),server.repl_syncio_timeout*1000) == -1) + { + return sdscatprintf(sdsempty(),"-Reading from master: %s", + strerror(errno)); + } + server.repl_transfer_lastio = server.unixtime; + return sdsnew(buf); +} + +/* Send a pre-formatted multi-bulk command to the connection. */ +char* sendCommandRaw(connection *conn, sds cmd) { + if (connSyncWrite(conn,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) == -1) { + return sdscatprintf(sdsempty(),"-Writing to master: %s", + connGetLastError(conn)); + } + return NULL; +} + +/* Compose a multi-bulk command and send it to the connection. + * Used to send AUTH and REPLCONF commands to the master before starting the + * replication. + * + * Takes a list of char* arguments, terminated by a NULL argument. * * The command returns an sds string representing the result of the * operation. On error the first byte is a "-". */ -#define SYNC_CMD_READ (1<<0) -#define SYNC_CMD_WRITE (1<<1) -#define SYNC_CMD_WRITE_SDS (1<<2) -#define SYNC_CMD_FULL (SYNC_CMD_READ|SYNC_CMD_WRITE) -char *sendSynchronousCommand(int flags, connection *conn, ...) { +char *sendCommand(connection *conn, ...) { + va_list ap; + sds cmd = sdsempty(); + sds cmdargs = sdsempty(); + size_t argslen = 0; + char *arg; /* Create the command to send to the master, we use redis binary * protocol to make sure correct arguments are sent. This function * is not safe for all binary data. */ - if (flags & SYNC_CMD_WRITE) { - char *arg; - va_list ap; - sds cmd = sdsempty(); - sds cmdargs = sdsempty(); - size_t argslen = 0; - va_start(ap,conn); - - while(1) { - arg = va_arg(ap, char*); - if (arg == NULL) break; - if (flags & SYNC_CMD_WRITE_SDS) { - cmdargs = sdscatprintf(cmdargs,"$%zu\r\n", sdslen((sds)arg)); - cmdargs = sdscatsds(cmdargs, (sds)arg); - cmdargs = sdscat(cmdargs, "\r\n"); - } else { - cmdargs = sdscatprintf(cmdargs,"$%zu\r\n%s\r\n",strlen(arg),arg); - } - argslen++; - } - - va_end(ap); - - cmd = sdscatprintf(cmd,"*%zu\r\n",argslen); - cmd = sdscatsds(cmd,cmdargs); - sdsfree(cmdargs); - - /* Transfer command to the server. */ - if (connSyncWrite(conn,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) - == -1) - { - sdsfree(cmd); - return sdscatprintf(sdsempty(),"-Writing to master: %s", - connGetLastError(conn)); - } - sdsfree(cmd); + va_start(ap,conn); + while(1) { + arg = va_arg(ap, char*); + if (arg == NULL) break; + cmdargs = sdscatprintf(cmdargs,"$%zu\r\n%s\r\n",strlen(arg),arg); + argslen++; } - /* Read the reply from the server. */ - if (flags & SYNC_CMD_READ) { - char buf[256]; + cmd = sdscatprintf(cmd,"*%zu\r\n",argslen); + cmd = sdscatsds(cmd,cmdargs); + sdsfree(cmdargs); - if (connSyncReadLine(conn,buf,sizeof(buf),server.repl_syncio_timeout*1000) - == -1) - { - return sdscatprintf(sdsempty(),"-Reading from master: %s", - strerror(errno)); - } - server.repl_transfer_lastio = server.unixtime; - return sdsnew(buf); + va_end(ap); + char* err = sendCommandRaw(conn, cmd); + sdsfree(cmd); + if(err) + return err; + return NULL; +} + +/* Compose a multi-bulk command and send it to the connection. + * Used to send AUTH and REPLCONF commands to the master before starting the + * replication. + * + * argv_lens is optional, when NULL, strlen is used. + * + * The command returns an sds string representing the result of the + * operation. On error the first byte is a "-". + */ +char *sendCommandArgv(connection *conn, int argc, char **argv, size_t *argv_lens) { + sds cmd = sdsempty(); + char *arg; + int i; + + /* Create the command to send to the master. */ + cmd = sdscatfmt(cmd,"*%i\r\n",argc); + for (i=0; i