/*
* Copyright (c) 2008, Jan Stender, Bjoern Kolbeck, Mikael Hoegqvist,
* Felix Hupfeld, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
package de.mxro.thrd.babudb05.index.writer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import de.mxro.thrd.babudb05.index.reader.DefaultBlockReader;
import de.mxro.thrd.babudb05.index.reader.InternalBufferUtil;
public class DefaultBlockWriter implements BlockWriter {
private List<Object> keys;
private List<Object> values;
private boolean varLenKeys;
private boolean varLenVals;
private boolean serialized;
public DefaultBlockWriter(boolean varLenKeys, boolean varLenVals) {
keys = new LinkedList<Object>();
values = new LinkedList<Object>();
this.varLenKeys = varLenKeys;
this.varLenVals = varLenVals;
}
/*
* (non-Javadoc)
*
* @see org.xtreemfs.babudb.index.writer.BlockWriter#add(byte[], byte[])
*/
public void add(Object key, Object value) {
if (serialized)
throw new UnsupportedOperationException("already serialized");
keys.add(key);
values.add(value);
}
/*
* (non-Javadoc)
*
* @see org.xtreemfs.babudb.index.writer.BlockWriter#serialize()
*/
public SerializedBlock serialize() {
if (serialized)
throw new UnsupportedOperationException("already serialized");
serialized = true;
SerializedPage keyPage = varLenKeys ? serializeVarLenPage(keys) : serializeFixedLenPage(keys);
SerializedPage valPage = varLenVals ? serializeVarLenPage(values) : serializeFixedLenPage(values);
int entries = keys.size();
int valsOffset = DefaultBlockReader.KEYS_OFFSET + keyPage.size;
// header: [offset of value page, #entries, entry size]
ByteBuffer tmp = ByteBuffer.wrap(new byte[4 * Integer.SIZE / 8]);
tmp.putInt(valsOffset);
tmp.putInt(entries);
tmp.putInt(varLenKeys ? -1 : entries == 0 ? 0 : (keyPage.size / entries));
tmp.putInt(varLenVals ? -1 : entries == 0 ? 0 : (valPage.size / entries));
List<Object> header = new ArrayList<Object>(1);
header.add(tmp.array());
SerializedBlock result = new SerializedBlock();
result.addBuffers(tmp.limit(), header);
result.addBuffers(keyPage.size, keyPage.entries);
result.addBuffers(valPage.size, valPage.entries);
return result;
}
/*
* (non-Javadoc)
*
* @see org.xtreemfs.babudb.index.writer.BlockWriter#getBlockKey()
*/
public Object getBlockKey() {
return keys.get(0);
}
private static SerializedPage serializeVarLenPage(List<Object> list) {
List<Object> offsetList = new LinkedList<Object>();
// append buffers containing all offsets at the end of the list
int size = 0;
for (Object buf : list) {
size += InternalBufferUtil.size(buf);
final ByteBuffer tmp = ByteBuffer.wrap(new byte[Integer.SIZE / 8]);
tmp.putInt(size);
offsetList.add(tmp.array());
}
size += list.size() * Integer.SIZE / 8;
return new SerializedPage(size, list, offsetList);
}
private static SerializedPage serializeFixedLenPage(List<Object> list) {
int size = 0;
for (Object buf : list)
size += InternalBufferUtil.size(buf);
return new SerializedPage(size, list);
}
}