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 d594e585a781797082fcd3cb5202cc67cf84e45a Merge: 8375719384 b8089dd528 Author: Christopher L. Shannon (cshannon) <christopher.l.shan...@gmail.com> AuthorDate: Sat Nov 18 15:09:55 2023 -0500 Merge branch 'main' into elasticity .../core/metadata/schema/MetadataSchema.java | 13 ++ .../core/metadata/schema/TabletMetadata.java | 11 ++ .../core/metadata/schema/TabletsMetadata.java | 4 + .../core/metadata/schema/TabletMetadataTest.java | 29 ++++ .../server/constraints/MetadataConstraints.java | 6 +- test/pom.xml | 4 + .../java/org/apache/accumulo/test/CloneIT.java | 149 +++++++++++++-------- .../org/apache/accumulo/test/ImportExportIT.java | 74 +++++++--- .../java/org/apache/accumulo/test/MetaSplitIT.java | 9 ++ .../apache/accumulo/test/functional/MergeIT.java | 22 ++- .../accumulo/test/util/FileMetadataUtil.java | 9 ++ 11 files changed, 248 insertions(+), 82 deletions(-) diff --cc core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataSchema.java index fefe9b6911,2bc0a6e18e..d7f6452670 --- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataSchema.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataSchema.java @@@ -35,6 -35,6 +35,7 @@@ import org.apache.accumulo.core.schema. import org.apache.accumulo.core.util.ColumnFQ; import org.apache.accumulo.core.util.Pair; import org.apache.hadoop.io.Text; ++import org.checkerframework.common.returnsreceiver.qual.This; import com.google.common.base.Preconditions; @@@ -397,23 -326,17 +398,35 @@@ public class MetadataSchema public static final Text NAME = new Text(STR_NAME); } + /** + * Column family for indicating that the files in a tablet contain fenced files that have been + * merged from other tablets during a merge operation. This is used to support resuming a failed + * merge operation. + */ + public static class MergedColumnFamily { + public static final String STR_NAME = "merged"; + public static final Text NAME = new Text(STR_NAME); + public static final ColumnFQ MERGED_COLUMN = new ColumnFQ(NAME, new Text(STR_NAME)); + public static final Value MERGED_VALUE = new Value("merged"); + } ++ + /** + * This family is used to track which tablets were compacted by a user compaction. The column + * qualifier is expected to contain the fate transaction id that is executing the compaction. + */ + public static class CompactedColumnFamily { + public static final String STR_NAME = "compacted"; + public static final Text NAME = new Text(STR_NAME); + } + + public static class HostingColumnFamily { + public static final String STR_NAME = "hosting"; + public static final Text NAME = new Text(STR_NAME); + public static final String GOAL_QUAL = "goal"; + public static final ColumnFQ GOAL_COLUMN = new ColumnFQ(NAME, new Text(GOAL_QUAL)); + public static final String REQUESTED_QUAL = "requested"; + public static final ColumnFQ REQUESTED_COLUMN = new ColumnFQ(NAME, new Text(REQUESTED_QUAL)); + } } /** diff --cc core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java index 2ae7f394b7,af31605d51..391f81ffed --- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java @@@ -68,9 -60,9 +68,10 @@@ import org.apache.accumulo.core.metadat import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ExternalCompactionColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.HostingColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LogColumnFamily; + import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.MergedColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ScanFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.SuspendLocationColumn; @@@ -118,15 -105,7 +119,16 @@@ public class TabletMetadata private OptionalLong compact = OptionalLong.empty(); private Double splitRatio = null; private Map<ExternalCompactionId,ExternalCompactionMetadata> extCompactions; + private boolean merged; + private TabletHostingGoal goal = TabletHostingGoal.ONDEMAND; + private boolean onDemandHostingRequested = false; + private TabletOperationId operationId; + private boolean futureAndCurrentLocationSet = false; + private Set<Long> compacted; + + public static TabletMetadataBuilder builder(KeyExtent extent) { + return new TabletMetadataBuilder(extent); + } public enum LocationType { CURRENT, FUTURE, LAST @@@ -149,11 -128,7 +151,12 @@@ SPLIT_RATIO, SUSPEND, ECOMP, - MERGED ++ MERGED, + HOSTING_GOAL, + HOSTING_REQUESTED, + OPID, + SELECTED, + COMPACTED } public static class Location { @@@ -379,37 -348,11 +382,42 @@@ return splitRatio; } + public boolean hasMerged() { + ensureFetched(ColumnType.MERGED); + return merged; + } + + public TabletHostingGoal getHostingGoal() { + if (RootTable.ID.equals(getTableId()) || MetadataTable.ID.equals(getTableId())) { + // Override the goal for the system tables + return TabletHostingGoal.ALWAYS; + } + ensureFetched(ColumnType.HOSTING_GOAL); + return goal; + } + + public boolean getHostingRequested() { + ensureFetched(ColumnType.HOSTING_REQUESTED); + return onDemandHostingRequested; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("tableId", tableId) + .append("prevEndRow", prevEndRow).append("sawPrevEndRow", sawPrevEndRow) + .append("oldPrevEndRow", oldPrevEndRow).append("sawOldPrevEndRow", sawOldPrevEndRow) + .append("endRow", endRow).append("location", location).append("files", files) + .append("scans", scans).append("loadedFiles", loadedFiles) + .append("fetchedCols", fetchedCols).append("extent", extent).append("last", last) + .append("suspend", suspend).append("dirName", dirName).append("time", time) + .append("cloned", cloned).append("flush", flush).append("logs", logs) + .append("compact", compact).append("splitRatio", splitRatio) + .append("extCompactions", extCompactions).append("goal", goal) + .append("onDemandHostingRequested", onDemandHostingRequested) + .append("operationId", operationId).append("selectedFiles", selectedFiles) + .append("futureAndCurrentLocationSet", futureAndCurrentLocationSet).toString(); + } + public SortedMap<Key,Value> getKeyValues() { Preconditions.checkState(keyValues != null, "Requested key values when it was not saved"); return keyValues; @@@ -549,21 -487,11 +557,24 @@@ extCompBuilder.put(ExternalCompactionId.of(qual), ExternalCompactionMetadata.fromJson(val)); break; + case MergedColumnFamily.STR_NAME: + te.merged = true; + break; - default: - throw new IllegalStateException("Unexpected family " + fam); + case CompactedColumnFamily.STR_NAME: + compactedBuilder.add(FateTxId.fromString(qual)); + break; + case HostingColumnFamily.STR_NAME: + switch (qual) { + case GOAL_QUAL: + te.goal = TabletHostingGoalUtil.fromValue(kv.getValue()); + break; + case REQUESTED_QUAL: + te.onDemandHostingRequested = true; + break; + default: + throw new IllegalStateException("Unexpected family " + fam); + } + break; } } diff --cc core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java index 3e50d5d17d,515e6a08ef..997d082084 --- 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 @@@ -77,9 -74,9 +77,10 @@@ import org.apache.accumulo.core.metadat import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ExternalCompactionColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.HostingColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LogColumnFamily; + import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.MergedColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ScanFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.SuspendLocationColumn; import org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType; @@@ -346,17 -337,12 +347,20 @@@ public class TabletsMetadata implement case ECOMP: families.add(ExternalCompactionColumnFamily.NAME); break; + case MERGED: + families.add(MergedColumnFamily.NAME); + break; + case OPID: + qualifiers.add(OPID_COLUMN); + break; + case SELECTED: + qualifiers.add(SELECTED_COLUMN); + break; + case COMPACTED: + families.add(CompactedColumnFamily.NAME); + break; default: throw new IllegalArgumentException("Unknown col type " + colToFetch); - } } diff --cc core/src/test/java/org/apache/accumulo/core/metadata/schema/TabletMetadataTest.java index b890a54299,d547b8596d..fd8c8a80b8 --- 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 @@@ -19,8 -19,9 +19,10 @@@ package org.apache.accumulo.core.metadata.schema; import static java.util.stream.Collectors.toSet; +import static org.apache.accumulo.core.fate.FateTxId.formatTid; import static org.apache.accumulo.core.metadata.StoredTabletFile.serialize; + import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.MergedColumnFamily.MERGED_COLUMN; + import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.MergedColumnFamily.MERGED_VALUE; import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily.COMPACT_COLUMN; import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily.DIRECTORY_COLUMN; import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily.FLUSH_COLUMN; @@@ -274,6 -263,30 +279,30 @@@ public class TabletMetadataTest assertFalse(tm.hasCurrent()); } + @Test + public void testMergedColumn() { + KeyExtent extent = new KeyExtent(TableId.of("5"), new Text("df"), new Text("da")); + + // Test merged column set + Mutation mutation = TabletColumnFamily.createPrevRowMutation(extent); + MERGED_COLUMN.put(mutation, MERGED_VALUE); + TabletMetadata tm = TabletMetadata.convertRow(toRowMap(mutation).entrySet().iterator(), - EnumSet.of(ColumnType.MERGED), true); ++ EnumSet.of(ColumnType.MERGED), true, false); + assertTrue(tm.hasMerged()); + + // Column not set + mutation = TabletColumnFamily.createPrevRowMutation(extent); + tm = TabletMetadata.convertRow(toRowMap(mutation).entrySet().iterator(), - EnumSet.of(ColumnType.MERGED), true); ++ EnumSet.of(ColumnType.MERGED), true, false); + assertFalse(tm.hasMerged()); + + // MERGED Column not fetched + mutation = TabletColumnFamily.createPrevRowMutation(extent); + tm = TabletMetadata.convertRow(toRowMap(mutation).entrySet().iterator(), - EnumSet.of(ColumnType.PREV_ROW), true); ++ EnumSet.of(ColumnType.PREV_ROW), true, false); + assertThrows(IllegalStateException.class, tm::hasMerged); + } + private SortedMap<Key,Value> toRowMap(Mutation mutation) { SortedMap<Key,Value> rowMap = new TreeMap<>(); mutation.getUpdates().forEach(cu -> { diff --cc server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java index 10e1aa9fc1,ca45a05e8a..3507130f4c --- a/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java +++ b/server/base/src/main/java/org/apache/accumulo/server/constraints/MetadataConstraints.java @@@ -46,9 -45,9 +46,10 @@@ import org.apache.accumulo.core.metadat import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ExternalCompactionColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.HostingColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LogColumnFamily; + import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.MergedColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ScanFileColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.SuspendLocationColumn; @@@ -103,8 -99,8 +104,9 @@@ public class MetadataConstraints implem FutureLocationColumnFamily.NAME, ClonedColumnFamily.NAME, ExternalCompactionColumnFamily.NAME, - CompactedColumnFamily.NAME, - UpgraderDeprecatedConstants.ChoppedColumnFamily.NAME ++ CompactedColumnFamily.NAME, + UpgraderDeprecatedConstants.ChoppedColumnFamily.NAME, + MergedColumnFamily.NAME ); // @formatter:on diff --cc test/pom.xml index c5eab3f771,7fbc514f9b..7231e1bada --- a/test/pom.xml +++ b/test/pom.xml @@@ -198,10 -202,10 +198,14 @@@ <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> </dependency> + <dependency> + <groupId>org.opentest4j</groupId> + <artifactId>opentest4j</artifactId> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --cc test/src/main/java/org/apache/accumulo/test/functional/MergeIT.java index a538d60bba,4d265a1120..cf37fb3369 --- a/test/src/main/java/org/apache/accumulo/test/functional/MergeIT.java +++ b/test/src/main/java/org/apache/accumulo/test/functional/MergeIT.java @@@ -20,9 -20,9 +20,10 @@@ package org.apache.accumulo.test.functi import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.accumulo.test.util.FileMetadataUtil.printAndVerifyFileMetadata; + import static org.apache.accumulo.test.util.FileMetadataUtil.verifyMergedMarkerCleared; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@@ -174,23 -98,9 +175,26 @@@ public class MergeIT extends AccumuloCl c.tableOperations().flush(tableName, null, null, true); c.tableOperations().merge(tableName, new Text("c1"), new Text("f1")); assertEquals(8, c.tableOperations().listSplits(tableName).size()); + // Verify that the MERGED marker was cleared + verifyMergedMarkerCleared(getServerContext(), + TableId.of(c.tableOperations().tableIdMap().get(tableName))); + try (Scanner s = c.createScanner(MetadataTable.NAME)) { + String tid = c.tableOperations().tableIdMap().get(tableName); + s.setRange(new Range(tid + ";g")); + TabletColumnFamily.PREV_ROW_COLUMN.fetch(s); + HostingColumnFamily.GOAL_COLUMN.fetch(s); + assertEquals(2, Iterables.size(s)); + for (Entry<Key,Value> rows : s) { + if (TabletColumnFamily.PREV_ROW_COLUMN.hasColumns(rows.getKey())) { + assertEquals("c", TabletColumnFamily.decodePrevEndRow(rows.getValue()).toString()); + } else if (HostingColumnFamily.GOAL_COLUMN.hasColumns(rows.getKey())) { + assertEquals(TabletHostingGoal.ALWAYS, + TabletHostingGoalUtil.fromValue(rows.getValue())); + } else { + fail("Unknown column"); + } + } + } } }