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

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

commit 5e4ec67ac0ba337d21b815e5a8c5cb95f49a5f89
Merge: 5220f009cc 5aca4f67bc
Author: Christopher L. Shannon <cshan...@apache.org>
AuthorDate: Fri May 10 17:05:27 2024 -0400

    Merge branch 'main' into elasticity

 .../org/apache/accumulo/core/logging/TabletLogger.java  |  7 +++----
 .../accumulo/core/metadata/SuspendingTServer.java       | 17 ++++++++++-------
 .../org/apache/accumulo/core/metadata/schema/Ample.java |  3 ++-
 .../core/metadata/schema/TabletMetadataBuilder.java     |  3 ++-
 .../core/metadata/schema/TabletMutatorBase.java         |  3 ++-
 .../org/apache/accumulo/core/util/time/SteadyTime.java  | 14 ++++++++++++++
 .../core/metadata/schema/TabletMetadataTest.java        | 16 ++++++++++------
 .../server/manager/state/AbstractTabletStateStore.java  |  9 +++++----
 .../server/manager/state/LoggingTabletStateStore.java   |  6 +++---
 .../server/manager/state/MetaDataStateStore.java        |  7 ++++---
 .../accumulo/server/manager/state/TabletStateStore.java |  5 +++--
 .../server/manager/state/ZooTabletStateStore.java       |  5 +++--
 .../org/apache/accumulo/manager/TabletGroupWatcher.java |  4 ++--
 .../apache/accumulo/tserver/TabletClientHandler.java    |  5 +++--
 .../apache/accumulo/tserver/UnloadTabletHandler.java    | 14 ++++++++------
 15 files changed, 74 insertions(+), 44 deletions(-)

diff --cc core/src/main/java/org/apache/accumulo/core/logging/TabletLogger.java
index e76c62a6c9,2209e41c27..40dc0b5eb1
--- a/core/src/main/java/org/apache/accumulo/core/logging/TabletLogger.java
+++ b/core/src/main/java/org/apache/accumulo/core/logging/TabletLogger.java
@@@ -23,15 -23,12 +23,14 @@@ import static java.util.stream.Collecto
  import java.util.Collection;
  import java.util.List;
  import java.util.Optional;
 +import java.util.SortedSet;
  import java.util.UUID;
- import java.util.concurrent.TimeUnit;
  
 -import org.apache.accumulo.core.client.admin.CompactionConfig;
  import org.apache.accumulo.core.client.admin.compaction.CompactableFile;
  import org.apache.accumulo.core.dataImpl.KeyExtent;
 +import org.apache.accumulo.core.fate.FateId;
  import org.apache.accumulo.core.metadata.CompactableFileImpl;
 +import org.apache.accumulo.core.metadata.ReferencedTabletFile;
  import org.apache.accumulo.core.metadata.StoredTabletFile;
  import org.apache.accumulo.core.metadata.TServerInstance;
  import org.apache.accumulo.core.metadata.TabletFile;
@@@ -40,8 -36,8 +39,9 @@@ import org.apache.accumulo.core.metadat
  import org.apache.accumulo.core.spi.compaction.CompactionJob;
  import org.apache.accumulo.core.spi.compaction.CompactionKind;
  import org.apache.accumulo.core.tabletserver.log.LogEntry;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.commons.io.FileUtils;
 +import org.apache.hadoop.io.Text;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
