2010-03-29 12 views
6

Tengo una Función definida por el usuario (UDF) escrita en Java para analizar líneas en un archivo de registro y devolver la información a pig, para que pueda hacer todo el procesamiento.¿Lanza una excepción en una UDF de cerdo EvalFunc salte solo esa línea, o pare completamente?

se ve algo como esto:

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

Mi pregunta es: si se lanza el IOException, se detendrá por completo, o lo devolverá resultados para el resto de las líneas que no una excepción ?

Ejemplo: I ejecutar este en cerdo

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

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

Con esta entrada:

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

¿Va a procesar las dos líneas y a 'logs' tener 2 tuplas, o solo morir en ¿un incendio?

Respuesta

8

Si la UDF emite la excepción, la tarea fallará y se volverá a intentar.

Volverá a fallar tres veces más (4 intentos por defecto) y todo el trabajo será FALLADO.

Si desea registrar el error y no quieren tener la tarea interrumpida se puede devolver un nulo:

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

y filtrarlos después en cerdo:

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

En su ejemplo la salida solo tendrá las dos líneas válidas (¡pero tenga cuidado con este comportamiento ya que el error solo está presente en los registros y no va a fallar en su trabajo!).

Responder al comentario # 1:

En realidad, toda la tupla resultante sería nulo (lo que no hay campos en el interior).

Por ejemplo si el esquema tiene 3 campos:

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

y algunas líneas son incorrectos que se pueden conseguir:

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

Y si no filtrar la línea nula y se intenta acceder un campo se obtiene una java.lang.NullPointerException:

events = FOREACH events_all GENERATE line.a; 
+0

En mi caso , También defino un esquema en el UDF, entonces al devolver nulo, todo en la tupla resultante sería nulo, ¿correcto? –

+0

¿Cómo se filtra eso? Los eventos FILTER BY a IS NOT NULL, suponiendo que EvalFunc siempre devuelve null si no puede resolver 'a'? –

+0

Debe filtrar el nombre del campo devuelto por el UDF. En nuestro caso, su nombre es 'línea' y sus valores podrían ser 'nulo' o '(1,2,3)'. Así que haces un 'FILTRO eventos por línea NO ES nulo' como se muestra en el primer ejemplo de Cerdo. Si devolvía una tupla con 3 campos nulos, p. '(,,)' en lugar de 'nulo' podría hacer sus 'eventos FILTRO POR línea.a NO ES NULO', pero es menos simple. – Romain

Cuestiones relacionadas