blob: 3217753067372e04eebe4f60c67825d67153b885 [file] [log] [blame]
/**
* 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);
}
}