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

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


The following commit(s) were added to refs/heads/main by this push:
     new 8fe933a671 Add a constraint check for suspend column (#4546)
8fe933a671 is described below

commit 8fe933a6710066bb88c63401d12e9ff0d88cdf0f
Author: Christopher L. Shannon <cshan...@apache.org>
AuthorDate: Fri May 17 16:40:22 2024 -0400

    Add a constraint check for suspend column (#4546)
    
    This adds a new metadata constraint check for the suspend metadata
    column to ensure that the suspension time is not negative as we should
    never have a negative value.
    
    This is a follow on to #4494
---
 .../server/constraints/MetadataConstraints.java    | 66 +++++++++++++---------
 .../constraints/MetadataConstraintsTest.java       | 33 +++++++++++
 2 files changed, 72 insertions(+), 27 deletions(-)

diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java
 
b/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java
index 0f4a361312..1b99a5b307 100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java
@@ -36,6 +36,7 @@ import org.apache.accumulo.core.fate.zookeeper.ZooUtil;
 import org.apache.accumulo.core.lock.ServiceLock;
 import org.apache.accumulo.core.metadata.AccumuloTable;
 import org.apache.accumulo.core.metadata.StoredTabletFile;
+import org.apache.accumulo.core.metadata.SuspendingTServer;
 import org.apache.accumulo.core.metadata.schema.DataFileValue;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.BulkFileColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ChoppedColumnFamily;
@@ -306,40 +307,49 @@ public class MetadataConstraints implements Constraint {
       } else {
         if (!isValidColumn(columnUpdate)) {
           violations = addViolation(violations, 2);
-        } else if (new 
ColumnFQ(columnUpdate).equals(TabletColumnFamily.PREV_ROW_COLUMN)
-            && columnUpdate.getValue().length > 0
-            && (violations == null || !violations.contains((short) 4))) {
-          KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow()));
+        } else {
+          final var column = new ColumnFQ(columnUpdate);
+          if (column.equals(TabletColumnFamily.PREV_ROW_COLUMN)
+              && columnUpdate.getValue().length > 0
+              && (violations == null || !violations.contains((short) 4))) {
+            KeyExtent ke = KeyExtent.fromMetaRow(new Text(mutation.getRow()));
 
-          Text per = TabletColumnFamily.decodePrevEndRow(new 
Value(columnUpdate.getValue()));
+            Text per = TabletColumnFamily.decodePrevEndRow(new 
Value(columnUpdate.getValue()));
 
-          boolean prevEndRowLessThanEndRow =
-              per == null || ke.endRow() == null || per.compareTo(ke.endRow()) 
< 0;
+            boolean prevEndRowLessThanEndRow =
+                per == null || ke.endRow() == null || 
per.compareTo(ke.endRow()) < 0;
 
-          if (!prevEndRowLessThanEndRow) {
-            violations = addViolation(violations, 3);
-          }
-        } else if (new 
ColumnFQ(columnUpdate).equals(ServerColumnFamily.LOCK_COLUMN)) {
-          if (zooCache == null) {
-            zooCache = new ZooCache(context.getZooReader(), null);
-            CleanerUtil.zooCacheClearer(this, zooCache);
-          }
+            if (!prevEndRowLessThanEndRow) {
+              violations = addViolation(violations, 3);
+            }
+          } else if (column.equals(ServerColumnFamily.LOCK_COLUMN)) {
+            if (zooCache == null) {
+              zooCache = new ZooCache(context.getZooReader(), null);
+              CleanerUtil.zooCacheClearer(this, zooCache);
+            }
 
-          if (zooRoot == null) {
-            zooRoot = context.getZooKeeperRoot();
-          }
+            if (zooRoot == null) {
+              zooRoot = context.getZooKeeperRoot();
+            }
 
-          boolean lockHeld = false;
-          String lockId = new String(columnUpdate.getValue(), UTF_8);
+            boolean lockHeld = false;
+            String lockId = new String(columnUpdate.getValue(), UTF_8);
 
-          try {
-            lockHeld = ServiceLock.isLockHeld(zooCache, new 
ZooUtil.LockID(zooRoot, lockId));
-          } catch (Exception e) {
-            log.debug("Failed to verify lock was held {} {}", lockId, 
e.getMessage());
-          }
+            try {
+              lockHeld = ServiceLock.isLockHeld(zooCache, new 
ZooUtil.LockID(zooRoot, lockId));
+            } catch (Exception e) {
+              log.debug("Failed to verify lock was held {} {}", lockId, 
e.getMessage());
+            }
 
-          if (!lockHeld) {
-            violations = addViolation(violations, 7);
+            if (!lockHeld) {
+              violations = addViolation(violations, 7);
+            }
+          } else if (column.equals(SuspendLocationColumn.SUSPEND_COLUMN)) {
+            try {
+              SuspendingTServer.fromValue(new Value(columnUpdate.getValue()));
+            } catch (IllegalArgumentException e) {
+              violations = addViolation(violations, 10);
+            }
           }
         }
       }
@@ -379,6 +389,8 @@ public class MetadataConstraints implements Constraint {
         return "Bulk load mutation contains either inconsistent files or 
multiple fateTX ids";
       case 9:
         return "Invalid data file metadata format";
+      case 10:
+        return "Suspended timestamp is not valid";
     }
     return null;
   }
