HBASE-533 Region Historian (forgot to add these files)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@663346 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2008-06-04 19:10:03 +00:00
parent 4b2c5ed76d
commit 0271ef616d
2 changed files with 333 additions and 0 deletions

View File

@ -0,0 +1,291 @@
/**
* Copyright 2008 The Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.util.Bytes;
/**
* The Region Historian task is to keep track of every modification a region
* has to go trought. Public methods are used to update the information in the
* .META. table and to retreive it.
*/
public class RegionHistorian implements HConstants {
static final Log LOG = LogFactory.getLog(RegionHistorian.class);
private HTable metaTable;
private GregorianCalendar cal = new GregorianCalendar();
/** Singleton reference */
private static RegionHistorian historian;
/** Date formater for the timestamp in RegionHistoryInformation */
private static SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEE, d MMM yyyy HH:mm:ss");
public static enum HistorianColumnKey {
REGION_CREATION ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"creation")),
REGION_OPEN ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"open")),
REGION_SPLIT ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"split")),
REGION_COMPACTION ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"compaction")),
REGION_FLUSH ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"flush")),
REGION_ASSIGNMENT ( Bytes.toBytes(COLUMN_FAMILY_HISTORIAN_STR+"assignment"));
public byte[] key;
HistorianColumnKey(byte[] key) {
this.key = key;
}
}
/**
* Default constructor. Initializes reference to .META. table
*
*/
private RegionHistorian() {
HBaseConfiguration conf = new HBaseConfiguration();
try {
metaTable = new HTable(conf, META_TABLE_NAME);
LOG.debug("Region historian is ready.");
} catch (IOException ioe) {
LOG.warn("Unable to create RegionHistorian", ioe);
}
}
/**
* Singleton method
*
* @return The region historian
*/
public static RegionHistorian getInstance() {
if (historian == null) {
historian = new RegionHistorian();
}
return historian;
}
/**
* Returns, for a given region name, an ordered list by timestamp of all
* values in the historian column of the .META. table.
*
* @param regionName
* Region name as a string
* @return List of RegionHistoryInformation
*/
public static List<RegionHistoryInformation> getRegionHistory(
String regionName) {
getInstance();
List<RegionHistoryInformation> informations = new ArrayList<RegionHistoryInformation>();
try {
/*
* TODO REGION_HISTORIAN_KEYS is used because there is no other for the
* moment to retrieve all version and to have the column key information.
* To be changed when HTable.getRow handles versions.
*/
for (HistorianColumnKey keyEnu : HistorianColumnKey.values()) {
byte[] columnKey = keyEnu.key;
Cell[] cells = historian.metaTable.get(Bytes.toBytes(regionName),
columnKey, ALL_VERSIONS);
if (cells != null) {
for (Cell cell : cells) {
informations.add(historian.new RegionHistoryInformation(cell
.getTimestamp(), Bytes.toString(columnKey).split(":")[1], Bytes
.toString(cell.getValue())));
}
}
}
} catch (IOException ioe) {
LOG.warn("Unable to retrieve region history", ioe);
}
Collections.sort(informations);
return informations;
}
/**
* Method to add a creation event to the row in the .META table
*
* @param info
*/
public static void addRegionAssignment(HRegionInfo info, String serverName) {
add(HistorianColumnKey.REGION_ASSIGNMENT.key, "Region assigned to server "
+ serverName, info);
}
/**
* Method to add a creation event to the row in the .META table
*
* @param info
*/
public static void addRegionCreation(HRegionInfo info) {
add(HistorianColumnKey.REGION_CREATION.key, "Region creation", info);
}
/**
* Method to add a opening event to the row in the .META table
*
* @param info
* @param address
*/
public static void addRegionOpen(HRegionInfo info, HServerAddress address) {
add(HistorianColumnKey.REGION_OPEN.key, "Region opened on server : "
+ address.getHostname(), info);
}
/**
* Method to add a split event to the rows in the .META table with
* information from oldInfo.
* @param oldInfo
* @param newInfo1
* @param newInfo2
*/
public static void addRegionSplit(HRegionInfo oldInfo, HRegionInfo newInfo1,
HRegionInfo newInfo2) {
HRegionInfo[] infos = new HRegionInfo[] { newInfo1, newInfo2 };
for (HRegionInfo info : infos) {
add(HistorianColumnKey.REGION_SPLIT.key, "Region split from : "
+ oldInfo.getRegionNameAsString(), info);
}
}
/**
* Method to add a compaction event to the row in the .META table
*
* @param info
*/
public static void addRegionCompaction(HRegionInfo info, String timeTaken) {
if (LOG.isDebugEnabled()) {
add(HistorianColumnKey.REGION_COMPACTION.key,
"Region compaction completed in " + timeTaken, info);
}
}
/**
* Method to add a flush event to the row in the .META table
*
* @param info
*/
public static void addRegionFlush(HRegionInfo info, String timeTaken) {
if (LOG.isDebugEnabled()) {
add(HistorianColumnKey.REGION_FLUSH.key, "Region flush completed in "
+ timeTaken, info);
}
}
/**
* Method to add an event with LATEST_TIMESTAMP.
* @param column
* @param text
* @param info
*/
private static void add(byte[] column, String text, HRegionInfo info) {
add(column, text, info, LATEST_TIMESTAMP);
}
/**
* Method to add an event with provided information.
* @param column
* @param text
* @param info
* @param timestamp
*/
private static void add(byte[] column, String text, HRegionInfo info, long timestamp) {
if (!info.isMetaRegion()) {
getInstance();
BatchUpdate batch = new BatchUpdate(info.getRegionName());
batch.setTimestamp(timestamp);
batch.put(column, Bytes.toBytes(text));
try {
historian.metaTable.commit(batch);
} catch (IOException ioe) {
LOG.warn("Unable to '" + text + "'", ioe);
}
}
}
/**
* Inner class that only contains information about an event.
*
*/
public class RegionHistoryInformation implements
Comparable<RegionHistoryInformation> {
private long timestamp;
private String event;
private String description;
public RegionHistoryInformation(long timestamp, String event,
String description) {
this.timestamp = timestamp;
this.event = event;
this.description = description;
}
/**
* Returns the inverse value of Long.compareTo
*/
public int compareTo(RegionHistoryInformation otherInfo) {
return -1 * Long.valueOf(timestamp).compareTo(otherInfo.getTimestamp());
}
public String getEvent() {
return event;
}
public String getDescription() {
return description;
}
public long getTimestamp() {
return timestamp;
}
/**
* Returns the value of the timestamp processed
* with the date formater.
* @return
*/
public String getTimestampAsString() {
cal.setTimeInMillis(timestamp);
return dateFormat.format(cal.getTime());
}
}
}

