hbase InternalScanner и фильтр в сопроцессоре
Все:
Недавно я написал сопроцессор в Hbase(0.94.17), класс расширяет BaseEndpointCoprocessor, метод rowcount для подсчета строк в одной таблице.
И у меня проблема.
если я не установил фильтр при сканировании, мой код прекрасно работает для двух таблиц. Одна таблица содержит 1 000 000 строк, а другая - 160 000 000 строк. потребовалось около 2 минут, чтобы сосчитать большой стол.
однако, если я установлю фильтр при сканировании, он будет работать только на маленьком столе. это вызовет исключение на большом столе. org.apache.hadoop.hbase.ipc.ExecRPCInvoker$1@2c88652b, 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:
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;
}
1 ответ
Хорошо, это была моя ошибка. После того, как я использую 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 имеет значение true.
но я подумал, что если запись была отфильтрована, она должна перейти к следующей строке, и этот список никогда не должен быть пустым. Я был неправ.
И мой клиент не печатал никаких удаленных сообщений об ошибках на моей консоли, он просто перехватывал это удаленное исключение и повторял попытку. после 10 повторных попыток выдается еще одно исключение, которое не имеет смысла.