2010-03-29 11 views
6

Mam funkcji zdefiniowanej przez użytkownika (UDF) napisane w języku Java, aby analizować linie w pliku dziennika i zwracać informacje z powrotem do świni, aby mógł wykonać wszystkie przetwarzania.Czy rzucając wyjątek w UDF EvalFunc, pomiń tę linię lub całkowicie ją zatrzymaj?

Wygląda to mniej więcej tak:

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); 
     } 
    } 
} 

Moje pytanie brzmi: czy to rzuca IOException, będzie całkowicie zatrzymać lub zwróci wyniki dla pozostałych linii, które nie wyjątek ?

przykład: uruchomić to w świni

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

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

Z tego wejścia:

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

będzie przetwarzać dwa wiersze i 'dzienników mają 2 krotki, albo po prostu umrzeć ogień?

Odpowiedz

8

Jeśli wyjątek zostanie zgłoszony przez UDF, zadanie nie powiedzie się i zostanie ponowione.

Ponownie uruchomi się jeszcze trzy razy (domyślnie 4 razy), a całe zadanie zostanie NIEPOWODZONE.

Jeśli chcesz się zalogować błąd i nie chce mieć pracę przestał można powrócić null:

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

I filtrować je później w Pig:

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); 

W przykładzie dane wyjściowe będą miały tylko dwie ważne linie (ale zachowaj ostrożność przy takim zachowaniu, ponieważ błąd występuje tylko w dziennikach i nie zawiedzie twojej pracy!).

Odpowiedź # 1:

Właściwie cała krotka wypadkowa będzie zerowa (więc nie ma pola wewnątrz).

Na przykład, jeśli schemat ma 3 pola:

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

i niektóre linie są błędne byłoby otrzymujemy:

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

A jeśli nie filtrować zerową linię i próby uzyskania dostępu do pole dostaniesz java.lang.NullPointerException:

events = FOREACH events_all GENERATE line.a; 
+0

W moim przypadku , Definiuję również schemat w UDF, więc zwracając wartość zerową, wszystko w wynikowej krotce byłoby zerowe, prawda? –

+0

Jak to filtrować? FILTER events BY a NIE JEST NULL, zakładając, że EvalFunc zawsze zwraca wartość null, jeśli nie może znaleźć "a"? –

+0

Musisz filtrować nazwę pola zwróconego przez UDF. W naszym przypadku jego nazwa to "linia", a jej wartości mogą być "zerowe" lub "(1,2,3)". Wykonuje się "FILTER zdarzenia po linii IS NOT null", jak pokazano w pierwszym przykładzie Pig. Jeśli zwróciłeś krotkę z 3 pustymi polami, np. '(,,)' zamiast 'null' możesz zrobić swoje 'FILTER events BY line.a IS NOT NULL', ale jest to mniej proste. – Romain