You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2010/05/04 23:50:46 UTC

svn commit: r941063 - in /hadoop/hbase/branches/0.20: CHANGES.txt src/java/org/apache/hadoop/hbase/regionserver/HRegion.java src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java

Author: stack
Date: Tue May  4 21:50:45 2010
New Revision: 941063

URL: http://svn.apache.org/viewvc?rev=941063&view=rev
Log:
HBASE-2509 NPEs in various places, HRegion.get, HRS.close

Modified:
    hadoop/hbase/branches/0.20/CHANGES.txt
    hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hadoop/hbase/branches/0.20/src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java

Modified: hadoop/hbase/branches/0.20/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/CHANGES.txt?rev=941063&r1=941062&r2=941063&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/CHANGES.txt (original)
+++ hadoop/hbase/branches/0.20/CHANGES.txt Tue May  4 21:50:45 2010
@@ -116,6 +116,8 @@ Release 0.20.4 - Unreleased
                useful (Benoit Sigoure via Stack)
    HBASE-2482  regions in transition do not get reassigned by master when RS
                crashes (Todd Lipcon via Stack)
+   HBASE-2509  NPEs in various places, HRegion.get, HRS.close
+               (Ryan Rawson via Stack)
 
   IMPROVEMENTS
    HBASE-2180  Bad read performance from synchronizing hfile.fddatainputstream

Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=941063&r1=941062&r2=941063&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/regionserver/HRegion.java Tue May  4 21:50:45 2010
@@ -1915,7 +1915,8 @@ public class HRegion implements HConstan
    * It is used to combine scanners from multiple Stores (aka column families).
    */
   class RegionScanner implements InternalScanner {
-    private KeyValueHeap storeHeap = null;
+    // Package local for testability
+    KeyValueHeap storeHeap = null;
     private final byte [] stopRow;
     private Filter filter;
     private RowFilterInterface oldFilter;
@@ -2089,7 +2090,10 @@ public class HRegion implements HConstan
     }
 
     public void close() {
-      storeHeap.close();
+      if (storeHeap != null) {
+        storeHeap.close();
+        storeHeap = null;
+      }
     }
 
     /**
@@ -2101,13 +2105,6 @@ public class HRegion implements HConstan
         scanner.close();
       } catch(NullPointerException npe) {}
     }
-    
-    /**
-     * @return the current storeHeap
-     */
-    public KeyValueHeap getStoreHeap() {
-      return this.storeHeap;
-    }
   }
   
   // Utility methods

Modified: hadoop/hbase/branches/0.20/src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java?rev=941063&r1=941062&r2=941063&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java (original)
+++ hadoop/hbase/branches/0.20/src/test/org/apache/hadoop/hbase/regionserver/TestHRegion.java Tue May  4 21:50:45 2010
@@ -21,11 +21,15 @@ package org.apache.hadoop.hbase.regionse
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
-import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.Assert;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -42,19 +46,16 @@ import org.apache.hadoop.hbase.client.Ge
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.BinaryComparator;
 import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter;
+import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.filter.FilterList;
 import org.apache.hadoop.hbase.filter.PrefixFilter;
 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
-import org.apache.hadoop.hbase.filter.CompareFilter;
-import org.apache.hadoop.hbase.filter.BinaryComparator;
-import org.apache.hadoop.hbase.filter.RowFilter;
-import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.regionserver.HRegion.RegionScanner;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.util.Pair;
-import junit.framework.Assert;
 
 /**
  * Basic stand-alone testing of HRegion.
@@ -92,7 +93,94 @@ public class TestHRegion extends HBaseTe
   // individual code pieces in the HRegion. Putting files locally in
   // /tmp/testtable
   //////////////////////////////////////////////////////////////////////////////
-  
+
+  public void testGetWhileRegionClose() throws IOException {
+    HBaseConfiguration hc = initSplit();
+    int numRows = 100;
+    byte [][] families = {fam1, fam2, fam3};
+    
+    //Setting up region
+    String method = this.getName();
+    initHRegion(tableName, method, hc, families);
+
+    // Put data in region
+    final int startRow = 100;
+    putData(startRow, numRows, qual1, families);
+    putData(startRow, numRows, qual2, families);
+    putData(startRow, numRows, qual3, families);
+    // this.region.flushcache();
+    final AtomicBoolean done = new AtomicBoolean(false);
+    final AtomicInteger gets = new AtomicInteger(0);
+    GetTillDoneOrException [] threads = new GetTillDoneOrException[10];
+    try {
+      // Set ten threads running concurrently getting from the region.
+      for (int i = 0; i < threads.length / 2; i++) {
+        threads[i] = new GetTillDoneOrException(i, Bytes.toBytes("" + startRow),
+          done, gets);
+        threads[i].setDaemon(true);
+        threads[i].start();
+      }
+      // Artificially make the condition by setting closing flag explicitly.
+      // I can't make the issue happen with a call to region.close().
+      this.region.closing.set(true);
+      for (int i = threads.length / 2; i < threads.length; i++) {
+        threads[i] = new GetTillDoneOrException(i, Bytes.toBytes("" + startRow),
+          done, gets);
+        threads[i].setDaemon(true);
+        threads[i].start();
+      }
+    } finally {
+      if (this.region != null) {
+        this.region.close();
+        this.region.getLog().closeAndDelete();
+      }
+    }
+    done.set(true);
+    for (GetTillDoneOrException t: threads) {
+      try {
+        t.join();
+      } catch (InterruptedException e) {
+        e.printStackTrace();
+      }
+      if (t.e != null) {
+        LOG.info("Exception=" + t.e);
+        assertFalse("Found a NPE in " + t.getName(),
+          t.e instanceof NullPointerException);
+      }
+    }
+  }
+
+  /*
+   * Thread that does get on single row until 'done' flag is flipped.  If an
+   * exception causes us to fail, it records it.
+   */
+  class GetTillDoneOrException extends Thread {
+    private final Get g;
+    private final AtomicBoolean done;
+    private final AtomicInteger count;
+    private Exception e;
+
+    GetTillDoneOrException(final int i, final byte[] r, final AtomicBoolean d,
+        final AtomicInteger c) {
+      super("getter." + i);
+      this.g = new Get(r);
+      this.done = d;
+      this.count = c;
+    }
+
+    @Override
+    public void run() {
+      while (!this.done.get()) {
+        try {
+          assertTrue(region.get(g, null).size() > 0);
+          this.count.incrementAndGet();
+        } catch (Exception e) {
+          this.e = e;
+          break;
+        }
+      }
+    }
+  }
 
   /*
    * An involved filter test.  Has multiple column families and deletes in mix.
@@ -1019,13 +1107,13 @@ public class TestHRegion extends HBaseTe
     scan.addFamily(fam4);
     is = (RegionScanner) region.getScanner(scan);
     is.initHeap(); // i dont like this test
-    assertEquals(1, ((RegionScanner)is).getStoreHeap().getHeap().size());
+    assertEquals(1, ((RegionScanner)is).storeHeap.getHeap().size());
     
     scan = new Scan();
     is = (RegionScanner) region.getScanner(scan);
     is.initHeap();
     assertEquals(families.length -1, 
-        ((RegionScanner)is).getStoreHeap().getHeap().size());
+        ((RegionScanner)is).storeHeap.getHeap().size());
   }
 
   public void testRegionScanner_Next() throws IOException {