private int _modCount;
/** temp buffer used to writing the index */
private final TempBufferHolder _indexBufferH =
- TempBufferHolder.newHolder(false, true);
+ TempBufferHolder.newHolder(TempBufferHolder.Type.SOFT, true);
/** FIXME, for now, we can't write multi-page indexes or indexes using the funky primary key compression scheme */
boolean _readOnly;
byte[] valuePrefix = null;
boolean firstEntry = true;
TempBufferHolder tmpEntryBufferH =
- TempBufferHolder.newHolder(true, true, ByteOrder.BIG_ENDIAN);
+ TempBufferHolder.newHolder(TempBufferHolder.Type.HARD, true,
+ ByteOrder.BIG_ENDIAN);
for (int i = 0; i < entryMaskLength; i++) {
byte entryMask = indexPage.get(entryMaskPos + i);
private int _modCount;
/** page buffer used to update data pages when adding rows */
private final TempPageHolder _addRowBufferH =
- TempPageHolder.newHolder(false);
+ TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
/** page buffer used to update the table def page */
private final TempPageHolder _tableDefBufferH =
- TempPageHolder.newHolder(false);
+ TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
/** buffer used to writing single rows of data */
private final TempBufferHolder _singleRowBufferH =
- TempBufferHolder.newHolder(false, true);
+ TempBufferHolder.newHolder(TempBufferHolder.Type.SOFT, true);
+ /** "buffer" used to writing multi rows of data (will create new buffer on
+ every call) */
+ private final TempBufferHolder _multiRowBufferH =
+ TempBufferHolder.newHolder(TempBufferHolder.Type.NONE, true);
/** common cursor for iterating through the table, kept here for historic
reasons */
}
public RowState createRowState() {
- return new RowState(true);
+ return new RowState(TempBufferHolder.Type.HARD);
}
protected UsageMap.PageCursor getOwnedPagesCursor() {
* Add a single row to this table and write it to disk
*/
public void addRow(Object... row) throws IOException {
- addRows(Collections.singletonList(row));
+ addRows(Collections.singletonList(row), _singleRowBufferH);
}
/**
* @param rows List of Object[] row values
*/
public void addRows(List<? extends Object[]> rows) throws IOException {
+ addRows(rows, _multiRowBufferH);
+ }
+
+ /**
+ * Add multiple rows to this table, only writing to disk after all
+ * rows have been written, and every time a data page is filled. This
+ * is much more efficient than calling <code>addRow</code> multiple times.
+ * @param rows List of Object[] row values
+ * @param writeRowBufferH TempBufferHolder used to generate buffers for
+ * writing the row data
+ */
+ private void addRows(List<? extends Object[]> rows,
+ TempBufferHolder writeRowBufferH)
+ throws IOException
+ {
ByteBuffer[] rowData = new ByteBuffer[rows.size()];
Iterator<? extends Object[]> iter = rows.iterator();
for (int i = 0; iter.hasNext(); i++) {
- // note, use the cached _singleRowBufferH for the first row. this will
- // speed up single row writes
- rowData[i] = createRow(
- iter.next(), getFormat().MAX_ROW_SIZE,
- ((i == 0) ? _singleRowBufferH.getPageBuffer(getPageChannel()) :
- getPageChannel().createPageBuffer()));
+ rowData[i] = createRow(iter.next(), getFormat().MAX_ROW_SIZE,
+ writeRowBufferH.getPageBuffer(getPageChannel()));
if (rowData[i].limit() > getFormat().MAX_ROW_SIZE) {
throw new IOException("Row size " + rowData[i].limit() +
" is too large");
private RowStatus _rowStatus = RowStatus.INIT;
/** buffer used for reading overflow pages */
private final TempPageHolder _overflowRowBufferH =
- TempPageHolder.newHolder(false);
+ TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
/** the row buffer which contains the final data (after following any
overflow pointers) */
private ByteBuffer _finalRowBuffer;
data */
private int _lastModCount;
- private RowState(boolean hardRowBuffer) {
- _headerRowBufferH = TempPageHolder.newHolder(hardRowBuffer);
+ private RowState(TempBufferHolder.Type headerType) {
+ _headerRowBufferH = TempPageHolder.newHolder(headerType);
_rowValues = new Object[Table.this.getColumnCount()];
_lastModCount = Table.this._modCount;
}
private static final Reference<ByteBuffer> EMPTY_BUFFER_REF =
new SoftReference<ByteBuffer>(null);
+ /**
+ * The caching type for the buffer holder.
+ */
+ public enum Type {
+ /** a hard reference is maintained to the created buffer */
+ HARD,
+ /** a soft reference is maintained to the created buffer (may be garbage
+ collected if memory gets tight) */
+ SOFT,
+ /** no reference is maintained to a created buffer (new buffer every
+ time) */
+ NONE;
+ }
+
/** whether or not every get automatically rewinds the buffer */
private final boolean _autoRewind;
/** ByteOrder for all allocated buffers */
/**
* Creates a new TempBufferHolder.
- * @param hard iff true, the TempBufferHolder will maintain a hard reference
- * to the current buffer, otherwise will maintain a
- * SoftReference.
+ * @param type the type of reference desired for any created buffer
* @param autoRewind whether or not every get automatically rewinds the
* buffer
*/
- public static TempBufferHolder newHolder(boolean hard, boolean autoRewind) {
- return newHolder(hard, autoRewind, PageChannel.DEFAULT_BYTE_ORDER);
+ public static TempBufferHolder newHolder(Type type, boolean autoRewind) {
+ return newHolder(type, autoRewind, PageChannel.DEFAULT_BYTE_ORDER);
}
/**
* Creates a new TempBufferHolder.
- * @param hard iff true, the TempBufferHolder will maintain a hard reference
- * to the current buffer, otherwise will maintain a
- * SoftReference.
+ * @param type the type of reference desired for any created buffer
* @param autoRewind whether or not every get automatically rewinds the
* buffer
* @param order byte order for all allocated buffers
*/
- public static TempBufferHolder newHolder(boolean hard, boolean autoRewind,
+ public static TempBufferHolder newHolder(Type type, boolean autoRewind,
ByteOrder order)
{
- if(hard) {
+ switch(type) {
+ case HARD:
return new HardTempBufferHolder(autoRewind, order);
+ case SOFT:
+ return new SoftTempBufferHolder(autoRewind, order);
+ case NONE:
+ return new NoneTempBufferHolder(autoRewind, order);
+ default:
+ throw new IllegalStateException("Unknown type " + type);
}
- return new SoftTempBufferHolder(autoRewind, order);
}
/**
protected abstract void setNewBuffer(ByteBuffer newBuffer);
/**
- * TempBufferHolder which has a hard reference to the buffer buffer.
+ * TempBufferHolder which has a hard reference to the buffer.
*/
private static final class HardTempBufferHolder extends TempBufferHolder
{
}
/**
- * TempBufferHolder which has a soft reference to the buffer buffer.
+ * TempBufferHolder which has a soft reference to the buffer.
*/
private static final class SoftTempBufferHolder extends TempBufferHolder
{
protected void setNewBuffer(ByteBuffer newBuffer) {
_buffer.clear();
_buffer = new SoftReference<ByteBuffer>(newBuffer);
-// // FIXME, enable for testing (make this automatic)
-// _buffer = new PhantomReference<ByteBuffer>(newBuffer, null);
}
@Override
}
}
+ /**
+ * TempBufferHolder which has a no reference to the buffer.
+ */
+ private static final class NoneTempBufferHolder extends TempBufferHolder
+ {
+ private NoneTempBufferHolder(boolean autoRewind, ByteOrder order) {
+ super(autoRewind, order);
+ }
+
+ @Override
+ public ByteBuffer getExistingBuffer() {
+ return null;
+ }
+
+ @Override
+ protected void setNewBuffer(ByteBuffer newBuffer) {
+ // nothing to do
+ }
+
+ @Override
+ public void clear() {
+ // nothing to do
+ }
+ }
}
buffer has been discarded since the last page read */
private int _bufferModCount;
- private TempPageHolder(boolean hard) {
- _buffer = TempBufferHolder.newHolder(hard, false);
+ private TempPageHolder(TempBufferHolder.Type type) {
+ _buffer = TempBufferHolder.newHolder(type, false);
_bufferModCount = _buffer.getModCount();
}
/**
* Creates a new TempPageHolder.
- * @param hard iff true, the TempPageHolder will maintain a hard reference
- * to the current page buffer, otherwise will maintain a
- * SoftReference.
+ * @param type the type of reference desired for any create page buffers
*/
- public static TempPageHolder newHolder(boolean hard) {
- return new TempPageHolder(hard);
+ public static TempPageHolder newHolder(TempBufferHolder.Type type) {
+ return new TempPageHolder(type);
}
/**
{
/** Buffer that contains the current reference map page */
private final TempPageHolder _mapPageHolder =
- TempPageHolder.newHolder(false);
+ TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
private ReferenceHandler()
throws IOException