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 java.util.concurrent.atomic.AtomicBoolean;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.hbase.util.Sleeper;
27
28 /**
29 * Chore is a task performed on a period in hbase. The chore is run in its own
30 * thread. This base abstract class provides while loop and sleeping facility.
31 * If an unhandled exception, the threads exit is logged.
32 * Implementers just need to add checking if there is work to be done and if
33 * so, do it. Its the base of most of the chore threads in hbase.
34 *
35 * Don't subclass Chore if the task relies on being woken up for something to
36 * do, such as an entry being added to a queue, etc.
37 */
38 public abstract class Chore extends Thread {
39 private final Log LOG = LogFactory.getLog(this.getClass());
40 private final Sleeper sleeper;
41 protected volatile AtomicBoolean stop;
42
43 /**
44 * @param p Period at which we should run. Will be adjusted appropriately
45 * should we find work and it takes time to complete.
46 * @param s When this flag is set to true, this thread will cleanup and exit
47 * cleanly.
48 */
49 public Chore(String name, final int p, final AtomicBoolean s) {
50 super(name);
51 this.sleeper = new Sleeper(p, s);
52 this.stop = s;
53 }
54
55 /**
56 * @see java.lang.Thread#run()
57 */
58 @Override
59 public void run() {
60 try {
61 boolean initialChoreComplete = false;
62 while (!this.stop.get()) {
63 long startTime = System.currentTimeMillis();
64 try {
65 if (!initialChoreComplete) {
66 initialChoreComplete = initialChore();
67 } else {
68 chore();
69 }
70 } catch (Exception e) {
71 LOG.error("Caught exception", e);
72 if (this.stop.get()) {
73 continue;
74 }
75 }
76 this.sleeper.sleep(startTime);
77 }
78 } catch (Throwable t) {
79 LOG.fatal("Caught error. Starting shutdown.", t);
80 this.stop.set(true);
81 } finally {
82 LOG.info(getName() + " exiting");
83 }
84 }
85
86 /**
87 * If the thread is currently sleeping, trigger the core to happen immediately.
88 * If it's in the middle of its operation, will begin another operation
89 * immediately after finishing this one.
90 */
91 public void triggerNow() {
92 this.sleeper.skipSleepCycle();
93 }
94
95 /**
96 * Override to run a task before we start looping.
97 * @return true if initial chore was successful
98 */
99 protected boolean initialChore() {
100 // Default does nothing.
101 return true;
102 }
103
104 /**
105 * Look for chores. If any found, do them else just return.
106 */
107 protected abstract void chore();
108
109 /**
110 * Sleep for period.
111 */
112 protected void sleep() {
113 this.sleeper.sleep();
114 }
115 }