1 /**
2 * Copyright 2007 The Apache Software Foundation
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 package org.apache.hadoop.hbase;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.hbase.util.HasThread;
25 import org.apache.hadoop.hbase.util.Sleeper;
26
27 /**
28 * Chore is a task performed on a period in hbase. The chore is run in its own
29 * thread. This base abstract class provides while loop and sleeping facility.
30 * If an unhandled exception, the threads exit is logged.
31 * Implementers just need to add checking if there is work to be done and if
32 * so, do it. Its the base of most of the chore threads in hbase.
33 *
34 * <p>Don't subclass Chore if the task relies on being woken up for something to
35 * do, such as an entry being added to a queue, etc.
36 */
37 public abstract class Chore extends HasThread {
38 private final Log LOG = LogFactory.getLog(this.getClass());
39 private final Sleeper sleeper;
40 protected final Stoppable stopper;
41
42 /**
43 * @param p Period at which we should run. Will be adjusted appropriately
44 * should we find work and it takes time to complete.
45 * @param stopper When {@link Stoppable#isStopped()} is true, this thread will
46 * cleanup and exit cleanly.
47 */
48 public Chore(String name, final int p, final Stoppable stopper) {
49 super(name);
50 this.sleeper = new Sleeper(p, stopper);
51 this.stopper = stopper;
52 }
53
54 /**
55 * @see java.lang.Thread#run()
56 */
57 @Override
58 public void run() {
59 try {
60 boolean initialChoreComplete = false;
61 while (!this.stopper.isStopped()) {
62 long startTime = System.currentTimeMillis();
63 try {
64 if (!initialChoreComplete) {
65 initialChoreComplete = initialChore();
66 } else {
67 chore();
68 }
69 } catch (Exception e) {
70 LOG.error("Caught exception", e);
71 if (this.stopper.isStopped()) {
72 continue;
73 }
74 }
75 this.sleeper.sleep(startTime);
76 }
77 } catch (Throwable t) {
78 LOG.fatal(getName() + "error", t);
79 } finally {
80 LOG.info(getName() + " exiting");
81 }
82 }
83
84 /**
85 * If the thread is currently sleeping, trigger the core to happen immediately.
86 * If it's in the middle of its operation, will begin another operation
87 * immediately after finishing this one.
88 */
89 public void triggerNow() {
90 this.sleeper.skipSleepCycle();
91 }
92
93 /**
94 * Override to run a task before we start looping.
95 * @return true if initial chore was successful
96 */
97 protected boolean initialChore() {
98 // Default does nothing.
99 return true;
100 }
101
102 /**
103 * Look for chores. If any found, do them else just return.
104 */
105 protected abstract void chore();
106
107 /**
108 * Sleep for period.
109 */
110 protected void sleep() {
111 this.sleeper.sleep();
112 }
113 }