Author: kturner
Date: Fri Oct 12 00:22:14 2012
New Revision: 1397391

URL: http://svn.apache.org/viewvc?rev=1397391&view=rev
Log:
ACCUMULO-806 fixed bug where a tablet location could not be found when the 
metadata table had empty tablets (merged from 1.4)

Modified:
    accumulo/trunk/   (props changed)
    accumulo/trunk/core/   (props changed)
    
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/MetadataLocationObtainer.java
    
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
    
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocatorImpl.java
    
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/util/MetadataTable.java
    
accumulo/trunk/core/src/test/java/org/apache/accumulo/core/client/impl/TabletLocatorImplTest.java
    accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java   
(props changed)
    accumulo/trunk/server/   (props changed)
    accumulo/trunk/src/   (props changed)

Propchange: accumulo/trunk/
------------------------------------------------------------------------------
  Merged /accumulo/branches/1.4/src:r1397383
  Merged /accumulo/branches/1.4:r1397383

Propchange: accumulo/trunk/core/
------------------------------------------------------------------------------
  Merged /accumulo/branches/1.4/core:r1397383
  Merged /accumulo/branches/1.4/src/core:r1397383

Modified: 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/MetadataLocationObtainer.java
URL: 
http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/MetadataLocationObtainer.java?rev=1397391&r1=1397390&r2=1397391&view=diff
==============================================================================
--- 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/MetadataLocationObtainer.java
 (original)
+++ 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/MetadataLocationObtainer.java
 Fri Oct 12 00:22:14 2012
@@ -32,6 +32,7 @@ import org.apache.accumulo.core.client.A
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocation;
+import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocations;
 import 
org.apache.accumulo.core.client.impl.TabletLocatorImpl.TabletLocationObtainer;
 import 
org.apache.accumulo.core.client.impl.TabletServerBatchReaderIterator.ResultReceiver;
 import org.apache.accumulo.core.data.Column;
@@ -44,6 +45,7 @@ import org.apache.accumulo.core.security
 import org.apache.accumulo.core.tabletserver.thrift.NotServingTabletException;
 import org.apache.accumulo.core.util.MetadataTable;
 import org.apache.accumulo.core.util.OpTimer;
+import org.apache.accumulo.core.util.Pair;
 import org.apache.accumulo.core.util.TextUtil;
 import org.apache.hadoop.io.Text;
 import org.apache.log4j.Level;
@@ -68,12 +70,12 @@ public class MetadataLocationObtainer im
   }
   
   @Override
-  public List<TabletLocation> lookupTablet(TabletLocation src, Text row, Text 
stopRow, TabletLocator parent) throws AccumuloSecurityException,
+  public TabletLocations lookupTablet(TabletLocation src, Text row, Text 
stopRow, TabletLocator parent) throws AccumuloSecurityException,
       AccumuloException {
-    
-    ArrayList<TabletLocation> list = new ArrayList<TabletLocation>();
-    
+
     try {
+      ArrayList<TabletLocation> list = new ArrayList<TabletLocation>();
+
       OpTimer opTimer = null;
       if (log.isTraceEnabled())
         opTimer = new OpTimer(log, Level.TRACE).start("Looking up in " + 
src.tablet_extent.getTableId() + " row=" + TextUtil.truncate(row) + "  extent="
@@ -98,12 +100,14 @@ public class MetadataLocationObtainer im
       
       // System.out.println("results "+results.keySet());
       
-      SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results);
+      Pair<SortedMap<KeyExtent,Text>,List<KeyExtent>> metadata = 
MetadataTable.getMetadataLocationEntries(results);
       
-      for (Entry<KeyExtent,Text> entry : metadata.entrySet()) {
+      for (Entry<KeyExtent,Text> entry : metadata.getFirst().entrySet()) {
         list.add(new TabletLocation(entry.getKey(), 
entry.getValue().toString()));
       }
       
+      return new TabletLocations(list, metadata.getSecond());
+
     } catch (AccumuloServerException ase) {
       if (log.isTraceEnabled())
         log.trace(src.tablet_extent.getTableId() + " lookup failed, " + 
src.tablet_location + " server side exception");
@@ -118,7 +122,7 @@ public class MetadataLocationObtainer im
       parent.invalidateCache(src.tablet_location);
     }
     
-    return list;
+    return null;
   }
   
   @Override
@@ -161,7 +165,7 @@ public class MetadataLocationObtainer im
       throw e;
     }
     
