You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2014/11/12 00:24:23 UTC
[2/3] hbase git commit: HBASE-12460 Moving Chore to hbase-common
module
HBASE-12460 Moving Chore to hbase-common module
Signed-off-by: Matteo Bertozzi <ma...@cloudera.com>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/133c79a3
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/133c79a3
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/133c79a3
Branch: refs/heads/branch-1
Commit: 133c79a391793cdfced86f3818cd4bf1873a9bd2
Parents: bebf018
Author: Srikanth Srungarapu <ss...@cloudera.com>
Authored: Tue Nov 11 14:47:48 2014 -0800
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Tue Nov 11 23:18:37 2014 +0000
----------------------------------------------------------------------
.../java/org/apache/hadoop/hbase/Chore.java | 142 -------------------
.../java/org/apache/hadoop/hbase/Stoppable.java | 38 -----
.../org/apache/hadoop/hbase/util/HasThread.java | 100 -------------
.../org/apache/hadoop/hbase/util/Sleeper.java | 117 ---------------
.../java/org/apache/hadoop/hbase/Chore.java | 142 +++++++++++++++++++
.../java/org/apache/hadoop/hbase/Stoppable.java | 38 +++++
.../org/apache/hadoop/hbase/util/HasThread.java | 100 +++++++++++++
.../org/apache/hadoop/hbase/util/Sleeper.java | 117 +++++++++++++++
8 files changed, 397 insertions(+), 397 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-client/src/main/java/org/apache/hadoop/hbase/Chore.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/Chore.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/Chore.java
deleted file mode 100644
index c2c7964..0000000
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/Chore.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-import org.apache.hadoop.hbase.util.HasThread;
-import org.apache.hadoop.hbase.util.Sleeper;
-
-/**
- * Chore is a task performed on a period in hbase. The chore is run in its own
- * thread. This base abstract class provides while loop and sleeping facility.
- * If an unhandled exception, the threads exit is logged.
- * Implementers just need to add checking if there is work to be done and if
- * so, do it. Its the base of most of the chore threads in hbase.
- *
- * <p>Don't subclass Chore if the task relies on being woken up for something to
- * do, such as an entry being added to a queue, etc.
- */
-@InterfaceAudience.Private
-public abstract class Chore extends HasThread {
- private final Log LOG = LogFactory.getLog(this.getClass());
- private final Sleeper sleeper;
- protected final Stoppable stopper;
-
- /**
- * @param p Period at which we should run. Will be adjusted appropriately
- * should we find work and it takes time to complete.
- * @param stopper When {@link Stoppable#isStopped()} is true, this thread will
- * cleanup and exit cleanly.
- */
- public Chore(String name, final int p, final Stoppable stopper) {
- super(name);
- if (stopper == null){
- throw new NullPointerException("stopper cannot be null");
- }
- this.sleeper = new Sleeper(p, stopper);
- this.stopper = stopper;
- }
-
- /**
- * This constructor is for test only. It allows to create an object and to call chore() on
- * it. There is no sleeper nor stoppable.
- */
- protected Chore(){
- sleeper = null;
- stopper = null;
- }
-
- /**
- * @see java.lang.Thread#run()
- */
- @Override
- public void run() {
- try {
- boolean initialChoreComplete = false;
- while (!this.stopper.isStopped()) {
- long startTime = System.currentTimeMillis();
- try {
- if (!initialChoreComplete) {
- initialChoreComplete = initialChore();
- } else {
- chore();
- }
- } catch (Exception e) {
- LOG.error("Caught exception", e);
- if (this.stopper.isStopped()) {
- continue;
- }
- }
- this.sleeper.sleep(startTime);
- }
- } catch (Throwable t) {
- LOG.fatal(getName() + "error", t);
- } finally {
- LOG.info(getName() + " exiting");
- cleanup();
- }
- }
-
- /**
- * 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();
- }
-
- /*
- * Exposed for TESTING!
- * calls directly the chore method, from the current thread.
- */
- public void choreForTesting() {
- chore();
- }
-
- /**
- * Override to run a task before we start looping.
- * @return true if initial chore was successful
- */
- protected boolean initialChore() {
- // Default does nothing.
- return true;
- }
-
- /**
- * Look for chores. If any found, do them else just return.
- */
- protected abstract void chore();
-
- /**
- * Sleep for period.
- */
- protected void sleep() {
- this.sleeper.sleep();
- }
-
- /**
- * Called when the chore has completed, allowing subclasses to cleanup any
- * extra overhead
- */
- protected void cleanup() {
- }
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-client/src/main/java/org/apache/hadoop/hbase/Stoppable.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/Stoppable.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/Stoppable.java
deleted file mode 100644
index b87b764..0000000
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/Stoppable.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase;
-
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-
-/**
- * Implementers are Stoppable.
- */
-@InterfaceAudience.Private
-public interface Stoppable {
- /**
- * Stop this service.
- * @param why Why we're stopping.
- */
- void stop(String why);
-
- /**
- * @return True if {@link #stop(String)} has been closed.
- */
- boolean isStopped();
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-client/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/util/HasThread.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
deleted file mode 100644
index 4457fe0..0000000
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase.util;
-
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-
-/**
- * Abstract class which contains a Thread and delegates the common Thread
- * methods to that instance.
- *
- * The purpose of this class is to workaround Sun JVM bug #6915621, in which
- * something internal to the JDK uses Thread.currentThread() as a monitor
- * lock. This can produce deadlocks like HBASE-4367, HBASE-4101, etc.
- */
-@InterfaceAudience.Private
-public abstract class HasThread implements Runnable {
- private final Thread thread;
-
- public HasThread() {
- this.thread = new Thread(this);
- }
-
- public HasThread(String name) {
- this.thread = new Thread(this, name);
- }
-
- public Thread getThread() {
- return thread;
- }
-
- public abstract void run();
-
- //// Begin delegation to Thread
-
- public final String getName() {
- return thread.getName();
- }
-
- public void interrupt() {
- thread.interrupt();
- }
-
- public final boolean isAlive() {
- return thread.isAlive();
- }
-
- public boolean isInterrupted() {
- return thread.isInterrupted();
- }
-
- public final void setDaemon(boolean on) {
- thread.setDaemon(on);
- }
-
- public final void setName(String name) {
- thread.setName(name);
- }
-
- public final void setPriority(int newPriority) {
- thread.setPriority(newPriority);
- }
-
- public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
- thread.setUncaughtExceptionHandler(eh);
- }
-
- public void start() {
- thread.start();
- }
-
- public final void join() throws InterruptedException {
- thread.join();
- }
-
- public final void join(long millis, int nanos) throws InterruptedException {
- thread.join(millis, nanos);
- }
-
- public final void join(long millis) throws InterruptedException {
- thread.join(millis);
- }
- //// End delegation to Thread
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-client/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
deleted file mode 100644
index 071250b..0000000
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase.util;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-import org.apache.hadoop.hbase.Stoppable;
-
-/**
- * Sleeper for current thread.
- * Sleeps for passed period. Also checks passed boolean and if interrupted,
- * will return if the flag is set (rather than go back to sleep until its
- * sleep time is up).
- */
-@InterfaceAudience.Private
-public class Sleeper {
- private final Log LOG = LogFactory.getLog(this.getClass().getName());
- private final int period;
- private final Stoppable stopper;
- 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 stopper When {@link Stoppable#isStopped()} is true, this thread will
- * cleanup and exit cleanly.
- */
- public Sleeper(final int sleep, final Stoppable stopper) {
- this.period = sleep;
- this.stopper = stopper;
- }
-
- /**
- * Sleep for period.
- */
- 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.notifyAll();
- }
- }
-
- /**
- * Sleep for period adjusted by passed <code>startTime<code>
- * @param startTime Time some task started previous to now. Time to sleep
- * will be docked current time minus passed <code>startTime<code>.
- */
- public void sleep(final long startTime) {
- if (this.stopper.isStopped()) {
- return;
- }
- long now = System.currentTimeMillis();
- long waitTime = this.period - (now - startTime);
- if (waitTime > this.period) {
- LOG.warn("Calculated wait time > " + this.period +
- "; setting to this.period: " + System.currentTimeMillis() + ", " +
- startTime);
- waitTime = this.period;
- }
- while (waitTime > 0) {
- long woke = -1;
- try {
- synchronized (sleepLock) {
- if (triggerWake) break;
- sleepLock.wait(waitTime);
- }
- woke = System.currentTimeMillis();
- long slept = woke - now;
- if (slept - this.period > MINIMAL_DELTA_FOR_LOGGING) {
- LOG.warn("We slept " + slept + "ms instead of " + this.period +
- "ms, this is likely due to a long " +
- "garbage collecting pause and it's usually bad, see " +
- "http://hbase.apache.org/book.html#trouble.rs.runtime.zkexpired");
- }
- } catch(InterruptedException iex) {
- // We we interrupted because we're meant to stop? If not, just
- // continue ignoring the interruption
- if (this.stopper.isStopped()) {
- return;
- }
- }
- // Recalculate waitTime.
- woke = (woke == -1)? System.currentTimeMillis(): woke;
- waitTime = this.period - (woke - startTime);
- }
- synchronized(sleepLock) {
- triggerWake = false;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-common/src/main/java/org/apache/hadoop/hbase/Chore.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/Chore.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/Chore.java
new file mode 100644
index 0000000..c2c7964
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/Chore.java
@@ -0,0 +1,142 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.util.HasThread;
+import org.apache.hadoop.hbase.util.Sleeper;
+
+/**
+ * Chore is a task performed on a period in hbase. The chore is run in its own
+ * thread. This base abstract class provides while loop and sleeping facility.
+ * If an unhandled exception, the threads exit is logged.
+ * Implementers just need to add checking if there is work to be done and if
+ * so, do it. Its the base of most of the chore threads in hbase.
+ *
+ * <p>Don't subclass Chore if the task relies on being woken up for something to
+ * do, such as an entry being added to a queue, etc.
+ */
+@InterfaceAudience.Private
+public abstract class Chore extends HasThread {
+ private final Log LOG = LogFactory.getLog(this.getClass());
+ private final Sleeper sleeper;
+ protected final Stoppable stopper;
+
+ /**
+ * @param p Period at which we should run. Will be adjusted appropriately
+ * should we find work and it takes time to complete.
+ * @param stopper When {@link Stoppable#isStopped()} is true, this thread will
+ * cleanup and exit cleanly.
+ */
+ public Chore(String name, final int p, final Stoppable stopper) {
+ super(name);
+ if (stopper == null){
+ throw new NullPointerException("stopper cannot be null");
+ }
+ this.sleeper = new Sleeper(p, stopper);
+ this.stopper = stopper;
+ }
+
+ /**
+ * This constructor is for test only. It allows to create an object and to call chore() on
+ * it. There is no sleeper nor stoppable.
+ */
+ protected Chore(){
+ sleeper = null;
+ stopper = null;
+ }
+
+ /**
+ * @see java.lang.Thread#run()
+ */
+ @Override
+ public void run() {
+ try {
+ boolean initialChoreComplete = false;
+ while (!this.stopper.isStopped()) {
+ long startTime = System.currentTimeMillis();
+ try {
+ if (!initialChoreComplete) {
+ initialChoreComplete = initialChore();
+ } else {
+ chore();
+ }
+ } catch (Exception e) {
+ LOG.error("Caught exception", e);
+ if (this.stopper.isStopped()) {
+ continue;
+ }
+ }
+ this.sleeper.sleep(startTime);
+ }
+ } catch (Throwable t) {
+ LOG.fatal(getName() + "error", t);
+ } finally {
+ LOG.info(getName() + " exiting");
+ cleanup();
+ }
+ }
+
+ /**
+ * 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();
+ }
+
+ /*
+ * Exposed for TESTING!
+ * calls directly the chore method, from the current thread.
+ */
+ public void choreForTesting() {
+ chore();
+ }
+
+ /**
+ * Override to run a task before we start looping.
+ * @return true if initial chore was successful
+ */
+ protected boolean initialChore() {
+ // Default does nothing.
+ return true;
+ }
+
+ /**
+ * Look for chores. If any found, do them else just return.
+ */
+ protected abstract void chore();
+
+ /**
+ * Sleep for period.
+ */
+ protected void sleep() {
+ this.sleeper.sleep();
+ }
+
+ /**
+ * Called when the chore has completed, allowing subclasses to cleanup any
+ * extra overhead
+ */
+ protected void cleanup() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-common/src/main/java/org/apache/hadoop/hbase/Stoppable.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/Stoppable.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/Stoppable.java
new file mode 100644
index 0000000..b87b764
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/Stoppable.java
@@ -0,0 +1,38 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+
+/**
+ * Implementers are Stoppable.
+ */
+@InterfaceAudience.Private
+public interface Stoppable {
+ /**
+ * Stop this service.
+ * @param why Why we're stopping.
+ */
+ void stop(String why);
+
+ /**
+ * @return True if {@link #stop(String)} has been closed.
+ */
+ boolean isStopped();
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-common/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/HasThread.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
new file mode 100644
index 0000000..4457fe0
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/HasThread.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.util;
+
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+
+/**
+ * Abstract class which contains a Thread and delegates the common Thread
+ * methods to that instance.
+ *
+ * The purpose of this class is to workaround Sun JVM bug #6915621, in which
+ * something internal to the JDK uses Thread.currentThread() as a monitor
+ * lock. This can produce deadlocks like HBASE-4367, HBASE-4101, etc.
+ */
+@InterfaceAudience.Private
+public abstract class HasThread implements Runnable {
+ private final Thread thread;
+
+ public HasThread() {
+ this.thread = new Thread(this);
+ }
+
+ public HasThread(String name) {
+ this.thread = new Thread(this, name);
+ }
+
+ public Thread getThread() {
+ return thread;
+ }
+
+ public abstract void run();
+
+ //// Begin delegation to Thread
+
+ public final String getName() {
+ return thread.getName();
+ }
+
+ public void interrupt() {
+ thread.interrupt();
+ }
+
+ public final boolean isAlive() {
+ return thread.isAlive();
+ }
+
+ public boolean isInterrupted() {
+ return thread.isInterrupted();
+ }
+
+ public final void setDaemon(boolean on) {
+ thread.setDaemon(on);
+ }
+
+ public final void setName(String name) {
+ thread.setName(name);
+ }
+
+ public final void setPriority(int newPriority) {
+ thread.setPriority(newPriority);
+ }
+
+ public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
+ thread.setUncaughtExceptionHandler(eh);
+ }
+
+ public void start() {
+ thread.start();
+ }
+
+ public final void join() throws InterruptedException {
+ thread.join();
+ }
+
+ public final void join(long millis, int nanos) throws InterruptedException {
+ thread.join(millis, nanos);
+ }
+
+ public final void join(long millis) throws InterruptedException {
+ thread.join(millis);
+ }
+ //// End delegation to Thread
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/133c79a3/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
new file mode 100644
index 0000000..071250b
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Sleeper.java
@@ -0,0 +1,117 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.Stoppable;
+
+/**
+ * Sleeper for current thread.
+ * Sleeps for passed period. Also checks passed boolean and if interrupted,
+ * will return if the flag is set (rather than go back to sleep until its
+ * sleep time is up).
+ */
+@InterfaceAudience.Private
+public class Sleeper {
+ private final Log LOG = LogFactory.getLog(this.getClass().getName());
+ private final int period;
+ private final Stoppable stopper;
+ 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 stopper When {@link Stoppable#isStopped()} is true, this thread will
+ * cleanup and exit cleanly.
+ */
+ public Sleeper(final int sleep, final Stoppable stopper) {
+ this.period = sleep;
+ this.stopper = stopper;
+ }
+
+ /**
+ * Sleep for period.
+ */
+ 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.notifyAll();
+ }
+ }
+
+ /**
+ * Sleep for period adjusted by passed <code>startTime<code>
+ * @param startTime Time some task started previous to now. Time to sleep
+ * will be docked current time minus passed <code>startTime<code>.
+ */
+ public void sleep(final long startTime) {
+ if (this.stopper.isStopped()) {
+ return;
+ }
+ long now = System.currentTimeMillis();
+ long waitTime = this.period - (now - startTime);
+ if (waitTime > this.period) {
+ LOG.warn("Calculated wait time > " + this.period +
+ "; setting to this.period: " + System.currentTimeMillis() + ", " +
+ startTime);
+ waitTime = this.period;
+ }
+ while (waitTime > 0) {
+ long woke = -1;
+ try {
+ synchronized (sleepLock) {
+ if (triggerWake) break;
+ sleepLock.wait(waitTime);
+ }
+ woke = System.currentTimeMillis();
+ long slept = woke - now;
+ if (slept - this.period > MINIMAL_DELTA_FOR_LOGGING) {
+ LOG.warn("We slept " + slept + "ms instead of " + this.period +
+ "ms, this is likely due to a long " +
+ "garbage collecting pause and it's usually bad, see " +
+ "http://hbase.apache.org/book.html#trouble.rs.runtime.zkexpired");
+ }
+ } catch(InterruptedException iex) {
+ // We we interrupted because we're meant to stop? If not, just
+ // continue ignoring the interruption
+ if (this.stopper.isStopped()) {
+ return;
+ }
+ }
+ // Recalculate waitTime.
+ woke = (woke == -1)? System.currentTimeMillis(): woke;
+ waitTime = this.period - (woke - startTime);
+ }
+ synchronized(sleepLock) {
+ triggerWake = false;
+ }
+ }
+}