Example usage for java.nio ByteBuffer reset

List of usage examples for java.nio ByteBuffer reset

Introduction

In this page you can find the example usage for java.nio ByteBuffer reset.

Prototype

public final Buffer reset() 

Source Link

Document

Resets the position of this buffer to the mark.

Usage

From source file:com.healthmarketscience.jackcess.impl.TableImpl.java

/**
 * Update the row for the given rowId.//from  w  w w  .  j av a 2  s . c  o m
 * @usage _advanced_method_
 */
public Object[] updateRow(RowState rowState, RowIdImpl rowId, Object... row) throws IOException {
    requireValidRowId(rowId);

    getPageChannel().startWrite();
    try {

        // ensure that the relevant row state is up-to-date
        ByteBuffer rowBuffer = positionAtRowData(rowState, rowId);
        int oldRowSize = rowBuffer.remaining();

        requireNonDeletedRow(rowState, rowId);

        // we need to make sure the row is the right length & type (fill with
        // null if too short).
        if ((row.length < _columns.size()) || (row.getClass() != Object[].class)) {
            row = dupeRow(row, _columns.size());
        }

        // hang on to the raw values of var length columns we are "keeping".  this
        // will allow us to re-use pre-written var length data, which can save
        // space for things like long value columns.
        Map<ColumnImpl, byte[]> keepRawVarValues = (!_varColumns.isEmpty() ? new HashMap<ColumnImpl, byte[]>()
                : null);

        // handle various value massaging activities
        for (ColumnImpl column : _columns) {

            Object rowValue = null;
            if (column.isAutoNumber()) {

                // fill in any auto-numbers (we don't allow autonumber values to be
                // modified)
                rowValue = getRowColumn(getFormat(), rowBuffer, column, rowState, null);

            } else {

                rowValue = column.getRowValue(row);
                if (rowValue == Column.KEEP_VALUE) {

                    // fill in any "keep value" fields (restore old value)
                    rowValue = getRowColumn(getFormat(), rowBuffer, column, rowState, keepRawVarValues);

                } else {

                    // set oldValue to something that could not possibly be a real value
                    Object oldValue = Column.KEEP_VALUE;
                    if (_indexColumns.contains(column)) {
                        // read (old) row value to help update indexes
                        oldValue = getRowColumn(getFormat(), rowBuffer, column, rowState, null);
                    } else {
                        oldValue = rowState.getRowCacheValue(column.getColumnIndex());
                    }

                    // if the old value was passed back in, we don't need to validate
                    if (oldValue != rowValue) {
                        // pass input value through column validator
                        rowValue = column.validate(rowValue);
                    }
                }
            }

            column.setRowValue(row, rowValue);
        }

        // generate new row bytes
        ByteBuffer newRowData = createRow(row, _writeRowBufferH.getPageBuffer(getPageChannel()), oldRowSize,
                keepRawVarValues);

        if (newRowData.limit() > getFormat().MAX_ROW_SIZE) {
            throw new IOException("Row size " + newRowData.limit() + " is too large");
        }

        if (!_indexDatas.isEmpty()) {

            IndexData.PendingChange idxChange = null;
            try {

                Object[] oldRowValues = rowState.getRowCacheValues();

                // check foreign keys before actually updating
                _fkEnforcer.updateRow(oldRowValues, row);

                // prepare index updates
                for (IndexData indexData : _indexDatas) {
                    idxChange = indexData.prepareUpdateRow(oldRowValues, rowId, row, idxChange);
                }

                // complete index updates
                IndexData.commitAll(idxChange);

            } catch (ConstraintViolationException ce) {
                IndexData.rollbackAll(idxChange);
                throw ce;
            }
        }

        // see if we can squeeze the new row data into the existing row
        rowBuffer.reset();
        int rowSize = newRowData.remaining();

        ByteBuffer dataPage = null;
        int pageNumber = PageChannel.INVALID_PAGE_NUMBER;

        if (oldRowSize >= rowSize) {

            // awesome, slap it in!
            rowBuffer.put(newRowData);

            // grab the page we just updated
            dataPage = rowState.getFinalPage();
            pageNumber = rowState.getFinalRowId().getPageNumber();

        } else {

            // bummer, need to find a new page for the data
            dataPage = findFreeRowSpace(rowSize, null, PageChannel.INVALID_PAGE_NUMBER);
            pageNumber = _addRowBufferH.getPageNumber();

            RowIdImpl headerRowId = rowState.getHeaderRowId();
            ByteBuffer headerPage = rowState.getHeaderPage();
            if (pageNumber == headerRowId.getPageNumber()) {
                // new row is on the same page as header row, share page
                dataPage = headerPage;
            }

            // write out the new row data (set the deleted flag on the new data row
            // so that it is ignored during normal table traversal)
            int rowNum = addDataPageRow(dataPage, rowSize, getFormat(), DELETED_ROW_MASK);
            dataPage.put(newRowData);

            // write the overflow info into the header row and clear out the
            // remaining header data
            rowBuffer = PageChannel.narrowBuffer(headerPage,
                    findRowStart(headerPage, headerRowId.getRowNumber(), getFormat()),
                    findRowEnd(headerPage, headerRowId.getRowNumber(), getFormat()));
            rowBuffer.put((byte) rowNum);
            ByteUtil.put3ByteInt(rowBuffer, pageNumber);
            ByteUtil.clearRemaining(rowBuffer);

            // set the overflow flag on the header row
            int headerRowIndex = getRowStartOffset(headerRowId.getRowNumber(), getFormat());
            headerPage.putShort(headerRowIndex,
                    (short) (headerPage.getShort(headerRowIndex) | OVERFLOW_ROW_MASK));
            if (pageNumber != headerRowId.getPageNumber()) {
                writeDataPage(headerPage, headerRowId.getPageNumber());
            }
        }

        writeDataPage(dataPage, pageNumber);

        updateTableDefinition(0);

    } finally {
        getPageChannel().finishWrite();
    }

    return row;
}