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 f7e6183271 speeds up tablet mgmt iterator (#4568)
f7e6183271 is described below
commit f7e61832716a196b6b2e9d61666561ef66e27929
Author: Keith Turner <[email protected]>
AuthorDate: Sat May 18 13:20:22 2024 -0400
speeds up tablet mgmt iterator (#4568)
Based on profiling tablet servers while running SplitMillionIT, made
the following changes related to TabletManagementIterator
* Made TabletMgmtIterator extend WholeRowIterator instead of stack on
top of it. This avoids encoding->decoding->encoding rows on the
iterator stack.
* Avoided lookuping and parsing multiple table props for each tablet
inorder to determine if it needs split. Moved this be done once per
table.
* Changed a stream to compute file size sum into a loop.
---
.../core/manager/state/TabletManagement.java | 14 +-
.../core/metadata/schema/TabletMetadata.java | 11 +-
.../manager/state/TabletManagementIterator.java | 164 +++++++++++----------
.../server/manager/state/ZooTabletStateStore.java | 5 +-
.../apache/accumulo/server/split/SplitUtils.java | 8 -
.../state/TabletManagementIteratorTest.java | 6 +-
.../server/manager/state/TabletManagementTest.java | 7 +-
.../manager/ManagerClientServiceHandler.java | 5 +-
8 files changed, 118 insertions(+), 102 deletions(-)
diff --git
a/core/src/main/java/org/apache/accumulo/core/manager/state/TabletManagement.java
b/core/src/main/java/org/apache/accumulo/core/manager/state/TabletManagement.java
index 0649791623..7b13e76b7f 100644
---
a/core/src/main/java/org/apache/accumulo/core/manager/state/TabletManagement.java
+++
b/core/src/main/java/org/apache/accumulo/core/manager/state/TabletManagement.java
@@ -23,6 +23,7 @@ import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedMap;
+import java.util.function.BiConsumer;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Value;
@@ -58,17 +59,18 @@ public class TabletManagement {
NEEDS_VOLUME_REPLACEMENT;
}
- public static void addActions(final SortedMap<Key,Value> decodedRow,
+ public static void addActions(final BiConsumer<Key,Value> bic, final Text
row,
final Set<ManagementAction> actions) {
- final Key reasonsKey = new Key(decodedRow.firstKey().getRow(),
REASONS_COLUMN_NAME, EMPTY);
+ final Key reasonsKey = new Key(row, REASONS_COLUMN_NAME, EMPTY);
final Value reasonsValue = new Value(Joiner.on(',').join(actions));
- decodedRow.put(reasonsKey, reasonsValue);
+ bic.accept(reasonsKey, reasonsValue);
}
- public static void addError(final SortedMap<Key,Value> decodedRow, final
Exception error) {
- final Key errorKey = new Key(decodedRow.firstKey().getRow(),
ERROR_COLUMN_NAME, EMPTY);
+ public static void addError(final BiConsumer<Key,Value> bic, final Text row,
+ final Exception error) {
+ final Key errorKey = new Key(row, ERROR_COLUMN_NAME, EMPTY);
final Value errorValue = new Value(error.getMessage());
- decodedRow.put(errorKey, errorValue);
+ bic.accept(errorKey, errorValue);
}
private final Set<ManagementAction> actions;
diff --git
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
index 6f2ffd6237..ef1fd5ea9c 100644
---
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
@@ -156,8 +156,15 @@ public class TabletMetadata {
this.compacted = tmBuilder.compacted.build();
this.userCompactionsRequested = tmBuilder.userCompactionsRequested.build();
this.unSplittableMetadata = tmBuilder.unSplittableMetadata;
- this.fileSize =
- Suppliers.memoize(() ->
files.values().stream().mapToLong(DataFileValue::getSize).sum());
+ this.fileSize = Suppliers.memoize(() -> {
+ // This code was using a java stream. While profiling SplitMillionIT,
the stream was showing
+ // up as hot when scanning 1 million tablets. Converted to a for loop to
improve performance.
+ long sum = 0;
+ for (var dfv : files.values()) {
+ sum += dfv.getSize();
+ }
+ return sum;
+ });
this.extent =
Suppliers.memoize(() -> new KeyExtent(getTableId(), getEndRow(),
getPrevEndRow()));
}
diff --git
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletManagementIterator.java
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletManagementIterator.java
index b9c64c7f84..e5c7bd32b4 100644
---
a/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletManagementIterator.java
+++
b/server/base/src/main/java/org/apache/accumulo/server/manager/state/TabletManagementIterator.java
@@ -19,15 +19,16 @@
package org.apache.accumulo.server.manager.state;
import java.io.IOException;
-import java.util.ArrayList;
+import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.SortedMap;
import org.apache.accumulo.core.client.IteratorSetting;
import org.apache.accumulo.core.client.PluginEnvironment.Configuration;
@@ -39,9 +40,9 @@ import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.TableId;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.IteratorEnvironment;
-import org.apache.accumulo.core.iterators.SkippingIterator;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.iterators.user.WholeRowIterator;
import org.apache.accumulo.core.manager.state.TabletManagement;
@@ -58,6 +59,7 @@ import org.apache.accumulo.server.fs.VolumeUtil;
import org.apache.accumulo.server.iterators.TabletIteratorEnvironment;
import org.apache.accumulo.server.manager.balancer.BalancerEnvironmentImpl;
import org.apache.accumulo.server.split.SplitUtils;
+import org.apache.hadoop.io.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,35 +68,55 @@ import org.slf4j.LoggerFactory;
* TabletManagement objects for each Tablet that needs some type of action
performed on it by the
* Manager.
*/
-public class TabletManagementIterator extends SkippingIterator {
+public class TabletManagementIterator extends WholeRowIterator {
private static final Logger LOG =
LoggerFactory.getLogger(TabletManagementIterator.class);
public static final String TABLET_GOAL_STATE_PARAMS_OPTION = "tgsParams";
private CompactionJobGenerator compactionGenerator;
private TabletBalancer balancer;
+ private final SplitConfig splitConfig = new SplitConfig();
+
+ private static class SplitConfig {
+ TableId tableId;
+ long splitThreshold;
+ long maxEndRowSize;
+ int maxFilesToOpen;
+
+ void update(TableId tableId, Configuration tableConfig) {
+ if (!tableId.equals(this.tableId)) {
+ this.tableId = tableId;
+ splitThreshold = ConfigurationTypeHelper
+
.getFixedMemoryAsBytes(tableConfig.get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
+ maxEndRowSize = ConfigurationTypeHelper
+
.getFixedMemoryAsBytes(tableConfig.get(Property.TABLE_MAX_END_ROW_SIZE.getKey()));
+ maxFilesToOpen = (int) ConfigurationTypeHelper
+
.getFixedMemoryAsBytes(tableConfig.get(Property.SPLIT_MAXOPEN.getKey()));
+ }
+ }
+ }
private static boolean shouldReturnDueToSplit(final TabletMetadata tm,
- final Configuration tableConfig) {
+ final Configuration tableConfig, SplitConfig splitConfig) {
- final long splitThreshold = ConfigurationTypeHelper
-
.getFixedMemoryAsBytes(tableConfig.get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
- final long maxEndRowSize = ConfigurationTypeHelper
-
.getFixedMemoryAsBytes(tableConfig.get(Property.TABLE_MAX_END_ROW_SIZE.getKey()));
- final int maxFilesToOpen = (int) ConfigurationTypeHelper
-
.getFixedMemoryAsBytes(tableConfig.get(Property.SPLIT_MAXOPEN.getKey()));
+ // Should see the same table many times in a row, so this should only read
config the first time
+ // seen. Reading the config for each tablet was showing up as performance
problem when profiling
+ // SplitMillionIT that reads one million tablets. It is also nice to have
snapshot of config
+ // that is used for all tablet in a table.
+ splitConfig.update(tm.getTableId(), tableConfig);
// If the current computed metadata matches the current marker then we
can't split,
// so we return false. If the marker is set but doesn't match then return
true
// which gives a chance to clean up the marker and recheck.
var unsplittable = tm.getUnSplittable();
if (unsplittable != null) {
- return
!unsplittable.equals(UnSplittableMetadata.toUnSplittable(tm.getExtent(),
- splitThreshold, maxEndRowSize, maxFilesToOpen, tm.getFiles()));
+ return !unsplittable
+ .equals(UnSplittableMetadata.toUnSplittable(tm.getExtent(),
splitConfig.splitThreshold,
+ splitConfig.maxEndRowSize, splitConfig.maxFilesToOpen,
tm.getFiles()));
}
// If unsplittable is not set at all then check if over split threshold
- final boolean shouldSplit = SplitUtils.needsSplit(tableConfig, tm);
+ final boolean shouldSplit =
SplitUtils.needsSplit(splitConfig.splitThreshold, tm);
LOG.trace("{} should split? sum: {}, threshold: {}, result: {}",
tm.getExtent(),
- tm.getFileSize(), splitThreshold, shouldSplit);
+ tm.getFileSize(), splitConfig.splitThreshold, shouldSplit);
return shouldSplit;
}
@@ -137,7 +159,6 @@ public class TabletManagementIterator extends
SkippingIterator {
final TabletManagementParameters tabletMgmtParams) {
// Note : if the scanner is ever made to fetch columns, then
TabletManagement.CONFIGURED_COLUMNS
// must be updated
- scanner.addScanIterator(new IteratorSetting(1000, "wholeRows",
WholeRowIterator.class));
IteratorSetting tabletChange =
new IteratorSetting(1001, "ManagerTabletInfoIterator",
TabletManagementIterator.class);
tabletChange.addOption(TABLET_GOAL_STATE_PARAMS_OPTION,
tabletMgmtParams.serialize());
@@ -149,8 +170,7 @@ public class TabletManagementIterator extends
SkippingIterator {
}
private IteratorEnvironment env;
- private Key topKey = null;
- private Value topValue = null;
+
private TabletManagementParameters tabletMgmtParams = null;
@Override
@@ -188,69 +208,64 @@ public class TabletManagementIterator extends
SkippingIterator {
}
@Override
- public Key getTopKey() {
- return topKey;
- }
-
- @Override
- public Value getTopValue() {
- return topValue;
- }
-
- @Override
- public boolean hasTop() {
- return topKey != null && topValue != null;
- }
+ protected boolean filter(Text currentRow, List<Key> keys, List<Value>
values) {
- @Override
- protected void consume() throws IOException {
- topKey = null;
- topValue = null;
+ var keyIter = keys.listIterator();
+ var kvIter = new Iterator<Map.Entry<Key,Value>>() {
+ @Override
+ public boolean hasNext() {
+ return keyIter.hasNext();
+ }
- final Set<ManagementAction> actions = new HashSet<>();
- while (getSource().hasTop()) {
- final Key k = getSource().getTopKey();
- final Value v = getSource().getTopValue();
- final SortedMap<Key,Value> decodedRow = WholeRowIterator.decodeRow(k, v);
- final TabletMetadata tm =
TabletMetadata.convertRow(decodedRow.entrySet().iterator(),
- TabletManagement.CONFIGURED_COLUMNS, false, true);
-
- actions.clear();
- Exception error = null;
- try {
- LOG.trace("Evaluating extent: {}", tm);
- computeTabletManagementActions(tm, actions);
- } catch (Exception e) {
- LOG.error("Error computing tablet management actions for extent: {}",
tm.getExtent(), e);
- error = e;
+ @Override
+ public Entry<Key,Value> next() {
+ var valueIdx = keyIter.nextIndex();
+ var key = keyIter.next();
+ return new AbstractMap.SimpleImmutableEntry<>(key,
values.get(valueIdx));
}
+ };
- if (!actions.isEmpty() || error != null) {
- if (error != null) {
- // Insert the error into K,V pair representing
- // the tablet metadata.
- TabletManagement.addError(decodedRow, error);
- } else if (!actions.isEmpty()) {
- // If we simply returned here, then the client would get the encoded
K,V
- // from the WholeRowIterator. However, it would not know the
reason(s) why
- // it was returned. Insert a K,V pair to represent the reasons. The
client
- // can pull this K,V pair from the results by looking at the colf.
- TabletManagement.addActions(decodedRow, actions);
- }
+ final Set<ManagementAction> actions = new HashSet<>();
+ final TabletMetadata tm =
+ TabletMetadata.convertRow(kvIter, TabletManagement.CONFIGURED_COLUMNS,
false, true);
+
+ Exception error = null;
+ try {
+ LOG.trace("Evaluating extent: {}", tm);
+ computeTabletManagementActions(tm, actions);
+ } catch (Exception e) {
+ LOG.error("Error computing tablet management actions for extent: {}",
tm.getExtent(), e);
+ error = e;
+ }
- // This key is being created exactly the same way as the whole row
iterator creates keys.
- // This is important for ensuring that seek works as expected in the
continue case. See
- // WholeRowIterator seek function for details, it looks for keys w/o
columns.
- topKey = new Key(decodedRow.firstKey().getRow());
- topValue = WholeRowIterator.encodeRow(new
ArrayList<>(decodedRow.keySet()),
- new ArrayList<>(decodedRow.values()));
- LOG.trace("Returning extent {} with reasons: {}", tm.getExtent(),
actions);
- return;
+ if (!actions.isEmpty() || error != null) {
+ if (error != null) {
+ // Insert the error into K,V pair representing
+ // the tablet metadata.
+ TabletManagement.addError((k, v) -> {
+ keys.add(k);
+ values.add(v);
+ }, currentRow, error);
+ } else if (!actions.isEmpty()) {
+ // If we simply returned here, then the client would get the encoded
K,V
+ // from the WholeRowIterator. However, it would not know the reason(s)
why
+ // it was returned. Insert a K,V pair to represent the reasons. The
client
+ // can pull this K,V pair from the results by looking at the colf.
+ TabletManagement.addActions((k, v) -> {
+ keys.add(k);
+ values.add(v);
+ }, currentRow, actions);
}
- LOG.trace("No reason to return extent {}, continuing", tm.getExtent());
- getSource().next();
+ // This key is being created exactly the same way as the whole row
iterator creates keys.
+ // This is important for ensuring that seek works as expected in the
continue case. See
+ // WholeRowIterator seek function for details, it looks for keys w/o
columns.
+ LOG.trace("Returning extent {} with reasons: {}", tm.getExtent(),
actions);
+ return true;
}
+
+ LOG.trace("No reason to return extent {}, continuing", tm.getExtent());
+ return false;
}
private static final Set<ManagementAction> REASONS_NOT_TO_SPLIT_OR_COMPACT =
@@ -285,7 +300,8 @@ public class TabletManagementIterator extends
SkippingIterator {
if (tm.getOperationId() == null &&
tabletMgmtParams.isTableOnline(tm.getTableId())
&& Collections.disjoint(REASONS_NOT_TO_SPLIT_OR_COMPACT,
reasonsToReturnThisTablet)) {
try {
- if (shouldReturnDueToSplit(tm,
this.env.getPluginEnv().getConfiguration(tm.getTableId()))) {
+ if (shouldReturnDueToSplit(tm,
this.env.getPluginEnv().getConfiguration(tm.getTableId()),
+ splitConfig)) {
reasonsToReturnThisTablet.add(ManagementAction.NEEDS_SPLITTING);
}
// important to call this since reasonsToReturnThisTablet is passed to
it
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 cbb5c280ac..504d9e5589 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
@@ -34,7 +34,6 @@ 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;
@@ -79,7 +78,6 @@ class ZooTabletStateStore extends AbstractTabletStateStore
implements TabletStat
final String zpath = ctx.getZooKeeperRoot() + RootTable.ZROOT_TABLET;
final TabletIteratorEnvironment env = new TabletIteratorEnvironment(ctx,
IteratorScope.scan,
ctx.getTableConfiguration(AccumuloTable.ROOT.tableId()),
AccumuloTable.ROOT.tableId());
- final WholeRowIterator wri = new WholeRowIterator();
final TabletManagementIterator tmi = new TabletManagementIterator();
final AtomicBoolean closed = new AtomicBoolean(false);
@@ -88,8 +86,7 @@ class ZooTabletStateStore extends AbstractTabletStateStore
implements TabletStat
ctx.getZooReaderWriter().getZooKeeper().getData(zpath, false, null);
final RootTabletMetadata rtm = new RootTabletMetadata(new
String(rootTabletMetadata, UTF_8));
final SortedMapIterator iter = new SortedMapIterator(rtm.toKeyValues());
- wri.init(iter, Map.of(), env);
- tmi.init(wri,
+ tmi.init(iter,
Map.of(TabletManagementIterator.TABLET_GOAL_STATE_PARAMS_OPTION,
parameters.serialize()),
env);
tmi.seek(new Range(), null, true);
diff --git
a/server/base/src/main/java/org/apache/accumulo/server/split/SplitUtils.java
b/server/base/src/main/java/org/apache/accumulo/server/split/SplitUtils.java
index 5cf5c9edc6..e844deb779 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/split/SplitUtils.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/split/SplitUtils.java
@@ -29,8 +29,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.function.Predicate;
-import org.apache.accumulo.core.client.PluginEnvironment.Configuration;
-import org.apache.accumulo.core.conf.ConfigurationTypeHelper;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.data.ByteSequence;
import org.apache.accumulo.core.data.Key;
@@ -294,12 +292,6 @@ public class SplitUtils {
return needsSplit(splitThreshold, tabletMetadata);
}
- public static boolean needsSplit(final Configuration tableConf,
TabletMetadata tabletMetadata) {
- var splitThreshold = ConfigurationTypeHelper
-
.getFixedMemoryAsBytes(tableConf.get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
- return needsSplit(splitThreshold, tabletMetadata);
- }
-
public static boolean needsSplit(long splitThreshold, TabletMetadata
tabletMetadata) {
return tabletMetadata.getFileSize() > splitThreshold;
}
diff --git
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementIteratorTest.java
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementIteratorTest.java
index a673777721..599a44c1c1 100644
---
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementIteratorTest.java
+++
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementIteratorTest.java
@@ -42,10 +42,10 @@ public class TabletManagementIteratorTest {
Key badStartKey = new Key("row", "colf", "colq", 1234L);
Key badEndKey = new Key("rowEnd", "colf", "colq", 1234L);
- assertThrows(IllegalStateException.class, () -> iter.seek(null, Set.of(),
false));
- assertThrows(IllegalStateException.class,
+ assertThrows(NullPointerException.class, () -> iter.seek(null, Set.of(),
false));
+ assertThrows(NullPointerException.class,
() -> iter.seek(new Range((Key) null, (Key) null), Set.of(), false));
- assertThrows(IllegalStateException.class,
+ assertThrows(NullPointerException.class,
() -> iter.seek(new Range(goodStartKey, goodEndKey), Set.of(), false));
assertTrue(assertThrows(IllegalArgumentException.class,
() -> iter.seek(new Range(goodStartKey, badEndKey), Set.of(),
false)).getMessage()
diff --git
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementTest.java
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementTest.java
index 9bc99cd0c4..207c1d0a01 100644
---
a/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementTest.java
+++
b/server/base/src/test/java/org/apache/accumulo/server/manager/state/TabletManagementTest.java
@@ -129,7 +129,7 @@ public class TabletManagementTest {
final SortedMap<Key,Value> entries = createMetadataEntryKV(extent);
- TabletManagement.addActions(entries, actions);
+ TabletManagement.addActions(entries::put, entries.firstKey().getRow(),
actions);
Key key = entries.firstKey();
Value val = WholeRowIterator.encodeRow(new ArrayList<>(entries.keySet()),
new ArrayList<>(entries.values()));
@@ -149,7 +149,8 @@ public class TabletManagementTest {
final SortedMap<Key,Value> entries = createMetadataEntryKV(extent);
- TabletManagement.addError(entries, new UnsupportedOperationException("Not
supported."));
+ TabletManagement.addError(entries::put, entries.firstKey().getRow(),
+ new UnsupportedOperationException("Not supported."));
Key key = entries.firstKey();
Value val = WholeRowIterator.encodeRow(new ArrayList<>(entries.keySet()),
new ArrayList<>(entries.values()));
@@ -174,7 +175,7 @@ public class TabletManagementTest {
final SortedMap<Key,Value> entries = createMetadataEntryKV(extent);
- TabletManagement.addActions(entries, actions);
+ TabletManagement.addActions(entries::put, entries.firstKey().getRow(),
actions);
Key key = entries.firstKey();
Value val = WholeRowIterator.encodeRow(new ArrayList<>(entries.keySet()),
new ArrayList<>(entries.values()));
diff --git
a/server/manager/src/main/java/org/apache/accumulo/manager/ManagerClientServiceHandler.java
b/server/manager/src/main/java/org/apache/accumulo/manager/ManagerClientServiceHandler.java
index dd14024db6..e70e151ace 100644
---
a/server/manager/src/main/java/org/apache/accumulo/manager/ManagerClientServiceHandler.java
+++
b/server/manager/src/main/java/org/apache/accumulo/manager/ManagerClientServiceHandler.java
@@ -648,8 +648,9 @@ public class ManagerClientServiceHandler implements
ManagerClientService.Iface {
inProgress.forEach(hostingRequestInProgress::remove);
}
- manager.getEventCoordinator().event(success, "Tablet hosting requested for
%d tablets in %s",
- success.size(), tableId);
+ manager.getEventCoordinator().event(success,
+ "Tablet hosting requested for %d of %d tablets in %s", success.size(),
extents.size(),
+ tableId);
}
protected TableId getTableId(ClientContext context, String tableName)