View File

@ -0,0 +1,42 @@
<%@ page contentType="text/html;charset=UTF-8"
import="java.util.List"
import="org.apache.hadoop.hbase.RegionHistorian"
import="org.apache.hadoop.hbase.RegionHistorian.RegionHistoryInformation"
import="org.apache.hadoop.hbase.HConstants"%><%
String regionName = request.getParameter("regionname");
List<RegionHistoryInformation> informations = RegionHistorian.getRegionHistory(regionName);
%><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>Region in <%= regionName %></title>
<link rel="stylesheet" type="text/css" href="/static/hbase.css" />
</head>
<body>
<a id="logo" href="http://wiki.apache.org/lucene-hadoop/Hbase"><img src="/static/hbase_logo_med.gif" alt="HBase Logo" title="HBase Logo" /></a>
<h1 id="page_title">Region <%= regionName %></h1>
<p id="links_menu"><a href="/master.jsp">Master</a>, <a href="/logs/">Local logs</a>, <a href="/stacks">Thread Dump</a>, <a href="/logLevel">Log Level</a></p>
<hr id="head_rule" />
<%if(informations != null && informations.size() > 0) { %>
<table><tr><th>Timestamp</th><th>Event</th><th>Description</th></tr>
<% for( RegionHistoryInformation information : informations) {%>
<tr><td><%= information.getTimestampAsString() %></td><td><%= information.getEvent() %></td><td><%= information.getDescription()%></td></tr>
<% } %>
</table>
<p>
Master is the source of following events :
creation,open,assignment.
Regions are the source of following events :
split,compaction, flush
</p>
<%} else {%>
<p>
This region is no longer available. It may be due to a split, a merge or the name changed.
</p>
<%} %>
</body>
</html>