-    SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results);
+    SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results).getFirst();
     
     for (Entry<KeyExtent,Text> entry : metadata.entrySet()) {
       list.add(new TabletLocation(entry.getKey(), 
entry.getValue().toString()));

Modified: 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
URL: 
http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java?rev=1397391&r1=1397390&r2=1397391&view=diff
==============================================================================
--- 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
 (original)
+++ 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
 Fri Oct 12 00:22:14 2012
@@ -126,6 +126,25 @@ public abstract class TabletLocator {
     return tl;
   }
   
+  public static class TabletLocations {
+    
+    private final List<TabletLocation> locations;
+    private final List<KeyExtent> locationless;
+    
+    public TabletLocations(List<TabletLocation> locations, List<KeyExtent> 
locationless) {
+      this.locations = locations;
+      this.locationless = locationless;
+    }
+    
+    public List<TabletLocation> getLocations() {
+      return locations;
+    }
+    
+    public List<KeyExtent> getLocationless() {
+      return locationless;
+    }
+  }
+
   public static class TabletLocation implements Comparable<TabletLocation> {
     private static WeakHashMap<String,WeakReference<String>> tabletLocs = new 
WeakHashMap<String,WeakReference<String>>();
     

Modified: 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocatorImpl.java
URL: 
http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocatorImpl.java?rev=1397391&r1=1397390&r2=1397391&view=diff
==============================================================================
--- 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocatorImpl.java
 (original)
+++ 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocatorImpl.java
 Fri Oct 12 00:22:14 2012
@@ -91,7 +91,10 @@ public class TabletLocatorImpl extends T
   private Lock wLock = rwLock.writeLock();
   
   public static interface TabletLocationObtainer {
-    List<TabletLocation> lookupTablet(TabletLocation src, Text row, Text 
stopRow, TabletLocator parent) throws AccumuloSecurityException, 
AccumuloException;
+    /**
+     * @return null when unable to read information successfully
+     */
+    TabletLocations lookupTablet(TabletLocation src, Text row, Text stopRow, 
TabletLocator parent) throws AccumuloSecurityException, AccumuloException;
     
     List<TabletLocation> lookupTablets(String tserver, 
Map<KeyExtent,List<Range>> map, TabletLocator parent) throws 
AccumuloSecurityException,
         AccumuloException;
@@ -389,23 +392,31 @@ public class TabletLocatorImpl extends T
     TabletLocation ptl = parent.locateTablet(metadataRow, false, retry);
     
     if (ptl != null) {
-      List<TabletLocation> locations = locationObtainer.lookupTablet(ptl, 
metadataRow, lastTabletRow, parent);
-      if (locations.size() == 0 && !ptl.tablet_extent.isRootTablet()) {
-        // try the next tablet
+      TabletLocations locations = locationObtainer.lookupTablet(ptl, 
metadataRow, lastTabletRow, parent);
+      while (locations != null && locations.getLocations().isEmpty() && 
locations.getLocationless().isEmpty()
+ && !ptl.tablet_extent.isRootTablet()) {
+        // try the next tablet, the current tablet does not have any tablets 
that overlap the row
         Text er = ptl.tablet_extent.getEndRow();
         if (er != null && er.compareTo(lastTabletRow) < 0) {
           // System.out.println("er "+er+"  ltr "+lastTabletRow);
           ptl = parent.locateTablet(er, true, retry);
           if (ptl != null)
             locations = locationObtainer.lookupTablet(ptl, metadataRow, 
lastTabletRow, parent);
+          else
+            break;
+        } else {
+          break;
         }
       }
       
+      if (locations == null)
+        return;
+
       // cannot assume the list contains contiguous key extents... so it is 
probably
       // best to deal with each extent individually
       
       Text lastEndRow = null;
-      for (TabletLocation tabletLocation : locations) {
+      for (TabletLocation tabletLocation : locations.getLocations()) {
         
         KeyExtent ke = tabletLocation.tablet_extent;
         TabletLocation locToCache;

Modified: 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/util/MetadataTable.java
URL: 
http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/util/MetadataTable.java?rev=1397391&r1=1397390&r2=1397391&view=diff
==============================================================================
--- 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/util/MetadataTable.java
 (original)
+++ 
accumulo/trunk/core/src/main/java/org/apache/accumulo/core/util/MetadataTable.java
 Fri Oct 12 00:22:14 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.accumulo.core.util;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -118,7 +119,7 @@ public class MetadataTable {
     }
   }
   
-  public static SortedMap<KeyExtent,Text> 
getMetadataLocationEntries(SortedMap<Key,Value> entries) {
+  public static Pair<SortedMap<KeyExtent,Text>,List<KeyExtent>> 
getMetadataLocationEntries(SortedMap<Key,Value> entries) {
     Key key;
     Value val;
     Text location = null;
@@ -126,6 +127,7 @@ public class MetadataTable {
     KeyExtent ke;
     
     SortedMap<KeyExtent,Text> results = new TreeMap<KeyExtent,Text>();
+    ArrayList<KeyExtent> locationless = new ArrayList<KeyExtent>();
     
     Text lastRowFromKey = new Text();
     
@@ -152,15 +154,19 @@ public class MetadataTable {
       else if (Constants.METADATA_PREV_ROW_COLUMN.equals(colf, colq))
         prevRow = new Value(val);
       
-      if (location != null && prevRow != null) {
+      if (prevRow != null) {
         ke = new KeyExtent(key.getRow(), prevRow);
-        results.put(ke, location);
-        
+        if (location != null)
+          results.put(ke, location);
+        else
+          locationless.add(ke);
+
         location = null;
         prevRow = null;
       }
     }
-    return results;
+    
+    return new Pair<SortedMap<KeyExtent,Text>,List<KeyExtent>>(results, 
locationless);
   }
   
   public static SortedMap<Text,SortedMap<ColumnFQ,Value>> 
getTabletEntries(Instance instance, KeyExtent ke, List<ColumnFQ> columns, 
AuthInfo credentials) {

Modified: 
accumulo/trunk/core/src/test/java/org/apache/accumulo/core/client/impl/TabletLocatorImplTest.java
URL: 
http://svn.apache.org/viewvc/accumulo/trunk/core/src/test/java/org/apache/accumulo/core/client/impl/TabletLocatorImplTest.java?rev=1397391&r1=1397390&r2=1397391&view=diff
==============================================================================
--- 
accumulo/trunk/core/src/test/java/org/apache/accumulo/core/client/impl/TabletLocatorImplTest.java
 (original)
+++ 
accumulo/trunk/core/src/test/java/org/apache/accumulo/core/client/impl/TabletLocatorImplTest.java
 Fri Oct 12 00:22:14 2012
@@ -37,6 +37,7 @@ import org.apache.accumulo.core.client.A
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocation;
+import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocations;
 import 
org.apache.accumulo.core.client.impl.TabletLocator.TabletServerMutations;
 import 
org.apache.accumulo.core.client.impl.TabletLocatorImpl.TabletLocationObtainer;
 import org.apache.accumulo.core.conf.AccumuloConfiguration;
@@ -48,6 +49,7 @@ import org.apache.accumulo.core.data.Ran
 import org.apache.accumulo.core.data.Value;
 import org.apache.accumulo.core.security.thrift.AuthInfo;
 import org.apache.accumulo.core.util.MetadataTable;
+import org.apache.accumulo.core.util.Pair;
 import org.apache.hadoop.io.Text;
 
 public class TabletLocatorImplTest extends TestCase {
@@ -461,7 +463,7 @@ public class TabletLocatorImplTest exten
     }
     
     @Override
-    public List<TabletLocation> lookupTablet(TabletLocation src, Text row, 
Text stopRow, TabletLocator parent) throws AccumuloSecurityException {
+    public TabletLocations lookupTablet(TabletLocation src, Text row, Text 
stopRow, TabletLocator parent) throws AccumuloSecurityException {
       
       // System.out.println("lookupTablet("+src+","+row+","+stopRow+","+ 
parent+")");
       // System.out.println(tservers);
@@ -472,14 +474,14 @@ public class TabletLocatorImplTest exten
       
       if (tablets == null) {
         parent.invalidateCache(src.tablet_location);
-        return list;
+        return null;
       }
       
       SortedMap<Key,Value> tabletData = tablets.get(src.tablet_extent);
       
       if (tabletData == null) {
         parent.invalidateCache(src.tablet_extent);
-        return list;
+        return null;
       }
       
       // the following clip is done on a tablet, do it here to see if it 
throws exceptions
@@ -490,13 +492,13 @@ public class TabletLocatorImplTest exten
       
       SortedMap<Key,Value> results = 
tabletData.tailMap(startKey).headMap(stopKey);
       
-      SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results);
+      Pair<SortedMap<KeyExtent,Text>,List<KeyExtent>> metadata = 
MetadataTable.getMetadataLocationEntries(results);
       
-      for (Entry<KeyExtent,Text> entry : metadata.entrySet()) {
+      for (Entry<KeyExtent,Text> entry : metadata.getFirst().entrySet()) {
         list.add(new TabletLocation(entry.getKey(), 
entry.getValue().toString()));
       }
       
-      return list;
+      return new TabletLocations(list, metadata.getSecond());
     }
     
     @Override
@@ -545,7 +547,7 @@ public class TabletLocatorImplTest exten
       if (failures.size() > 0)
         parent.invalidateCache(failures);
       
-      SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results);
+      SortedMap<KeyExtent,Text> metadata = 
MetadataTable.getMetadataLocationEntries(results).getFirst();
       
       for (Entry<KeyExtent,Text> entry : metadata.entrySet()) {
         list.add(new TabletLocation(entry.getKey(), 
entry.getValue().toString()));
@@ -557,6 +559,22 @@ public class TabletLocatorImplTest exten
     
   }
   
+  static void createEmptyTablet(TServers tservers, String server, KeyExtent 
tablet) {
+    Map<KeyExtent,SortedMap<Key,Value>> tablets = 
tservers.tservers.get(server);
+    if (tablets == null) {
+      tablets = new HashMap<KeyExtent,SortedMap<Key,Value>>();
+      tservers.tservers.put(server, tablets);
+    }
+    
+    SortedMap<Key,Value> tabletData = tablets.get(tablet);
+    if (tabletData == null) {
+      tabletData = new TreeMap<Key,Value>();
+      tablets.put(tablet, tabletData);
+    } else if (tabletData.size() > 0) {
+      throw new RuntimeException("Asked for empty tablet, but non empty tablet 
exists");
+    }
+  }
+
   static void setLocation(TServers tservers, String server, KeyExtent tablet, 
KeyExtent ke, String location) {
     Map<KeyExtent,SortedMap<Key,Value>> tablets = 
tservers.tservers.get(server);
     if (tablets == null) {
@@ -1185,4 +1203,40 @@ public class TabletLocatorImplTest exten
     assertNull(tab0TabletCache.locateTablet(new Text("row_0000000000"), false, 
false));
     
   }
+  
+  // this test reproduces a problem where empty metadata tablets, that were 
created by user tablets being merged away, caused locating tablets to fail
+  public void testBug3() throws Exception {
+    
+    KeyExtent mte1 = new KeyExtent(new Text(Constants.METADATA_TABLE_ID), new 
Text("1;c"), RTE.getEndRow());
+    KeyExtent mte2 = new KeyExtent(new Text(Constants.METADATA_TABLE_ID), new 
Text("1;f"), new Text("1;c"));
+    KeyExtent mte3 = new KeyExtent(new Text(Constants.METADATA_TABLE_ID), new 
Text("1;j"), new Text("1;f"));
+    KeyExtent mte4 = new KeyExtent(new Text(Constants.METADATA_TABLE_ID), new 
Text("1;r"), new Text("1;j"));
+    KeyExtent mte5 = new KeyExtent(new Text(Constants.METADATA_TABLE_ID), 
null, new Text("1;r"));
+    
+    KeyExtent ke1 = new KeyExtent(new Text("1"), null, null);
+    
+    TServers tservers = new TServers();
+    TestTabletLocationObtainer ttlo = new TestTabletLocationObtainer(tservers);
+    TestInstance testInstance = new TestInstance("instance1", "tserver1");
+    
+    RootTabletLocator rtl = new RootTabletLocator(testInstance);
+    
+    TabletLocatorImpl rootTabletCache = new TabletLocatorImpl(new 
Text(Constants.METADATA_TABLE_ID), rtl, ttlo);
+    TabletLocatorImpl tab0TabletCache = new TabletLocatorImpl(new Text("1"), 
rootTabletCache, ttlo);
+    
+    setLocation(tservers, "tserver1", RTE, mte1, "tserver2");
+    setLocation(tservers, "tserver1", RTE, mte2, "tserver3");
+    setLocation(tservers, "tserver1", RTE, mte3, "tserver4");
+    setLocation(tservers, "tserver1", RTE, mte4, "tserver5");
+    setLocation(tservers, "tserver1", RTE, mte5, "tserver6");
+    
+    createEmptyTablet(tservers, "tserver2", mte1);
+    createEmptyTablet(tservers, "tserver3", mte2);
+    createEmptyTablet(tservers, "tserver4", mte3);
+    createEmptyTablet(tservers, "tserver5", mte4);
+    setLocation(tservers, "tserver6", mte5, ke1, "tserver7");
+    
+    locateTabletTest(tab0TabletCache, "a", ke1, "tserver7");
+    
+  }
 }

Propchange: 
accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java
------------------------------------------------------------------------------
  Merged 
/accumulo/branches/1.4/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java:r1397383
  Merged 
/accumulo/branches/1.4/src/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java:r1397383

Propchange: accumulo/trunk/server/
------------------------------------------------------------------------------
  Merged /accumulo/branches/1.4/server:r1397383
  Merged /accumulo/branches/1.4/src/server:r1397383

Propchange: accumulo/trunk/src/
------------------------------------------------------------------------------
  Merged /accumulo/branches/1.4/src:r1397383
  Merged /accumulo/branches/1.4/src/src:r1397383


Reply via email to