This is an automated email from the ASF dual-hosted git repository.

siyao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hadoop-ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new ac5fb0f  HDDS-3374. OMVolumeSetOwnerRequest doesn't check if user is 
already the owner (#806)
ac5fb0f is described below

commit ac5fb0f46f41e19e68d70673157e7fe439f1c9af
Author: Siyao Meng <[email protected]>
AuthorDate: Tue Apr 14 10:54:02 2020 -0700

    HDDS-3374. OMVolumeSetOwnerRequest doesn't check if user is already the 
owner (#806)
---
 .../ozone/om/request/volume/OMVolumeRequest.java   | 21 ++++++----
 .../om/request/volume/OMVolumeSetOwnerRequest.java | 17 +++++---
 .../response/volume/OMVolumeSetOwnerResponse.java  | 21 +++++++++-
 .../volume/TestOMVolumeSetOwnerRequest.java        | 49 ++++++++++++++++++++++
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeRequest.java
index bbd0480..4c481a1 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeRequest.java
@@ -29,16 +29,23 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
     .UserVolumeInfo;
 import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
 import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Defines common methods required for volume requests.
  */
 public abstract class OMVolumeRequest extends OMClientRequest {
 
+  private static final Logger LOG =
+      LoggerFactory.getLogger(OMVolumeRequest.class);
+
   public OMVolumeRequest(OMRequest omRequest) {
     super(omRequest);
   }
@@ -99,22 +106,18 @@ public abstract class OMVolumeRequest extends 
OMClientRequest {
           OMException.ResultCodes.USER_TOO_MANY_VOLUMES);
     }
 
-    List<String> prevVolList = new ArrayList<>();
+    Set<String> volumeSet = new HashSet<>();
     long objectID = txID;
     if (volumeList != null) {
-      prevVolList.addAll(volumeList.getVolumeNamesList());
+      volumeSet.addAll(volumeList.getVolumeNamesList());
       objectID = volumeList.getObjectID();
     }
 
-
-    // Add the new volume to the list
-    prevVolList.add(volume);
-    UserVolumeInfo newVolList = UserVolumeInfo.newBuilder()
+    volumeSet.add(volume);
+    return UserVolumeInfo.newBuilder()
         .setObjectID(objectID)
         .setUpdateID(txID)
-        .addAllVolumeNames(prevVolList).build();
-
-    return newVolList;
+        .addAllVolumeNames(volumeSet).build();
   }
 
   /**
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetOwnerRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetOwnerRequest.java
index 6b603e5..fd0898d 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetOwnerRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/OMVolumeSetOwnerRequest.java
@@ -71,7 +71,6 @@ public class OMVolumeSetOwnerRequest extends OMVolumeRequest {
 
     SetVolumePropertyRequest setVolumePropertyRequest =
         getOmRequest().getSetVolumePropertyRequest();
-
     Preconditions.checkNotNull(setVolumePropertyRequest);
 
     OMResponse.Builder omResponse = OMResponse.newBuilder().setCmdType(
@@ -112,7 +111,6 @@ public class OMVolumeSetOwnerRequest extends 
OMVolumeRequest {
       }
 
       long maxUserVolumeCount = ozoneManager.getMaxUserVolumeCount();
-
       String dbVolumeKey = omMetadataManager.getVolumeKey(volume);
 
       OzoneManagerProtocolProtos.UserVolumeInfo oldOwnerVolumeList = null;
@@ -121,7 +119,6 @@ public class OMVolumeSetOwnerRequest extends 
OMVolumeRequest {
 
       acquiredVolumeLock = omMetadataManager.getLock().acquireWriteLock(
           VOLUME_LOCK, volume);
-
       omVolumeArgs = omMetadataManager.getVolumeTable().get(dbVolumeKey);
 
       if (omVolumeArgs == null) {
@@ -143,6 +140,16 @@ public class OMVolumeSetOwnerRequest extends 
OMVolumeRequest {
 
       oldOwner = omVolumeArgs.getOwnerName();
 
+      // Return OK immediately if newOwner is the same as oldOwner.
+      if (oldOwner.equals(newOwner)) {
+        LOG.warn("Volume '{}' owner is already user '{}'.", volume, oldOwner);
+        omResponse.setStatus(OzoneManagerProtocolProtos.Status.OK)
+          .setMessage(
+            "Volume '" + volume + "' owner is already '" + newOwner + "'.")
+          .setSuccess(false);
+        return new OMVolumeSetOwnerResponse(omResponse.build());
+      }
+
       acquiredUserLocks =
           omMetadataManager.getLock().acquireMultiUserLock(newOwner, oldOwner);
 
@@ -165,8 +172,8 @@ public class OMVolumeSetOwnerRequest extends 
OMVolumeRequest {
       // Update cache.
       omMetadataManager.getUserTable().addCacheEntry(
           new CacheKey<>(omMetadataManager.getUserKey(newOwner)),
-              new CacheValue<>(Optional.of(newOwnerVolumeList),
-                  transactionLogIndex));
+          new CacheValue<>(Optional.of(newOwnerVolumeList),
+              transactionLogIndex));
       omMetadataManager.getUserTable().addCacheEntry(
           new CacheKey<>(omMetadataManager.getUserKey(oldOwner)),
           new CacheValue<>(Optional.of(oldOwnerVolumeList),
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeSetOwnerResponse.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeSetOwnerResponse.java
index 8cd1f05..469f1ae 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeSetOwnerResponse.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeSetOwnerResponse.java
@@ -24,6 +24,7 @@ import org.apache.hadoop.ozone.om.OMMetadataManager;
 import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
 import org.apache.hadoop.ozone.om.response.OMClientResponse;
 
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
     .UserVolumeInfo;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
@@ -55,11 +56,27 @@ public class OMVolumeSetOwnerResponse extends 
OMClientResponse {
 
   /**
    * For when the request is not successful or it is a replay transaction.
-   * For a successful request, the other constructor should be used.
+   * Or when newOwner is the same as oldOwner.
+   * For other successful requests, the other constructor should be used.
    */
   public OMVolumeSetOwnerResponse(@Nonnull OMResponse omResponse) {
     super(omResponse);
-    checkStatusNotOK();
+    // When newOwner is the same as oldOwner, status is OK but success is 
false.
+    // We want to bypass the check in this case.
+    if (omResponse.getSuccess()) {
+      checkStatusNotOK();
+    }
+  }
+
+  @Override
+  public void checkAndUpdateDB(OMMetadataManager omMetadataManager,
+      BatchOperation batchOperation) throws IOException {
+    // When newOwner is the same as oldOwner, status is OK but success is 
false.
+    // We don't want to add it to DB batch in this case.
+    if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK &&
+        getOMResponse().getSuccess()) {
+      addToDBBatch(omMetadataManager, batchOperation);
+    }
   }
 
   @Override
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
index 3c69a3b..c71c1a8 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeSetOwnerRequest.java
@@ -18,6 +18,9 @@
 
 package org.apache.hadoop.ozone.om.request.volume;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 
 import org.junit.Assert;
