DonalEvans commented on a change in pull request #7513:
URL: https://github.com/apache/geode/pull/7513#discussion_r838872401



##########
File path: 
geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisSet.java
##########
@@ -77,12 +82,20 @@ public static int smove(RedisKey sourceKey, RedisKey 
destKey, byte[] member,
       RegionProvider regionProvider) {
     RedisSet source = regionProvider.getTypedRedisData(REDIS_SET, sourceKey, 
false);
     RedisSet destination = regionProvider.getTypedRedisData(REDIS_SET, 
destKey, false);
-    List<byte[]> memberList = new ArrayList<>();
-    memberList.add(member);
-    if (source.srem(memberList, regionProvider.getDataRegion(), sourceKey) == 
0) {
+
+    if (!source.sismember(member)) {
       return 0;
     }
-    destination.sadd(memberList, regionProvider.getDataRegion(), destKey);
+    if (sourceKey.equals(destKey)) {
+      return 1;
+    }
+
+    List<byte[]> memberList = new ArrayList<>();
+    memberList.add(member);
+    RedisSet newSource = new RedisSet(source);
+    newSource.srem(memberList, regionProvider.getDataRegion(), sourceKey);
+    RedisSet newDestination = new RedisSet(destination);
+    newDestination.sadd(memberList, regionProvider.getDataRegion(), destKey);

Review comment:
       Creating new copies of the RedisSets here will result in the version and 
expiration timestamp fields being reset to the initial value. This could lead 
to the secondary copies not applying a versioned delta that they should have if 
the versions line up properly, and to keys that should expire not expiring. I 
think we need a true copy constructor for our Redis data classes to retain the 
same version and expiration timestamp info.

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/string/MSetDUnitTest.java
##########
@@ -114,6 +119,33 @@ public void 
testMSet_concurrentInstancesHandleBucketMovement() {
                     .allSatisfy(value -> 
assertThat(value).startsWith("valueTwo"))));
   }
 
+  @Test
+  public void testMSet_isTransactional() {
+    String hashTag = "{" + clusterStartUp.getKeyOnServer("tag", 1) + "}";
+    String key1 = hashTag + "key1";
+    String value1 = "value1";
+    jedis.set(key1, value1);
+
+    clusterStartUp.getMember(1).invoke(() -> {
+      valueReference =
+          (RedisString) 
ClusterStartupRule.getCache().getRegion(DEFAULT_REDIS_REGION_NAME)
+              .get(new RedisKey(key1.getBytes()));
+      assertThat(new String(valueReference.getValue())).isEqualTo(value1);
+    });
+
+    String newValue = "should_not_be_set";

Review comment:
       This should be changed, since the test expects that it should be set.

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/string/MSetDUnitTest.java
##########
@@ -48,6 +51,8 @@
 
   private static final Logger logger = LogService.getLogger();
 
+  public static RedisString valueReference;

Review comment:
       This should probably be replaced with a local variable in the test that 
uses it:
   ```
       AtomicReference<RedisString> valueReference = new AtomicReference<>();
   
       clusterStartUp.getMember(1).invoke(() -> {
         valueReference.set((RedisString) ClusterStartupRule.getCache()
             .getRegion(DEFAULT_REDIS_REGION_NAME).get(new 
RedisKey(key1.getBytes())));
         assertThat(new 
String(valueReference.get().getValue())).isEqualTo(value1);
       });
   ```

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/set/SmoveDunitTest.java
##########
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.set;
+
+import static 
org.apache.geode.redis.internal.services.RegionProvider.DEFAULT_REDIS_REGION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class SmoveDunitTest {
+
+  @ClassRule
+  public static RedisClusterStartupRule clusterStartUp = new 
RedisClusterStartupRule(4);
+
+  private static final String LOCAL_HOST = "127.0.0.1";
+  private static final int SET_SIZE = 1000;
+  private static final int JEDIS_TIMEOUT =
+      Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());
+  private static JedisCluster jedis;
+  public static RedisSet srcValueReference;
+  public static RedisSet destValueReference;
+
+  private static MemberVM locator;
+  private static MemberVM server1;
+  private static MemberVM server2;
+  private static MemberVM server3;

Review comment:
       This fields are never used and can be removed.

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/set/SmoveDunitTest.java
##########
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.set;
+
+import static 
org.apache.geode.redis.internal.services.RegionProvider.DEFAULT_REDIS_REGION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class SmoveDunitTest {
+
+  @ClassRule
+  public static RedisClusterStartupRule clusterStartUp = new 
RedisClusterStartupRule(4);
+
+  private static final String LOCAL_HOST = "127.0.0.1";
+  private static final int SET_SIZE = 1000;
+  private static final int JEDIS_TIMEOUT =
+      Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());

Review comment:
       Rather than defining new constants in this class for host and timeout, 
the `BIND_ADDRESS` and `REDIS_CLIENT_TIMEOUT` constants in 
RedisClusterStartupRule should be used.

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/set/SmoveDunitTest.java
##########
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.set;
+
+import static 
org.apache.geode.redis.internal.services.RegionProvider.DEFAULT_REDIS_REGION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class SmoveDunitTest {
+
+  @ClassRule
+  public static RedisClusterStartupRule clusterStartUp = new 
RedisClusterStartupRule(4);
+
+  private static final String LOCAL_HOST = "127.0.0.1";
+  private static final int SET_SIZE = 1000;
+  private static final int JEDIS_TIMEOUT =
+      Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());
+  private static JedisCluster jedis;
+  public static RedisSet srcValueReference;
+  public static RedisSet destValueReference;
+
+  private static MemberVM locator;

Review comment:
       This can be a local variable in `setUp()`

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/string/MSetDUnitTest.java
##########
@@ -114,6 +119,33 @@ public void 
testMSet_concurrentInstancesHandleBucketMovement() {
                     .allSatisfy(value -> 
assertThat(value).startsWith("valueTwo"))));
   }
 
