You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ji...@apache.org on 2008/03/12 19:00:45 UTC
svn commit: r636438 - in /hadoop/hbase/branches/0.1: CHANGES.txt
src/java/org/apache/hadoop/hbase/HMaster.java
src/java/org/apache/hadoop/hbase/HRegion.java
src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java
Author: jimk
Date: Wed Mar 12 11:00:37 2008
New Revision: 636438
URL: http://svn.apache.org/viewvc?rev=636438&view=rev
Log:
HBASE-27 hregioninfo cell empty in meta table
Summary of changes:
HMaster:
- When a row has an empty HRegionInfo (info:regioninfo), log it with the row name and and the other keys still in the row.
- Log the number of rows with empty HRegionInfo
- Delete the rows
- Make RowMap inner class static, change methods to have package scope to avoid synthetic accessors.
- Provide row name to getHRegionInfo so it can issue better log messages
- add method deleteEmptyMetaRows to remove rows with empty HRegionInfo
HRegion
- change removeRegionFromMETA to use deleteAll rather than using a BatchUpdate containing deletes for each cell.
TestEmptyMetaInfo
- new test case
Added:
hadoop/hbase/branches/0.1/src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java
Modified:
hadoop/hbase/branches/0.1/CHANGES.txt
hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HMaster.java
hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HRegion.java
Modified: hadoop/hbase/branches/0.1/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.1/CHANGES.txt?rev=636438&r1=636437&r2=636438&view=diff
==============================================================================
--- hadoop/hbase/branches/0.1/CHANGES.txt (original)
+++ hadoop/hbase/branches/0.1/CHANGES.txt Wed Mar 12 11:00:37 2008
@@ -38,6 +38,7 @@
HBASE-495 No server address listed in .META.
HBASE-433 HBASE-251 Region server should delete restore log after successful
restore, Stuck replaying the edits of crashed machine.
+ HBASE-27 hregioninfo cell empty in meta table
IMPROVEMENTS
HADOOP-2555 Refactor the HTable#get and HTable#getRow methods to avoid
Modified: hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HMaster.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HMaster.java?rev=636438&r1=636437&r2=636438&view=diff
==============================================================================
--- hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HMaster.java (original)
+++ hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HMaster.java Wed Mar 12 11:00:37 2008
@@ -215,6 +215,7 @@
// scan we go check if parents can be removed.
Map<HRegionInfo, SortedMap<Text, byte[]>> splitParents =
new HashMap<HRegionInfo, SortedMap<Text, byte[]>>();
+ List<Text> emptyRows = new ArrayList<Text>();
try {
regionServer = connection.getHRegionConnection(region.getServer());
scannerId =
@@ -229,10 +230,13 @@
}
// TODO: Why does this have to be a sorted map?
- SortedMap<Text, byte[]> results = toRowMap(values).getMap();
-
- HRegionInfo info = getHRegionInfo(results);
+ RowMap m = toRowMap(values);
+ SortedMap<Text, byte[]> results = m.getMap();
+
+ Text row = m.getRow();
+ HRegionInfo info = getHRegionInfo(row, results);
if (info == null) {
+ emptyRows.add(row);
continue;
}
@@ -272,12 +276,23 @@
}
} catch (IOException e) {
LOG.error("Closing scanner",
- RemoteExceptionHandler.checkIOException(e));
+ RemoteExceptionHandler.checkIOException(e));
}
}
- // Scan is finished. Take a look at split parents to see if any we can
- // clean up.
+ // Scan is finished.
+
+ // First clean up any meta region rows which had null HRegionInfo's
+
+ if (emptyRows.size() > 0) {
+ LOG.warn("Found " + emptyRows.size() +
+ " rows with empty HRegionInfo while scanning meta region " +
+ region.getRegionName());
+ deleteEmptyMetaRows(regionServer, region.getRegionName(), emptyRows);
+ }
+
+ // Take a look at split parents to see if any we can clean up.
+
if (splitParents.size() > 0) {
for (Map.Entry<HRegionInfo, SortedMap<Text, byte[]>> e:
splitParents.entrySet()) {
@@ -356,7 +371,7 @@
* @return True if still has references to parent.
* @throws IOException
*/
- protected boolean hasReferences(final Text metaRegionName,
+ private boolean hasReferences(final Text metaRegionName,
final HRegionInterface srvr, final Text parent,
SortedMap<Text, byte[]> rowContent, final Text splitColumn)
throws IOException {
@@ -1263,6 +1278,7 @@
* HMasterRegionInterface
*/
+ /** {@inheritDoc} */
@SuppressWarnings("unused")
public HbaseMapWritable regionServerStartup(HServerInfo serverInfo)
throws IOException {
@@ -2002,8 +2018,9 @@
private void scanMetaRegion(HRegionInterface server, long scannerId,
Text regionName)
throws IOException {
- ArrayList<ToDoEntry> toDoList = new ArrayList<ToDoEntry>();
- HashSet<HRegionInfo> regions = new HashSet<HRegionInfo>();
+ List<ToDoEntry> toDoList = new ArrayList<ToDoEntry>();
+ Set<HRegionInfo> regions = new HashSet<HRegionInfo>();
+ List<Text> emptyRows = new ArrayList<Text>();
try {
while (true) {
HbaseMapWritable values = null;
@@ -2038,8 +2055,9 @@
}
// Bingo! Found it.
- HRegionInfo info = getHRegionInfo(map);
+ HRegionInfo info = getHRegionInfo(row, map);
if (info == null) {
+ emptyRows.add(row);
continue;
}
LOG.info(info.getRegionName() + " was on shutdown server <" +
@@ -2099,6 +2117,15 @@
}
}
+ // Scan complete. Remove any rows which had empty HRegionInfo
+
+ if (emptyRows.size() > 0) {
+ LOG.warn("Found " + emptyRows.size() +
+ " rows with empty HRegionInfo while scanning meta region " +
+ regionName);
+ deleteEmptyMetaRows(server, regionName, emptyRows);
+ }
+
// Update server in root/meta entries
for (ToDoEntry e: toDoList) {
if (e.deleteRegion) {
@@ -2697,6 +2724,7 @@
server.openScanner(m.getRegionName(), COLUMN_FAMILY_ARRAY,
tableName, System.currentTimeMillis(), null);
+ List<Text> emptyRows = new ArrayList<Text>();
try {
while (true) {
HbaseMapWritable values = server.next(scannerId);
@@ -2705,10 +2733,12 @@
}
RowMap rm = toRowMap(values);
SortedMap<Text, byte[]> map = rm.getMap();
- HRegionInfo info = getHRegionInfo(map);
+ Text row = rm.getRow();
+ HRegionInfo info = getHRegionInfo(row, map);
if (info == null) {
+ emptyRows.add(row);
throw new IOException(COL_REGIONINFO + " not found on " +
- rm.getRow());
+ row);
}
String serverName = Writables.bytesToString(map.get(COL_SERVER));
long startCode = Writables.bytesToLong(map.get(COL_STARTCODE));
@@ -2734,6 +2764,15 @@
scannerId = -1L;
}
+ // Get rid of any rows that have a null HRegionInfo
+
+ if (emptyRows.size() > 0) {
+ LOG.warn("Found " + emptyRows.size() +
+ " rows with empty HRegionInfo while scanning meta region " +
+ m.getRegionName());
+ deleteEmptyMetaRows(server, m.getRegionName(), emptyRows);
+ }
+
if (!tableExists) {
throw new IOException(tableName + " does not exist");
}
@@ -3120,20 +3159,28 @@
/*
* Data structure used to return results out of the toRowMap method.
*/
- private class RowMap {
- final Text row;
- final SortedMap<Text, byte[]> map;
+ private static class RowMap {
+ private final Text row;
+ private final SortedMap<Text, byte[]> map;
- private RowMap(final Text r, final SortedMap<Text, byte[]> m) {
+ /**
+ * Constructor
+ *
+ * @param r the row
+ * @param m the map of column names to values
+ */
+ RowMap(final Text r, final SortedMap<Text, byte[]> m) {
this.row = r;
this.map = m;
}
- private Text getRow() {
+ /** @return the row */
+ Text getRow() {
return this.row;
}
- private SortedMap<Text, byte[]> getMap() {
+ /** @return the column value map */
+ SortedMap<Text, byte[]> getMap() {
return this.map;
}
}
@@ -3171,19 +3218,44 @@
* Get HRegionInfo from passed META map of row values.
* Returns null if none found (and logs fact that expected COL_REGIONINFO
* was missing). Utility method used by scanners of META tables.
+ * @param row name of the row
* @param map Map to do lookup in.
* @return Null or found HRegionInfo.
* @throws IOException
*/
- protected HRegionInfo getHRegionInfo(final Map<Text, byte[]> map)
+ protected HRegionInfo getHRegionInfo(final Text row,
+ final Map<Text, byte[]> map)
throws IOException {
byte [] bytes = map.get(COL_REGIONINFO);
if (bytes == null) {
- LOG.warn(COL_REGIONINFO.toString() + " is empty; has keys: " +
- map.keySet().toString());
+ LOG.warn(COL_REGIONINFO.toString() + " is empty for row: " + row +
+ "; has keys: " + map.keySet().toString());
return null;
}
return (HRegionInfo)Writables.getWritable(bytes, new HRegionInfo());
+ }
+
+ /*
+ * When we find rows in a meta region that has an empty HRegionInfo, we
+ * clean them up here.
+ *
+ * @param server connection to server serving meta region
+ * @param metaRegionName name of the meta region we scanned
+ * @param emptyRows the row keys that had empty HRegionInfos
+ */
+ protected void deleteEmptyMetaRows(HRegionInterface server,
+ Text metaRegionName,
+ List<Text> emptyRows) {
+ for (Text regionName: emptyRows) {
+ try {
+ HRegion.removeRegionFromMETA(server, metaRegionName, regionName);
+ LOG.warn("Removed region: " + regionName + " from meta region: " +
+ metaRegionName + " because HRegionInfo was empty");
+ } catch (IOException e) {
+ LOG.error("deleting region: " + regionName + " from meta region: " +
+ metaRegionName, e);
+ }
+ }
}
/*
Modified: hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HRegion.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HRegion.java?rev=636438&r1=636437&r2=636438&view=diff
==============================================================================
--- hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HRegion.java (original)
+++ hadoop/hbase/branches/0.1/src/java/org/apache/hadoop/hbase/HRegion.java Wed Mar 12 11:00:37 2008
@@ -1851,22 +1851,17 @@
* Delete a region's meta information from the passed
* <code>meta</code> region.
*
- * @param srvr META server to be updated
+ * @param server META server to be updated
* @param metaRegionName Meta region name
* @param regionNmae HRegion to remove from <code>meta</code>
*
* @throws IOException
* @see {@link #addRegionToMETA(HRegion, HRegion)}
*/
- static void removeRegionFromMETA(final HRegionInterface srvr,
+ static void removeRegionFromMETA(final HRegionInterface server,
final Text metaRegionName, final Text regionName)
throws IOException {
- BatchUpdate b = new BatchUpdate(rand.nextLong());
- long lockid = b.startUpdate(regionName);
- for (int i = 0; i < ALL_META_COLUMNS.length; i++) {
- b.delete(lockid, ALL_META_COLUMNS[i]);
- }
- srvr.batchUpdate(metaRegionName, System.currentTimeMillis(), b);
+ server.deleteAll(metaRegionName, regionName, LATEST_TIMESTAMP);
}
/**
Added: hadoop/hbase/branches/0.1/src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.1/src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java?rev=636438&view=auto
==============================================================================
--- hadoop/hbase/branches/0.1/src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java (added)
+++ hadoop/hbase/branches/0.1/src/test/org/apache/hadoop/hbase/TestEmptyMetaInfo.java Wed Mar 12 11:00:37 2008
@@ -0,0 +1,76 @@
+/**
+ * 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.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.hadoop.io.Text;
+
+/**
+ * Tests master cleanup of rows in meta table where there is no HRegionInfo
+ */
+public class TestEmptyMetaInfo extends HBaseClusterTestCase {
+ /**
+ * Insert some bogus rows in meta. Master should clean them up.
+ * @throws IOException
+ */
+ public void testEmptyMetaInfo() throws IOException {
+ HTable t = new HTable(conf, HConstants.META_TABLE_NAME);
+ for (int i = 0; i < 5; i++) {
+ Text regionName = new Text("tablename," + (i == 0 ? "" : (i +",")) +
+ System.currentTimeMillis());
+ long lockid = t.startUpdate(regionName);
+ t.put(lockid, HConstants.COL_SERVER,
+ "localhost:1234".getBytes(HConstants.UTF8_ENCODING));
+ t.commit(lockid);
+ }
+ long sleepTime =
+ conf.getLong("hbase.master.meta.thread.rescanfrequency", 10000);
+ int tries = conf.getInt("hbase.client.retries.number", 5);
+ int count = 0;
+ do {
+ tries -= 1;
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ HScannerInterface scanner =
+ t.obtainScanner(HConstants.ALL_META_COLUMNS, new Text("tablename"));
+
+ try {
+ count = 0;
+ HStoreKey key = new HStoreKey();
+ SortedMap<Text, byte[]> results = new TreeMap<Text, byte[]>();
+ while (scanner.next(key, results)) {
+ count += 1;
+ }
+ } finally {
+ scanner.close();
+ }
+ } while (count != 0 && tries >= 0);
+ assertTrue(tries >= 0);
+ assertEquals(0, count);
+ }
+}