@@ -189,4 +192,50 @@ public class TestOMVolumeSetOwnerRequest extends 
TestOMVolumeRequest {
     Assert.assertEquals(OzoneManagerProtocolProtos.Status.REPLAY,
         omClientResponse.getOMResponse().getStatus());
   }
+
+
+  @Test
+  public void testOwnSameVolumeTwice() throws Exception {
+    String volumeName = UUID.randomUUID().toString();
+    String owner = "user1";
+    TestOMRequestUtils.addVolumeToDB(volumeName, owner, omMetadataManager);
+    TestOMRequestUtils.addUserToDB(volumeName, owner, omMetadataManager);
+    String newOwner = "user2";
+
+    // Create request to set new owner
+    OMRequest omRequest =
+        TestOMRequestUtils.createSetVolumePropertyRequest(volumeName, 
newOwner);
+
+    OMVolumeSetOwnerRequest setOwnerRequest =
+        new OMVolumeSetOwnerRequest(omRequest);
+    // Execute the request
+    setOwnerRequest.preExecute(ozoneManager);
+    OMClientResponse omClientResponse = setOwnerRequest.validateAndUpdateCache(
+        ozoneManager, 1, ozoneManagerDoubleBufferHelper);
+    // Response status should be OK and success flag should be true.
+    Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK,
+        omClientResponse.getOMResponse().getStatus());
+    Assert.assertTrue(omClientResponse.getOMResponse().getSuccess());
+
+    // Execute the same request again but with higher index
+    setOwnerRequest.preExecute(ozoneManager);
+    omClientResponse = setOwnerRequest.validateAndUpdateCache(
+        ozoneManager, 2, ozoneManagerDoubleBufferHelper);
+    // Response status should be OK, but success flag should be false.
+    Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK,
+        omClientResponse.getOMResponse().getStatus());
+    Assert.assertFalse(omClientResponse.getOMResponse().getSuccess());
+
+    // Check volume names list
+    OzoneManagerProtocolProtos.UserVolumeInfo userVolumeInfo =
+        omMetadataManager.getUserTable().get(newOwner);
+    Assert.assertNotNull(userVolumeInfo);
+    List<String> volumeNamesList = userVolumeInfo.getVolumeNamesList();
+    Assert.assertEquals(1, volumeNamesList.size());
+
+    Set<String> volumeNamesSet = new HashSet<>(volumeNamesList);
+    // If the set size isn't equal to list size, there are duplicates
+    // in the list (which was the bug before the fix).
+    Assert.assertEquals(volumeNamesList.size(), volumeNamesSet.size());
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to