/** * @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(); }