From cc7f0434b5c590e5a61c3cefa6ed9fb193d021dd Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Mon, 9 Feb 2015 23:44:42 +0100
Subject: [PATCH] Change alsoPropagate() behavior to make it more usable.

Now the API automatically creates its argv copy and increment ref count
of passed objects.
---
 src/redis.c | 21 +++++++++++++++++++--
 src/t_set.c | 12 +++++-------
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/src/redis.c b/src/redis.c
index 277d2e4b..8bfcfdaa 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -2016,11 +2016,28 @@ void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,
 }
 
 /* Used inside commands to schedule the propagation of additional commands
- * after the current command is propagated to AOF / Replication. */
+ * after the current command is propagated to AOF / Replication.
+ *
+ * 'cmd' must be a pointer to the Redis command to replicate, dbid is the
+ * database ID the command should be propagated into.
+ * Arguments of the command to propagte are passed as an array of redis
+ * objects pointers of len 'argc', using the 'argv' vector.
+ *
+ * The function does not take a reference to the passed 'argv' vector,
+ * so it is up to the caller to release the passed argv (but it is usually
+ * stack allocated).  The function autoamtically increments ref count of
+ * passed objects, so the caller does not need to. */
 void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,
                    int target)
 {
-    redisOpArrayAppend(&server.also_propagate,cmd,dbid,argv,argc,target);
+    robj **argvcopy = zmalloc(sizeof(robj*)*argc);
+    int j;
+
+    for (j = 0; j < argc; j++) {
+        argvcopy[j] = argv[j];
+        incrRefCount(argv[j]);
+    }
+    redisOpArrayAppend(&server.also_propagate,cmd,dbid,argvcopy,argc,target);
 }
 
 /* It is possible to call the function forceCommandPropagation() inside a
diff --git a/src/t_set.c b/src/t_set.c
index 619b0f8a..47aa173a 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -556,10 +556,12 @@ void spopWithCountCommand(redisClient *c) {
 
     {
         setTypeIterator *si;
-        robj *objele, **propargv;
+        robj *objele, *propargv[3];
         int element_encoding;
 
         addReplyMultiBulkLen(c, elements_returned);
+        propargv[0] = createStringObject("SREM",4);
+        propargv[1] = c->argv[1];
 
         si = setTypeInitIterator(aux_set);
         while ((element_encoding = setTypeNext(si, &objele, &llele)) != -1) {
@@ -574,17 +576,13 @@ void spopWithCountCommand(redisClient *c) {
             addReplyBulk(c, objele);
 
             /* Replicate/AOF this command as an SREM operation */
-            propargv = zmalloc(sizeof(robj*)*3);
-            propargv[0] = createStringObject("SREM",4);
-            propargv[1] = c->argv[1];
-            incrRefCount(c->argv[1]);
             propargv[2] = objele;
-            incrRefCount(objele);
-
             alsoPropagate(server.sremCommand,c->db->id,propargv,3,REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);
+
             decrRefCount(objele);
             server.dirty++;
         }
+        decrRefCount(propargv[0]);
         setTypeReleaseIterator(si);
     }