2014-09-19 169 views
0

所有:HBase的InternalScanner和過濾協處理器

近日,筆者在HBase的(0.94.17)寫了一個協處理器,A類擴展BaseEndpointCoprocessor,一個行數的方法來計算一個表中的行。

我遇到了問題。

如果我沒有在掃描中設置過濾器,我的代碼對兩個表格工作正常。一個表有1,000,000行,另一個有1.6億行。花費大約2分鐘來計算更大的表格。

但是,如果我在掃描中設置過濾器,它只能在小桌子上工作。它會在更大的桌子上拋出異常。 [email protected],java.io.IOException異常:java.io.IOException的:java.lang.IndexOutOfBoundsException:指數:0,大小:0

信任我,我檢查我的代碼一遍又一遍。因此,爲了使用過濾器計算我的表,我必須編寫下面的愚蠢代碼,首先,我沒有在掃描中設置過濾器,然後,在獲得一行記錄後,我編寫了一個方法來過濾它。

它可以在兩個表上工作。

但我不知道爲什麼。

我嘗試閱讀HRegion.java中的掃描程序源代碼,但是,我沒有得到它。

所以,如果你知道答案,請幫助我。謝謝。

@Override 
    public long rowCount(Configuration conf) throws IOException { 
     // TODO Auto-generated method stub 
     Scan scan = new Scan(); 
     parseConfiguration(conf); 
     Filter filter = null; 
     if (this.mFilterString != null && !mFilterString.equals("")) { 
      ParseFilter parse = new ParseFilter(); 
      filter = parse.parseFilterString(mFilterString); 
      // scan.setFilter(filter); 
     } 

     scan.setCaching(this.mScanCaching); 
     InternalScanner scanner = ((RegionCoprocessorEnvironment) getEnvironment()).getRegion().getScanner(scan); 
     long sum = 0; 

     try { 
      List<KeyValue> curVals = new ArrayList<KeyValue>(); 
      boolean hasMore = false; 
      do { 
       curVals.clear(); 
       hasMore = scanner.next(curVals); 
       if (filter != null) { 
        filter.reset(); 
        if (HbaseUtil.filterOneResult(curVals, filter)) { 
         continue; 
        } 
       } 
       sum++; 
      } while (hasMore); 

     } finally { 
      scanner.close(); 
     } 
     return sum; 
    } 

以下是我的HBase UTIL代碼:

public static boolean filterOneResult(List<KeyValue> kvList, Filter filter) { 
     if (kvList.size() == 0) 
      return true; 
     KeyValue kv = kvList.get(0); 
     if (filter.filterRowKey(kv.getBuffer(), kv.getRowOffset(), kv.getRowLength())) { 
      return true; 
     } 

     for (KeyValue kv2 : kvList) { 
      if (filter.filterKeyValue(kv2) == Filter.ReturnCode.NEXT_ROW) { 
       return true; 
      } 
     } 
     filter.filterRow(kvList); 
     if (filter.filterRow()) 
      return true; 
     else 
      return false; 
    } 
+0

而我的過濾器是SingleColumnVaueFilter。很短。 SingleColumnValueFilter( 'F', 'S',= '二進制:0',真實,真) – dape 2014-09-19 12:03:19

回答

0

好吧,這是我的錯誤。我使用JDB調試我的代碼後,我得到了以下異常,

"org.apache.hadoop.ipc.RemoteException: java.io.IOException: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
    at java.util.ArrayList.rangeCheck(ArrayList.java:635) 
    at java.util.ArrayList.get(ArrayList.java:411) 

很明顯,我的結果列表是空的。

hasMore = scanner.next(curVals); 

這意味着,如果我在掃描使用過濾器,這curVals列表可能是空的,但hasMore是真實的。

但我想,如果一條記錄被過濾了,它應該跳轉到下一行,並且這個列表不應該是空的。我錯了。

而我的客戶端沒有在我的控制檯上打印任何遠程錯誤消息,它只是捕獲這個遠程異常,然後重試。 重試10次後,它會打印另一個異常,這是沒有意義的。