/** * 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.trevni; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; class ColumnOutputBuffer { private ColumnFileWriter writer; private ColumnMetaData meta; private Codec codec; private Checksum checksum; private OutputBuffer buffer; private List<BlockDescriptor> blockDescriptors; private List<byte[]> blockData; private List<byte[]> firstValues; private int rowCount; private long size = 4; // room for block count public ColumnOutputBuffer(ColumnFileWriter writer, ColumnMetaData meta) throws IOException { this.writer = writer; this.meta = meta; this.codec = Codec.get(meta); this.checksum = Checksum.get(meta); this.buffer = new OutputBuffer(); this.blockDescriptors = new ArrayList<BlockDescriptor>(); this.blockData = new ArrayList<byte[]>(); if (meta.hasIndexValues()) this.firstValues = new ArrayList<byte[]>(); } public ColumnMetaData getMeta() { return meta; } public OutputBuffer getBuffer() { return buffer; } public void startRow() throws IOException { if (buffer.isFull()) flushBuffer(); } public void writeLength(int length) throws IOException { throw new TrevniRuntimeException("Not an array column: "+meta); } public void writeValue(Object value) throws IOException { buffer.writeValue(value, meta.getType()); if (meta.hasIndexValues() && rowCount == 0) firstValues.add(buffer.toByteArray()); } public void endRow() throws IOException { rowCount++; } void flushBuffer() throws IOException { if (rowCount == 0) return; ByteBuffer raw = buffer.asByteBuffer(); ByteBuffer c = codec.compress(raw); blockDescriptors.add(new BlockDescriptor(rowCount, raw.remaining(), c.remaining())); ByteBuffer data = ByteBuffer.allocate(c.remaining() + checksum.size()); data.put(c); data.put(checksum.compute(raw)); blockData.add(data.array()); int sizeIncrement = (4*3) // descriptor + (firstValues != null // firstValue ? firstValues.get(firstValues.size()-1).length : 0) + data.position(); // data writer.incrementSize(sizeIncrement); size += sizeIncrement; buffer = new OutputBuffer(); rowCount = 0; } public long size() throws IOException { flushBuffer(); return size; } public void writeTo(OutputStream out) throws IOException { OutputBuffer header = new OutputBuffer(); header.writeFixed32(blockDescriptors.size()); for (int i = 0; i < blockDescriptors.size(); i++) { blockDescriptors.get(i).writeTo(header); if (meta.hasIndexValues()) header.write(firstValues.get(i)); } header.writeTo(out); for (byte[] data : blockData) out.write(data); } }