blob: 697475f1c3ed9d194a06e6ea630f42a25d97484e [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.commons.lang3.mutable.MutableInt;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.mapred.JobConf;
import org.apache.sysds.conf.ConfigurationManager;
import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.matrix.data.MatrixBlock;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.sysds.runtime.io.IOUtilFunctions;
import org.apache.sysds.runtime.io.MatrixReader;
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.Collections;
import java.util.List;
public abstract class MatrixGenerateReader extends MatrixReader {
protected static CustomProperties _props;
protected final FastStringTokenizer fastStringTokenizerDelim;
public MatrixGenerateReader(CustomProperties _props) {
MatrixGenerateReader._props = _props;
fastStringTokenizerDelim = new FastStringTokenizer(_props.getDelim());
}
protected MatrixBlock computeSize(List<Path> files, FileSystem fs, long rlen, long clen)
throws IOException, DMLRuntimeException {
// allocate target matrix block based on given size;
return new MatrixBlock(getNumRows(files, fs), (int) clen, rlen * clen);
}
private static 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 MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int blen, long estnnz)
throws IOException, DMLRuntimeException {
MatrixBlock ret = null;
if(rlen >= 0 && clen >= 0) //otherwise allocated on read
ret = createOutputMatrixBlock(rlen, clen, (int) rlen, estnnz, true, false);
//prepare file access
JobConf job = new JobConf(ConfigurationManager.getCachedJobConf());
Path path = new Path(fname);
FileSystem fs = IOUtilFunctions.getFileSystem(path, job);
//core read
ret = readMatrixFromHDFS(path, job, fs, ret, rlen, clen, blen);
return ret;
}
@Override
public MatrixBlock readMatrixFromInputStream(InputStream is, long rlen, long clen, int blen, long estnnz)
throws IOException, DMLRuntimeException {
MatrixBlock ret = null;
if(rlen >= 0 && clen >= 0) //otherwise allocated on read
ret = createOutputMatrixBlock(rlen, clen, (int) rlen, estnnz, true, false);
return ret;
}
private MatrixBlock readMatrixFromHDFS(Path path, JobConf job, FileSystem fs, MatrixBlock dest, long rlen,
long clen, int blen) throws IOException, DMLRuntimeException {
//prepare file paths in alphanumeric order
ArrayList<Path> files = new ArrayList<>();
if(fs.getFileStatus(path).isDirectory()) {
for(FileStatus stat : fs.listStatus(path, IOUtilFunctions.hiddenFileFilter))
files.add(stat.getPath());
Collections.sort(files);
}
else
files.add(path);
//determine matrix size via additional pass if required
if(dest == null) {
dest = computeSize(files, fs, rlen, clen);
rlen = dest.getNumRows();
//clen = dest.getNumColumns();
}
//actual read of individual files
long lnnz = 0;
MutableInt row = new MutableInt(0);
for(int fileNo = 0; fileNo < files.size(); fileNo++) {
lnnz += readMatrixFromInputStream(fs.open(files.get(fileNo)), path.toString(), dest, row, rlen, clen, blen);
}
//post processing
dest.setNonZeros(lnnz);
return dest;
}
protected abstract long readMatrixFromInputStream(InputStream is, String srcInfo, MatrixBlock dest,
MutableInt rowPos, long rlen, long clen, int blen) throws IOException;
public static class MatrixReaderRowRegularColRegular extends MatrixGenerateReader {
public MatrixReaderRowRegularColRegular(CustomProperties _props) {
super(_props);
}
@Override
protected long readMatrixFromInputStream(InputStream is, String srcInfo, MatrixBlock dest,
MutableInt rowPos, long rlen, long clen, int blen) throws IOException {
String value = null;
int row = rowPos.intValue();
double cellValue = 0;
int col = 0;
long lnnz = 0;
fastStringTokenizerDelim.setNaStrings(_props.getNaStrings());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//TODO: separate implementation for Sparse and Dens Matrix Blocks
// Read the data
try {
while((value = br.readLine()) != null) //foreach line
{
fastStringTokenizerDelim.reset(value);
while(col != -1) {
cellValue = fastStringTokenizerDelim.nextDouble();
col = fastStringTokenizerDelim.getIndex();
if(cellValue != 0) {
dest.appendValue(row, col, cellValue);
lnnz++;
}
}
row++;
col = 0;
}
}
finally {
IOUtilFunctions.closeSilently(br);
}
rowPos.setValue(row);
return lnnz;
}
}
public static class MatrixReaderRowRegularColIrregular extends MatrixGenerateReader {
public MatrixReaderRowRegularColIrregular(CustomProperties _props) {
super(_props);
}
@Override
protected long readMatrixFromInputStream(InputStream is, String srcInfo, MatrixBlock dest,
MutableInt rowPos, long rlen, long clen, int blen) throws IOException {
String value = null;
int row = rowPos.intValue();
double cellValue = 0;
int col = 0;
long lnnz = 0;
final FastStringTokenizer fastStringTokenizerIndexDelim = new FastStringTokenizer(_props.getIndexDelim());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//TODO: separate implementation for Sparse and Dens Matrix Blocks
// Read the data
try {
while((value = br.readLine()) != null) //foreach line
{
fastStringTokenizerDelim.reset(value);
String cellValueString = fastStringTokenizerDelim.nextToken();
cellValue = UtilFunctions.parseToDouble(cellValueString, null);
dest.appendValue(row, (int) clen-_props.getFirstColIndex()-1, cellValue);
while(col != -1) {
String nt = fastStringTokenizerDelim.nextToken();
if(fastStringTokenizerDelim.getIndex() == -1)
break;
fastStringTokenizerIndexDelim.reset(nt);
col = fastStringTokenizerIndexDelim.nextInt();
cellValue = fastStringTokenizerIndexDelim.nextDouble();
if(cellValue != 0) {
dest.appendValue(row, col-_props.getFirstColIndex(), cellValue);
lnnz++;
}
}
row++;
col = 0;
}
}
finally {
IOUtilFunctions.closeSilently(br);
}
rowPos.setValue(row);
return lnnz;
}
}
public static class MatrixReaderRowIrregular extends MatrixGenerateReader {
public MatrixReaderRowIrregular(CustomProperties _props) {
super(_props);
}
@Override
protected long readMatrixFromInputStream(InputStream is, String srcInfo, MatrixBlock dest,
MutableInt rowPos, long rlen, long clen, int blen) throws IOException {
String value = null;
int row = rowPos.intValue();
double cellValue = 0;
int col = 0;
long lnnz = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//TODO: separate implementation for Sparse and Dens Matrix Blocks
// Read the data
try {
while((value = br.readLine()) != null) //foreach line
{
fastStringTokenizerDelim.reset(value);
int ri = fastStringTokenizerDelim.nextInt();
col = fastStringTokenizerDelim.nextInt();
cellValue = fastStringTokenizerDelim.nextDouble();
if(cellValue != 0) {
dest.appendValue(ri-_props.getFirstColIndex(), col-_props.getFirstColIndex(), cellValue);
lnnz++;
}
row = Math.max(row, ri);
}
}
finally {
IOUtilFunctions.closeSilently(br);
}
rowPos.setValue(row);
return lnnz;
}
}
}