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

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


The following commit(s) were added to refs/heads/elasticity by this push:
     new 063d12057a Moves reading root tablet metadata w/ zoocache out of Ample 
(#4673)
063d12057a is described below

commit 063d12057adeaa98810f560eb663609b12302c99
Author: Keith Turner <ktur...@apache.org>
AuthorDate: Fri Jun 14 16:27:23 2024 -0400

    Moves reading root tablet metadata w/ zoocache out of Ample (#4673)
    
    After the changes in #4669 only a single location in the code was
    reading tablet metadata w/ eventual consistency using Ample.  This
    single location was the root tablet location cache.  Since this
    was the only use of the code and its a highly nuanced use case,
    moved the code out of Ample to the only place that was using it.
    Removing the levels of indirection makes it easier to understand
    the root tablet location cache. Also added some comments about
    what the the root tablet location cache is doing and noticed and
    uneeded cache clear it was doing and removed it.
---
 .../core/clientImpl/RootClientTabletCache.java     | 42 ++++++++++++++------
 .../accumulo/core/metadata/schema/Ample.java       | 33 +---------------
 .../accumulo/core/metadata/schema/AmpleImpl.java   |  5 +--
 .../core/metadata/schema/RootTabletMetadata.java   | 25 +++++++-----
 .../core/metadata/schema/TabletsMetadata.java      | 45 ++--------------------
 .../core/clientImpl/RootClientTabletCacheTest.java | 14 +++++--
 .../server/manager/state/ZooTabletStateStore.java  |  3 +-
 7 files changed, 63 insertions(+), 104 deletions(-)

diff --git 
a/core/src/main/java/org/apache/accumulo/core/clientImpl/RootClientTabletCache.java
 
b/core/src/main/java/org/apache/accumulo/core/clientImpl/RootClientTabletCache.java
index 4e3af2a5d6..e3e959e536 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/clientImpl/RootClientTabletCache.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/clientImpl/RootClientTabletCache.java
@@ -19,9 +19,9 @@
 package org.apache.accumulo.core.clientImpl;
 
 import static 
com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.LOCATION;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -30,15 +30,13 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.function.BiConsumer;
 
-import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.admin.TabletAvailability;
 import 
org.apache.accumulo.core.clientImpl.ClientTabletCacheImpl.TabletServerLockChecker;
 import org.apache.accumulo.core.data.Mutation;
 import org.apache.accumulo.core.data.Range;
 import org.apache.accumulo.core.dataImpl.KeyExtent;
-import org.apache.accumulo.core.fate.zookeeper.ZooCache;
 import org.apache.accumulo.core.metadata.RootTable;
-import org.apache.accumulo.core.metadata.schema.Ample.ReadConsistency;
+import org.apache.accumulo.core.metadata.schema.RootTabletMetadata;
 import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
 import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
 import org.apache.accumulo.core.util.OpTimer;
@@ -46,6 +44,20 @@ import org.apache.hadoop.io.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Provides ability to get the location of the root tablet from a zoocache. 
This cache
+ * implementation does not actually do any caching on its own and soley relies 
on zoocache. One nice
+ * feature of using zoo cache is that if the location changes in zookeeper, it 
will eventually be
+ * updated by zookeeper watchers in zoocache. Therefore, the invalidation 
functions are
+ * intentionally no-ops and rely on the zookeeper watcher to keep things up to 
date.
+ *
+ * <p>
+ * This code is relying on the assumption that if two client objects are 
created for the same
+ * accumulo instance in the same process that both will have the same 
zoocache. This assumption
+ * means there is only a single zookeeper watch per process per accumulo 
instance. This assumptions
+ * leads to efficiencies at the cluster level by reduce the total number of 
zookeeper watches.
+ * </p>
+ */
 public class RootClientTabletCache extends ClientTabletCache {
 
   private final TabletServerLockChecker lockChecker;
@@ -87,20 +99,24 @@ public class RootClientTabletCache extends 
ClientTabletCache {
   }
 
   @Override
-  public void invalidateCache(KeyExtent failedExtent) {}
+  public void invalidateCache(KeyExtent failedExtent) {
+    // no-op see class level javadoc
+  }
 
   @Override
-  public void invalidateCache(Collection<KeyExtent> keySet) {}
+  public void invalidateCache(Collection<KeyExtent> keySet) {
+    // no-op see class level javadoc
+  }
 
   @Override
   public void invalidateCache(ClientContext context, String server) {
-    ZooCache zooCache = context.getZooCache();
-    String root = context.getZooKeeperRoot() + Constants.ZTSERVERS;
-    zooCache.clear(root + "/" + server);
+    // no-op see class level javadoc
   }
 
   @Override
-  public void invalidateCache() {}
+  public void invalidateCache() {
+    // no-op see class level javadoc
+  }
 
   protected CachedTablet getRootTabletLocation(ClientContext context) {
     Logger log = LoggerFactory.getLogger(this.getClass());
@@ -113,8 +129,10 @@ public class RootClientTabletCache extends 
ClientTabletCache {
       timer = new OpTimer().start();
     }
 
-    Location loc = context.getAmple()
-        .readTablet(RootTable.EXTENT, ReadConsistency.EVENTUAL, 
LOCATION).getLocation();
+    var zpath = RootTabletMetadata.zooPath(context);
+    var zooCache = context.getZooCache();
+    Location loc = new RootTabletMetadata(new String(zooCache.get(zpath), 
UTF_8)).toTabletMetadata()
+        .getLocation();
 
     if (timer != null) {
       timer.stop();
diff --git 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/Ample.java 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/Ample.java
index 8243ad50d4..888775aed5 100644
--- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/Ample.java
+++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/Ample.java
@@ -121,24 +121,6 @@ public interface Ample {
     }
   }
 
-  /**
-   * Controls how Accumulo metadata is read. Currently this only impacts 
reading the root tablet
-   * stored in Zookeeper. Reading data stored in the Accumulo metadata table 
is always immediate
-   * consistency.
-   */
-  public enum ReadConsistency {
-    /**
-     * Read data in a way that is slower, but should always yield the latest 
data. In addition to
-     * being slower, it's possible this read consistency can place higher load 
on shared resource
-     * which can negatively impact an entire cluster.
-     */
-    IMMEDIATE,
-    /**
-     * Read data in a way that may be faster but may yield out of date data.
-     */
-    EVENTUAL
-  }
-
   /**
    * Enables status based processing of GcCandidates.
    */
@@ -157,26 +139,13 @@ public interface Ample {
     INVALID
   }
 
-  /**
-   * Read a single tablets metadata. No checking is done for prev row, so it 
could differ. The
-   * method will read the data using {@link ReadConsistency#IMMEDIATE}.
-   *
-   * @param extent Reads tablet metadata using the table id and end row from 
this extent.
-   * @param colsToFetch What tablets columns to fetch. If empty, then 
everything is fetched.
-   */
-  default TabletMetadata readTablet(KeyExtent extent, ColumnType... 
colsToFetch) {
-    return readTablet(extent, ReadConsistency.IMMEDIATE, colsToFetch);
-  }
-
   /**
    * Read a single tablets metadata. No checking is done for prev row, so it 
could differ.
    *
    * @param extent Reads tablet metadata using the table id and end row from 
this extent.
-   * @param readConsistency Controls how the data is read.
    * @param colsToFetch What tablets columns to fetch. If empty, then 
everything is fetched.
    */
-  TabletMetadata readTablet(KeyExtent extent, ReadConsistency readConsistency,
-      ColumnType... colsToFetch);
+  TabletMetadata readTablet(KeyExtent extent, ColumnType... colsToFetch);
 
   /**
    * Entry point for reading multiple tablets' metadata. Generates a 
TabletsMetadata builder object
diff --git 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/AmpleImpl.java 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/AmpleImpl.java
index cdad8708e6..7b01ea3989 100644
--- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/AmpleImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/AmpleImpl.java
@@ -46,15 +46,12 @@ public class AmpleImpl implements Ample {
   }
 
   @Override
-  public TabletMetadata readTablet(KeyExtent extent, ReadConsistency 
readConsistency,
-      ColumnType... colsToFetch) {
+  public TabletMetadata readTablet(KeyExtent extent, ColumnType... 
colsToFetch) {
     Options builder = newBuilder().forTablet(extent);
     if (colsToFetch.length > 0) {
       builder.fetch(colsToFetch);
     }
 
-    builder.readConsistency(readConsistency);
-
     try (TabletsMetadata tablets = builder.build()) {
       return tablets.stream().collect(onlyElement());
     } catch (NoSuchElementException e) {
diff --git 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java
 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java
index a89fded331..107e9f4004 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java
@@ -61,18 +61,25 @@ public class RootTabletMetadata {
 
   private static final int VERSION = 1;
 
+  public static String zooPath(ClientContext ctx) {
+    return ctx.getZooKeeperRoot() + RootTable.ZROOT_TABLET;
+  }
+
   /**
    * Reads the tablet metadata for the root tablet from zookeeper
    */
-  public static RootTabletMetadata read(ClientContext ctx)
-      throws InterruptedException, KeeperException {
-    final String zpath = ctx.getZooKeeperRoot() + RootTable.ZROOT_TABLET;
-    ZooReader zooReader = ctx.getZooReader();
-    // attempt (see ZOOKEEPER-1675) to ensure the latest root table metadata 
is read from
-    // zookeeper
-    zooReader.sync(zpath);
-    byte[] bytes = zooReader.getData(zpath);
-    return new RootTabletMetadata(new String(bytes, UTF_8));
+  public static RootTabletMetadata read(ClientContext ctx) {
+    try {
+      final String zpath = zooPath(ctx);
+      ZooReader zooReader = ctx.getZooReader();
+      // attempt (see ZOOKEEPER-1675) to ensure the latest root table metadata 
is read from
+      // zookeeper
+      zooReader.sync(zpath);
+      byte[] bytes = zooReader.getData(zpath);
+      return new RootTabletMetadata(new String(bytes, UTF_8));
+    } catch (KeeperException | InterruptedException e) {
+      throw new IllegalStateException(e);
+    }
   }
 
   // This class is used to serialize and deserialize root tablet metadata 
using GSon. Any changes to
diff --git 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java
 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java
index 2bb8082c4b..a3914ea0ed 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java
@@ -19,7 +19,6 @@
 package org.apache.accumulo.core.metadata.schema;
 
 import static com.google.common.base.Preconditions.checkState;
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.stream.Collectors.groupingBy;
 import static java.util.stream.Collectors.toList;
 import static 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily.DIRECTORY_COLUMN;
@@ -61,12 +60,9 @@ import org.apache.accumulo.core.clientImpl.ClientContext;
 import org.apache.accumulo.core.data.Range;
 import org.apache.accumulo.core.data.TableId;
 import org.apache.accumulo.core.dataImpl.KeyExtent;
-import org.apache.accumulo.core.fate.zookeeper.ZooCache;
 import org.apache.accumulo.core.iterators.user.WholeRowIterator;
 import org.apache.accumulo.core.metadata.AccumuloTable;
-import org.apache.accumulo.core.metadata.RootTable;
 import org.apache.accumulo.core.metadata.schema.Ample.DataLevel;
-import org.apache.accumulo.core.metadata.schema.Ample.ReadConsistency;
 import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.BulkFileColumnFamily;
 import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ClonedColumnFamily;
@@ -87,7 +83,6 @@ import 
org.apache.accumulo.core.metadata.schema.filters.TabletMetadataFilter;
 import org.apache.accumulo.core.security.Authorizations;
 import org.apache.accumulo.core.util.ColumnFQ;
 import org.apache.hadoop.io.Text;
-import org.apache.zookeeper.KeeperException;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterators;
@@ -113,7 +108,6 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
     private boolean checkConsistency = false;
     private boolean saveKeyValues;
     private TableId tableId;
-    private ReadConsistency readConsistency = ReadConsistency.IMMEDIATE;
     private final AccumuloClient _client;
     private final List<TabletMetadataFilter> tabletMetadataFilters = new 
ArrayList<>();
     private final Function<DataLevel,String> tableMapper;
@@ -153,7 +147,7 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
           level, table);
       if (level == DataLevel.ROOT) {
         ClientContext ctx = ((ClientContext) _client);
-        return new TabletsMetadata(getRootMetadata(ctx, readConsistency));
+        return new TabletsMetadata(getRootMetadata(ctx));
       } else {
         return buildNonRoot(_client);
       }
@@ -176,8 +170,7 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
 
       for (DataLevel level : groupedExtents.keySet()) {
         if (level == DataLevel.ROOT) {
-          iterables.add(() -> Iterators
-              .singletonIterator(getRootMetadata((ClientContext) client, 
readConsistency)));
+          iterables.add(() -> 
Iterators.singletonIterator(getRootMetadata((ClientContext) client)));
         } else {
           try {
             BatchScanner scanner =
@@ -496,12 +489,6 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
       this.tabletMetadataFilters.add(filter);
       return this;
     }
-
-    @Override
-    public Options readConsistency(ReadConsistency readConsistency) {
-      this.readConsistency = Objects.requireNonNull(readConsistency);
-      return this;
-    }
   }
 
   public interface Options {
@@ -522,12 +509,6 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
      */
     Options saveKeyValues();
 
-    /**
-     * Controls how the data is read. If not, set then the default is
-     * {@link ReadConsistency#IMMEDIATE}
-     */
-    Options readConsistency(ReadConsistency readConsistency);
-
     /**
      * Adds a filter to be applied while fetching the data. Filters are 
applied in the order they
      * are added. This method can be called multiple times to chain multiple 
filters together. The
@@ -662,26 +643,8 @@ public class TabletsMetadata implements 
Iterable<TabletMetadata>, AutoCloseable
     return new Builder(client, tableMapper);
   }
 
-  private static TabletMetadata getRootMetadata(ClientContext ctx,
-      ReadConsistency readConsistency) {
-    String zkRoot = ctx.getZooKeeperRoot();
-    switch (readConsistency) {
-      case EVENTUAL:
-        return getRootMetadata(zkRoot, ctx.getZooCache());
-      case IMMEDIATE:
-        try {
-          return RootTabletMetadata.read(ctx).toTabletMetadata();
-        } catch (InterruptedException | KeeperException e) {
-          throw new IllegalStateException(e);
-        }
-      default:
-        throw new IllegalArgumentException("Unknown consistency level " + 
readConsistency);
-    }
-  }
-
-  public static TabletMetadata getRootMetadata(String zkRoot, ZooCache zc) {
-    byte[] jsonBytes = zc.get(zkRoot + RootTable.ZROOT_TABLET);
-    return new RootTabletMetadata(new String(jsonBytes, 
UTF_8)).toTabletMetadata();
+  private static TabletMetadata getRootMetadata(ClientContext ctx) {
+    return RootTabletMetadata.read(ctx).toTabletMetadata();
   }
 
   private final AutoCloseable closeable;
diff --git 
a/core/src/test/java/org/apache/accumulo/core/clientImpl/RootClientTabletCacheTest.java
 
b/core/src/test/java/org/apache/accumulo/core/clientImpl/RootClientTabletCacheTest.java
index a50a314bd5..178b2e7ec4 100644
--- 
a/core/src/test/java/org/apache/accumulo/core/clientImpl/RootClientTabletCacheTest.java
+++ 
b/core/src/test/java/org/apache/accumulo/core/clientImpl/RootClientTabletCacheTest.java
@@ -19,13 +19,16 @@
 package org.apache.accumulo.core.clientImpl;
 
 import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
-import org.apache.accumulo.core.Constants;
+import java.util.List;
+
 import 
org.apache.accumulo.core.clientImpl.ClientTabletCacheImpl.TabletServerLockChecker;
 import org.apache.accumulo.core.fate.zookeeper.ZooCache;
+import org.apache.accumulo.core.metadata.RootTable;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -39,7 +42,7 @@ public class RootClientTabletCacheTest {
   public void setUp() {
     context = createMock(ClientContext.class);
     expect(context.getZooKeeperRoot()).andReturn("/accumulo/iid").anyTimes();
-    zc = createMock(ZooCache.class);
+    zc = createStrictMock(ZooCache.class);
     expect(context.getZooCache()).andReturn(zc).anyTimes();
     replay(context);
     lockChecker = createMock(TabletServerLockChecker.class);
@@ -47,10 +50,13 @@ public class RootClientTabletCacheTest {
   }
 
   @Test
-  public void testInvalidateCache_Server() {
-    zc.clear(context.getZooKeeperRoot() + Constants.ZTSERVERS + "/server");
+  public void testInvalidateCache_Noop() {
     replay(zc);
+    // its not expected that any of the validate functions will interact w/ 
zoocache
     rtl.invalidateCache(context, "server");
+    rtl.invalidateCache(RootTable.EXTENT);
+    rtl.invalidateCache();
+    rtl.invalidateCache(List.of(RootTable.EXTENT));
     verify(zc);
   }
 }
diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/ZooTabletStateStore.java
 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/ZooTabletStateStore.java
index 2b8dded1dd..110563f1e9 100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/ZooTabletStateStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/ZooTabletStateStore.java
@@ -47,7 +47,6 @@ import org.apache.accumulo.core.util.time.SteadyTime;
 import org.apache.accumulo.server.ServerContext;
 import org.apache.accumulo.server.iterators.TabletIteratorEnvironment;
 import org.apache.hadoop.fs.Path;
-import org.apache.zookeeper.KeeperException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,7 +86,7 @@ class ZooTabletStateStore extends AbstractTabletStateStore 
implements TabletStat
           Map.of(TabletManagementIterator.TABLET_GOAL_STATE_PARAMS_OPTION, 
parameters.serialize()),
           env);
       tmi.seek(new Range(), null, true);
-    } catch (KeeperException | InterruptedException | IOException e2) {
+    } catch (IOException e2) {
       throw new IllegalStateException(
           "Error setting up TabletManagementIterator for the root tablet", e2);
     }

Reply via email to