@Override public int compareTo(CompactionRunner o) { // Only compare the underlying request (if any), for queue sorting purposes. int compareVal = queuedPriority - o.queuedPriority; // compare priority if (compareVal != 0) return compareVal; CompactionContext tc = this.compaction, oc = o.compaction; // Sort pre-selected (user?) compactions before system ones with equal priority. return (tc == null) ? ((oc == null) ? 0 : 1) : ((oc == null) ? -1 : tc.getRequest().compareTo(oc.getRequest())); }
private CompactionContext selectCompaction( final HRegion r, final Store s, int priority, CompactionRequest request) throws IOException { CompactionContext compaction = s.requestCompaction(priority, request); if (compaction == null) { if (LOG.isDebugEnabled()) { LOG.debug( "Not compacting " + r.getRegionNameAsString() + " because compaction request was cancelled"); } return null; } assert compaction.hasSelection(); if (priority != Store.NO_PRIORITY) { compaction.getRequest().setPriority(priority); } return compaction; }
public CompactionRunner( Store store, HRegion region, CompactionContext compaction, ThreadPoolExecutor parent) { super(); this.store = store; this.region = region; this.compaction = compaction; this.queuedPriority = (this.compaction == null) ? store.getCompactPriority() : compaction.getRequest().getPriority(); this.parent = parent; }
/** * @param r HRegion store belongs to * @param s Store to request compaction on * @param why Why compaction requested -- used in debug messages * @param priority override the default priority (NO_PRIORITY == decide) * @param request custom compaction request. Can be <tt>null</tt> in which case a simple * compaction will be used. */ private synchronized CompactionRequest requestCompactionInternal( final HRegion r, final Store s, final String why, int priority, CompactionRequest request, boolean selectNow) throws IOException { if (this.server.isStopped() || (r.getTableDesc() != null && !r.getTableDesc().isCompactionEnabled())) { return null; } CompactionContext compaction = null; if (selectNow) { compaction = selectCompaction(r, s, priority, request); if (compaction == null) return null; // message logged inside } // 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. long size = selectNow ? compaction.getRequest().getSize() : 0; ThreadPoolExecutor pool = (!selectNow && s.throttleCompaction(size)) ? longCompactions : shortCompactions; pool.execute(new CompactionRunner(s, r, compaction, pool)); if (LOG.isDebugEnabled()) { String type = (pool == shortCompactions) ? "Small " : "Large "; LOG.debug( type + "Compaction requested: " + (selectNow ? compaction.toString() : "system") + (why != null && !why.isEmpty() ? "; Because: " + why : "") + "; " + this); } return selectNow ? compaction.getRequest() : null; }
@Override public void run() { Preconditions.checkNotNull(server); if (server.isStopped() || (region.getTableDesc() != null && !region.getTableDesc().isCompactionEnabled())) { return; } // Common case - system compaction without a file selection. Select now. if (this.compaction == null) { int oldPriority = this.queuedPriority; this.queuedPriority = this.store.getCompactPriority(); if (this.queuedPriority > oldPriority) { // Store priority decreased while we were in queue (due to some other compaction?), // requeue with new priority to avoid blocking potential higher priorities. this.parent.execute(this); return; } try { this.compaction = selectCompaction(this.region, this.store, queuedPriority, null); } catch (IOException ex) { LOG.error("Compaction selection failed " + this, ex); server.checkFileSystem(); return; } if (this.compaction == null) return; // nothing to do // Now see if we are in correct pool for the size; if not, go to the correct one. // We might end up waiting for a while, so cancel the selection. assert this.compaction.hasSelection(); ThreadPoolExecutor pool = store.throttleCompaction(compaction.getRequest().getSize()) ? longCompactions : shortCompactions; if (this.parent != pool) { this.store.cancelRequestedCompaction(this.compaction); this.compaction = null; this.parent = pool; this.parent.execute(this); return; } } // Finally we can compact something. assert this.compaction != null; this.compaction.getRequest().beforeExecute(); try { // Note: please don't put single-compaction logic here; // put it into region/store/etc. This is CST logic. long start = EnvironmentEdgeManager.currentTime(); boolean completed = region.compact(compaction, store); long now = EnvironmentEdgeManager.currentTime(); LOG.info( ((completed) ? "Completed" : "Aborted") + " compaction: " + this + "; duration=" + StringUtils.formatTimeDiff(now, start)); if (completed) { // degenerate case: blocked regions require recursive enqueues if (store.getCompactPriority() <= 0) { requestSystemCompaction(region, store, "Recursive enqueue"); } else { // see if the compaction has caused us to exceed max region size requestSplit(region); } } } catch (IOException ex) { IOException remoteEx = ex instanceof RemoteException ? ((RemoteException) ex).unwrapRemoteException() : ex; LOG.error("Compaction failed " + this, remoteEx); if (remoteEx != ex) { LOG.info("Compaction failed at original callstack: " + formatStackTrace(ex)); } server.checkFileSystem(); } catch (Exception ex) { LOG.error("Compaction failed " + this, ex); server.checkFileSystem(); } finally { LOG.debug("CompactSplitThread Status: " + CompactSplitThread.this); } this.compaction.getRequest().afterExecute(); }
@Override public String toString() { return (this.compaction != null) ? ("Request = " + compaction.getRequest()) : ("Store = " + store.toString() + ", pri = " + queuedPriority); }