HBASE-19069 Do not wrap the original CompactionLifeCycleTracker when calling CP hooks
This commit is contained in:
parent
81133f89fc
commit
37b29e909d
|
@ -237,80 +237,73 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compaction life cycle tracker to trace the execution of all the compactions triggered by one
|
private interface CompactionCompleteTracker {
|
||||||
// request and delegate to the source CompactionLifeCycleTracker. It will call completed method if
|
|
||||||
// all the compactions are finished.
|
default void completed(Store store) {
|
||||||
private static final class AggregatingCompactionLifeCycleTracker
|
}
|
||||||
implements CompactionLifeCycleTracker {
|
}
|
||||||
|
|
||||||
|
private static final CompactionCompleteTracker DUMMY_COMPLETE_TRACKER =
|
||||||
|
new CompactionCompleteTracker() {
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final class AggregatingCompleteTracker implements CompactionCompleteTracker {
|
||||||
|
|
||||||
private final CompactionLifeCycleTracker tracker;
|
private final CompactionLifeCycleTracker tracker;
|
||||||
|
|
||||||
private final AtomicInteger remaining;
|
private final AtomicInteger remaining;
|
||||||
|
|
||||||
public AggregatingCompactionLifeCycleTracker(CompactionLifeCycleTracker tracker,
|
public AggregatingCompleteTracker(CompactionLifeCycleTracker tracker, int numberOfStores) {
|
||||||
int numberOfStores) {
|
|
||||||
this.tracker = tracker;
|
this.tracker = tracker;
|
||||||
this.remaining = new AtomicInteger(numberOfStores);
|
this.remaining = new AtomicInteger(numberOfStores);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryCompleted() {
|
@Override
|
||||||
|
public void completed(Store store) {
|
||||||
if (remaining.decrementAndGet() == 0) {
|
if (remaining.decrementAndGet() == 0) {
|
||||||
tracker.completed();
|
tracker.completed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notExecuted(Store store, String reason) {
|
|
||||||
tracker.notExecuted(store, reason);
|
|
||||||
tryCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private CompactionCompleteTracker getCompleteTracker(CompactionLifeCycleTracker tracker,
|
||||||
public void beforeExecution(Store store) {
|
|
||||||
tracker.beforeExecution(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterExecution(Store store) {
|
|
||||||
tracker.afterExecution(store);
|
|
||||||
tryCompleted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompactionLifeCycleTracker wrap(CompactionLifeCycleTracker tracker,
|
|
||||||
IntSupplier numberOfStores) {
|
IntSupplier numberOfStores) {
|
||||||
if (tracker == CompactionLifeCycleTracker.DUMMY) {
|
if (tracker == CompactionLifeCycleTracker.DUMMY) {
|
||||||
// a simple optimization to avoid creating unnecessary objects as usually we do not care about
|
// a simple optimization to avoid creating unnecessary objects as usually we do not care about
|
||||||
// the life cycle of a compaction.
|
// the life cycle of a compaction.
|
||||||
return tracker;
|
return DUMMY_COMPLETE_TRACKER;
|
||||||
} else {
|
} else {
|
||||||
return new AggregatingCompactionLifeCycleTracker(tracker, numberOfStores.getAsInt());
|
return new AggregatingCompleteTracker(tracker, numberOfStores.getAsInt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void requestCompaction(HRegion region, String why, int priority,
|
public synchronized void requestCompaction(HRegion region, String why, int priority,
|
||||||
CompactionLifeCycleTracker tracker, User user) throws IOException {
|
CompactionLifeCycleTracker tracker, User user) throws IOException {
|
||||||
requestCompactionInternal(region, why, priority, true,
|
requestCompactionInternal(region, why, priority, true, tracker,
|
||||||
wrap(tracker, () -> region.getTableDescriptor().getColumnFamilyCount()), user);
|
getCompleteTracker(tracker, () -> region.getTableDescriptor().getColumnFamilyCount()), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void requestCompaction(HRegion region, HStore store, String why, int priority,
|
public synchronized void requestCompaction(HRegion region, HStore store, String why, int priority,
|
||||||
CompactionLifeCycleTracker tracker, User user) throws IOException {
|
CompactionLifeCycleTracker tracker, User user) throws IOException {
|
||||||
requestCompactionInternal(region, store, why, priority, true, wrap(tracker, () -> 1), user);
|
requestCompactionInternal(region, store, why, priority, true, tracker,
|
||||||
|
getCompleteTracker(tracker, () -> 1), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestCompactionInternal(HRegion region, String why, int priority,
|
private void requestCompactionInternal(HRegion region, String why, int priority,
|
||||||
boolean selectNow, CompactionLifeCycleTracker tracker, User user) throws IOException {
|
boolean selectNow, CompactionLifeCycleTracker tracker,
|
||||||
|
CompactionCompleteTracker completeTracker, User user) throws IOException {
|
||||||
// request compaction on all stores
|
// request compaction on all stores
|
||||||
for (HStore store : region.stores.values()) {
|
for (HStore store : region.stores.values()) {
|
||||||
requestCompactionInternal(region, store, why, priority, selectNow, tracker, user);
|
requestCompactionInternal(region, store, why, priority, selectNow, tracker, completeTracker,
|
||||||
|
user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestCompactionInternal(HRegion region, HStore store, String why, int priority,
|
private void requestCompactionInternal(HRegion region, HStore store, String why, int priority,
|
||||||
boolean selectNow, CompactionLifeCycleTracker tracker, User user) throws IOException {
|
boolean selectNow, CompactionLifeCycleTracker tracker,
|
||||||
|
CompactionCompleteTracker completeTracker, User user) throws IOException {
|
||||||
if (this.server.isStopped() || (region.getTableDescriptor() != null &&
|
if (this.server.isStopped() || (region.getTableDescriptor() != null &&
|
||||||
!region.getTableDescriptor().isCompactionEnabled())) {
|
!region.getTableDescriptor().isCompactionEnabled())) {
|
||||||
return;
|
return;
|
||||||
|
@ -322,33 +315,36 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
String reason = "Ignoring compaction request for " + region +
|
String reason = "Ignoring compaction request for " + region +
|
||||||
" as an active space quota violation " + " policy disallows compactions.";
|
" as an active space quota violation " + " policy disallows compactions.";
|
||||||
tracker.notExecuted(store, reason);
|
tracker.notExecuted(store, reason);
|
||||||
|
completeTracker.completed(store);
|
||||||
LOG.debug(reason);
|
LOG.debug(reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<CompactionContext> compaction;
|
CompactionContext compaction;
|
||||||
if (selectNow) {
|
if (selectNow) {
|
||||||
compaction = selectCompaction(region, store, priority, tracker, user);
|
Optional<CompactionContext> c = selectCompaction(region, store, priority, tracker, completeTracker, user);
|
||||||
if (!compaction.isPresent()) {
|
if (!c.isPresent()) {
|
||||||
// message logged inside
|
// message logged inside
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
compaction = c.get();
|
||||||
} else {
|
} else {
|
||||||
compaction = Optional.empty();
|
compaction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPoolExecutor pool;
|
ThreadPoolExecutor pool;
|
||||||
if (selectNow) {
|
if (selectNow) {
|
||||||
// compaction.get is safe as we will just return if selectNow is true but no compaction is
|
// compaction.get is safe as we will just return if selectNow is true but no compaction is
|
||||||
// selected
|
// selected
|
||||||
pool = store.throttleCompaction(compaction.get().getRequest().getSize()) ? longCompactions
|
pool = store.throttleCompaction(compaction.getRequest().getSize()) ? longCompactions
|
||||||
: shortCompactions;
|
: shortCompactions;
|
||||||
} else {
|
} else {
|
||||||
// We assume that most compactions are small. So, put system compactions into small
|
// We assume that most compactions are small. So, put system compactions into small
|
||||||
// pool; we will do selection there, and move to large pool if necessary.
|
// pool; we will do selection there, and move to large pool if necessary.
|
||||||
pool = shortCompactions;
|
pool = shortCompactions;
|
||||||
}
|
}
|
||||||
pool.execute(new CompactionRunner(store, region, compaction, pool, user));
|
pool.execute(
|
||||||
|
new CompactionRunner(store, region, compaction, tracker, completeTracker, pool, user));
|
||||||
region.incrementCompactionsQueuedCount();
|
region.incrementCompactionsQueuedCount();
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
String type = (pool == shortCompactions) ? "Small " : "Large ";
|
String type = (pool == shortCompactions) ? "Small " : "Large ";
|
||||||
|
@ -358,23 +354,25 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void requestSystemCompaction(HRegion region, String why) throws IOException {
|
public synchronized void requestSystemCompaction(HRegion region, String why) throws IOException {
|
||||||
requestCompactionInternal(region, why, NO_PRIORITY, false,
|
requestCompactionInternal(region, why, NO_PRIORITY, false, CompactionLifeCycleTracker.DUMMY,
|
||||||
CompactionLifeCycleTracker.DUMMY, null);
|
DUMMY_COMPLETE_TRACKER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void requestSystemCompaction(HRegion region, HStore store, String why)
|
public synchronized void requestSystemCompaction(HRegion region, HStore store, String why)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
requestCompactionInternal(region, store, why, NO_PRIORITY, false,
|
requestCompactionInternal(region, store, why, NO_PRIORITY, false,
|
||||||
CompactionLifeCycleTracker.DUMMY, null);
|
CompactionLifeCycleTracker.DUMMY, DUMMY_COMPLETE_TRACKER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<CompactionContext> selectCompaction(HRegion region, HStore store, int priority,
|
private Optional<CompactionContext> selectCompaction(HRegion region, HStore store, int priority,
|
||||||
CompactionLifeCycleTracker tracker, User user) throws IOException {
|
CompactionLifeCycleTracker tracker, CompactionCompleteTracker completeTracker, User user)
|
||||||
|
throws IOException {
|
||||||
Optional<CompactionContext> compaction = store.requestCompaction(priority, tracker, user);
|
Optional<CompactionContext> compaction = store.requestCompaction(priority, tracker, user);
|
||||||
if (!compaction.isPresent() && region.getRegionInfo() != null) {
|
if (!compaction.isPresent() && region.getRegionInfo() != null) {
|
||||||
String reason = "Not compacting " + region.getRegionInfo().getRegionNameAsString() +
|
String reason = "Not compacting " + region.getRegionInfo().getRegionNameAsString() +
|
||||||
" because compaction request was cancelled";
|
" because compaction request was cancelled";
|
||||||
tracker.notExecuted(store, reason);
|
tracker.notExecuted(store, reason);
|
||||||
|
completeTracker.completed(store);
|
||||||
LOG.debug(reason);
|
LOG.debug(reason);
|
||||||
}
|
}
|
||||||
return compaction;
|
return compaction;
|
||||||
|
@ -491,12 +489,12 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
if (cmp != 0) {
|
if (cmp != 0) {
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
Optional<CompactionContext> c1 = o1.compaction;
|
CompactionContext c1 = o1.compaction;
|
||||||
Optional<CompactionContext> c2 = o2.compaction;
|
CompactionContext c2 = o2.compaction;
|
||||||
if (c1.isPresent()) {
|
if (c1 != null) {
|
||||||
return c2.isPresent() ? compare(c1.get().getRequest(), c2.get().getRequest()) : -1;
|
return c2 != null ? compare(c1.getRequest(), c2.getRequest()) : -1;
|
||||||
} else {
|
} else {
|
||||||
return c2.isPresent() ? 1 : 0;
|
return c2 != null ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -504,19 +502,24 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
private final class CompactionRunner implements Runnable {
|
private final class CompactionRunner implements Runnable {
|
||||||
private final HStore store;
|
private final HStore store;
|
||||||
private final HRegion region;
|
private final HRegion region;
|
||||||
private final Optional<CompactionContext> compaction;
|
private final CompactionContext compaction;
|
||||||
|
private final CompactionLifeCycleTracker tracker;
|
||||||
|
private final CompactionCompleteTracker completeTracker;
|
||||||
private int queuedPriority;
|
private int queuedPriority;
|
||||||
private ThreadPoolExecutor parent;
|
private ThreadPoolExecutor parent;
|
||||||
private User user;
|
private User user;
|
||||||
private long time;
|
private long time;
|
||||||
|
|
||||||
public CompactionRunner(HStore store, HRegion region, Optional<CompactionContext> compaction,
|
public CompactionRunner(HStore store, HRegion region, CompactionContext compaction,
|
||||||
|
CompactionLifeCycleTracker tracker, CompactionCompleteTracker completeTracker,
|
||||||
ThreadPoolExecutor parent, User user) {
|
ThreadPoolExecutor parent, User user) {
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.region = region;
|
this.region = region;
|
||||||
this.compaction = compaction;
|
this.compaction = compaction;
|
||||||
this.queuedPriority = compaction.isPresent() ? compaction.get().getRequest().getPriority()
|
this.tracker = tracker;
|
||||||
: store.getCompactPriority();
|
this.completeTracker = completeTracker;
|
||||||
|
this.queuedPriority =
|
||||||
|
compaction != null ? compaction.getRequest().getPriority() : store.getCompactPriority();
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.time = EnvironmentEdgeManager.currentTime();
|
this.time = EnvironmentEdgeManager.currentTime();
|
||||||
|
@ -524,15 +527,18 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return compaction.map(c -> "Request = " + c.getRequest())
|
if (compaction != null) {
|
||||||
.orElse("regionName = " + region.toString() + ", storeName = " + store.toString() +
|
return "Request = " + compaction.getRequest();
|
||||||
", priority = " + queuedPriority + ", time = " + time);
|
} else {
|
||||||
|
return "regionName = " + region.toString() + ", storeName = " + store.toString() +
|
||||||
|
", priority = " + queuedPriority + ", time = " + time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doCompaction(User user) {
|
private void doCompaction(User user) {
|
||||||
CompactionContext c;
|
CompactionContext c;
|
||||||
// Common case - system compaction without a file selection. Select now.
|
// Common case - system compaction without a file selection. Select now.
|
||||||
if (!compaction.isPresent()) {
|
if (compaction == null) {
|
||||||
int oldPriority = this.queuedPriority;
|
int oldPriority = this.queuedPriority;
|
||||||
this.queuedPriority = this.store.getCompactPriority();
|
this.queuedPriority = this.store.getCompactPriority();
|
||||||
if (this.queuedPriority > oldPriority) {
|
if (this.queuedPriority > oldPriority) {
|
||||||
|
@ -543,8 +549,8 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
}
|
}
|
||||||
Optional<CompactionContext> selected;
|
Optional<CompactionContext> selected;
|
||||||
try {
|
try {
|
||||||
selected = selectCompaction(this.region, this.store, queuedPriority,
|
selected = selectCompaction(this.region, this.store, queuedPriority, tracker,
|
||||||
CompactionLifeCycleTracker.DUMMY, user);
|
completeTracker, user);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOG.error("Compaction selection failed " + this, ex);
|
LOG.error("Compaction selection failed " + this, ex);
|
||||||
server.checkFileSystem();
|
server.checkFileSystem();
|
||||||
|
@ -572,12 +578,12 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = compaction.get();
|
c = compaction;
|
||||||
}
|
}
|
||||||
// Finally we can compact something.
|
// Finally we can compact something.
|
||||||
assert c != null;
|
assert c != null;
|
||||||
|
|
||||||
c.getRequest().getTracker().beforeExecution(store);
|
tracker.beforeExecution(store);
|
||||||
try {
|
try {
|
||||||
// Note: please don't put single-compaction logic here;
|
// Note: please don't put single-compaction logic here;
|
||||||
// put it into region/store/etc. This is CST logic.
|
// put it into region/store/etc. This is CST logic.
|
||||||
|
@ -610,7 +616,8 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
region.reportCompactionRequestFailure();
|
region.reportCompactionRequestFailure();
|
||||||
server.checkFileSystem();
|
server.checkFileSystem();
|
||||||
} finally {
|
} finally {
|
||||||
c.getRequest().getTracker().afterExecution(store);
|
tracker.afterExecution(store);
|
||||||
|
completeTracker.completed(store);
|
||||||
region.decrementCompactionsQueuedCount();
|
region.decrementCompactionsQueuedCount();
|
||||||
LOG.debug("CompactSplitThread Status: " + CompactSplit.this);
|
LOG.debug("CompactSplitThread Status: " + CompactSplit.this);
|
||||||
}
|
}
|
||||||
|
@ -645,7 +652,9 @@ public class CompactSplit implements CompactionRequester, PropagatingConfigurati
|
||||||
if (runnable instanceof CompactionRunner) {
|
if (runnable instanceof CompactionRunner) {
|
||||||
CompactionRunner runner = (CompactionRunner) runnable;
|
CompactionRunner runner = (CompactionRunner) runnable;
|
||||||
LOG.debug("Compaction Rejected: " + runner);
|
LOG.debug("Compaction Rejected: " + runner);
|
||||||
runner.compaction.ifPresent(c -> runner.store.cancelRequestedCompaction(c));
|
if (runner.compaction != null) {
|
||||||
|
runner.store.cancelRequestedCompaction(runner.compaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
@ -34,6 +35,7 @@ import org.apache.hadoop.hbase.client.Put;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
|
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
|
||||||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||||
|
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
|
||||||
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
|
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
|
||||||
import org.apache.hadoop.hbase.coprocessor.RegionObserver;
|
import org.apache.hadoop.hbase.coprocessor.RegionObserver;
|
||||||
import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
|
import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
|
||||||
|
@ -76,7 +78,12 @@ public class TestCompactionLifeCycleTracker {
|
||||||
private static CompactionLifeCycleTracker TRACKER = null;
|
private static CompactionLifeCycleTracker TRACKER = null;
|
||||||
|
|
||||||
// make sure that we pass the correct CompactionLifeCycleTracker to CP hooks.
|
// make sure that we pass the correct CompactionLifeCycleTracker to CP hooks.
|
||||||
public static final class CompactionObserver implements RegionObserver {
|
public static final class CompactionObserver implements RegionObserver, RegionCoprocessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<RegionObserver> getRegionObserver() {
|
||||||
|
return Optional.of(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
|
public void preCompactSelection(ObserverContext<RegionCoprocessorEnvironment> c, Store store,
|
||||||
|
|
Loading…
Reference in New Issue