+  @Test
+  public void testMSet_isTransactional() {

Review comment:
       It's not clear to me how this test is showing that MSET is 
transactional, since it doesn't test any transactional behaviour, specifically 
that failure part way through setting multiple keys results in rolling back the 
changes. The assertion that gets made on lines 143-144 shows that the value 
stored in the region is not the same object that was originally present, but 
that doesn't strictly speaking guarantee that the command is transactional.
   
   To show transactional behaviour, we need a test that attempts to set 
multiple keys using MSET, one of the keys should throw an exception causing an 
error to be returned to the jedis client, then confirm that we did not set any 
of the keys.

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/set/SmoveDunitTest.java
##########
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.set;
+
+import static 
org.apache.geode.redis.internal.services.RegionProvider.DEFAULT_REDIS_REGION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class SmoveDunitTest {

Review comment:
       For consistency, could this be "SMoveDUnitTest"?

##########
File path: 
geode-for-redis/src/distributedTest/java/org/apache/geode/redis/internal/commands/executor/set/SmoveDunitTest.java
##########
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.set;
+
+import static 
org.apache.geode.redis.internal.services.RegionProvider.DEFAULT_REDIS_REGION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class SmoveDunitTest {
+
+  @ClassRule
+  public static RedisClusterStartupRule clusterStartUp = new 
RedisClusterStartupRule(4);
+
+  private static final String LOCAL_HOST = "127.0.0.1";
+  private static final int SET_SIZE = 1000;
+  private static final int JEDIS_TIMEOUT =
+      Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());
+  private static JedisCluster jedis;
+  public static RedisSet srcValueReference;
+  public static RedisSet destValueReference;
+
+  private static MemberVM locator;
+  private static MemberVM server1;
+  private static MemberVM server2;
+  private static MemberVM server3;
+
+  @BeforeClass
+  public static void classSetup() {

Review comment:
       The class that was used as the template to create this one was not a 
good choice, unfortunately, as the tests added here are not actually testing 
any distributed behaviour. A better example class to base this one off would be 
one of the List command distributed tests, such as `RPopLPushDUnitTest`. 
Specifically, the tests we should have are for:
   
   - Performing an operation on the primary, crashing the primary and then 
verifying that the data on the secondary is correct
   - Performing operations while simultaneously moving buckets and verifying 
that no operations are lost or duplicated
   - Confirming that if the operation fails part way through, we don't apply 
half of it i.e. we don't ever remove something from the source set and then not 
add it to the destination set




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@geode.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to