diff --git 
a/server/base/src/test/java/org/apache/accumulo/server/constraints/MetadataConstraintsTest.java
 
b/server/base/src/test/java/org/apache/accumulo/server/constraints/MetadataConstraintsTest.java
index b209a01f76..b7e2bd2a11 100644
--- 
a/server/base/src/test/java/org/apache/accumulo/server/constraints/MetadataConstraintsTest.java
+++ 
b/server/base/src/test/java/org/apache/accumulo/server/constraints/MetadataConstraintsTest.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import java.lang.reflect.Method;
 import java.util.Base64;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -32,19 +33,25 @@ import org.apache.accumulo.core.data.Range;
 import org.apache.accumulo.core.data.Value;
 import org.apache.accumulo.core.metadata.AccumuloTable;
 import org.apache.accumulo.core.metadata.StoredTabletFile;
+import org.apache.accumulo.core.metadata.SuspendingTServer;
+import org.apache.accumulo.core.metadata.TServerInstance;
 import org.apache.accumulo.core.metadata.schema.DataFileValue;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.BulkFileColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.CurrentLocationColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ScanFileColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily;
+import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.SuspendLocationColumn;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.TabletColumnFamily;
+import org.apache.accumulo.core.util.time.SteadyTime;
 import org.apache.accumulo.server.ServerContext;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.Text;
 import org.easymock.EasyMock;
 import org.junit.jupiter.api.Test;
 
+import com.google.common.net.HostAndPort;
+
 public class MetadataConstraintsTest {
 
   private SystemEnvironment createEnv() {
@@ -130,6 +137,32 @@ public class MetadataConstraintsTest {
 
   }
 
+  @Test
+  public void testSuspensionCheck() {
+    Mutation m = new Mutation(new Text("0;foo"));
+    MetadataConstraints mc = new MetadataConstraints();
+    TServerInstance ser1 = new 
TServerInstance(HostAndPort.fromParts("server1", 8555), "s001");
+
+    SuspendLocationColumn.SUSPEND_COLUMN.put(m, SuspendingTServer.toValue(ser1,
+        SteadyTime.from(System.currentTimeMillis(), TimeUnit.MILLISECONDS)));
+    List<Short> violations = mc.check(createEnv(), m);
+    assertNull(violations);
+
+    m = new Mutation(new Text("0;foo"));
+    SuspendLocationColumn.SUSPEND_COLUMN.put(m,
+        SuspendingTServer.toValue(ser1, SteadyTime.from(0, 
TimeUnit.MILLISECONDS)));
+    violations = mc.check(createEnv(), m);
+    assertNull(violations);
+
+    m = new Mutation(new Text("0;foo"));
+    // We must encode manually since SteadyTime won't allow a negative
+    SuspendLocationColumn.SUSPEND_COLUMN.put(m, new Value(ser1.getHostPort() + 
"|" + -1L));
+    violations = mc.check(createEnv(), m);
+    assertNotNull(violations);
+    assertEquals(1, violations.size());
+    assertEquals(Short.valueOf((short) 10), violations.get(0));
+  }
+
   @Test
   public void testBulkFileCheck() {
     MetadataConstraints mc = new MetadataConstraints();

Reply via email to