Author: stack Date: Sat Apr 24 17:15:58 2010 New Revision: 937651 URL: http://svn.apache.org/viewvc?rev=937651&view=rev Log: HBASE-2448 Scanner threads are interrupted without acquiring lock properly
Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/Chore.java hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ModifyTableMeta.java hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/Chore.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/Chore.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/Chore.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/Chore.java Sat Apr 24 17:15:58 2010 @@ -84,6 +84,15 @@ public abstract class Chore extends Thre } /** + * If the thread is currently sleeping, trigger the core to happen immediately. + * If it's in the middle of its operation, will begin another operation + * immediately after finishing this one. + */ + public void triggerNow() { + this.sleeper.skipSleepCycle(); + } + + /** * Override to run a task before we start looping. * @return true if initial chore was successful */ Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java Sat Apr 24 17:15:58 2010 @@ -588,9 +588,9 @@ abstract class BaseScanner extends Chore } /** - * Notify the thread to die at the end of its next run + * Interrupt thread regardless of what it's doing */ - public void interruptIfAlive() { + public void interruptAndStop() { synchronized(scannerLock){ if (isAlive()) { super.interrupt(); Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ModifyTableMeta.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ModifyTableMeta.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ModifyTableMeta.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ModifyTableMeta.java Sat Apr 24 17:15:58 2010 @@ -72,6 +72,6 @@ class ModifyTableMeta extends TableOpera updateRegionInfo(server, m.getRegionName(), i); } // kick off a meta scan right away - master.getRegionManager().metaScannerThread.interrupt(); + master.getRegionManager().metaScannerThread.triggerNow(); } } Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java Sat Apr 24 17:15:58 2010 @@ -100,7 +100,7 @@ class ProcessRegionOpen extends ProcessR master.getRegionManager().putMetaRegionOnline(m); // Interrupting the Meta Scanner sleep so that it can // process regions right away - master.getRegionManager().metaScannerThread.interrupt(); + master.getRegionManager().metaScannerThread.triggerNow(); } } // If updated successfully, remove from pending list if the state @@ -120,4 +120,4 @@ class ProcessRegionOpen extends ProcessR protected int getPriority() { return 0; // highest priority } -} \ No newline at end of file +} Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java Sat Apr 24 17:15:58 2010 @@ -581,11 +581,11 @@ public class RegionManager implements HC if (LOG.isDebugEnabled()) { LOG.debug("telling root scanner to stop"); } - rootScannerThread.interruptIfAlive(); + rootScannerThread.interruptAndStop(); if (LOG.isDebugEnabled()) { LOG.debug("telling meta scanner to stop"); } - metaScannerThread.interruptIfAlive(); + metaScannerThread.interruptAndStop(); if (LOG.isDebugEnabled()) { LOG.debug("meta and root scanners notified"); } Modified: hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java?rev=937651&r1=937650&r2=937651&view=diff ============================================================================== --- hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java (original) +++ hadoop/hbase/trunk/core/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java Sat Apr 24 17:15:58 2010 @@ -35,7 +35,10 @@ public class Sleeper { private final int period; private final AtomicBoolean stop; private static final long MINIMAL_DELTA_FOR_LOGGING = 10000; - + + private final Object sleepLock = new Object(); + private boolean triggerWake = false; + /** * @param sleep sleep time in milliseconds * @param stop flag for when we stop @@ -51,6 +54,17 @@ public class Sleeper { public void sleep() { sleep(System.currentTimeMillis()); } + + /** + * If currently asleep, stops sleeping; if not asleep, will skip the next + * sleep cycle. + */ + public void skipSleepCycle() { + synchronized (sleepLock) { + triggerWake = true; + sleepLock.notify(); + } + } /** * Sleep for period adjusted by passed <code>startTime<code> @@ -72,7 +86,10 @@ public class Sleeper { while (waitTime > 0) { long woke = -1; try { - Thread.sleep(waitTime); + synchronized (sleepLock) { + if (triggerWake) break; + sleepLock.wait(waitTime); + } woke = System.currentTimeMillis(); long slept = woke - now; if (slept - this.period > MINIMAL_DELTA_FOR_LOGGING) { @@ -92,5 +109,6 @@ public class Sleeper { woke = (woke == -1)? System.currentTimeMillis(): woke; waitTime = this.period - (woke - startTime); } + triggerWake = false; } }