View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.monitoring;
20  
21  import static org.junit.Assert.*;
22  
23  import java.util.concurrent.atomic.AtomicBoolean;
24  
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.testclassification.SmallTests;
27  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
28  import org.junit.Test;
29  import org.junit.experimental.categories.Category;
30  
31  @Category(SmallTests.class)
32  public class TestTaskMonitor {
33  
34    @Test
35    public void testTaskMonitorBasics() {
36      TaskMonitor tm = new TaskMonitor(new Configuration());
37      assertTrue("Task monitor should start empty",
38          tm.getTasks().isEmpty());
39      
40      // Make a task and fetch it back out
41      MonitoredTask task = tm.createStatus("Test task");
42      MonitoredTask taskFromTm = tm.getTasks().get(0);
43      
44      // Make sure the state is reasonable.
45      assertEquals(task.getDescription(), taskFromTm.getDescription());
46      assertEquals(-1, taskFromTm.getCompletionTimestamp());
47      assertEquals(MonitoredTask.State.RUNNING, taskFromTm.getState());
48      
49      // Mark it as finished
50      task.markComplete("Finished!");
51      assertEquals(MonitoredTask.State.COMPLETE, task.getState());
52      
53      // It should still show up in the TaskMonitor list
54      assertEquals(1, tm.getTasks().size());
55      
56      // If we mark its completion time back a few minutes, it should get gced
57      task.expireNow();
58      assertEquals(0, tm.getTasks().size());
59  
60      tm.shutdown();
61    }
62    
63    @Test
64    public void testTasksGetAbortedOnLeak() throws InterruptedException {
65      final TaskMonitor tm = new TaskMonitor(new Configuration());
66      assertTrue("Task monitor should start empty",
67          tm.getTasks().isEmpty());
68      
69      final AtomicBoolean threadSuccess = new AtomicBoolean(false);
70      // Make a task in some other thread and leak it
71      Thread t = new Thread() {
72        @Override
73        public void run() {
74          MonitoredTask task = tm.createStatus("Test task");    
75          assertEquals(MonitoredTask.State.RUNNING, task.getState());
76          threadSuccess.set(true);
77        }
78      };
79      t.start();
80      t.join();
81      // Make sure the thread saw the correct state
82      assertTrue(threadSuccess.get());
83      
84      // Make sure the leaked reference gets cleared
85      System.gc();
86      System.gc();
87      System.gc();
88      
89      // Now it should be aborted 
90      MonitoredTask taskFromTm = tm.getTasks().get(0);
91      assertEquals(MonitoredTask.State.ABORTED, taskFromTm.getState());
92  
93      tm.shutdown();
94    }
95    
96    @Test
97    public void testTaskLimit() throws Exception {
98      TaskMonitor tm = new TaskMonitor(new Configuration());
99      for (int i = 0; i < TaskMonitor.DEFAULT_MAX_TASKS + 10; i++) {
100       tm.createStatus("task " + i);
101     }
102     // Make sure it was limited correctly
103     assertEquals(TaskMonitor.DEFAULT_MAX_TASKS, tm.getTasks().size());
104     // Make sure we culled the earlier tasks, not later
105     // (i.e. tasks 0 through 9 should have been deleted)
106     assertEquals("task 10", tm.getTasks().get(0).getDescription());
107     tm.shutdown();
108   }
109 
110   @Test
111   public void testDoNotPurgeRPCTask() throws Exception {
112     int RPCTaskNums = 10;
113     TaskMonitor tm = TaskMonitor.get();
114     for(int i = 0; i < RPCTaskNums; i++) {
115       tm.createRPCStatus("PRCTask" + i);
116     }
117     for(int i = 0; i < TaskMonitor.DEFAULT_MAX_TASKS; i++) {
118       tm.createStatus("otherTask" + i);
119     }
120     int remainRPCTask = 0;
121     for(MonitoredTask task: tm.getTasks()) {
122       if(task instanceof MonitoredRPCHandler) {
123         remainRPCTask++;
124       }
125     }
126     assertEquals("RPC Tasks have been purged!", RPCTaskNums, remainRPCTask);
127     tm.shutdown();
128   }
129 
130   @Test
131   public void testWarnStuckTasks() throws Exception {
132     final int RPC_WARN_TIME = 1500;
133     final int MONITOR_INTERVAL = 500;
134     Configuration conf = new Configuration();
135     conf.setLong(TaskMonitor.RPC_WARN_TIME_KEY, RPC_WARN_TIME);
136     conf.setLong(TaskMonitor.MONITOR_INTERVAL_KEY, MONITOR_INTERVAL);
137     final TaskMonitor tm = new TaskMonitor(conf);
138     MonitoredRPCHandler t = tm.createRPCStatus("test task");
139     long beforeSetRPC = EnvironmentEdgeManager.currentTime();
140     assertTrue("Validating initialization assumption", t.getWarnTime() <= beforeSetRPC);
141     Thread.sleep(MONITOR_INTERVAL * 2);
142     t.setRPC("testMethod", new Object[0], beforeSetRPC);
143     long afterSetRPC = EnvironmentEdgeManager.currentTime();
144     Thread.sleep(MONITOR_INTERVAL * 2);
145     assertTrue("Validating no warn after starting RPC", t.getWarnTime() <= afterSetRPC);
146     Thread.sleep(MONITOR_INTERVAL * 2);
147     assertTrue("Validating warn after RPC_WARN_TIME", t.getWarnTime() > afterSetRPC);
148     tm.shutdown();
149   }
150 
151   @Test
152   public void testStatusJournal() {
153     TaskMonitor tm = new TaskMonitor(new Configuration());
154     MonitoredTask task = tm.createStatus("Test task");
155     assertTrue(task.getStatusJournal().isEmpty());
156     task.disableStatusJournal();
157     task.setStatus("status1");
158     // journal should be empty since it is disabled
159     assertTrue(task.getStatusJournal().isEmpty());
160     task.enableStatusJournal(true);
161     // check existing status entered in journal
162     assertEquals("status1", task.getStatusJournal().get(0).getStatus());
163     assertTrue(task.getStatusJournal().get(0).getTimeStamp() > 0);
164     task.disableStatusJournal();
165     task.setStatus("status2");
166     // check status 2 not added since disabled
167     assertEquals(1, task.getStatusJournal().size());
168     task.enableStatusJournal(false);
169     // size should still be 1 since we didn't include current status
170     assertEquals(1, task.getStatusJournal().size());
171     task.setStatus("status3");
172     assertEquals("status3", task.getStatusJournal().get(1).getStatus());
173     tm.shutdown();
174   }
175 
176 }
177