hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject 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
Date Wed, 12 Mar 2008 18:00:45 GMT
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);
+  }
+}



Mime
View raw message