blob: e16c2d35bbda08c2f10cf2ebbe816eed5e3cde54 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sysds.runtime.iogen;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;
import org.apache.sysds.common.Types;
import org.apache.sysds.conf.ConfigurationManager;
import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.frame.data.FrameBlock;
import org.apache.sysds.runtime.io.FrameReader;
import org.apache.sysds.runtime.io.IOUtilFunctions;
import org.apache.sysds.runtime.util.InputStreamInputFormat;
import org.apache.sysds.runtime.util.UtilFunctions;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public abstract class FrameGenerateReader extends FrameReader {
protected CustomProperties _props;
protected final FastStringTokenizer fastStringTokenizerDelim;
public FrameGenerateReader(CustomProperties _props) {
this._props = _props;
fastStringTokenizerDelim = new FastStringTokenizer(_props.getDelim());
}
private int getNumRows(List<Path> files, FileSystem fs) throws IOException, DMLRuntimeException {
int rows = 0;
String value;
for(int fileNo = 0; fileNo < files.size(); fileNo++) {
BufferedReader br = new BufferedReader(new InputStreamReader(fs.open(files.get(fileNo))));
try {
// Row Regular
if(_props.getRowPattern().equals(CustomProperties.GRPattern.Regular)) {
// TODO: check the file has header?
while(br.readLine() != null)
rows++;
}
// Row Irregular
else {
FastStringTokenizer st = new FastStringTokenizer(_props.getDelim());
while((value = br.readLine()) != null) {
st.reset(value);
int row = st.nextInt();
rows = Math.max(rows, row);
}
rows++;
}
}
finally {
IOUtilFunctions.closeSilently(br);
}
}
return rows;
}
@Override
public FrameBlock readFrameFromHDFS(String fname, Types.ValueType[] schema, String[] names, long rlen,
long clen) throws IOException, DMLRuntimeException {
// prepare file access
JobConf job = new JobConf(ConfigurationManager.getCachedJobConf());
Path path = new Path(fname);
FileSystem fs = IOUtilFunctions.getFileSystem(path, job);
FileInputFormat.addInputPath(job, path);
// check existence and non-empty file
checkValidInputFile(fs, path);
// compute size if necessary
if(rlen <= 0) {
ArrayList<Path> paths = new ArrayList<>();
paths.add(path);
rlen = getNumRows(paths, fs);
}
// allocate output frame block
Types.ValueType[] lschema = createOutputSchema(schema, clen);
String[] lnames = createOutputNames(names, clen);
FrameBlock ret = createOutputFrameBlock(lschema, lnames, rlen);
// core read (sequential/parallel)
readFrameFromHDFS(path, job, fs, ret, lschema, lnames, rlen, clen);
return ret;
}
@Override
public FrameBlock readFrameFromInputStream(InputStream is, Types.ValueType[] schema, String[] names,
long rlen, long clen) throws IOException, DMLRuntimeException {
// allocate output frame block
Types.ValueType[] lschema = createOutputSchema(schema, clen);
String[] lnames = createOutputNames(names, clen);
FrameBlock ret = createOutputFrameBlock(lschema, lnames, rlen);
// core read (sequential/parallel)
InputStreamInputFormat informat = new InputStreamInputFormat(is);
InputSplit split = informat.getSplits(null, 1)[0];
readFrameFromInputSplit(split, informat, null, ret, schema, names, rlen, clen, 0, true);
return ret;
}
protected void readFrameFromHDFS(Path path, JobConf job, FileSystem fs, FrameBlock dest, Types.ValueType[] schema,
String[] names, long rlen, long clen) throws IOException {
TextInputFormat informat = new TextInputFormat();
informat.configure(job);
InputSplit[] splits = informat.getSplits(job, 1);
splits = IOUtilFunctions.sortInputSplits(splits);
for(int i = 0, rpos = 0; i < splits.length; i++)
rpos = readFrameFromInputSplit(splits[i], informat, job, dest, schema, names, rlen, clen, rpos, i == 0);
}
protected abstract int readFrameFromInputSplit(InputSplit split, InputFormat<LongWritable, Text> informat,
JobConf job, FrameBlock dest, Types.ValueType[] schema, String[] names, long rlen, long clen, int rl,
boolean first) throws IOException;
public static class FrameReaderRowRegularColRegular extends FrameGenerateReader {
public FrameReaderRowRegularColRegular(CustomProperties _props) {
super(_props);
}
@Override
protected int readFrameFromInputSplit(InputSplit split, InputFormat<LongWritable, Text> informat,
JobConf job, FrameBlock dest, Types.ValueType[] schema, String[] names, long rlen, long clen, int rl,
boolean first) throws IOException {
String cellValue;
fastStringTokenizerDelim.setNaStrings(_props.getNaStrings());
// create record reader
RecordReader<LongWritable, Text> reader = informat.getRecordReader(split, job, Reporter.NULL);
LongWritable key = new LongWritable();
Text value = new Text();
int row = rl;
int col = 0;
Set<String> naValues = _props.getNaStrings();
// Read the data
try {
while(reader.next(key, value)) // foreach line
{
String cellStr = value.toString();
fastStringTokenizerDelim.reset(cellStr);
while(col != -1) {
cellValue = fastStringTokenizerDelim.nextToken();
col = fastStringTokenizerDelim.getIndex();
if(col != -1 && cellValue != null && (naValues == null || !naValues.contains(cellValue))) {
dest.set(row, col, UtilFunctions.stringToObject(schema[col], cellValue));
}
}
row++;
col = 0;
}
}
finally {
IOUtilFunctions.closeSilently(reader);
}
return row;
}
}
public static class FrameReaderRowRegularColIrregular extends FrameGenerateReader {
public FrameReaderRowRegularColIrregular(CustomProperties _props) {
super(_props);
}
@Override
protected int readFrameFromInputSplit(InputSplit split, InputFormat<LongWritable, Text> informat,
JobConf job, FrameBlock dest, Types.ValueType[] schema, String[] names, long rlen, long clen, int rl,
boolean first) throws IOException {
String cellValue;
FastStringTokenizer fastStringTokenizerIndexDelim = new FastStringTokenizer(_props.getIndexDelim());
// create record reader
RecordReader<LongWritable, Text> reader = informat.getRecordReader(split, job, Reporter.NULL);
LongWritable key = new LongWritable();
Text value = new Text();
int row = rl;
int col = 0;
// Read the data
try {
while(reader.next(key, value)) // foreach line
{
String cellStr = value.toString();
fastStringTokenizerDelim.reset(cellStr);
String cellValueString = fastStringTokenizerDelim.nextToken();
dest.set(row, (int) clen - 1 - _props.getFirstColIndex(),
UtilFunctions.stringToObject(schema[(int) clen - 1 - _props.getFirstColIndex()], cellValueString));
while(col != -1) {
String nt = fastStringTokenizerDelim.nextToken();
if(fastStringTokenizerDelim.getIndex() == -1)
break;
fastStringTokenizerIndexDelim.reset(nt);
col = fastStringTokenizerIndexDelim.nextInt();
cellValue = fastStringTokenizerIndexDelim.nextToken();
if(col != -1 && cellValue != null) {
dest.set(row, col - _props.getFirstColIndex(),
UtilFunctions.stringToObject(schema[col - _props.getFirstColIndex()], cellValue));
}
}
row++;
col = 0;
}
}
finally {
IOUtilFunctions.closeSilently(reader);
}
return row;
}
}
public static class FrameReaderRowIrregular extends FrameGenerateReader {
public FrameReaderRowIrregular(CustomProperties _props) {
super(_props);
}
@Override
protected int readFrameFromInputSplit(InputSplit split, InputFormat<LongWritable, Text> informat,
JobConf job, FrameBlock dest, Types.ValueType[] schema, String[] names, long rlen, long clen, int rl,
boolean first) throws IOException {
String cellValue;
fastStringTokenizerDelim.setNaStrings(_props.getNaStrings());
// create record reader
RecordReader<LongWritable, Text> reader = informat.getRecordReader(split, job, Reporter.NULL);
LongWritable key = new LongWritable();
Text value = new Text();
int row = rl;
int col = 0;
// Read the data
try {
while(reader.next(key, value)) // foreach line
{
String cellStr = value.toString();
fastStringTokenizerDelim.reset(cellStr);
int ri = fastStringTokenizerDelim.nextInt();
col = fastStringTokenizerDelim.nextInt();
cellValue = fastStringTokenizerDelim.nextToken();
if(col != -1 && cellValue != null) {
dest.set(ri-_props.getFirstRowIndex(), col - _props.getFirstColIndex(),
UtilFunctions.stringToObject(schema[col - _props.getFirstColIndex()], cellValue));
}
row = Math.max(row, ri);
}
}
finally {
IOUtilFunctions.closeSilently(reader);
}
return row;
}
}
}