Skip to content

Commit f09116d

Browse files
committed
Merge branch '3.1'
2 parents 121758a + e4d83cc commit f09116d

File tree

5 files changed

+388
-26
lines changed

5 files changed

+388
-26
lines changed

core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ public static <E extends Entry<Key,Value>> TabletMetadata convertRow(Iterator<E>
792792
}
793793

794794
@VisibleForTesting
795-
static TabletMetadata create(String id, String prevEndRow, String endRow) {
795+
public static TabletMetadata create(String id, String prevEndRow, String endRow) {
796796
final var tmBuilder = new Builder();
797797
tmBuilder.table(TableId.of(id));
798798
tmBuilder.sawPrevEndRow(true);

core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletsMetadata.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,8 @@ private TabletsMetadata(TabletMetadata tm) {
570570
this.tablets = Collections.singleton(tm);
571571
}
572572

573-
private TabletsMetadata(AutoCloseable closeable, Iterable<TabletMetadata> tmi) {
573+
// visible for testing
574+
public TabletsMetadata(AutoCloseable closeable, Iterable<TabletMetadata> tmi) {
574575
this.closeable = closeable;
575576
this.tablets = tmi;
576577
}

server/manager/src/main/java/org/apache/accumulo/manager/tableOps/bulkVer2/LoadFiles.java

+71-22
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.apache.accumulo.core.metadata.schema.TabletMetadata.ColumnType.TIME;
2626
import static org.apache.accumulo.core.metadata.schema.TabletMetadata.LocationType.CURRENT;
2727

28+
import java.time.Duration;
2829
import java.util.ArrayList;
2930
import java.util.Collections;
3031
import java.util.Comparator;
@@ -63,6 +64,7 @@
6364
import org.apache.accumulo.core.tabletserver.thrift.TabletServerClientService;
6465
import org.apache.accumulo.core.trace.TraceUtil;
6566
import org.apache.accumulo.core.util.PeekingIterator;
67+
import org.apache.accumulo.core.util.Timer;
6668
import org.apache.accumulo.manager.Manager;
6769
import org.apache.accumulo.manager.tableOps.ManagerRepo;
6870
import org.apache.accumulo.server.fs.VolumeManager;
@@ -82,6 +84,13 @@
8284
*/
8385
class LoadFiles extends ManagerRepo {
8486

87+
// visible for testing
88+
interface TabletsMetadataFactory {
89+
90+
TabletsMetadata newTabletsMetadata(Text startRow);
91+
92+
}
93+
8594
private static final long serialVersionUID = 1L;
8695

8796
private static final Logger log = LoggerFactory.getLogger(LoadFiles.class);
@@ -94,6 +103,7 @@ public LoadFiles(BulkInfo bulkInfo) {
94103

95104
@Override
96105
public long isReady(FateId fateId, Manager manager) throws Exception {
106+
log.info("Starting bulk import for {} (tid = {})", bulkInfo.sourceDir, fateId);
97107
if (manager.onlineTabletServers().isEmpty()) {
98108
log.warn("There are no tablet server to process bulkDir import, waiting (fateId = " + fateId
99109
+ ")");
@@ -104,7 +114,19 @@ public long isReady(FateId fateId, Manager manager) throws Exception {
104114
manager.updateBulkImportStatus(bulkInfo.sourceDir, BulkImportState.LOADING);
105115
try (LoadMappingIterator lmi =
106116
BulkSerialize.getUpdatedLoadMapping(bulkDir.toString(), bulkInfo.tableId, fs::open)) {
107-
return loadFiles(bulkInfo.tableId, bulkDir, lmi, manager, fateId);
117+
118+
Loader loader = new Loader();
119+
120+
List<ColumnType> fetchCols = new ArrayList<>(List.of(PREV_ROW, LOCATION, LOADED, TIME));
121+
if (loader.pauseLimit > 0) {
122+
fetchCols.add(FILES);
123+
}
124+
125+
TabletsMetadataFactory tmf = (startRow) -> TabletsMetadata.builder(manager.getContext())
126+
.forTable(bulkInfo.tableId).overlapping(startRow, null).checkConsistency()
127+
.fetch(fetchCols.toArray(new ColumnType[0])).build();
128+
129+
return loadFiles(loader, bulkInfo, bulkDir, lmi, tmf, manager, fateId);
108130
}
109131
}
110132

@@ -113,7 +135,8 @@ public Repo<Manager> call(final FateId fateId, final Manager manager) {
113135
return new RefreshTablets(bulkInfo);
114136
}
115137

116-
private static class Loader {
138+
// visible for testing
139+
public static class Loader {
117140
protected Path bulkDir;
118141
protected Manager manager;
119142
protected FateId fateId;
@@ -344,14 +367,26 @@ long finish() {
344367
}
345368
}
346369

370+
/**
371+
* Stats for the loadFiles method. Helps track wasted time and iterations.
372+
*/
373+
static class ImportTimingStats {
374+
Duration totalWastedTime = Duration.ZERO;
375+
long wastedIterations = 0;
376+
long tabletCount = 0;
377+
long callCount = 0;
378+
}
379+
347380
/**
348381
* Make asynchronous load calls to each overlapping Tablet in the bulk mapping. Return a sleep
349382
* time to isReady based on a factor of the TabletServer with the most Tablets. This method will
350383
* scan the metadata table getting Tablet range and location information. It will return 0 when
351384
* all files have been loaded.
352385
*/
353-
private long loadFiles(TableId tableId, Path bulkDir, LoadMappingIterator loadMapIter,
354-
Manager manager, FateId fateId) throws Exception {
386+
// visible for testing
387+
static long loadFiles(Loader loader, BulkInfo bulkInfo, Path bulkDir,
388+
LoadMappingIterator loadMapIter, TabletsMetadataFactory factory, Manager manager,
389+
FateId fateId) throws Exception {
355390
PeekingIterator<Map.Entry<KeyExtent,Bulk.Files>> lmi = new PeekingIterator<>(loadMapIter);
356391
Map.Entry<KeyExtent,Bulk.Files> loadMapEntry = lmi.peek();
357392

@@ -360,39 +395,41 @@ private long loadFiles(TableId tableId, Path bulkDir, LoadMappingIterator loadMa
360395
String fmtTid = fateId.getTxUUIDStr();
361396
log.trace("{}: Starting bulk load at row: {}", fmtTid, startRow);
362397

363-
Loader loader = new Loader();
364-
long t1;
365-
loader.start(bulkDir, manager, tableId, fateId, bulkInfo.setTime);
398+
loader.start(bulkDir, manager, bulkInfo.tableId, fateId, bulkInfo.setTime);
366399

367-
List<ColumnType> fetchCols = new ArrayList<>(List.of(PREV_ROW, LOCATION, LOADED, TIME));
368-
if (loader.pauseLimit > 0) {
369-
fetchCols.add(FILES);
370-
}
371-
372-
try (TabletsMetadata tabletsMetadata =
373-
TabletsMetadata.builder(manager.getContext()).forTable(tableId).overlapping(startRow, null)
374-
.checkConsistency().fetch(fetchCols.toArray(new ColumnType[0])).build()) {
400+
ImportTimingStats importTimingStats = new ImportTimingStats();
401+
Timer timer = Timer.startNew();
402+
try (TabletsMetadata tabletsMetadata = factory.newTabletsMetadata(startRow)) {
375403

376404
// The tablet iterator and load mapping iterator are both iterating over data that is sorted
377405
// in the same way. The two iterators are each independently advanced to find common points in
378406
// the sorted data.
379-
var tabletIter = tabletsMetadata.iterator();
380-
381-
t1 = System.currentTimeMillis();
407+
Iterator<TabletMetadata> tabletIter = tabletsMetadata.iterator();
382408
while (lmi.hasNext()) {
383409
loadMapEntry = lmi.next();
384410
List<TabletMetadata> tablets =
385-
findOverlappingTablets(fmtTid, loadMapEntry.getKey(), tabletIter);
411+
findOverlappingTablets(fmtTid, loadMapEntry.getKey(), tabletIter, importTimingStats);
386412
loader.load(tablets, loadMapEntry.getValue());
387413
}
388414
}
415+
Duration totalProcessingTime = timer.elapsed();
389416

390417
log.trace("{}: Completed Finding Overlapping Tablets", fmtTid);
391418

419+
if (importTimingStats.callCount > 0) {
420+
log.debug(
421+
"Bulk import stats for {} (tid = {}): processed {} tablets in {} calls which took {}ms ({} nanos). Skipped {} iterations which took {}ms ({} nanos) or {}% of the processing time.",
422+
bulkInfo.sourceDir, fateId, importTimingStats.tabletCount, importTimingStats.callCount,
423+
totalProcessingTime.toMillis(), totalProcessingTime.toNanos(),
424+
importTimingStats.wastedIterations, importTimingStats.totalWastedTime.toMillis(),
425+
importTimingStats.totalWastedTime.toNanos(),
426+
(importTimingStats.totalWastedTime.toNanos() * 100) / totalProcessingTime.toNanos());
427+
}
428+
392429
long sleepTime = loader.finish();
393430
if (sleepTime > 0) {
394431
log.trace("{}: Tablet Max Sleep is {}", fmtTid, sleepTime);
395-
long scanTime = Math.min(System.currentTimeMillis() - t1, 30_000);
432+
long scanTime = Math.min(totalProcessingTime.toMillis(), 30_000);
396433
log.trace("{}: Scan time is {}", fmtTid, scanTime);
397434
sleepTime = Math.max(sleepTime, scanTime * 2);
398435
}
@@ -406,8 +443,9 @@ private long loadFiles(TableId tableId, Path bulkDir, LoadMappingIterator loadMa
406443
/**
407444
* Find all the tablets within the provided bulk load mapping range.
408445
*/
409-
private List<TabletMetadata> findOverlappingTablets(String fmtTid, KeyExtent loadRange,
410-
Iterator<TabletMetadata> tabletIter) {
446+
// visible for testing
447+
static List<TabletMetadata> findOverlappingTablets(String fmtTid, KeyExtent loadRange,
448+
Iterator<TabletMetadata> tabletIter, ImportTimingStats importTimingStats) {
411449

412450
TabletMetadata currTablet = null;
413451

@@ -419,12 +457,18 @@ private List<TabletMetadata> findOverlappingTablets(String fmtTid, KeyExtent loa
419457

420458
int cmp;
421459

460+
long wastedIterations = 0;
461+
Timer timer = Timer.startNew();
462+
422463
// skip tablets until we find the prevEndRow of loadRange
423464
while ((cmp = PREV_COMP.compare(currTablet.getPrevEndRow(), loadRange.prevEndRow())) < 0) {
465+
wastedIterations++;
424466
log.trace("{}: Skipping tablet: {}", fmtTid, currTablet.getExtent());
425467
currTablet = tabletIter.next();
426468
}
427469

470+
Duration wastedTime = timer.elapsed();
471+
428472
if (cmp != 0) {
429473
throw new IllegalStateException(
430474
"Unexpected prev end row " + currTablet.getExtent() + " " + loadRange);
@@ -445,6 +489,11 @@ private List<TabletMetadata> findOverlappingTablets(String fmtTid, KeyExtent loa
445489
throw new IllegalStateException("Unexpected end row " + currTablet + " " + loadRange);
446490
}
447491

492+
importTimingStats.wastedIterations += wastedIterations;
493+
importTimingStats.totalWastedTime = importTimingStats.totalWastedTime.plus(wastedTime);
494+
importTimingStats.tabletCount += tablets.size();
495+
importTimingStats.callCount++;
496+
448497
return tablets;
449498
} catch (NoSuchElementException e) {
450499
NoSuchElementException ne2 = new NoSuchElementException(

0 commit comments

Comments
 (0)