/** * 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.tajo.storage.trevni; import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.tajo.catalog.Column; import org.apache.tajo.catalog.Schema; import org.apache.tajo.catalog.TableMeta; import org.apache.tajo.catalog.statistics.TableStats; import org.apache.tajo.common.TajoDataTypes.Type; import org.apache.tajo.storage.FileAppender; import org.apache.tajo.storage.TableStatistics; import org.apache.tajo.storage.Tuple; import org.apache.trevni.ColumnFileMetaData; import org.apache.trevni.ColumnFileWriter; import org.apache.trevni.ColumnMetaData; import org.apache.trevni.ValueType; import java.io.FileNotFoundException; import java.io.IOException; public class TrevniAppender extends FileAppender { private FileSystem fs; private ColumnFileWriter writer; private FSDataOutputStream fos; private TableStatistics stats = null; private boolean flushed = false; public TrevniAppender(Configuration conf, Schema schema, TableMeta meta, Path path) throws IOException { super(conf, schema, meta, path); } public void init() throws IOException { fs = path.getFileSystem(conf); if (!fs.exists(path.getParent())) { throw new FileNotFoundException(path.toString()); } fos = fs.create(path); ColumnMetaData [] trevniMetas = new ColumnMetaData[schema.size()]; int i = 0; for (Column column : schema.getColumns()) { trevniMetas[i++] = new ColumnMetaData(column.getSimpleName(), getType(column.getDataType().getType())); } writer = new ColumnFileWriter(createFileMeta(), trevniMetas); if (enabledStats) { this.stats = new TableStatistics(this.schema); } super.init(); } private ColumnFileMetaData createFileMeta() { return new ColumnFileMetaData() .setCodec("null") .setChecksum("null"); } private static ValueType getType(Type type) { switch (type) { case BOOLEAN: return ValueType.INT; case BIT: return ValueType.INT; case CHAR: return ValueType.STRING; case INT2: return ValueType.INT; case INT4: return ValueType.INT; case INT8: return ValueType.LONG; case FLOAT4: return ValueType.FLOAT; case FLOAT8: return ValueType.DOUBLE; case TEXT: return ValueType.STRING; case BLOB: return ValueType.BYTES; case INET4: return ValueType.BYTES; case INET6: return ValueType.BYTES; case PROTOBUF: return ValueType.BYTES; case NULL_TYPE: return ValueType.NULL; default: return null; } } @Override public long getOffset() throws IOException { return 0; } @Override public void addTuple(Tuple t) throws IOException { Column col; writer.startRow(); for (int i = 0; i < schema.size(); i++) { if (enabledStats) { stats.analyzeField(i, t.get(i)); } if (!t.isNull(i)) { col = schema.getColumn(i); switch (col.getDataType().getType()) { case NULL_TYPE: break; case BOOLEAN: case BIT: case INT2: case INT4: writer.writeValue(t.get(i).asInt4(), i); break; case INT8: writer.writeValue(t.get(i).asInt8(), i); break; case FLOAT4: writer.writeValue(t.get(i).asFloat4(), i); break; case FLOAT8: writer.writeValue(t.get(i).asFloat8(), i); break; case CHAR: case TEXT: writer.writeValue(t.get(i).asChars(), i); break; case PROTOBUF: case BLOB: case INET4: case INET6: writer.writeValue(t.get(i).asByteArray(), i); break; default: break; } } } writer.endRow(); // Statistical section if (enabledStats) { stats.incrementRow(); } } @Override public void flush() throws IOException { if (!flushed) { writer.writeTo(fos); fos.flush(); flushed = true; } } @Override public void close() throws IOException { flush(); IOUtils.closeQuietly(fos); } @Override public TableStats getStats() { if (enabledStats) { return stats.getTableStat(); } else { return null; } } }