-
Notifications
You must be signed in to change notification settings - Fork 491
Move checks to the MergeCommand class #6431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 2.1
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,7 +36,8 @@ | |
| import org.apache.accumulo.core.data.Key; | ||
| import org.apache.accumulo.core.data.TableId; | ||
| import org.apache.accumulo.core.dataImpl.KeyExtent; | ||
| import org.apache.accumulo.core.metadata.MetadataTable; | ||
| import org.apache.accumulo.core.metadata.RootTable; | ||
| import org.apache.accumulo.core.metadata.schema.Ample.DataLevel; | ||
| import org.apache.accumulo.core.metadata.schema.DataFileValue; | ||
| import org.apache.accumulo.core.metadata.schema.TabletsMetadata; | ||
| import org.apache.accumulo.core.trace.TraceUtil; | ||
|
|
@@ -63,7 +64,7 @@ public static class MergeException extends Exception { | |
| private static final Logger log = LoggerFactory.getLogger(Merge.class); | ||
|
|
||
| protected void message(String format, Object... args) { | ||
| log.info(String.format(format, args)); | ||
| log.info("{}", String.format(format, args)); | ||
| } | ||
|
|
||
| public static class MemoryConverter implements IStringConverter<Long> { | ||
|
|
@@ -109,10 +110,16 @@ public void start(String[] args) throws MergeException { | |
| System.err.println("table " + opts.tableName + " does not exist"); | ||
| return; | ||
| } | ||
| if (RootTable.NAME.equals(opts.tableName)) { | ||
| throw new IllegalArgumentException("Cannot merge the root table"); | ||
| } | ||
| if (opts.goalSize == null || opts.goalSize < 1) { | ||
| AccumuloConfiguration tableConfig = | ||
| new ConfigurationCopy(client.tableOperations().getConfiguration(opts.tableName)); | ||
| opts.goalSize = tableConfig.getAsBytes(Property.TABLE_SPLIT_THRESHOLD); | ||
| long newGoalSize = tableConfig.getAsBytes(Property.TABLE_SPLIT_THRESHOLD); | ||
| message("Invalid goal size: " + opts.goalSize + " Using the " | ||
| + Property.TABLE_SPLIT_THRESHOLD.getKey() + " value of : " + newGoalSize); | ||
| opts.goalSize = newGoalSize; | ||
| } | ||
|
|
||
| message("Merging tablets in table %s to %d bytes", opts.tableName, opts.goalSize); | ||
|
|
@@ -144,9 +151,6 @@ public Size(KeyExtent extent, long size) { | |
| public void mergomatic(AccumuloClient client, String table, Text start, Text end, long goalSize, | ||
| boolean force) throws MergeException { | ||
| try { | ||
| if (table.equals(MetadataTable.NAME)) { | ||
| throw new IllegalArgumentException("cannot merge tablets on the metadata table"); | ||
| } | ||
| List<Size> sizes = new ArrayList<>(); | ||
| long totalSize = 0; | ||
| // Merge any until you get larger than the goal size, and then merge one less tablet | ||
|
|
@@ -239,16 +243,17 @@ protected void merge(AccumuloClient client, String table, List<Size> sizes, int | |
| } | ||
| } | ||
|
|
||
| protected Iterator<Size> getSizeIterator(AccumuloClient client, String tablename, Text start, | ||
| protected Iterator<Size> getSizeIterator(AccumuloClient client, String tableName, Text start, | ||
| Text end) throws MergeException { | ||
| // open up metadata, walk through the tablets. | ||
|
|
||
| TableId tableId; | ||
| TabletsMetadata tablets; | ||
| try { | ||
| ClientContext context = (ClientContext) client; | ||
| tableId = context.getTableId(tablename); | ||
| tablets = TabletsMetadata.builder(context).scanMetadataTable() | ||
| tableId = context.getTableId(tableName); | ||
| DataLevel dataLevel = DataLevel.of(tableId); | ||
| tablets = TabletsMetadata.builder(context).scanTable(dataLevel.metaTable()) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the dataLevel of the current table instead of |
||
| .overRange(new KeyExtent(tableId, end, start).toMetaRange()).fetch(FILES, PREV_ROW) | ||
| .build(); | ||
| } catch (Exception e) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,11 @@ | |
| */ | ||
| package org.apache.accumulo.shell.commands; | ||
|
|
||
| import org.apache.accumulo.core.client.AccumuloException; | ||
| import org.apache.accumulo.core.client.AccumuloSecurityException; | ||
| import org.apache.accumulo.core.client.TableNotFoundException; | ||
| import org.apache.accumulo.core.conf.ConfigurationTypeHelper; | ||
| import org.apache.accumulo.core.metadata.MetadataTable; | ||
| import org.apache.accumulo.core.util.Merge; | ||
| import org.apache.accumulo.shell.Shell; | ||
| import org.apache.accumulo.shell.Shell.Command; | ||
|
|
@@ -52,6 +56,15 @@ public int execute(final String fullCommand, final CommandLine cl, final Shell s | |
| if (cl.hasOption(sizeOpt.getOpt())) { | ||
| size = ConfigurationTypeHelper.getFixedMemoryAsBytes(cl.getOptionValue(sizeOpt.getOpt())); | ||
| } | ||
| if (tableName.equals(MetadataTable.NAME)) { | ||
| if (!shellState | ||
| .confirm( | ||
| " Warning!!! Merging the " + MetadataTable.NAME + " table incorrectly can result in " | ||
| + "system instability. Are you REALLY sure you want to merge?!?!?!") | ||
|
Comment on lines
+62
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Merge will lock the metadata table for write and then unhost the tablets in the range for some period of time while the merge occurs. The metadata tablets could be unhosted under normal balance conditions, but the system will try to host them immediately. I certainly think we should add a test case for this in MergeIT or some other merge related IT. And I'm wondering if we should add a merge of the metadata table during some Fate operations in some Fate IT.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added test cases for merge operations in MergeIT. For the FateITs it sounds like you want to see what system interruptions might occur if merging the metadata table happened while other fate operation are ongoing.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Exactly. It should be fine as metadata tablets can become unhosted during normal balancing, but it would be good to test this case since we are changing the behavior of merge for the metadata table late in the development cycle in a patch release. In fact, we may want to add that something to the message to say that it's experimental if only to get users to test it first. |
||
| .orElse(false)) { | ||
| return 0; | ||
| } | ||
| } | ||
| if (startRow == null && endRow == null && size < 0 && !all) { | ||
| if (!shellState | ||
| .confirm(" Warning!!! Are you REALLY sure you want to merge the entire table { " | ||
|
|
@@ -60,21 +73,7 @@ public int execute(final String fullCommand, final CommandLine cl, final Shell s | |
| return 0; | ||
| } | ||
| } | ||
| if (size < 0) { | ||
| shellState.getAccumuloClient().tableOperations().merge(tableName, startRow, endRow); | ||
| } else { | ||
| final boolean finalVerbose = verbose; | ||
| final Merge merge = new Merge() { | ||
| @Override | ||
| protected void message(String fmt, Object... args) { | ||
| if (finalVerbose) { | ||
| shellState.getWriter().println(String.format(fmt, args)); | ||
| } | ||
| } | ||
| }; | ||
| merge.mergomatic(shellState.getAccumuloClient(), tableName, startRow, endRow, size, force); | ||
| } | ||
| return 0; | ||
| return executeMerge(shellState, tableName, startRow, endRow, size, verbose, force); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -110,4 +109,25 @@ public Options getOptions() { | |
| return o; | ||
| } | ||
|
|
||
| // This method is stubbed out to allow for mock testing | ||
| int executeMerge(Shell shellState, String tableName, Text startRow, Text endRow, long size, | ||
| boolean verbose, boolean force) throws AccumuloException, TableNotFoundException, | ||
| AccumuloSecurityException, Merge.MergeException { | ||
| if (size < 0) { | ||
| shellState.getAccumuloClient().tableOperations().merge(tableName, startRow, endRow); | ||
| } else { | ||
| final boolean finalVerbose = verbose; | ||
| final Merge merge = new Merge() { | ||
| @Override | ||
| protected void message(String fmt, Object... args) { | ||
| if (finalVerbose) { | ||
| shellState.getWriter().println(String.format(fmt, args)); | ||
| } | ||
| } | ||
| }; | ||
| merge.mergomatic(shellState.getAccumuloClient(), tableName, startRow, endRow, size, force); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code would previously just output a
Merging tablets in table <table> to <size> bytesmessage but would not explicitly state that the size has changed from what was instructed.The new code change provides a message describing the change in the size selector.