diff --cc core/src/main/java/org/apache/accumulo/core/metadata/schema/Ample.java
index 27856c899b,931e415774..7d7086649a
--- 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
@@@ -342,87 -265,50 +343,87 @@@ public interface Ample 
    /**
     * Interface for changing a tablets persistent data.
     */
 -  interface TabletMutator {
 -    TabletMutator putPrevEndRow(Text per);
 +  interface TabletUpdates<T> {
 +    T putPrevEndRow(Text per);
 +
 +    T putFile(ReferencedTabletFile path, DataFileValue dfv);
 +
 +    T putFile(StoredTabletFile path, DataFileValue dfv);
  
 -    TabletMutator putFile(ReferencedTabletFile path, DataFileValue dfv);
 +    T deleteFile(StoredTabletFile path);
  
 -    TabletMutator putFile(StoredTabletFile path, DataFileValue dfv);
 +    T putScan(StoredTabletFile path);
  
 -    TabletMutator deleteFile(StoredTabletFile path);
 +    T deleteScan(StoredTabletFile path);
  
 -    TabletMutator putScan(StoredTabletFile path);
 +    T putFlushId(long flushId);
  
 -    TabletMutator deleteScan(StoredTabletFile path);
 +    T putFlushNonce(long flushNonce);
  
 -    TabletMutator putCompactionId(long compactionId);
 +    T putLocation(Location location);
  
 -    TabletMutator putFlushId(long flushId);
 +    T deleteLocation(Location location);
  
 -    TabletMutator putLocation(Location location);
 +    T putDirName(String dirName);
  
 -    TabletMutator deleteLocation(Location location);
 +    T putWal(LogEntry logEntry);
  
 -    TabletMutator putZooLock(ServiceLock zooLock);
 +    T deleteWal(LogEntry logEntry);
  
 -    TabletMutator putDirName(String dirName);
 +    T putTime(MetadataTime time);
  
 -    TabletMutator putWal(LogEntry logEntry);
 +    T putBulkFile(ReferencedTabletFile bulkref, FateId fateId);
  
 -    TabletMutator deleteWal(LogEntry wal);
 +    T deleteBulkFile(StoredTabletFile bulkref);
  
-     T putSuspension(TServerInstance tserver, long suspensionTime);
 -    TabletMutator putTime(MetadataTime time);
++    T putSuspension(TServerInstance tserver, SteadyTime suspensionTime);
  
 -    TabletMutator putBulkFile(ReferencedTabletFile bulkref, long tid);
 +    T deleteSuspension();
  
 -    TabletMutator deleteBulkFile(StoredTabletFile bulkref);
 +    T putExternalCompaction(ExternalCompactionId ecid, CompactionMetadata 
ecMeta);
  
 -    TabletMutator putSuspension(TServerInstance tserver, SteadyTime 
suspensionTime);
 +    T deleteExternalCompaction(ExternalCompactionId ecid);
  
 -    TabletMutator deleteSuspension();
 +    T putCompacted(FateId fateId);
  
 -    TabletMutator putExternalCompaction(ExternalCompactionId ecid,
 -        ExternalCompactionMetadata ecMeta);
 +    T deleteCompacted(FateId fateId);
  
 -    TabletMutator deleteExternalCompaction(ExternalCompactionId ecid);
 +    T putTabletAvailability(TabletAvailability tabletAvailability);
 +
 +    T setHostingRequested();
 +
 +    T deleteHostingRequested();
 +
 +    T putOperation(TabletOperationId opId);
 +
 +    T deleteOperation();
 +
 +    T putSelectedFiles(SelectedFiles selectedFiles);
 +
 +    T deleteSelectedFiles();
 +
 +    /**
 +     * Deletes all the columns in the keys.
 +     *
 +     * @throws IllegalArgumentException if rows in keys do not match tablet 
row or column visibility
 +     *         is not empty
 +     */
 +    T deleteAll(Set<Key> keys);
 +
 +    T setMerged();
 +
 +    T deleteMerged();
 +
 +    T putUserCompactionRequested(FateId fateId);
 +
 +    T deleteUserCompactionRequested(FateId fateId);
 +
 +    T setUnSplittable(UnSplittableMetadata unSplittableMeta);
 +
 +    T deleteUnSplittable();
 +  }
  
 +  interface TabletMutator extends TabletUpdates<TabletMutator> {
      /**
       * This method persist (or queues for persisting) previous put and 
deletes against this object.
       * Unless this method is called, previous calls will never be persisted. 
The purpose of this
diff --cc 
core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadataBuilder.java
index 8b7e96e59e,0000000000..4121ad2005
mode 100644,000000..100644
--- 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadataBuilder.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadataBuilder.java
@@@ -1,327 -1,0 +1,328 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   https://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.accumulo.core.metadata.schema;
 +
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.AVAILABILITY;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.COMPACTED;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.DIR;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.ECOMP;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.FILES;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.FLUSH_ID;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.FLUSH_NONCE;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.HOSTING_REQUESTED;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.LOADED;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.LOCATION;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.LOGS;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.MERGED;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.OPID;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.PREV_ROW;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.SCANS;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.SELECTED;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.SUSPEND;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.TIME;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.UNSPLITTABLE;
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.USER_COMPACTION_REQUESTED;
 +
 +import java.util.Arrays;
 +import java.util.EnumSet;
 +import java.util.Set;
 +import java.util.SortedMap;
 +import java.util.TreeMap;
 +
 +import org.apache.accumulo.core.client.admin.TabletAvailability;
 +import org.apache.accumulo.core.data.Key;
 +import org.apache.accumulo.core.data.Mutation;
 +import org.apache.accumulo.core.data.Value;
 +import org.apache.accumulo.core.dataImpl.KeyExtent;
 +import org.apache.accumulo.core.fate.FateId;
 +import org.apache.accumulo.core.metadata.ReferencedTabletFile;
 +import org.apache.accumulo.core.metadata.StoredTabletFile;
 +import org.apache.accumulo.core.metadata.TServerInstance;
 +import org.apache.accumulo.core.tabletserver.log.LogEntry;
++import org.apache.accumulo.core.util.time.SteadyTime;
 +import org.apache.hadoop.io.Text;
 +
 +public class TabletMetadataBuilder implements 
Ample.TabletUpdates<TabletMetadataBuilder> {
 +
 +  public static class InternalBuilder extends 
TabletMutatorBase<InternalBuilder> {
 +    protected InternalBuilder(KeyExtent extent) {
 +      super(extent);
 +    }
 +
 +    @Override
 +    public Mutation getMutation() {
 +      return super.getMutation();
 +    }
 +  }
 +
 +  private final InternalBuilder internalBuilder;
 +  EnumSet<TabletMetadata.ColumnType> fetched;
 +
 +  protected TabletMetadataBuilder(KeyExtent extent) {
 +    internalBuilder = new InternalBuilder(extent);
 +    fetched = EnumSet.noneOf(TabletMetadata.ColumnType.class);
 +    putPrevEndRow(extent.prevEndRow());
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putPrevEndRow(Text per) {
 +    fetched.add(PREV_ROW);
 +    internalBuilder.putPrevEndRow(per);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putFile(ReferencedTabletFile path, 
DataFileValue dfv) {
 +    fetched.add(FILES);
 +    internalBuilder.putFile(path, dfv);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putFile(StoredTabletFile path, DataFileValue 
dfv) {
 +    fetched.add(FILES);
 +    internalBuilder.putFile(path, dfv);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteFile(StoredTabletFile path) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putScan(StoredTabletFile path) {
 +    fetched.add(SCANS);
 +    internalBuilder.putScan(path);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteScan(StoredTabletFile path) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putFlushId(long flushId) {
 +    fetched.add(FLUSH_ID);
 +    internalBuilder.putFlushId(flushId);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putFlushNonce(long flushNonce) {
 +    fetched.add(FLUSH_NONCE);
 +    internalBuilder.putFlushId(flushNonce);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putLocation(TabletMetadata.Location location) {
 +    fetched.add(LOCATION);
 +    internalBuilder.putLocation(location);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteLocation(TabletMetadata.Location 
location) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putDirName(String dirName) {
 +    fetched.add(DIR);
 +    internalBuilder.putDirName(dirName);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putWal(LogEntry logEntry) {
 +    fetched.add(LOGS);
 +    internalBuilder.putWal(logEntry);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteWal(LogEntry logEntry) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putTime(MetadataTime time) {
 +    fetched.add(TIME);
 +    internalBuilder.putTime(time);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putBulkFile(ReferencedTabletFile bulkref, 
FateId fateId) {
 +    fetched.add(LOADED);
 +    internalBuilder.putBulkFile(bulkref, fateId);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteBulkFile(StoredTabletFile bulkref) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
-   public TabletMetadataBuilder putSuspension(TServerInstance tserver, long 
suspensionTime) {
++  public TabletMetadataBuilder putSuspension(TServerInstance tserver, 
SteadyTime suspensionTime) {
 +    fetched.add(SUSPEND);
 +    internalBuilder.putSuspension(tserver, suspensionTime);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteSuspension() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putExternalCompaction(ExternalCompactionId 
ecid,
 +      CompactionMetadata ecMeta) {
 +    fetched.add(ECOMP);
 +    internalBuilder.putExternalCompaction(ecid, ecMeta);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteExternalCompaction(ExternalCompactionId 
ecid) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putCompacted(FateId fateId) {
 +    fetched.add(COMPACTED);
 +    internalBuilder.putCompacted(fateId);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteCompacted(FateId fateId) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putTabletAvailability(TabletAvailability 
tabletAvailability) {
 +    fetched.add(AVAILABILITY);
 +    internalBuilder.putTabletAvailability(tabletAvailability);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder setHostingRequested() {
 +    fetched.add(HOSTING_REQUESTED);
 +    internalBuilder.setHostingRequested();
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteHostingRequested() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putOperation(TabletOperationId opId) {
 +    fetched.add(OPID);
 +    internalBuilder.putOperation(opId);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteOperation() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putSelectedFiles(SelectedFiles selectedFiles) {
 +    fetched.add(SELECTED);
 +    internalBuilder.putSelectedFiles(selectedFiles);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteSelectedFiles() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteAll(Set<Key> keys) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder setMerged() {
 +    fetched.add(MERGED);
 +    internalBuilder.setMerged();
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteMerged() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder putUserCompactionRequested(FateId fateId) {
 +    fetched.add(USER_COMPACTION_REQUESTED);
 +    internalBuilder.putUserCompactionRequested(fateId);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteUserCompactionRequested(FateId fateId) {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder setUnSplittable(UnSplittableMetadata 
unSplittableMeta) {
 +    fetched.add(UNSPLITTABLE);
 +    internalBuilder.setUnSplittable(unSplittableMeta);
 +    return this;
 +  }
 +
 +  @Override
 +  public TabletMetadataBuilder deleteUnSplittable() {
 +    throw new UnsupportedOperationException();
 +  }
 +
 +  /**
 +   * @param extraFetched Anything that was put on the builder will 
automatically be added to the
 +   *        fetched set. However, for the case where something was not put 
and it needs to be
 +   *        fetched it can be passed here. For example to simulate a tablet 
w/o a location it, no
 +   *        location will be put and LOCATION would be passed in via this 
argument.
 +   */
 +  public TabletMetadata build(TabletMetadata.ColumnType... extraFetched) {
 +    var mutation = internalBuilder.getMutation();
 +
 +    SortedMap<Key,Value> rowMap = new TreeMap<>();
 +    mutation.getUpdates().forEach(cu -> {
 +      Key k = new Key(mutation.getRow(), cu.getColumnFamily(), 
cu.getColumnQualifier(),
 +          cu.getTimestamp());
 +      Value v = new Value(cu.getValue());
 +      rowMap.put(k, v);
 +    });
 +
 +    fetched.addAll(Arrays.asList(extraFetched));
 +
 +    return TabletMetadata.convertRow(rowMap.entrySet().iterator(), fetched, 
true, false);
 +  }
 +
 +}
diff --cc 
core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMutatorBase.java
index 4fc978f150,a8b567775a..f4ee38e28d
--- 
a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMutatorBase.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMutatorBase.java
@@@ -51,6 -46,8 +51,7 @@@ import org.apache.accumulo.core.metadat
  import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
  import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
  import org.apache.accumulo.core.tabletserver.log.LogEntry;
+ import org.apache.accumulo.core.util.time.SteadyTime;
 -import org.apache.accumulo.server.ServerContext;
  import org.apache.hadoop.io.Text;
  
  import com.google.common.base.Preconditions;
@@@ -223,15 -202,7 +224,15 @@@ public abstract class TabletMutatorBase
    }
  
    @Override
 -  public Ample.TabletMutator putSuspension(TServerInstance tServer, 
SteadyTime suspensionTime) {
 +  public T deleteSelectedFiles() {
 +    Preconditions.checkState(updatesEnabled, "Cannot make updates after 
calling mutate.");
 +    mutation.putDelete(ServerColumnFamily.SELECTED_COLUMN.getColumnFamily(),
 +        ServerColumnFamily.SELECTED_COLUMN.getColumnQualifier());
 +    return getThis();
 +  }
 +
 +  @Override
-   public T putSuspension(TServerInstance tServer, long suspensionTime) {
++  public T putSuspension(TServerInstance tServer, SteadyTime suspensionTime) {
      Preconditions.checkState(updatesEnabled, "Cannot make updates after 
calling mutate.");
      mutation.put(SuspendLocationColumn.SUSPEND_COLUMN.getColumnFamily(),
          SuspendLocationColumn.SUSPEND_COLUMN.getColumnQualifier(),
diff --cc 
core/src/test/java/org/apache/accumulo/core/metadata/schema/TabletMetadataTest.java
index c2f6a19e69,3b2b4a85ac..109be1aadc
--- 
a/core/src/test/java/org/apache/accumulo/core/metadata/schema/TabletMetadataTest.java
+++ 
b/core/src/test/java/org/apache/accumulo/core/metadata/schema/TabletMetadataTest.java
@@@ -77,16 -71,15 +78,17 @@@ import org.apache.accumulo.core.metadat
  import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily;
  import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily;
  import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ScanFileColumnFamily;
 +import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.SplitColumnFamily;
  import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.TabletColumnFamily;
 +import 
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.UserCompactionRequestedColumnFamily;
  import org.apache.accumulo.core.metadata.schema.TabletMetadata.Builder;
  import org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
  import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
 -import org.apache.accumulo.core.spi.compaction.CompactionExecutorId;
  import org.apache.accumulo.core.spi.compaction.CompactionKind;
 +import org.apache.accumulo.core.spi.compaction.CompactorGroupId;
  import org.apache.accumulo.core.tabletserver.log.LogEntry;
 -import org.apache.accumulo.core.util.compaction.CompactionExecutorIdImpl;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.hadoop.fs.Path;
  import org.apache.hadoop.io.Text;
  import org.junit.jupiter.api.Test;
@@@ -138,13 -128,9 +140,13 @@@ public class TabletMetadataTest 
      
mutation.at().family(ScanFileColumnFamily.NAME).qualifier(sf2.getMetadata()).put("");
  
      MERGED_COLUMN.put(mutation, new Value());
 +    FateId userCompactFateId = FateId.from(type, UUID.randomUUID());
 +    mutation.put(UserCompactionRequestedColumnFamily.STR_NAME, 
userCompactFateId.canonical(), "");
 +    var unsplittableMeta =
 +        UnSplittableMetadata.toUnSplittable(extent, 100, 110, 120, 
Set.of(sf1, sf2));
 +    SplitColumnFamily.UNSPLITTABLE_COLUMN.put(mutation, new 
Value(unsplittableMeta.toBase64()));
  
-     long suspensionTime = System.currentTimeMillis();
 -    OLD_PREV_ROW_COLUMN.put(mutation, TabletColumnFamily.encodePrevEndRow(new 
Text("oldPrev")));
+     SteadyTime suspensionTime = SteadyTime.from(System.currentTimeMillis(), 
TimeUnit.MILLISECONDS);
      TServerInstance ser1 = new 
TServerInstance(HostAndPort.fromParts("server1", 8555), "s001");
      Value suspend = SuspendingTServer.toValue(ser1, suspensionTime);
      SUSPEND_COLUMN.put(mutation, suspend);
@@@ -303,13 -291,14 +305,14 @@@
      // test SUSPENDED
      mutation = TabletColumnFamily.createPrevRowMutation(extent);
      mutation.at().family(SUSPEND_COLUMN.getColumnFamily())
-         
.qualifier(SUSPEND_COLUMN.getColumnQualifier()).put(SuspendingTServer.toValue(ser2,
 1000L));
+         .qualifier(SUSPEND_COLUMN.getColumnQualifier())
+         .put(SuspendingTServer.toValue(ser2, SteadyTime.from(1000L, 
TimeUnit.MILLISECONDS)));
      rowMap = toRowMap(mutation);
  
 -    tm = TabletMetadata.convertRow(rowMap.entrySet().iterator(), colsToFetch, 
false);
 +    tm = TabletMetadata.convertRow(rowMap.entrySet().iterator(), colsToFetch, 
false, false);
  
 -    assertEquals(TabletState.SUSPENDED, tm.getTabletState(tservers));
 +    assertEquals(TabletState.SUSPENDED, TabletState.compute(tm, tservers));
-     assertEquals(1000L, tm.getSuspend().suspensionTime);
+     assertEquals(1000L, tm.getSuspend().suspensionTime.getMillis());
      assertEquals(ser2.getHostAndPort(), tm.getSuspend().server);
      assertNull(tm.getLocation());
      assertFalse(tm.hasCurrent());
@@@ -573,121 -422,4 +576,122 @@@
      });
      return rowMap;
    }
 +
 +  @Test
 +  public void testBuilder() {
 +    TServerInstance ser1 = new 
TServerInstance(HostAndPort.fromParts("server1", 8555), "s001");
 +
 +    KeyExtent extent = new KeyExtent(TableId.of("5"), new Text("df"), new 
Text("da"));
 +
 +    FateInstanceType type = FateInstanceType.fromTableId(extent.tableId());
 +
 +    StoredTabletFile sf1 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/sf1.rf")).insert();
 +    DataFileValue dfv1 = new DataFileValue(89, 67);
 +
 +    StoredTabletFile sf2 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/sf2.rf")).insert();
 +    DataFileValue dfv2 = new DataFileValue(890, 670);
 +
 +    ReferencedTabletFile rf1 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/imp1.rf"));
 +    ReferencedTabletFile rf2 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/imp2.rf"));
 +
 +    StoredTabletFile sf3 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/sf3.rf")).insert();
 +    StoredTabletFile sf4 =
 +        new ReferencedTabletFile(new 
Path("hdfs://nn1/acc/tables/1/t-0001/sf4.rf")).insert();
 +
 +    FateId loadedFateId1 = FateId.from(type, UUID.randomUUID());
 +    FateId loadedFateId2 = FateId.from(type, UUID.randomUUID());
 +    FateId compactFateId1 = FateId.from(type, UUID.randomUUID());
 +    FateId compactFateId2 = FateId.from(type, UUID.randomUUID());
 +
 +    TabletMetadata tm = TabletMetadata.builder(extent)
 +        
.putTabletAvailability(TabletAvailability.UNHOSTED).putLocation(Location.future(ser1))
 +        .putFile(sf1, dfv1).putFile(sf2, dfv2).putBulkFile(rf1, loadedFateId1)
 +        .putBulkFile(rf2, 
loadedFateId2).putFlushId(27).putDirName("dir1").putScan(sf3).putScan(sf4)
 +        .putCompacted(compactFateId1).putCompacted(compactFateId2)
 +        .build(ECOMP, HOSTING_REQUESTED, MERGED, USER_COMPACTION_REQUESTED, 
UNSPLITTABLE);
 +
 +    assertEquals(extent, tm.getExtent());
 +    assertEquals(TabletAvailability.UNHOSTED, tm.getTabletAvailability());
 +    assertEquals(Location.future(ser1), tm.getLocation());
 +    assertEquals(27L, tm.getFlushId().orElse(-1));
 +    assertEquals(Map.of(sf1, dfv1, sf2, dfv2), tm.getFilesMap());
 +    
assertEquals(tm.getFilesMap().values().stream().mapToLong(DataFileValue::getSize).sum(),
 +        tm.getFileSize());
 +    assertEquals(Map.of(rf1.insert(), loadedFateId1, rf2.insert(), 
loadedFateId2), tm.getLoaded());
 +    assertEquals("dir1", tm.getDirName());
 +    assertEquals(Set.of(sf3, sf4), Set.copyOf(tm.getScans()));
 +    assertEquals(Set.of(), tm.getExternalCompactions().keySet());
 +    assertEquals(Set.of(compactFateId1, compactFateId2), tm.getCompacted());
 +    assertFalse(tm.getHostingRequested());
 +    assertTrue(tm.getUserCompactionsRequested().isEmpty());
 +    assertFalse(tm.hasMerged());
 +    assertNull(tm.getUnSplittable());
 +    assertThrows(IllegalStateException.class, tm::getOperationId);
 +    assertThrows(IllegalStateException.class, tm::getSuspend);
 +    assertThrows(IllegalStateException.class, tm::getTime);
 +
 +    TabletOperationId opid1 =
 +        TabletOperationId.from(TabletOperationType.SPLITTING, 
FateId.from(type, UUID.randomUUID()));
 +    TabletMetadata tm2 = 
TabletMetadata.builder(extent).putOperation(opid1).build(LOCATION);
 +
 +    assertEquals(extent, tm2.getExtent());
 +    assertEquals(opid1, tm2.getOperationId());
 +    assertNull(tm2.getLocation());
 +    assertThrows(IllegalStateException.class, tm2::getFiles);
 +    assertThrows(IllegalStateException.class, tm2::getTabletAvailability);
 +    assertThrows(IllegalStateException.class, tm2::getFlushId);
 +    assertThrows(IllegalStateException.class, tm2::getFiles);
 +    assertThrows(IllegalStateException.class, tm2::getLogs);
 +    assertThrows(IllegalStateException.class, tm2::getLoaded);
 +    assertThrows(IllegalStateException.class, tm2::getDirName);
 +    assertThrows(IllegalStateException.class, tm2::getScans);
 +    assertThrows(IllegalStateException.class, tm2::getExternalCompactions);
 +    assertThrows(IllegalStateException.class, tm2::getHostingRequested);
 +    assertThrows(IllegalStateException.class, tm2::getSelectedFiles);
 +    assertThrows(IllegalStateException.class, tm2::getCompacted);
 +    assertThrows(IllegalStateException.class, tm2::hasMerged);
 +    assertThrows(IllegalStateException.class, 
tm2::getUserCompactionsRequested);
 +    assertThrows(IllegalStateException.class, tm2::getUnSplittable);
 +
 +    var ecid1 = ExternalCompactionId.generate(UUID.randomUUID());
 +    CompactionMetadata ecm =
 +        new CompactionMetadata(Set.of(sf1, sf2), rf1, "cid1", 
CompactionKind.USER, (short) 3,
 +            CompactorGroupId.of("Q1"), true, FateId.from(type, 
UUID.randomUUID()));
 +
 +    LogEntry le1 = LogEntry.fromPath("localhost+8020/" + UUID.randomUUID());
 +    LogEntry le2 = LogEntry.fromPath("localhost+8020/" + UUID.randomUUID());
 +
 +    FateId selFilesFateId = FateId.from(type, UUID.randomUUID());
 +    SelectedFiles selFiles = new SelectedFiles(Set.of(sf1, sf4), false, 
selFilesFateId);
 +    var unsplittableMeta =
 +        UnSplittableMetadata.toUnSplittable(extent, 100, 110, 120, 
Set.of(sf1, sf2));
 +
 +    TabletMetadata tm3 = 
TabletMetadata.builder(extent).putExternalCompaction(ecid1, ecm)
-         .putSuspension(ser1, 45L).putTime(new MetadataTime(479, 
TimeType.LOGICAL)).putWal(le1)
-         
.putWal(le2).setHostingRequested().putSelectedFiles(selFiles).setMerged()
++        .putSuspension(ser1, SteadyTime.from(45L, TimeUnit.MILLISECONDS))
++        .putTime(new MetadataTime(479, 
TimeType.LOGICAL)).putWal(le1).putWal(le2)
++        .setHostingRequested().putSelectedFiles(selFiles).setMerged()
 +        
.putUserCompactionRequested(selFilesFateId).setUnSplittable(unsplittableMeta).build();
 +
 +    assertEquals(Set.of(ecid1), tm3.getExternalCompactions().keySet());
 +    assertEquals(Set.of(sf1, sf2), 
tm3.getExternalCompactions().get(ecid1).getJobFiles());
 +    assertEquals(ser1.getHostAndPort(), tm3.getSuspend().server);
-     assertEquals(45L, tm3.getSuspend().suspensionTime);
++    assertEquals(SteadyTime.from(45L, TimeUnit.MILLISECONDS), 
tm3.getSuspend().suspensionTime);
 +    assertEquals(new MetadataTime(479, TimeType.LOGICAL), tm3.getTime());
 +    assertTrue(tm3.getHostingRequested());
 +    assertEquals(Stream.of(le1, le2).map(LogEntry::toString).collect(toSet()),
 +        tm3.getLogs().stream().map(LogEntry::toString).collect(toSet()));
 +    assertEquals(Set.of(sf1, sf4), tm3.getSelectedFiles().getFiles());
 +    assertEquals(selFilesFateId, tm3.getSelectedFiles().getFateId());
 +    assertFalse(tm3.getSelectedFiles().initiallySelectedAll());
 +    assertEquals(selFiles.getMetadataValue(), 
tm3.getSelectedFiles().getMetadataValue());
 +    assertTrue(tm3.hasMerged());
 +    assertTrue(tm3.getUserCompactionsRequested().contains(selFilesFateId));
 +    assertEquals(unsplittableMeta, tm3.getUnSplittable());
 +  }
 +
  }
diff --cc 
server/base/src/main/java/org/apache/accumulo/server/manager/state/AbstractTabletStateStore.java
index 977aa98afb,0000000000..e6c78ace50
mode 100644,000000..100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/AbstractTabletStateStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/AbstractTabletStateStore.java
@@@ -1,189 -1,0 +1,190 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   https://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.accumulo.server.manager.state;
 +
 +import java.util.Collection;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +
 +import org.apache.accumulo.core.dataImpl.KeyExtent;
 +import org.apache.accumulo.core.metadata.TServerInstance;
 +import org.apache.accumulo.core.metadata.schema.Ample;
 +import org.apache.accumulo.core.metadata.schema.Ample.ConditionalResult;
 +import 
org.apache.accumulo.core.metadata.schema.Ample.ConditionalResult.Status;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
 +import org.apache.accumulo.core.tabletserver.log.LogEntry;
++import org.apache.accumulo.core.util.time.SteadyTime;
 +import org.apache.accumulo.server.ServerContext;
 +import org.apache.hadoop.fs.Path;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +import com.google.common.base.Preconditions;
 +
 +public abstract class AbstractTabletStateStore implements TabletStateStore {
 +
 +  private static final Logger LOG = 
LoggerFactory.getLogger(AbstractTabletStateStore.class);
 +
 +  private final Ample ample;
 +
 +  protected AbstractTabletStateStore(ServerContext context) {
 +    this.ample = context.getAmple();
 +  }
 +
 +  @Override
 +  public void setLocations(Collection<Assignment> assignments) throws 
DistributedStoreException {
 +    try (var tabletsMutator = ample.conditionallyMutateTablets()) {
 +      for (Assignment assignment : assignments) {
 +        var conditionalMutator = 
tabletsMutator.mutateTablet(assignment.tablet)
 +            
.requireLocation(TabletMetadata.Location.future(assignment.server))
 +            .putLocation(TabletMetadata.Location.current(assignment.server))
 +            
.deleteLocation(TabletMetadata.Location.future(assignment.server)).deleteSuspension();
 +
 +        updateLastLocation(conditionalMutator, assignment.server, 
assignment.lastLocation);
 +
 +        conditionalMutator.submit(tabletMetadata -> {
 +          
Preconditions.checkArgument(tabletMetadata.getExtent().equals(assignment.tablet));
 +          return tabletMetadata.getLocation() != null && 
tabletMetadata.getLocation()
 +              .equals(TabletMetadata.Location.current(assignment.server));
 +        });
 +      }
 +
 +      if (tabletsMutator.process().values().stream()
 +          .anyMatch(result -> result.getStatus() != Status.ACCEPTED)) {
 +        throw new DistributedStoreException(
 +            "failed to set tablet location, conditional mutation failed");
 +      }
 +    } catch (RuntimeException ex) {
 +      throw new DistributedStoreException(ex);
 +    }
 +  }
 +
 +  @Override
 +  public void setFutureLocations(Collection<Assignment> assignments)
 +      throws DistributedStoreException {
 +    try (var tabletsMutator = ample.conditionallyMutateTablets()) {
 +      for (Assignment assignment : assignments) {
 +        
tabletsMutator.mutateTablet(assignment.tablet).requireAbsentOperation()
 +            .requireAbsentLocation().deleteSuspension()
 +            .putLocation(TabletMetadata.Location.future(assignment.server))
 +            .submit(tabletMetadata -> {
 +              
Preconditions.checkArgument(tabletMetadata.getExtent().equals(assignment.tablet));
 +              return tabletMetadata.getLocation() != null && 
tabletMetadata.getLocation()
 +                  .equals(TabletMetadata.Location.future(assignment.server));
 +            });
 +      }
 +
 +      Map<KeyExtent,ConditionalResult> results = tabletsMutator.process();
 +
 +      for (Entry<KeyExtent,ConditionalResult> entry : results.entrySet()) {
 +        if (entry.getValue().getStatus() != Status.ACCEPTED) {
 +          LOG.debug("Likely concurrent FATE operation prevented setting 
future location for {}, "
 +              + "Manager will retry soon.", entry.getKey());
 +        }
 +      }
 +
 +    } catch (RuntimeException ex) {
 +      throw new DistributedStoreException(ex);
 +    }
 +  }
 +
 +  @Override
 +  public void unassign(Collection<TabletMetadata> tablets,
 +      Map<TServerInstance,List<Path>> logsForDeadServers) throws 
DistributedStoreException {
-     unassign(tablets, logsForDeadServers, -1);
++    unassign(tablets, logsForDeadServers, null);
 +  }
 +
 +  @Override
 +  public void suspend(Collection<TabletMetadata> tablets,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
++      Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
 +      throws DistributedStoreException {
 +    unassign(tablets, logsForDeadServers, suspensionTimestamp);
 +  }
 +
 +  protected abstract void processSuspension(Ample.ConditionalTabletMutator 
tabletMutator,
-       TabletMetadata tm, long suspensionTimestamp);
++      TabletMetadata tm, SteadyTime suspensionTimestamp);
 +
 +  private void unassign(Collection<TabletMetadata> tablets,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
++      Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
 +      throws DistributedStoreException {
 +    try (var tabletsMutator = ample.conditionallyMutateTablets()) {
 +      for (TabletMetadata tm : tablets) {
 +        if (tm.getLocation() == null) {
 +          continue;
 +        }
 +
 +        var tabletMutator =
 +            
tabletsMutator.mutateTablet(tm.getExtent()).requireLocation(tm.getLocation());
 +
 +        if (tm.hasCurrent()) {
 +
 +          updateLastLocation(tabletMutator, 
tm.getLocation().getServerInstance(), tm.getLast());
 +          tabletMutator.deleteLocation(tm.getLocation());
 +          if (logsForDeadServers != null) {
 +            List<Path> logs = 
logsForDeadServers.get(tm.getLocation().getServerInstance());
 +            if (logs != null) {
 +              for (Path log : logs) {
 +                LogEntry entry = LogEntry.fromPath(log.toString());
 +                tabletMutator.putWal(entry);
 +              }
 +            }
 +          }
 +        }
 +
 +        if (tm.getLocation() != null && tm.getLocation().getType() != null
 +            && tm.getLocation().getType().equals(LocationType.FUTURE)) {
 +          tabletMutator.deleteLocation(tm.getLocation());
 +        }
 +
 +        processSuspension(tabletMutator, tm, suspensionTimestamp);
 +
 +        tabletMutator.submit(tabletMetadata -> tabletMetadata.getLocation() 
== null);
 +      }
 +
 +      Map<KeyExtent,Ample.ConditionalResult> results = 
tabletsMutator.process();
 +
 +      if (results.values().stream()
 +          .anyMatch(conditionalResult -> conditionalResult.getStatus() != 
Status.ACCEPTED)) {
 +        throw new DistributedStoreException("Some unassignments did not 
satisfy conditions.");
 +      }
 +
 +    } catch (RuntimeException ex) {
 +      throw new DistributedStoreException(ex);
 +    }
 +  }
 +
 +  protected static void updateLastLocation(Ample.TabletUpdates<?> 
tabletMutator,
 +      TServerInstance location, Location lastLocation) {
 +    Preconditions.checkArgument(
 +        lastLocation == null || lastLocation.getType() == 
TabletMetadata.LocationType.LAST);
 +    Location newLocation = Location.last(location);
 +    if (lastLocation != null) {
 +      if (!lastLocation.equals(newLocation)) {
 +        tabletMutator.deleteLocation(lastLocation);
 +        tabletMutator.putLocation(newLocation);
 +      }
 +    } else {
 +      tabletMutator.putLocation(newLocation);
 +    }
 +  }
 +
 +}
diff --cc 
server/base/src/main/java/org/apache/accumulo/server/manager/state/LoggingTabletStateStore.java
index 8545ecd7c7,63b00064e6..ec93787abb
--- 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/LoggingTabletStateStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/LoggingTabletStateStore.java
@@@ -21,14 -21,12 +21,14 @@@ package org.apache.accumulo.server.mana
  import java.util.Collection;
  import java.util.List;
  import java.util.Map;
- import java.util.concurrent.TimeUnit;
  
 +import org.apache.accumulo.core.data.Range;
  import org.apache.accumulo.core.logging.TabletLogger;
 +import org.apache.accumulo.core.manager.state.TabletManagement;
  import org.apache.accumulo.core.metadata.TServerInstance;
 -import org.apache.accumulo.core.metadata.TabletLocationState;
  import org.apache.accumulo.core.metadata.schema.Ample.DataLevel;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.hadoop.fs.Path;
  
  import com.google.common.net.HostAndPort;
@@@ -88,8 -85,8 +88,8 @@@ class LoggingTabletStateStore implement
    }
  
    @Override
 -  public void suspend(Collection<TabletLocationState> tablets,
 +  public void suspend(Collection<TabletMetadata> tablets,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
+       Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
        throws DistributedStoreException {
      wrapped.suspend(tablets, logsForDeadServers, suspensionTimestamp);
  
@@@ -103,8 -100,7 +103,8 @@@
        if (location != null) {
          server = location.getHostAndPort();
        }
-       TabletLogger.suspended(tm.getExtent(), server, suspensionTimestamp, 
TimeUnit.MILLISECONDS,
 -      TabletLogger.suspended(tls.extent, server, suspensionTimestamp, 
logsForDeadServers.size());
++      TabletLogger.suspended(tm.getExtent(), server, suspensionTimestamp,
 +          logsForDeadServers.size());
      }
    }
  
diff --cc 
server/base/src/main/java/org/apache/accumulo/server/manager/state/MetaDataStateStore.java
index 972d6e927e,acc37a2075..a7e22a75e8
--- 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/MetaDataStateStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/MetaDataStateStore.java
@@@ -18,26 -18,28 +18,27 @@@
   */
  package org.apache.accumulo.server.manager.state;
  
 +import static 
org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.SUSPEND;
 +
  import java.util.Collection;
  import java.util.List;
 -import java.util.Map;
  
  import org.apache.accumulo.core.clientImpl.ClientContext;
 +import org.apache.accumulo.core.data.Range;
 +import org.apache.accumulo.core.manager.state.TabletManagement;
  import org.apache.accumulo.core.metadata.AccumuloTable;
 -import org.apache.accumulo.core.metadata.TServerInstance;
 -import org.apache.accumulo.core.metadata.TabletLocationState;
  import org.apache.accumulo.core.metadata.schema.Ample;
 +import 
org.apache.accumulo.core.metadata.schema.Ample.ConditionalResult.Status;
  import org.apache.accumulo.core.metadata.schema.Ample.DataLevel;
 -import org.apache.accumulo.core.metadata.schema.Ample.TabletMutator;
 -import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
 -import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
 -import org.apache.accumulo.core.tabletserver.log.LogEntry;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata;
+ import org.apache.accumulo.core.util.time.SteadyTime;
 -import org.apache.accumulo.server.util.ManagerMetadataUtil;
 -import org.apache.hadoop.fs.Path;
 +import org.apache.accumulo.server.ServerContext;
 +
 +import com.google.common.base.Preconditions;
  
 -class MetaDataStateStore implements TabletStateStore {
 +class MetaDataStateStore extends AbstractTabletStateStore implements 
TabletStateStore {
  
    protected final ClientContext context;
 -  protected final CurrentState state;
    private final String targetTableName;
    private final Ample ample;
    private final DataLevel level;
@@@ -93,16 -104,64 +94,16 @@@
    }
  
    @Override
 -  public void suspend(Collection<TabletLocationState> tablets,
 -      Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
 -      throws DistributedStoreException {
 -    unassign(tablets, logsForDeadServers, suspensionTimestamp);
 -  }
 -
 -  private void unassign(Collection<TabletLocationState> tablets,
 -      Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
 -      throws DistributedStoreException {
 -    try (var tabletsMutator = ample.mutateTablets()) {
 -      for (TabletLocationState tls : tablets) {
 -        TabletMutator tabletMutator = tabletsMutator.mutateTablet(tls.extent);
 -        if (tls.current != null) {
 -          ManagerMetadataUtil.updateLastForAssignmentMode(context, 
tabletMutator,
 -              tls.current.getServerInstance(), tls.last);
 -          tabletMutator.deleteLocation(tls.current);
 -          if (logsForDeadServers != null) {
 -            List<Path> logs = 
logsForDeadServers.get(tls.current.getServerInstance());
 -            if (logs != null) {
 -              for (Path log : logs) {
 -                LogEntry entry = LogEntry.fromPath(log.toString());
 -                tabletMutator.putWal(entry);
 -              }
 -            }
 -          }
 -          if (suspensionTimestamp != null && suspensionTimestamp.getMillis() 
>= 0) {
 -            tabletMutator.putSuspension(tls.current.getServerInstance(), 
suspensionTimestamp);
 -          }
 -        }
 -        if (tls.suspend != null && suspensionTimestamp == null) {
 -          tabletMutator.deleteSuspension();
 -        }
 -        if (tls.hasFuture()) {
 -          tabletMutator.deleteLocation(tls.future);
 -        }
 -        tabletMutator.mutate();
 +  protected void processSuspension(Ample.ConditionalTabletMutator 
tabletMutator, TabletMetadata tm,
-       long suspensionTimestamp) {
++      SteadyTime suspensionTimestamp) {
 +    if (tm.hasCurrent()) {
-       if (suspensionTimestamp >= 0) {
++      if (suspensionTimestamp != null) {
 +        tabletMutator.putSuspension(tm.getLocation().getServerInstance(), 
suspensionTimestamp);
        }
 -    } catch (RuntimeException ex) {
 -      throw new DistributedStoreException(ex);
      }
 -  }
  
-     if (tm.getSuspend() != null && suspensionTimestamp < 0) {
 -  @Override
 -  public void unsuspend(Collection<TabletLocationState> tablets) throws 
DistributedStoreException {
 -    try (var tabletsMutator = ample.mutateTablets()) {
 -      for (TabletLocationState tls : tablets) {
 -        if (tls.suspend != null) {
 -          tabletsMutator.mutateTablet(tls.extent).deleteSuspension().mutate();
 -        }
 -      }
 -    } catch (RuntimeException ex) {
 -      throw new DistributedStoreException(ex);
++    if (tm.getSuspend() != null && suspensionTimestamp == null) {
 +      tabletMutator.deleteSuspension();
      }
    }
 -
 -  @Override
 -  public String name() {
 -    return "Normal Tablets";
 -  }
 -
  }
diff --cc 
server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletStateStore.java
index ee81950fe7,9f4302bfdb..602409125e
--- 
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletStateStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletStateStore.java
@@@ -23,13 -23,12 +23,14 @@@ import java.util.Collections
  import java.util.List;
  import java.util.Map;
  
 -import org.apache.accumulo.core.clientImpl.ClientContext;
 +import org.apache.accumulo.core.data.Range;
  import org.apache.accumulo.core.dataImpl.KeyExtent;
 +import org.apache.accumulo.core.manager.state.TabletManagement;
  import org.apache.accumulo.core.metadata.TServerInstance;
 -import org.apache.accumulo.core.metadata.TabletLocationState;
  import org.apache.accumulo.core.metadata.schema.Ample.DataLevel;
 +import org.apache.accumulo.core.metadata.schema.MetadataSchema;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.accumulo.server.ServerContext;
  import org.apache.hadoop.fs.Path;
  
@@@ -85,8 -76,8 +86,8 @@@ public interface TabletStateStore 
     * Mark tablets as having no known or future location, but desiring to be 
returned to their
     * previous tserver.
     */
 -  void suspend(Collection<TabletLocationState> tablets,
 +  void suspend(Collection<TabletMetadata> tablets,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
+       Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
        throws DistributedStoreException;
  
    /**
@@@ -100,10 -91,10 +101,10 @@@
          logsForDeadServers);
    }
  
 -  public static void suspend(ServerContext context, TabletLocationState tls,
 +  public static void suspend(ServerContext context, TabletMetadata tm,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
+       Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
        throws DistributedStoreException {
 -    getStoreForTablet(tls.extent, 
context).suspend(Collections.singletonList(tls),
 +    getStoreForTablet(tm.getExtent(), 
context).suspend(Collections.singletonList(tm),
          logsForDeadServers, suspensionTimestamp);
    }
  
diff --cc 
server/base/src/main/java/org/apache/accumulo/server/manager/state/ZooTabletStateStore.java
index f355f291ec,639c72f47f..cbb5c280ac
--- 
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
@@@ -26,28 -22,23 +26,29 @@@ import java.util.AbstractMap
  import java.util.Collection;
  import java.util.List;
  import java.util.Map;
 -
 -import org.apache.accumulo.core.clientImpl.ClientContext;
 +import java.util.Map.Entry;
 +import java.util.NoSuchElementException;
 +import java.util.concurrent.atomic.AtomicBoolean;
 +
 +import org.apache.accumulo.core.data.Key;
 +import org.apache.accumulo.core.data.Range;
 +import org.apache.accumulo.core.data.Value;
 +import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
 +import org.apache.accumulo.core.iterators.user.WholeRowIterator;
 +import org.apache.accumulo.core.iteratorsImpl.system.SortedMapIterator;
 +import org.apache.accumulo.core.manager.state.TabletManagement;
 +import org.apache.accumulo.core.metadata.AccumuloTable;
  import org.apache.accumulo.core.metadata.RootTable;
  import org.apache.accumulo.core.metadata.TServerInstance;
 -import org.apache.accumulo.core.metadata.TabletLocationState;
 -import 
org.apache.accumulo.core.metadata.TabletLocationState.BadLocationStateException;
  import org.apache.accumulo.core.metadata.schema.Ample;
  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.Ample.TabletMutator;
 +import org.apache.accumulo.core.metadata.schema.RootTabletMetadata;
  import org.apache.accumulo.core.metadata.schema.TabletMetadata;
 -import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
 -import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
 -import org.apache.accumulo.core.tabletserver.log.LogEntry;
+ import org.apache.accumulo.core.util.time.SteadyTime;
 -import org.apache.accumulo.server.util.ManagerMetadataUtil;
 +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;
  
@@@ -189,17 -188,11 +190,17 @@@ class ZooTabletStateStore extends Abstr
    }
  
    @Override
 -  public void suspend(Collection<TabletLocationState> tablets,
 +  public void suspend(Collection<TabletMetadata> tablets,
-       Map<TServerInstance,List<Path>> logsForDeadServers, long 
suspensionTimestamp)
+       Map<TServerInstance,List<Path>> logsForDeadServers, SteadyTime 
suspensionTimestamp)
        throws DistributedStoreException {
 -    // No support for suspending root tablet.
 -    unassign(tablets, logsForDeadServers);
 +    validateTablets(tablets);
 +    super.suspend(tablets, logsForDeadServers, suspensionTimestamp);
 +  }
 +
 +  @Override
 +  protected void processSuspension(Ample.ConditionalTabletMutator 
tabletMutator, TabletMetadata tm,
-       long suspensionTimestamp) {
++      SteadyTime suspensionTimestamp) {
 +    // No support for suspending root tablet, so this is a NOOP
    }
  
    @Override
diff --cc 
server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java
index ca69231394,7adba90fe0..7ab6415646
--- 
a/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java
+++ 
b/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java
@@@ -768,9 -452,9 +768,9 @@@ abstract class TabletGroupWatcher exten
      }
    }
  
 -  private void hostSuspendedTablet(TabletLists tLists, TabletLocationState 
tls, Location location,
 +  private void hostSuspendedTablet(TabletLists tLists, TabletMetadata tm, 
Location location,
        TableConfiguration tableConf) {
-     if (manager.getSteadyTime().getMillis() - tm.getSuspend().suspensionTime
 -    if (manager.getSteadyTime().minus(tls.suspend.suspensionTime).toMillis()
++    if 
(manager.getSteadyTime().minus(tm.getSuspend().suspensionTime).toMillis()
          < tableConf.getTimeInMillis(Property.TABLE_SUSPEND_DURATION)) {
        // Tablet is suspended. See if its tablet server is back.
        TServerInstance returnInstance = null;
diff --cc 
server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
index a1770b90cb,af16beed4c..4309c0bfe8
--- 
a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
+++ 
b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletClientHandler.java
@@@ -92,7 -101,9 +92,8 @@@ import org.apache.accumulo.core.tablets
  import org.apache.accumulo.core.trace.TraceUtil;
  import org.apache.accumulo.core.util.ByteBufferUtil;
  import org.apache.accumulo.core.util.Halt;
 -import org.apache.accumulo.core.util.Pair;
  import org.apache.accumulo.core.util.threads.Threads;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.accumulo.server.ServerContext;
  import org.apache.accumulo.server.compaction.CompactionInfo;
  import org.apache.accumulo.server.compaction.FileCompactor;
diff --cc 
server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java
index a1d46257ec,27c1048b24..c7db2ed117
--- 
a/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java
+++ 
b/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java
@@@ -21,10 -21,13 +21,10 @@@ package org.apache.accumulo.tserver
  import org.apache.accumulo.core.conf.Property;
  import org.apache.accumulo.core.dataImpl.KeyExtent;
  import org.apache.accumulo.core.manager.thrift.TabletLoadState;
 -import org.apache.accumulo.core.metadata.TServerInstance;
 -import org.apache.accumulo.core.metadata.TabletLocationState;
 -import 
org.apache.accumulo.core.metadata.TabletLocationState.BadLocationStateException;
 -import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
 +import org.apache.accumulo.core.metadata.schema.TabletMetadata;
  import org.apache.accumulo.core.tablet.thrift.TUnloadTabletGoal;
+ import org.apache.accumulo.core.util.time.NanoTime;
+ import org.apache.accumulo.core.util.time.SteadyTime;
  import org.apache.accumulo.server.manager.state.DistributedStoreException;
  import org.apache.accumulo.server.manager.state.TabletStateStore;
  import org.apache.accumulo.tserver.managermessage.TabletStatusMessage;
@@@ -109,10 -120,10 +111,10 @@@ class UnloadTabletHandler implements Ru
        if (!goalState.equals(TUnloadTabletGoal.SUSPENDED) || 
extent.isRootTablet()
            || (extent.isMeta()
                && 
!server.getConfiguration().getBoolean(Property.MANAGER_METADATA_SUSPENDABLE))) {
 -        TabletStateStore.unassign(server.getContext(), tls, null);
 +        TabletStateStore.unassign(server.getContext(), tm, null);
        } else {
 -        TabletStateStore.suspend(server.getContext(), tls, null,
 +        TabletStateStore.suspend(server.getContext(), tm, null,
-             requestTimeSkew + NANOSECONDS.toMillis(System.nanoTime()));
+             requestTime.plus(createTime.elapsed()));
        }
      } catch (DistributedStoreException ex) {
        log.warn("Unable to update storage", ex);

Reply via email to