2010-03-29 8 views
6

У меня есть пользовательская функция (UDF), написанная на Java, для анализа строк в файле журнала и возврата информации обратно в свиньи, поэтому она может выполнять всю обработку.Выбрасывает ли исключение в UDF-свинге EvalFunc, пропустив эту линию или полностью остановившись?

Это выглядит примерно так:

public abstract class Foo extends EvalFunc<Tuple> { 
    public Foo() { 
     super(); 
    } 

    public Tuple exec(Tuple input) throws IOException { 
     try { 
      // do stuff with input 
     } catch (Exception e) { 
      throw WrappedIOException.wrap("Error with line", e); 
     } 
    } 
} 

Мой вопрос: если он бросает IOException, будет ли он остановится полностью, или он будет возвращать результаты для остальных линий, которые не бросают исключение ?

Пример: я запускаю это в свинью

REGISTER myjar.jar 
DEFINE Extractor com.namespace.Extractor(); 

logs = LOAD '$IN' USING TextLoader AS (line: chararray); 
events = FOREACH logs GENERATE FLATTEN(Extractor(line)); 

С этим входом:

1.5 7 "Valid Line" 
1.3 gghyhtt Inv"alid line"" I throw an exceptioN!! 
1.8 10 "Valid Line 2" 

Будет ли обрабатывать две строки и «журналы» имеют 2 кортежи, или это будет просто умереть огонь?

ответ

8

Если исключение выбрано UDF, задача завершится неудачно и будет повторена.

Он будет терпеть неудачу еще три раза (по 4 попытки по умолчанию), и вся работа будет FAILED.

Если вы хотите зарегистрировать ошибку и не хочет иметь задание приостановленное вы можете возвратить нуль:

public Tuple exec(Tuple input) throws IOException { 
    try { 
     // do stuff with input 
    } catch (Exception e) { 
     System.err.println("Error with ..."); 
     return null; 
    } 
} 

и фильтровать их позже Свиньи:

events_all = FOREACH logs GENERATE Extractor(line) AS line; 
events_valid = FILTER events_all by line IS NOT null; 
events = FOREACH events_valid GENERATE FLATTEN(line); 

В вашем примере выход будет иметь только две допустимые строки (но будьте осторожны с этим поведением, так как ошибка присутствует только в журналах и не подведет вашу работу!).

Ответ на комментарий # 1:

На самом деле, весь результирующий набор будет нулевым (так нет поля внутри).

Например, если ваша схема имеет 3 поля:

events_all = FOREACH logs 
       GENERATE Extractor(line) AS line:tuple(a:int,b:int,c:int); 

и некоторые строки неверны мы получим:

() 
((1,2,3)) 
((1,2,3)) 
() 
((1,2,3)) 

И если вы не фильтровать нулевую линию и попытаться получить доступ поле вы получите java.lang.NullPointerException:

events = FOREACH events_all GENERATE line.a; 
+0

В моем случае , Я также определяю схему в UDF, поэтому, возвращая null, все в результирующем кортеже будет null, правильно? –

+0

Как вы отфильтровываете это? События FILTER BY IS NOT NULL, если EvalFunc всегда возвращает null, если он не может определить «a»? –

+0

Вам нужно отфильтровать имя поля, возвращаемого UDF. В нашем случае его имя - «строка», а его значения могут быть «null» или «(1,2,3)». Итак, вы делаете «FILTER events by line IS NOT NULL», как показано в первом примере Pig. Если вы возвращали кортеж с тремя полями нуля, например. '(,,)' вместо 'null' вы могли бы выполнять свои «FILTER events BY line.a IS NOT NULL», но это менее просто. – Romain