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 }