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

dlmarion 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 3a0d8e5c72 Added compaction service configuration validation to 
upgrade --start (#5807)
3a0d8e5c72 is described below

commit 3a0d8e5c72915fb4c7ce26d6156d15b0a444fb71
Author: Dave Marion <[email protected]>
AuthorDate: Thu Aug 21 09:11:56 2025 -0400

    Added compaction service configuration validation to upgrade --start (#5807)
    
    Added compaction service configuration validation to UpgradeUtil.
    When `accumulo upgrade --start` is run it will fail if any of the
    configured compaction services do not exist for tables other than
    the root and metadata table. For the root and metadata table, it will
    log a warning that, if not fixed, the compaction service configurations
    will be removed from the root and metadata tables on the upgrade so
    that they can use the default compaction service configuration.
    Modified the Upgrader to implement this change.
    
    Closes #5805
---
 .../compaction/RatioBasedCompactionPlanner.java    |   8 +-
 .../apache/accumulo/server/util/UpgradeUtil.java   | 115 +++++++++++++++++++++
 .../accumulo/manager/upgrade/Upgrader12to13.java   |  40 ++++++-
 3 files changed, 158 insertions(+), 5 deletions(-)

diff --git 
a/core/src/main/java/org/apache/accumulo/core/spi/compaction/RatioBasedCompactionPlanner.java
 
b/core/src/main/java/org/apache/accumulo/core/spi/compaction/RatioBasedCompactionPlanner.java
index fb44d038e6..11fcfb9a8d 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/spi/compaction/RatioBasedCompactionPlanner.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/spi/compaction/RatioBasedCompactionPlanner.java
@@ -64,10 +64,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  * <ul>
  * <li>Note that the CompactionCoordinator and at least one running Compactor 
must be assigned to
  * the "large" compactor group.
- * <li>{@code compaction.service.<service>.opts.maxOpen} This determines the 
maximum number of files
- * that will be included in a single compaction.
- * <li>{@code compaction.service.<service>.opts.groups} This is a json array 
of compactor group
- * objects which have the following fields:
+ * <li>{@code compaction.service.<service>.planner.opts.maxOpen} This 
determines the maximum number
+ * of files that will be included in a single compaction.
+ * <li>{@code compaction.service.<service>.planner.opts.groups} This is a json 
array of compactor
+ * group objects which have the following fields:
  * <table>
  * <caption>Default Compaction Planner Group options</caption>
  * <tr>
diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/util/UpgradeUtil.java 
b/server/base/src/main/java/org/apache/accumulo/server/util/UpgradeUtil.java
index 86abc4a42c..352de5de26 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/util/UpgradeUtil.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/util/UpgradeUtil.java
@@ -18,23 +18,39 @@
  */
 package org.apache.accumulo.server.util;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.accumulo.core.Constants.ZFATE;
 import static org.apache.accumulo.core.Constants.ZPREPARE_FOR_UPGRADE;
+import static org.apache.accumulo.core.Constants.ZTABLES;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.cli.ConfigOpts;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.conf.SiteConfiguration;
+import org.apache.accumulo.core.data.NamespaceId;
+import org.apache.accumulo.core.data.TableId;
 import org.apache.accumulo.core.fate.zookeeper.ZooReader;
 import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
 import org.apache.accumulo.core.fate.zookeeper.ZooUtil;
 import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
 import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.core.metadata.SystemTables;
+import org.apache.accumulo.core.spi.common.ServiceEnvironment;
+import org.apache.accumulo.core.spi.compaction.CompactionDispatcher;
+import org.apache.accumulo.core.spi.compaction.CompactionKind;
+import org.apache.accumulo.core.spi.compaction.CompactionServiceId;
+import org.apache.accumulo.core.spi.compaction.CompactionServices;
+import org.apache.accumulo.core.util.compaction.CompactionServicesConfig;
 import org.apache.accumulo.core.zookeeper.ZooSession;
 import org.apache.accumulo.server.AccumuloDataVersion;
 import org.apache.accumulo.server.ServerContext;
+import org.apache.accumulo.server.conf.NamespaceConfiguration;
+import org.apache.accumulo.server.conf.TableConfiguration;
 import org.apache.accumulo.server.security.SecurityUtil;
 import org.apache.accumulo.server.util.upgrade.PreUpgradeValidation;
 import org.apache.accumulo.server.util.upgrade.UpgradeProgress;
@@ -53,6 +69,7 @@ import com.google.auto.service.AutoService;
 public class UpgradeUtil implements KeywordExecutable {
 
   private static final Logger LOG = LoggerFactory.getLogger(UpgradeUtil.class);
+  private static final String ZTABLE_NAME = "/name";
 
   static class Opts extends ConfigOpts {
     @Parameter(names = "--prepare",
@@ -250,6 +267,14 @@ public class UpgradeUtil implements KeywordExecutable {
       }
     }
 
+    try {
+      validateCompactionServiceConfiguration(context);
+      LOG.info("Validated compaction service configuration");
+    } catch (KeeperException | InterruptedException e) {
+      LOG.error("Error validating compaction service configuration", e);
+      throw new IllegalStateException("Error validating compaction service 
configuration", e);
+    }
+
     // Run the PreUpgradeValidation code to validate the ZooKeeper ACLs
     try {
       new PreUpgradeValidation().validate(context);
@@ -304,4 +329,94 @@ public class UpgradeUtil implements KeywordExecutable {
 
   }
 
+  private void validateCompactionServiceConfiguration(ServerContext ctx)
+      throws KeeperException, InterruptedException {
+
+    boolean configurationError = false;
+
+    final CompactionServicesConfig servicesConfig =
+        new CompactionServicesConfig(ctx.getConfiguration());
+    final Set<CompactionServiceId> definedServiceIds = 
servicesConfig.getPlanners().keySet()
+        
.stream().map(CompactionServiceId::of).collect(Collectors.toUnmodifiableSet());
+
+    LOG.info("Defined compaction service ids: {}", definedServiceIds);
+
+    final ZooReader zr = ctx.getZooSession().asReader();
+    List<String> zooTableIds = zr.getChildren(ZTABLES);
+
+    for (String tableId : zooTableIds) {
+
+      final String tableName =
+          new String(zr.getData(Constants.ZTABLES + "/" + tableId + 
ZTABLE_NAME), UTF_8);
+      final String namespaceId = new String(
+          zr.getData(Constants.ZTABLES + "/" + tableId + 
Constants.ZTABLE_NAMESPACE), UTF_8);
+
+      final NamespaceId nsid = NamespaceId.of(namespaceId);
+      final TableId tid = TableId.of(tableId);
+
+      final NamespaceConfiguration nsConf =
+          new NamespaceConfiguration(ctx, nsid, ctx.getConfiguration());
+      final TableConfiguration tconf = new TableConfiguration(ctx, tid, 
nsConf);
+
+      final CompactionDispatcher dispatcher = tconf.getCompactionDispatcher();
+
+      for (CompactionKind kind : CompactionKind.values()) {
+        final CompactionDispatcher.DispatchParameters dispatchParams =
+            new CompactionDispatcher.DispatchParameters() {
+              @Override
+              public CompactionServices getCompactionServices() {
+                return () -> definedServiceIds;
+              }
+
+              @Override
+              public ServiceEnvironment getServiceEnv() {
+                return (ServiceEnvironment) ctx;
+              }
+
+              @Override
+              public CompactionKind getCompactionKind() {
+                return kind;
+              }
+
+              @Override
+              public Map<String,String> getExecutionHints() {
+                return Map.of();
+              }
+            };
+        final CompactionServiceId expectedCompactionService =
+            dispatcher.dispatch(dispatchParams).getService();
+        LOG.info("Table {} is configured to use service \"{}\" for compaction 
kind {}", tableName,
+            expectedCompactionService, kind);
+        if 
(!servicesConfig.getPlanners().containsKey(expectedCompactionService.canonical()))
 {
+          if ((tid.equals(SystemTables.ROOT.tableId())
+              && expectedCompactionService.canonical().equals("root"))
+              || (tid.equals(SystemTables.METADATA.tableId())
+                  && expectedCompactionService.canonical().equals("meta"))) {
+            LOG.warn(
+                "Table {} is using a default compaction service configuration 
from a prior version."
+                    + " The \"{}\" compaction service configuration is no 
longer defined. You can either define"
+                    + " it now in the accumulo.properties file, or the 
compaction service configuration will"
+                    + " be removed to adopt the new default in this version 
during the upgrade.",
+                tableName, expectedCompactionService);
+          } else {
+            LOG.error(
+                "Table {} returned non-existent compaction service \"{}\"  for 
compaction type {}.",
+                tid, expectedCompactionService, kind);
+            configurationError = true;
+          }
+        }
+      }
+    }
+    if (configurationError) {
+      LOG.error("Compaction configuration is incorrect. One or more tables is 
configured to use a"
+          + " compaction service that does not exist in the configuration. 
Configured compaction"
+          + " services are: {}", definedServiceIds);
+      throw new IllegalStateException(
+          "Compaction configuration is not correct. Continuing with upgrade"
+              + " will leave the instance in a state where compactions will 
not start for some tables. Please fix the system"
+              + " configuration by defining the expected compaction services 
in accumulo.properties and run"
+              + " --start again.");
+    }
+  }
+
 }
diff --git 
a/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/Upgrader12to13.java
 
b/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/Upgrader12to13.java
index 8bdd200f3e..ddb076e120 100644
--- 
a/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/Upgrader12to13.java
+++ 
b/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/Upgrader12to13.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.BatchWriter;
@@ -57,7 +58,9 @@ import 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType;
 import org.apache.accumulo.core.metadata.schema.TabletsMetadata;
 import org.apache.accumulo.core.schema.Section;
 import org.apache.accumulo.core.security.Authorizations;
+import org.apache.accumulo.core.util.compaction.CompactionServicesConfig;
 import org.apache.accumulo.server.ServerContext;
+import org.apache.accumulo.server.conf.codec.VersionedProperties;
 import org.apache.accumulo.server.conf.store.TablePropKey;
 import org.apache.accumulo.server.init.FileSystemInitializer;
 import org.apache.accumulo.server.init.InitialConfiguration;
@@ -82,7 +85,9 @@ public class Upgrader12to13 implements Upgrader {
   public void upgradeZookeeper(ServerContext context) {
     LOG.info("Ensuring all worker server processes are down.");
     validateEmptyZKWorkerServerPaths(context);
-    LOG.info("setting root table stored hosting availability");
+    LOG.info("Validating root and metadata compaction services");
+    validateCompactionServiceConfiguration(context);
+    LOG.info("Setting root table stored hosting availability");
     addHostingGoals(context, TabletAvailability.HOSTED, DataLevel.ROOT);
     LOG.info("Removing nodes no longer used from ZooKeeper");
     removeUnusedZKNodes(context);
@@ -441,4 +446,37 @@ public class Upgrader12to13 implements Upgrader {
           "Could not read or write metadata in ZooKeeper because of ZooKeeper 
exception", ex);
     }
   }
+
+  private void validateCompactionServiceConfiguration(ServerContext ctx) {
+
+    final String compactionSvcKey = 
Property.TABLE_COMPACTION_DISPATCHER_OPTS.getKey() + "service";
+    final Map<String,String> compactionPlanners =
+        new CompactionServicesConfig(ctx.getConfiguration()).getPlanners();
+
+    for (TableId tid : new TableId[] {SystemTables.ROOT.tableId(),
+        SystemTables.METADATA.tableId()}) {
+
+      final TablePropKey tpk = TablePropKey.of(tid);
+      final VersionedProperties tableProps = ctx.getPropStore().get(tpk);
+      final String value = tableProps.asMap().get(compactionSvcKey);
+
+      if (value != null) {
+        if (tid.equals(SystemTables.ROOT.tableId()) && value.equals("root")
+            && !compactionPlanners.containsKey(value)) {
+          LOG.warn(
+              "Compaction service \"root\" in configuration for root table, 
but is not defined. "
+                  + "Modifying root table configuration to use the default 
compaction service configuration");
+          ctx.getPropStore().removeProperties(tpk, Set.of(compactionSvcKey));
+        } else if (tid.equals(SystemTables.METADATA.tableId()) && 
value.equals("meta")
+            && !compactionPlanners.containsKey(value)) {
+          LOG.warn(
+              "Compaction service \"meta\" in configuration for metadata 
table, but is not defined. "
+                  + "Modifying metadata table configuration to use the default 
compaction service configuration");
+          ctx.getPropStore().removeProperties(tpk, Set.of(compactionSvcKey));
+        }
+      }
+
+    }
+  }
+
 }

Reply via email to