diff --git a/deps/xredis-gtid b/deps/xredis-gtid index 52841a2297b..e642bd25ac3 160000 --- a/deps/xredis-gtid +++ b/deps/xredis-gtid @@ -1 +1 @@ -Subproject commit 52841a2297b0efae5f0175a4dbd7c4b9539d3801 +Subproject commit e642bd25ac3a282b04472834dcb2928b8cbbcf47 diff --git a/runtest-moduleapi b/runtest-moduleapi index 56d149609d8..f76aaf6242e 100755 --- a/runtest-moduleapi +++ b/runtest-moduleapi @@ -21,6 +21,7 @@ $TCLSH tests/test_helper.tcl \ --single unit/moduleapi/testrdb \ --single unit/moduleapi/infotest \ --single unit/moduleapi/propagate \ +--single unit/moduleapi/propagate-gtid \ --single unit/moduleapi/hooks \ --single unit/moduleapi/misc \ --single unit/moduleapi/blockonkeys \ diff --git a/src/ctrip_swap_cmd.c b/src/ctrip_swap_cmd.c index 3b2b876d8e9..6d6453a6b23 100644 --- a/src/ctrip_swap_cmd.c +++ b/src/ctrip_swap_cmd.c @@ -1666,9 +1666,10 @@ int getKeyRequestSmove(int dbid, struct redisCommand *cmd, robj **argv, int argc SWAP_IN, SWAP_IN_DEL, cmd->flags, dbid); incrRefCount(argv[2]); - incrRefCount(argv[3]); + subkeys = zmalloc(sizeof(robj*)); - subkeys[0] = argv[3]; + /* must copy argv[3], setSwapAna use incrRefCount (in swap thread) */ + subkeys[0] = dupStringObject(argv[3]); getKeyRequestsAppendSubkeyResult(result,REQUEST_LEVEL_KEY,argv[2], 1, subkeys, SWAP_IN, 0, cmd->flags, dbid); diff --git a/tests/unit/moduleapi/propagate-gtid.tcl b/tests/unit/moduleapi/propagate-gtid.tcl new file mode 100644 index 00000000000..f104d6e5ff4 --- /dev/null +++ b/tests/unit/moduleapi/propagate-gtid.tcl @@ -0,0 +1,54 @@ +set testmodule [file normalize tests/modules/propagate.so] + +tags {"modules" "gtid"} { + test {module auto-wrapped RedisModule_Replicate maps to one GTID} { + # This guards the cc178563b0281843 fix: module commands enqueue + # internal writes plus EXEC, so GTID must still treat the whole + # auto-wrapped MULTI/EXEC block as exactly one GTID. + start_server [list overrides [list gtid-enabled yes loadmodule "$testmodule"]] { + set replica [srv 0 client] + set replica_host [srv 0 host] + set replica_port [srv 0 port] + + start_server [list overrides [list gtid-enabled yes loadmodule "$testmodule"]] { + set master [srv 0 client] + set master_host [srv 0 host] + set master_port [srv 0 port] + + $replica replicaof $master_host $master_port + wait_for_sync $replica + + set master_repl [attach_to_replication_stream] + set replica_repl [attach_to_replication_stream] + + set uuid [status $master gtid_uuid] + set before_gno [status $master gtid_executed_gno_count] + set before_master_gtidset [status $master gtid_set] + set before_replica_gtidset [status $replica gtid_set] + set before_master_reploff [status $master master_repl_offset] + set before_replica_reploff [status $replica master_repl_offset] + + $master propagate-test.simple + wait_for_gtid_sync $master $replica + + set expected_gno [expr {$before_gno + 1}] + set expected_gtid "$uuid:$expected_gno" + + assert_equal $expected_gno [status $master gtid_executed_gno_count] + assert_equal 1 [$replica get counter-1] + assert_equal 1 [$replica get counter-2] + assert {[gtid_set_is_equal [status $master gtid_set] [status $replica gtid_set]]} + + assert_replication_stream $master_repl [list {select *} {multi} {incr counter-1} {incr counter-2} "gtid $expected_gtid * EXEC"] + assert_replication_stream $replica_repl [list {select *} {multi} {incr counter-1} {incr counter-2} "gtid $expected_gtid * EXEC"] + + assert_equal [expr {$before_master_reploff + 1}] [lindex [$master GTIDX SEQ LOCATE $before_master_gtidset] 0] + assert_equal $expected_gtid [lindex [$master GTIDX SEQ LOCATE $before_master_gtidset] 1] + assert_equal $expected_gtid [lindex [$replica GTIDX SEQ LOCATE $before_replica_gtidset] 1] + + close_replication_stream $master_repl + close_replication_stream $replica_repl + } + } + } +}