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