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 c49e8f6a5c fixes metadata compactions and adds tests (#3539)
c49e8f6a5c is described below
commit c49e8f6a5c50382fe261988a50977d0574ef09d9
Author: Keith Turner <[email protected]>
AuthorDate: Fri Jun 30 12:14:03 2023 -0400
fixes metadata compactions and adds tests (#3539)
There are three changes in this commit.
1. Compactions were not being initiated for the root tablet. This was
fixed
2. Configures an external compaction queue named 'accumulo_meta' for
the root and metadata table. This was set in default properties.
3. Added an IT that ensures the root and metadata table will compact
down to one file.
fixes #3463
---
.../org/apache/accumulo/core/conf/Property.java | 6 +-
.../server/manager/state/TabletStateStore.java | 5 +-
.../server/manager/state/ZooTabletStateStore.java | 23 +-
.../manager/state/RootTabletStateStoreTest.java | 311 ---------------------
.../manager/state/ZooTabletStateStoreTest.java | 63 +++++
.../accumulo/tserver/tablet/CompactableImpl.java | 3 +-
.../test/ManagerRepairsDualAssignmentIT.java | 4 +-
.../accumulo/test/functional/CompactionIT.java | 67 +++++
8 files changed, 157 insertions(+), 325 deletions(-)
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
index 06bc8383c4..b9cd411847 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
@@ -570,8 +570,7 @@ public enum Property {
"The maximum number of files a compaction will open", "2.1.0"),
TSERV_COMPACTION_SERVICE_ROOT_EXECUTORS(
"tserver.compaction.major.service.root.planner.opts.executors",
-
"[{'name':'small','type':'internal','maxSize':'32M','numThreads':1},{'name':'huge','type':'internal','numThreads':1}]"
- .replaceAll("'", "\""),
+
"[{'name':'all','type':'external','queue':'accumulo_meta'}]".replaceAll("'",
"\""),
PropertyType.STRING,
"See {% jlink -f
org.apache.accumulo.core.spi.compaction.DefaultCompactionPlanner %} ",
"2.1.0"),
@@ -588,8 +587,7 @@ public enum Property {
"The maximum number of files a compaction will open", "2.1.0"),
TSERV_COMPACTION_SERVICE_META_EXECUTORS(
"tserver.compaction.major.service.meta.planner.opts.executors",
-
"[{'name':'small','type':'internal','maxSize':'32M','numThreads':2},{'name':'huge','type':'internal','numThreads':2}]"
- .replaceAll("'", "\""),
+
"[{'name':'all','type':'external','queue':'accumulo_meta'}]".replaceAll("'",
"\""),
PropertyType.STRING,
"See {% jlink -f
org.apache.accumulo.core.spi.compaction.DefaultCompactionPlanner %} ",
"2.1.0"),
diff --git
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
index 9b127b6220..6bba19ddac 100644
---
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,7 +23,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-import org.apache.accumulo.core.clientImpl.ClientContext;
import org.apache.accumulo.core.dataImpl.KeyExtent;
import org.apache.accumulo.core.manager.state.TabletManagement;
import org.apache.accumulo.core.metadata.TServerInstance;
@@ -103,11 +102,11 @@ public interface TabletStateStore extends
Iterable<TabletManagement> {
return getStoreForLevel(DataLevel.of(extent.tableId()), context);
}
- public static TabletStateStore getStoreForLevel(DataLevel level,
ClientContext context) {
+ public static TabletStateStore getStoreForLevel(DataLevel level,
ServerContext context) {
return getStoreForLevel(level, context, null);
}
- public static TabletStateStore getStoreForLevel(DataLevel level,
ClientContext context,
+ public static TabletStateStore getStoreForLevel(DataLevel level,
ServerContext context,
CurrentState state) {
TabletStateStore tss;
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 69eabaeb9f..7b9008249d 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
@@ -19,11 +19,10 @@
package org.apache.accumulo.server.manager.state;
import java.util.Collection;
+import java.util.EnumSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import org.apache.accumulo.core.clientImpl.ClientContext;
import org.apache.accumulo.core.manager.state.TabletManagement;
import
org.apache.accumulo.core.manager.state.TabletManagement.ManagementAction;
import org.apache.accumulo.core.metadata.RootTable;
@@ -31,6 +30,10 @@ import org.apache.accumulo.core.metadata.TServerInstance;
import org.apache.accumulo.core.metadata.schema.Ample;
import org.apache.accumulo.core.metadata.schema.Ample.ReadConsistency;
import org.apache.accumulo.core.metadata.schema.TabletMetadata;
+import org.apache.accumulo.core.spi.compaction.CompactionKind;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.accumulo.server.ServiceEnvironmentImpl;
+import org.apache.accumulo.server.compaction.CompactionJobGenerator;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +42,11 @@ class ZooTabletStateStore extends AbstractTabletStateStore
implements TabletStat
private static final Logger log =
LoggerFactory.getLogger(ZooTabletStateStore.class);
private final Ample ample;
+ private final ServerContext ctx;
- ZooTabletStateStore(ClientContext context) {
+ ZooTabletStateStore(ServerContext context) {
super(context);
+ this.ctx = context;
this.ample = context.getAmple();
}
@@ -60,7 +65,17 @@ class ZooTabletStateStore extends AbstractTabletStateStore
implements TabletStat
public TabletManagement next() {
finished = true;
TabletMetadata tm = ample.readTablet(RootTable.EXTENT,
ReadConsistency.EVENTUAL);
- return new
TabletManagement(Set.of(ManagementAction.NEEDS_LOCATION_UPDATE), tm);
+
+ var actions = EnumSet.of(ManagementAction.NEEDS_LOCATION_UPDATE);
+
+ CompactionJobGenerator cjg = new CompactionJobGenerator(new
ServiceEnvironmentImpl(ctx));
+ var jobs = cjg.generateJobs(tm,
+ EnumSet.of(CompactionKind.SYSTEM, CompactionKind.USER,
CompactionKind.SELECTOR));
+ if (!jobs.isEmpty()) {
+ actions.add(ManagementAction.NEEDS_COMPACTING);
+ }
+
+ return new TabletManagement(actions, tm);
}
@Override
diff --git
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/RootTabletStateStoreTest.java
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/RootTabletStateStoreTest.java
deleted file mode 100644
index 55f7cc2779..0000000000
---
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/RootTabletStateStoreTest.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * 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 static java.nio.charset.StandardCharsets.UTF_8;
-import static
org.apache.accumulo.server.init.ZooKeeperInitializer.getInitialRootTabletJson;
-import static org.easymock.EasyMock.expect;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.OptionalLong;
-import java.util.Set;
-import java.util.SortedMap;
-
-import org.apache.accumulo.core.client.ConditionalWriter;
-import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.client.admin.TabletHostingGoal;
-import org.apache.accumulo.core.data.ConditionalMutation;
-import org.apache.accumulo.core.data.Key;
-import org.apache.accumulo.core.data.TableId;
-import org.apache.accumulo.core.data.Value;
-import org.apache.accumulo.core.dataImpl.KeyExtent;
-import org.apache.accumulo.core.manager.state.TabletManagement;
-import org.apache.accumulo.core.metadata.RootTable;
-import org.apache.accumulo.core.metadata.StoredTabletFile;
-import org.apache.accumulo.core.metadata.SuspendingTServer;
-import org.apache.accumulo.core.metadata.TServerInstance;
-import org.apache.accumulo.core.metadata.TabletState;
-import org.apache.accumulo.core.metadata.schema.Ample;
-import org.apache.accumulo.core.metadata.schema.DataFileValue;
-import org.apache.accumulo.core.metadata.schema.ExternalCompactionId;
-import org.apache.accumulo.core.metadata.schema.ExternalCompactionMetadata;
-import org.apache.accumulo.core.metadata.schema.MetadataTime;
-import org.apache.accumulo.core.metadata.schema.RootTabletMetadata;
-import org.apache.accumulo.core.metadata.schema.TabletMetadata;
-import org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType;
-import org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType;
-import org.apache.accumulo.core.metadata.schema.TabletOperationId;
-import org.apache.accumulo.core.metadata.schema.TabletsMetadata;
-import org.apache.accumulo.core.tabletserver.log.LogEntry;
-import org.apache.accumulo.server.MockServerContext;
-import org.apache.accumulo.server.ServerContext;
-import org.apache.accumulo.server.metadata.ConditionalTabletsMutatorImpl;
-import org.apache.hadoop.io.Text;
-import org.easymock.EasyMock;
-import org.junit.jupiter.api.Test;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterators;
-import com.google.common.net.HostAndPort;
-
-public class RootTabletStateStoreTest {
-
- private static class BrokenTabletMetadata extends TabletMetadata {
- private final TabletMetadata tm;
-
- BrokenTabletMetadata(TabletMetadata tm) {
- this.tm = tm;
- }
-
- public boolean equals(Object obj) {
- return tm.equals(obj);
- }
-
- public TableId getTableId() {
- return TableId.of("0");
- }
-
- public KeyExtent getExtent() {
- return new KeyExtent(TableId.of("0"), null, null);
- }
-
- public Text getPrevEndRow() {
- return tm.getPrevEndRow();
- }
-
- public boolean sawPrevEndRow() {
- return tm.sawPrevEndRow();
- }
-
- public Text getOldPrevEndRow() {
- return tm.getOldPrevEndRow();
- }
-
- public boolean sawOldPrevEndRow() {
- return tm.sawOldPrevEndRow();
- }
-
- public Text getEndRow() {
- return tm.getEndRow();
- }
-
- public Location getLocation() {
- return tm.getLocation();
- }
-
- public boolean hasCurrent() {
- return tm.hasCurrent();
- }
-
- public Map<StoredTabletFile,Long> getLoaded() {
- return tm.getLoaded();
- }
-
- public Location getLast() {
- return tm.getLast();
- }
-
- public SuspendingTServer getSuspend() {
- return tm.getSuspend();
- }
-
- public Set<StoredTabletFile> getFiles() {
- return tm.getFiles();
- }
-
- public Map<StoredTabletFile,DataFileValue> getFilesMap() {
- return tm.getFilesMap();
- }
-
- public Collection<LogEntry> getLogs() {
- return tm.getLogs();
- }
-
- public List<StoredTabletFile> getScans() {
- return tm.getScans();
- }
-
- public String getDirName() {
- return tm.getDirName();
- }
-
- public MetadataTime getTime() {
- return tm.getTime();
- }
-
- public String getCloned() {
- return tm.getCloned();
- }
-
- public OptionalLong getFlushId() {
- return tm.getFlushId();
- }
-
- public OptionalLong getCompactId() {
- return tm.getCompactId();
- }
-
- public Double getSplitRatio() {
- return tm.getSplitRatio();
- }
-
- public boolean hasChopped() {
- return tm.hasChopped();
- }
-
- public TabletHostingGoal getHostingGoal() {
- return tm.getHostingGoal();
- }
-
- public boolean getHostingRequested() {
- return tm.getHostingRequested();
- }
-
- public SortedMap<Key,Value> getKeyValues() {
- return tm.getKeyValues();
- }
-
- public TabletState getTabletState(Set<TServerInstance> liveTServers) {
- return tm.getTabletState(liveTServers);
- }
-
- public Map<ExternalCompactionId,ExternalCompactionMetadata>
getExternalCompactions() {
- return tm.getExternalCompactions();
- }
-
- public TabletOperationId getOperationId() {
- return tm.getOperationId();
- }
-
- public int hashCode() {
- return tm.hashCode();
- }
-
- public String toString() {
- return tm.toString();
- }
- }
-
- private static class TestAmple implements Ample {
-
- private String json =
- new String(getInitialRootTabletJson("dir",
"hdfs://nn/acc/tables/some/dir/0000.rf"), UTF_8);
-
- @Override
- public TabletMetadata readTablet(KeyExtent extent, ReadConsistency rc,
- ColumnType... colsToFetch) {
- Preconditions.checkArgument(extent.equals(RootTable.EXTENT));
- return new RootTabletMetadata(json).toTabletMetadata();
- }
-
- @Override
- public TabletsMetadata.TableOptions readTablets() {
- throw new UnsupportedOperationException("This method should be
implemented in subclasses");
- }
-
- public ConditionalTabletsMutator conditionallyMutateTablets() {
- return new ConditionalTabletsMutatorImpl(null) {
- protected ConditionalWriter createConditionalWriter(Ample.DataLevel
dataLevel)
- throws TableNotFoundException {
- Preconditions.checkArgument(dataLevel == DataLevel.ROOT);
- return new ConditionalWriter() {
- @Override
- public Iterator<Result> write(Iterator<ConditionalMutation>
mutations) {
- return Iterators.transform(mutations, this::write);
- }
-
- @Override
- public Result write(ConditionalMutation mutation) {
- var rtm = new RootTabletMetadata(json);
- rtm.update(mutation);
- json = rtm.toJson();
- return new Result(Status.ACCEPTED, mutation, "server");
- }
-
- @Override
- public void close() {
-
- }
- };
- }
- };
- }
-
- }
-
- @Test
- public void testRootTabletStateStore() throws DistributedStoreException {
- ServerContext context = MockServerContext.get();
- expect(context.getAmple()).andReturn(new TestAmple()).anyTimes();
- EasyMock.replay(context);
- ZooTabletStateStore tstore = new ZooTabletStateStore(context);
- KeyExtent root = RootTable.EXTENT;
- String sessionId = "this is my unique session data";
- TServerInstance server =
- new TServerInstance(HostAndPort.fromParts("127.0.0.1", 10000),
sessionId);
- List<Assignment> assignments = Collections.singletonList(new
Assignment(root, server, null));
- tstore.setFutureLocations(assignments);
- int count = 0;
- for (TabletManagement mti : tstore) {
- assertEquals(mti.getTabletMetadata().getExtent(), root);
-
assertTrue(mti.getTabletMetadata().getLocation().getType().equals(LocationType.FUTURE));
- assertEquals(mti.getTabletMetadata().getLocation().getServerInstance(),
server);
- assertFalse(mti.getTabletMetadata().hasCurrent());
- count++;
- }
- assertEquals(count, 1);
- tstore.setLocations(assignments);
- count = 0;
- for (TabletManagement mti : tstore) {
- assertEquals(mti.getTabletMetadata().getExtent(), root);
-
assertFalse(mti.getTabletMetadata().getLocation().getType().equals(LocationType.FUTURE));
- assertTrue(mti.getTabletMetadata().hasCurrent());
- assertEquals(mti.getTabletMetadata().getLocation().getServerInstance(),
server);
- count++;
- }
- assertEquals(count, 1);
- TabletManagement rootTabletMetadataInfo = tstore.iterator().next();
-
tstore.unassign(Collections.singletonList(rootTabletMetadataInfo.getTabletMetadata()),
null);
- count = 0;
- for (TabletManagement mti : tstore) {
- assertEquals(mti.getTabletMetadata().getExtent(), root);
- assertFalse(mti.getTabletMetadata().hasCurrent());
- assertNull(mti.getTabletMetadata().getLocation());
- count++;
- }
- assertEquals(count, 1);
-
- KeyExtent notRoot = new KeyExtent(TableId.of("0"), null, null);
- final var assignmentList = List.of(new Assignment(notRoot, server, null));
- assertThrows(IllegalArgumentException.class, () ->
tstore.setLocations(assignmentList));
- assertThrows(IllegalArgumentException.class, () ->
tstore.setFutureLocations(assignmentList));
- final List<TabletMetadata> assignmentList1 =
- List.of(new
BrokenTabletMetadata(rootTabletMetadataInfo.getTabletMetadata()));
- assertThrows(IllegalArgumentException.class, () ->
tstore.unassign(assignmentList1, null));
- }
-}
diff --git
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/ZooTabletStateStoreTest.java
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/ZooTabletStateStoreTest.java
new file mode 100644
index 0000000000..c6023246c2
--- /dev/null
+++
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/ZooTabletStateStoreTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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 static org.easymock.EasyMock.expect;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.List;
+
+import org.apache.accumulo.core.data.TableId;
+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.TabletMetadata;
+import org.apache.accumulo.server.MockServerContext;
+import org.apache.accumulo.server.ServerContext;
+import org.easymock.EasyMock;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.net.HostAndPort;
+
+public class ZooTabletStateStoreTest {
+
+ @Test
+ public void testZooTabletStateStore() throws DistributedStoreException {
+ ServerContext context = MockServerContext.get();
+ Ample ample = EasyMock.createMock(Ample.class);
+ expect(context.getAmple()).andReturn(ample).anyTimes();
+ EasyMock.replay(context, ample);
+ ZooTabletStateStore tstore = new ZooTabletStateStore(context);
+
+ String sessionId = "this is my unique session data";
+ TServerInstance server =
+ new TServerInstance(HostAndPort.fromParts("127.0.0.1", 10000),
sessionId);
+
+ KeyExtent notRoot = new KeyExtent(TableId.of("0"), null, null);
+ final var assignmentList = List.of(new Assignment(notRoot, server, null));
+ assertThrows(IllegalArgumentException.class, () ->
tstore.setLocations(assignmentList));
+ assertThrows(IllegalArgumentException.class, () ->
tstore.setFutureLocations(assignmentList));
+
+ var nonRootMeta = TabletMetadata.builder(new
KeyExtent(TableId.of("notroot"), null, null))
+ .putPrevEndRow(null).build();
+
+ final List<TabletMetadata> assignmentList1 = List.of(nonRootMeta);
+ assertThrows(IllegalArgumentException.class, () ->
tstore.unassign(assignmentList1, null));
+ }
+}
diff --git
a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/CompactableImpl.java
b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/CompactableImpl.java
index 539bc26f11..ec3ed5d71c 100644
---
a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/CompactableImpl.java
+++
b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/CompactableImpl.java
@@ -1089,7 +1089,8 @@ public class CompactableImpl implements Compactable {
return Optional.empty();
}
- if (!getExtent().isRootTablet() && !getExtent().isMeta() && kind ==
CompactionKind.SYSTEM) {
+ if (kind == CompactionKind.SYSTEM || kind == CompactionKind.USER
+ || kind == CompactionKind.SELECTOR || kind == CompactionKind.CHOP) {
// ELASTICITY_TODO a hack added to disable system compactions for user
tablets
return Optional.empty();
}
diff --git
a/test/src/main/java/org/apache/accumulo/test/ManagerRepairsDualAssignmentIT.java
b/test/src/main/java/org/apache/accumulo/test/ManagerRepairsDualAssignmentIT.java
index c0f7c168e1..249c7072f9 100644
---
a/test/src/main/java/org/apache/accumulo/test/ManagerRepairsDualAssignmentIT.java
+++
b/test/src/main/java/org/apache/accumulo/test/ManagerRepairsDualAssignmentIT.java
@@ -88,7 +88,7 @@ public class ManagerRepairsDualAssignmentIT extends
ConfigurableMacBase {
// scan the metadata table and get the two table location states
Set<TabletMetadata.Location> states = new HashSet<>();
Set<TabletMetadata> oldLocations = new HashSet<>();
- TabletStateStore store =
TabletStateStore.getStoreForLevel(DataLevel.USER, context);
+ TabletStateStore store =
TabletStateStore.getStoreForLevel(DataLevel.USER, serverContext);
while (states.size() < 2) {
UtilWaitThread.sleep(250);
oldLocations.clear();
@@ -140,7 +140,7 @@ public class ManagerRepairsDualAssignmentIT extends
ConfigurableMacBase {
serverContext.getAmple().mutateTablet(new
KeyExtent(MetadataTable.ID, null, null));
tabletMutator.putLocation(moved.getLocation());
tabletMutator.mutate();
- waitForCleanStore(TabletStateStore.getStoreForLevel(DataLevel.METADATA,
context));
+ waitForCleanStore(TabletStateStore.getStoreForLevel(DataLevel.METADATA,
serverContext));
}
}
diff --git
a/test/src/main/java/org/apache/accumulo/test/functional/CompactionIT.java
b/test/src/main/java/org/apache/accumulo/test/functional/CompactionIT.java
index 50bea6c05e..0cb24e691f 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/CompactionIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/CompactionIT.java
@@ -19,6 +19,8 @@
package org.apache.accumulo.test.functional;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -66,6 +68,8 @@ import
org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.iterators.user.GrepIterator;
import org.apache.accumulo.core.metadata.MetadataTable;
+import org.apache.accumulo.core.metadata.RootTable;
+import org.apache.accumulo.core.metadata.StoredTabletFile;
import
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily;
import
org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.TabletColumnFamily;
import org.apache.accumulo.core.security.Authorizations;
@@ -75,6 +79,7 @@ import org.apache.accumulo.test.VerifyIngest;
import org.apache.accumulo.test.VerifyIngest.VerifyParams;
import org.apache.accumulo.test.compaction.CompactionExecutorIT;
import org.apache.accumulo.test.compaction.ExternalCompaction_1_IT.FSelector;
+import org.apache.accumulo.test.util.Wait;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
@@ -622,6 +627,68 @@ public class CompactionIT extends AccumuloClusterHarness {
}
}
+ @Test
+ public void testMetadataCompactions() throws Exception {
+ // The metadata and root table have default config that causes them to
compact down to one
+ // tablet. This test verifies that both tables compact to one file after a
flush.
+ try (AccumuloClient c =
Accumulo.newClient().from(getClientProps()).build()) {
+ String[] tableNames = getUniqueNames(2);
+
+ // creating a user table should cause a write to the metadata table
+ c.tableOperations().create(tableNames[0]);
+
+ var mfiles1 =
getServerContext().getAmple().readTablets().forTable(MetadataTable.ID).build()
+ .iterator().next().getFiles();
+ var rootFiles1 =
getServerContext().getAmple().readTablet(RootTable.EXTENT).getFiles();
+
+ log.debug("mfiles1 {}",
+
mfiles1.stream().map(StoredTabletFile::getFileName).collect(toList()));
+ log.debug("rootFiles1 {}",
+
rootFiles1.stream().map(StoredTabletFile::getFileName).collect(toList()));
+
+ c.tableOperations().flush(MetadataTable.NAME, null, null, true);
+ c.tableOperations().flush(RootTable.NAME, null, null, true);
+
+ // create another table to cause more metadata writes
+ c.tableOperations().create(tableNames[1]);
+ try (var writer = c.createBatchWriter(tableNames[1])) {
+ var m = new Mutation("r1");
+ m.put("f1", "q1", "v1");
+ writer.addMutation(m);
+ }
+ c.tableOperations().flush(tableNames[1], null, null, true);
+
+ // create another metadata file
+ c.tableOperations().flush(MetadataTable.NAME, null, null, true);
+ c.tableOperations().flush(RootTable.NAME, null, null, true);
+
+ // The multiple flushes should create multiple files. We expect the file
sets to changes and
+ // eventually equal one.
+
+ Wait.waitFor(() -> {
+ var mfiles2 =
getServerContext().getAmple().readTablets().forTable(MetadataTable.ID).build()
+ .iterator().next().getFiles();
+ log.debug("mfiles2 {}",
+
mfiles2.stream().map(StoredTabletFile::getFileName).collect(toList()));
+ return mfiles2.size() == 1 && !mfiles2.equals(mfiles1);
+ });
+
+ Wait.waitFor(() -> {
+ var rootFiles2 =
getServerContext().getAmple().readTablet(RootTable.EXTENT).getFiles();
+ log.debug("rootFiles2 {}",
+
rootFiles2.stream().map(StoredTabletFile::getFileName).collect(toList()));
+ return rootFiles2.size() == 1 && !rootFiles2.equals(rootFiles1);
+ });
+
+ var entries = c.createScanner(tableNames[1]).stream()
+ .map(e -> e.getKey().getRow() + ":" + e.getKey().getColumnFamily() +
":"
+ + e.getKey().getColumnQualifier() + ":" + e.getValue())
+ .collect(toSet());
+
+ assertEquals(Set.of("r1:f1:q1:v1"), entries);
+ }
+ }
+
private int countFiles(AccumuloClient c) throws Exception {
try (Scanner s = c.createScanner(MetadataTable.NAME,
Authorizations.EMPTY)) {
s.fetchColumnFamily(new Text(TabletColumnFamily.NAME));