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

ctubbsii pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/master by this push:
     new 7adc1f1  Fix #1463 Resolve relative delete markers on upgrade (#1558)
7adc1f1 is described below

commit 7adc1f1652607f7e8430b687e5f79b705803233a
Author: Mike Miller <mmil...@apache.org>
AuthorDate: Fri Mar 13 16:47:24 2020 -0400

    Fix #1463 Resolve relative delete markers on upgrade (#1558)
---
 .../apache/accumulo/server/fs/FileTypeTest.java    |  2 +
 .../accumulo/master/upgrade/Upgrader9to10.java     | 72 ++++++++++++++++------
 .../accumulo/master/upgrade/Upgrader9to10Test.java | 54 +++++++++++-----
 3 files changed, 91 insertions(+), 37 deletions(-)

diff --git 
a/server/base/src/test/java/org/apache/accumulo/server/fs/FileTypeTest.java 
b/server/base/src/test/java/org/apache/accumulo/server/fs/FileTypeTest.java
index ca52f84..a083d48 100644
--- a/server/base/src/test/java/org/apache/accumulo/server/fs/FileTypeTest.java
+++ b/server/base/src/test/java/org/apache/accumulo/server/fs/FileTypeTest.java
@@ -74,7 +74,9 @@ public class FileTypeTest {
 
     assertNull(FileType.WAL.getVolume(new Path("1.2.3.4/aaa-bbb-ccc-ddd")));
     assertNull(FileType.TABLE.getVolume(new Path("../2b/t-001/C00.rf")));
+    assertNull(FileType.TABLE.removeVolume(new Path("../2b/t-001/C00.rf")));
     assertNull(FileType.TABLE.getVolume(new Path("/t-001/C00.rf")));
+    assertNull(FileType.TABLE.removeVolume(new Path("/t-001/C00.rf")));
 
     assertEquals(new Path("hdfs://nn1/accumulo"),
         FileType.TABLE.getVolume(new 
Path("hdfs://nn1/accumulo/tables/2b/t-001/C00.rf")));
diff --git 
a/server/master/src/main/java/org/apache/accumulo/master/upgrade/Upgrader9to10.java
 
b/server/master/src/main/java/org/apache/accumulo/master/upgrade/Upgrader9to10.java
index 839bcbc..064f63b 100644
--- 
a/server/master/src/main/java/org/apache/accumulo/master/upgrade/Upgrader9to10.java
+++ 
b/server/master/src/main/java/org/apache/accumulo/master/upgrade/Upgrader9to10.java
@@ -33,6 +33,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.stream.StreamSupport;
 
 import org.apache.accumulo.core.Constants;
@@ -68,7 +69,6 @@ import org.apache.accumulo.fate.zookeeper.ZooReaderWriter;
 import org.apache.accumulo.fate.zookeeper.ZooUtil;
 import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
 import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeMissingPolicy;
-import org.apache.accumulo.server.ServerConstants;
 import org.apache.accumulo.server.ServerContext;
 import org.apache.accumulo.server.fs.VolumeManager;
 import org.apache.accumulo.server.gc.GcVolumeUtil;
@@ -405,6 +405,8 @@ public class Upgrader9to10 implements Upgrader {
     try (BatchWriter writer = c.createBatchWriter(tableName, new 
BatchWriterConfig())) {
       log.info("looking for candidates in table {}", tableName);
       Iterator<String> oldCandidates = getOldCandidates(ctx, tableName);
+      String upgradeProp = 
ctx.getConfiguration().get(Property.INSTANCE_VOLUMES_UPGRADE_RELATIVE);
+
       while (oldCandidates.hasNext()) {
         List<String> deletes = readCandidatesInBatch(oldCandidates);
         log.info("found {} deletes to upgrade", deletes.size());
@@ -412,7 +414,8 @@ public class Upgrader9to10 implements Upgrader {
           // create new formatted delete
           log.trace("upgrading delete entry for {}", olddelete);
 
-          String updatedDel = switchToAllVolumes(olddelete);
+          Path absolutePath = resolveRelativeDelete(olddelete, upgradeProp);
+          String updatedDel = switchToAllVolumes(absolutePath);
 
           writer.addMutation(ServerAmpleImpl.createDeleteMutation(updatedDel));
         }
@@ -430,26 +433,30 @@ public class Upgrader9to10 implements Upgrader {
     }
   }
 
+  /**
+   * If path of file to delete is a directory, change it to all volumes. See 
{@link GcVolumeUtil}.
+   * For example: A directory 
"hdfs://localhost:9000/accumulo/tables/5a/t-0005" with volume removed
+   * "tables/5a/t-0005" depth = 3 will be switched to 
"agcav:/tables/5a/t-0005". A file
+   * "hdfs://localhost:9000/accumulo/tables/5a/t-0005/A0012.rf" with volume 
removed
+   * "tables/5a/t-0005/A0012.rf" depth = 4 will be returned as is.
+   */
   @VisibleForTesting
-  static String switchToAllVolumes(String olddelete) {
-    Path relPath = VolumeManager.FileType.TABLE.removeVolume(new 
Path(olddelete));
-
-    if (relPath == null) {
-      // An old style relative delete marker of the form /<table id>/<tablet 
dir>[/<file>]
-      relPath = new Path("/" + VolumeManager.FileType.TABLE.getDirectory() + 
olddelete);
-      Preconditions.checkState(
-          olddelete.startsWith("/") && relPath.depth() == 3 || relPath.depth() 
== 4,
-          "Unrecongnized relative delete marker {}", olddelete);
-    }
-
-    if (relPath.depth() == 3 && 
!relPath.getName().startsWith(Constants.BULK_PREFIX)) {
-      return 
GcVolumeUtil.getDeleteTabletOnAllVolumesUri(TableId.of(relPath.getParent().getName()),
-          relPath.getName());
+  static String switchToAllVolumes(Path olddelete) {
+    Path pathNoVolume = 
Objects.requireNonNull(VolumeManager.FileType.TABLE.removeVolume(olddelete),
+        "Invalid delete marker. No volume in path: " + olddelete);
+
+    // a directory path with volume removed will have a depth of 3 so change 
volume to all volumes
+    if (pathNoVolume.depth() == 3 && 
!pathNoVolume.getName().startsWith(Constants.BULK_PREFIX)) {
+      return GcVolumeUtil.getDeleteTabletOnAllVolumesUri(
+          TableId.of(pathNoVolume.getParent().getName()), 
pathNoVolume.getName());
     } else {
-      return olddelete;
+      return olddelete.toString();
     }
   }
 
+  /**
+   * Return path of the file from old delete markers
+   */
   private Iterator<String> getOldCandidates(ServerContext ctx, String 
tableName)
       throws TableNotFoundException {
     Range range = MetadataSchema.DeletesSection.getRange();
@@ -548,7 +555,6 @@ public class Upgrader9to10 implements Upgrader {
           }
           Path relPath = resolveRelativePath(metaEntry, key);
           Path absPath = new Path(upgradeProperty, relPath);
-          // Path absPath = new 
Path(Paths.get(upgradeProperty).normalize().toString(), relPath);
           if (fs.exists(absPath)) {
             log.debug("Changing Tablet File path from {} to {}", metaEntry, 
absPath);
             Mutation m = new Mutation(key.getRow());
@@ -595,7 +601,6 @@ public class Upgrader9to10 implements Upgrader {
           }
           Path relPath = resolveRelativePath(metaEntry, key);
           Path absPath = new Path(upgradeProperty, relPath);
-          // Path absPath = new 
Path(Paths.get(upgradeProperty).normalize().toString(), relPath);
           if (!fs.exists(absPath)) {
             throw new IllegalArgumentException("Tablet file " + relPath + " 
not found at " + absPath
                 + " using volume: " + upgradeProperty);
@@ -615,7 +620,7 @@ public class Upgrader9to10 implements Upgrader {
    * Resolve old-style relative paths, returning Path of everything except 
volume and base
    */
   private static Path resolveRelativePath(String metadataEntry, Key key) {
-    String prefix = ServerConstants.TABLE_DIR + "/";
+    String prefix = VolumeManager.FileType.TABLE.getDirectory() + "/";
     if (metadataEntry.startsWith("../")) {
       // resolve style "../2a/t-0003/C0004.rf"
       return new Path(prefix + metadataEntry.substring(3));
@@ -625,4 +630,31 @@ public class Upgrader9to10 implements Upgrader {
       return new Path(prefix + tableId.canonical() + metadataEntry);
     }
   }
+
+  /**
+   * Resolve old relative delete markers of the form /tableId/tabletDir/[file] 
to
+   * UpgradeVolume/tables/tableId/tabletDir/[file]
+   */
+  static Path resolveRelativeDelete(String oldDelete, String upgradeProperty) {
+    Path pathNoVolume = VolumeManager.FileType.TABLE.removeVolume(new 
Path(oldDelete));
+    Path pathToCheck = new Path(oldDelete);
+
+    // if the volume was removed properly, the path is absolute so return, 
otherwise
+    // it is a relative path so proceed with more checks
+    if (pathNoVolume != null)
+      return pathToCheck;
+
+    // A relative path directory of the form "/tableId/tabletDir" will have 
depth == 2
+    // A relative path file of the form "/tableId/tabletDir/file" will have 
depth == 3
+    Preconditions.checkState(
+        oldDelete.startsWith("/") && (pathToCheck.depth() == 2 || 
pathToCheck.depth() == 3),
+        "Unrecognized relative delete marker {}", oldDelete);
+
+    // found relative paths so verify the property used to build the absolute 
paths
+    if (upgradeProperty == null || upgradeProperty.isBlank()) {
+      throw new IllegalArgumentException(
+          "Missing required property " + 
Property.INSTANCE_VOLUMES_UPGRADE_RELATIVE.getKey());
+    }
+    return new Path(upgradeProperty, 
VolumeManager.FileType.TABLE.getDirectory() + oldDelete);
+  }
 }
diff --git 
a/server/master/src/test/java/org/apache/accumulo/master/upgrade/Upgrader9to10Test.java
 
b/server/master/src/test/java/org/apache/accumulo/master/upgrade/Upgrader9to10Test.java
index 9b78dad..2f65f91 100644
--- 
a/server/master/src/test/java/org/apache/accumulo/master/upgrade/Upgrader9to10Test.java
+++ 
b/server/master/src/test/java/org/apache/accumulo/master/upgrade/Upgrader9to10Test.java
@@ -25,6 +25,7 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -57,33 +58,52 @@ import org.slf4j.LoggerFactory;
 public class Upgrader9to10Test {
   private static Logger log = LoggerFactory.getLogger(Upgrader9to10Test.class);
 
+  private static final String VOL_PROP = "hdfs://nn1:8020/accumulo";
+
   @Test
-  public void testSwitchRelative() {
+  public void testSwitchRelativeDeletes() {
+    Path resolved = Upgrader9to10.resolveRelativeDelete("/5a/t-0005", 
VOL_PROP);
+    assertEquals(new Path(VOL_PROP + "/tables/5a/t-0005"), resolved);
     assertEquals(GcVolumeUtil.getDeleteTabletOnAllVolumesUri(TableId.of("5a"), 
"t-0005"),
-        Upgrader9to10.switchToAllVolumes("/5a/t-0005"));
-    assertEquals("/5a/" + BULK_PREFIX + "0005",
-        Upgrader9to10.switchToAllVolumes("/5a/" + BULK_PREFIX + "0005"));
-    assertEquals("/5a/t-0005/F0009.rf", 
Upgrader9to10.switchToAllVolumes("/5a/t-0005/F0009.rf"));
+        Upgrader9to10.switchToAllVolumes(resolved));
+
+    resolved = Upgrader9to10.resolveRelativeDelete("/5a/" + BULK_PREFIX + 
"0005", VOL_PROP);
+    assertEquals(new Path(VOL_PROP + "/tables/5a/" + BULK_PREFIX + "0005"), 
resolved);
+    assertEquals(VOL_PROP + "/tables/5a/" + BULK_PREFIX + "0005",
+        Upgrader9to10.switchToAllVolumes(resolved));
+
+    resolved = Upgrader9to10.resolveRelativeDelete("/5a/t-0005/F0009.rf", 
VOL_PROP);
+    assertEquals(new Path(VOL_PROP + "/tables/5a/t-0005/F0009.rf"), resolved);
+    assertEquals(VOL_PROP + "/tables/5a/t-0005/F0009.rf",
+        Upgrader9to10.switchToAllVolumes(resolved));
   }
 
   @Test(expected = IllegalStateException.class)
-  public void testBadRelativeTooShort() {
-    Upgrader9to10.switchToAllVolumes("/5a");
+  public void testBadRelativeDeleteTooShort() {
+    Upgrader9to10.resolveRelativeDelete("/5a", VOL_PROP);
   }
 
   @Test(expected = IllegalStateException.class)
-  public void testBadRelativeTooLong() {
-    Upgrader9to10.switchToAllVolumes("/5a/5a/t-0005/F0009.rf");
+  public void testBadRelativeDeleteTooLong() throws Exception {
+    Upgrader9to10.resolveRelativeDelete("/5a/5a/t-0005/F0009.rf", VOL_PROP);
   }
 
   @Test
-  public void testSwitch() {
+  public void testSwitchAllVolumes() {
+    Path resolved = Upgrader9to10
+        
.resolveRelativeDelete("hdfs://localhost:9000/accumulo/tables/5a/t-0005", 
VOL_PROP);
     assertEquals(GcVolumeUtil.getDeleteTabletOnAllVolumesUri(TableId.of("5a"), 
"t-0005"),
-        
Upgrader9to10.switchToAllVolumes("hdfs://localhost:9000/accumulo/tables/5a/t-0005"));
-    assertEquals("hdfs://localhost:9000/accumulo/tables/5a/" + BULK_PREFIX + 
"0005", Upgrader9to10
-        .switchToAllVolumes("hdfs://localhost:9000/accumulo/tables/5a/" + 
BULK_PREFIX + "0005"));
-    assertEquals("hdfs://localhost:9000/accumulo/tables/5a/t-0005/C0009.rf", 
Upgrader9to10
-        
.switchToAllVolumes("hdfs://localhost:9000/accumulo/tables/5a/t-0005/C0009.rf"));
+        Upgrader9to10.switchToAllVolumes(resolved));
+
+    resolved = Upgrader9to10.resolveRelativeDelete(
+        "hdfs://localhost:9000/accumulo/tables/5a/" + BULK_PREFIX + "0005", 
VOL_PROP);
+    assertEquals("hdfs://localhost:9000/accumulo/tables/5a/" + BULK_PREFIX + 
"0005",
+        Upgrader9to10.switchToAllVolumes(resolved));
+
+    resolved = Upgrader9to10.resolveRelativeDelete(
+        "hdfs://localhost:9000/accumulo/tables/5a/t-0005/C0009.rf", VOL_PROP);
+    assertEquals("hdfs://localhost:9000/accumulo/tables/5a/t-0005/C0009.rf",
+        Upgrader9to10.switchToAllVolumes(resolved));
   }
 
   @Test
@@ -159,8 +179,8 @@ public class Upgrader9to10Test {
     List<Mutation> results = new ArrayList<>();
 
     setupMocks(c, fs, map, results);
-    assertEquals("Invalid Relative path check",
-        Upgrader9to10.checkForRelativePaths(c, fs, tableName, volumeUpgrade), 
false);
+    assertFalse("Invalid Relative path check",
+        Upgrader9to10.checkForRelativePaths(c, fs, tableName, volumeUpgrade));
     assertTrue(results.isEmpty());
   }
 

Reply via email to