Я начал работать с Apache Pig для одного из наших проектов. Я должен создать пользовательский формат ввода для загрузки наших файлов данных. Для этого я последовал этому примеру Hadoop: формат пользовательского ввода. Я также создал свою собственную реализацию RecordReader для чтения данных (мы получаем наши данные в двоичном формате из какого-либо другого приложения) и анализируем их в надлежащем формате JSON.
Проблема возникает, когда я использую свой пользовательский загрузчик в скрипте Pig. Как только мой метод getNext() загружается, он вызывает мой собственный метод RecordReader nextKeyValue(), который отлично работает. Он правильно считывает данные, передает их обратно моему загрузчику, который анализирует данные и возвращает кортеж. Все идет нормально.
Проблема возникает, когда метод getNext() моего загрузчика вызывается снова и снова. Он вызывается, работает нормально и возвращает правильный вывод (я отлаживал его до оператора return). Но вместо этого, вместо того, чтобы продолжить выполнение, мой загрузчик снова вызван. Я пытался увидеть количество раз, когда меня называет загрузчик, и я мог видеть, что число до 20K!
Может кто-нибудь, пожалуйста, помогите мне понять проблему в моем коде?
погрузчик
public class SimpleTextLoaderCustomFormat extends LoadFunc {
protected RecordReader in = null;
private byte fieldDel = '\t';
private ArrayList<Object> mProtoTuple = null;
private TupleFactory mTupleFactory = TupleFactory.getInstance();
@Override
public Tuple getNext() throws IOException {
Tuple t = null;
try {
boolean notDone = in.nextKeyValue();
if (!notDone) {
return null;
}
String value = (String) in.getCurrentValue();
byte[] buf = value.getBytes();
int len = value.length();
int start = 0;
for (int i = 0; i < len; i++) {
if (buf[i] == fieldDel) {
readField(buf, start, i);
start = i + 1;
}
}
// pick up the last field
readField(buf, start, len);
t = mTupleFactory.newTupleNoCopy(mProtoTuple);
mProtoTuple = null;
} catch (InterruptedException e) {
int errCode = 6018;
String errMsg = "Error while reading input";
e.printStackTrace();
throw new ExecException(errMsg, errCode,
PigException.REMOTE_ENVIRONMENT, e);
}
return t;
}
private void readField(byte[] buf, int start, int end) {
if (mProtoTuple == null) {
mProtoTuple = new ArrayList<Object>();
}
if (start == end) {
// NULL value
mProtoTuple.add(null);
} else {
mProtoTuple.add(new DataByteArray(buf, start, end));
}
}
@Override
public InputFormat getInputFormat() throws IOException {
//return new TextInputFormat();
return new CustomStringInputFormat();
}
@Override
public void setLocation(String location, Job job) throws IOException {
FileInputFormat.setInputPaths(job, location);
}
@Override
public void prepareToRead(RecordReader reader, PigSplit split)
throws IOException {
in = reader;
}
Пользовательский входной формат
public class CustomStringInputFormat extends FileInputFormat<String, String> {
@Override
public RecordReader<String, String> createRecordReader(InputSplit arg0,
TaskAttemptContext arg1) throws IOException, InterruptedException {
return new CustomStringInputRecordReader();
}
}
Пользовательский RecordReader
public class CustomStringInputRecordReader extends RecordReader<String, String> {
private String fileName = null;
private String data = null;
private Path file = null;
private Configuration jc = null;
private static int count = 0;
@Override
public void close() throws IOException {
// jc = null;
// file = null;
}
@Override
public String getCurrentKey() throws IOException, InterruptedException {
return fileName;
}
@Override
public String getCurrentValue() throws IOException, InterruptedException {
return data;
}
@Override
public float getProgress() throws IOException, InterruptedException {
return 0;
}
@Override
public void initialize(InputSplit genericSplit, TaskAttemptContext context)
throws IOException, InterruptedException {
FileSplit split = (FileSplit) genericSplit;
file = split.getPath();
jc = context.getConfiguration();
}
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
InputStream is = FileSystem.get(jc).open(file);
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, "UTF-8");
data = writer.toString();
fileName = file.getName();
writer.close();
is.close();
System.out.println("Count : " + ++count);
return true;
}
}
Попробуйте это в Loader
//....
boolean notDone = ((CustomStringInputFormat)in).nextKeyValue();
//...
Text value = new Text(((CustomStringInputFormat))in.getCurrentValue().toString())