Example usage for java.nio ByteBuffer get

List of usage examples for java.nio ByteBuffer get

Introduction

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

Prototype

public abstract byte get(int index);

Source Link

Document

Returns the byte at the specified index and does not change the position.

Usage

From source file:com.healthmarketscience.jackcess.Database.java

/**
 * @return the current database password, or {@code null} if none set.
 * @usage _general_method_//from  w w w. j  a v a2s .  co  m
 */
public String getDatabasePassword() throws IOException {
    ByteBuffer buffer = takeSharedBuffer();
    try {
        _pageChannel.readPage(buffer, 0);

        byte[] pwdBytes = new byte[_format.SIZE_PASSWORD];
        buffer.position(_format.OFFSET_PASSWORD);
        buffer.get(pwdBytes);

        // de-mask password using extra password mask if necessary (the extra
        // password mask is generated from the database creation date stored in
        // the header)
        byte[] pwdMask = getPasswordMask(buffer, _format);
        if (pwdMask != null) {
            for (int i = 0; i < pwdBytes.length; ++i) {
                pwdBytes[i] ^= pwdMask[i % pwdMask.length];
            }
        }

        boolean hasPassword = false;
        for (int i = 0; i < pwdBytes.length; ++i) {
            if (pwdBytes[i] != 0) {
                hasPassword = true;
                break;
            }
        }

        if (!hasPassword) {
            return null;
        }

        String pwd = Column.decodeUncompressedText(pwdBytes, getCharset());

        // remove any trailing null chars
        int idx = pwd.indexOf('\0');
        if (idx >= 0) {
            pwd = pwd.substring(0, idx);
        }

        return pwd;
    } finally {
        releaseSharedBuffer(buffer);
    }
}

From source file:com.healthmarketscience.jackcess.Column.java

/**
 * @param lvalDefinition Column value that points to an LVAL record
 * @return The LVAL data/*  w ww.  j ava2  s .c om*/
 */
private byte[] readLongValue(byte[] lvalDefinition) throws IOException {
    ByteBuffer def = ByteBuffer.wrap(lvalDefinition).order(PageChannel.DEFAULT_BYTE_ORDER);
    int lengthWithFlags = def.getInt();
    int length = lengthWithFlags & (~LONG_VALUE_TYPE_MASK);

    byte[] rtn = new byte[length];
    byte type = (byte) ((lengthWithFlags & LONG_VALUE_TYPE_MASK) >>> 24);

    if (type == LONG_VALUE_TYPE_THIS_PAGE) {

        // inline long value
        def.getInt(); //Skip over lval_dp
        def.getInt(); //Skip over unknown
        def.get(rtn);

    } else {

        // long value on other page(s)
        if (lvalDefinition.length != getFormat().SIZE_LONG_VALUE_DEF) {
            throw new IOException("Expected " + getFormat().SIZE_LONG_VALUE_DEF
                    + " bytes in long value definition, but found " + lvalDefinition.length);
        }

        int rowNum = ByteUtil.getUnsignedByte(def);
        int pageNum = ByteUtil.get3ByteInt(def, def.position());
        ByteBuffer lvalPage = getPageChannel().createPageBuffer();

        switch (type) {
        case LONG_VALUE_TYPE_OTHER_PAGE: {
            getPageChannel().readPage(lvalPage, pageNum);

            short rowStart = Table.findRowStart(lvalPage, rowNum, getFormat());
            short rowEnd = Table.findRowEnd(lvalPage, rowNum, getFormat());

            if ((rowEnd - rowStart) != length) {
                throw new IOException("Unexpected lval row length");
            }

            lvalPage.position(rowStart);
            lvalPage.get(rtn);
        }
            break;

        case LONG_VALUE_TYPE_OTHER_PAGES:

            ByteBuffer rtnBuf = ByteBuffer.wrap(rtn);
            int remainingLen = length;
            while (remainingLen > 0) {
                lvalPage.clear();
                getPageChannel().readPage(lvalPage, pageNum);

                short rowStart = Table.findRowStart(lvalPage, rowNum, getFormat());
                short rowEnd = Table.findRowEnd(lvalPage, rowNum, getFormat());

                // read next page information
                lvalPage.position(rowStart);
                rowNum = ByteUtil.getUnsignedByte(lvalPage);
                pageNum = ByteUtil.get3ByteInt(lvalPage);

                // update rowEnd and remainingLen based on chunkLength
                int chunkLength = (rowEnd - rowStart) - 4;
                if (chunkLength > remainingLen) {
                    rowEnd = (short) (rowEnd - (chunkLength - remainingLen));
                    chunkLength = remainingLen;
                }
                remainingLen -= chunkLength;

                lvalPage.limit(rowEnd);
                rtnBuf.put(lvalPage);
            }

            break;

        default:
            throw new IOException("Unrecognized long value type: " + type);
        }
    }

    return rtn;
}

From source file:com.healthmarketscience.jackcess.Table.java

/**
 * Read the table definition/*  ww  w  .java2 s  .c  om*/
 */
private void readTableDefinition(ByteBuffer tableBuffer) throws IOException {
    if (LOG.isDebugEnabled()) {
        tableBuffer.rewind();
        LOG.debug("Table def block:\n" + ByteUtil.toHexString(tableBuffer, getFormat().SIZE_TDEF_HEADER));
    }
    _rowCount = tableBuffer.getInt(getFormat().OFFSET_NUM_ROWS);
    _lastLongAutoNumber = tableBuffer.getInt(getFormat().OFFSET_NEXT_AUTO_NUMBER);
    if (getFormat().OFFSET_NEXT_COMPLEX_AUTO_NUMBER >= 0) {
        _lastComplexTypeAutoNumber = tableBuffer.getInt(getFormat().OFFSET_NEXT_COMPLEX_AUTO_NUMBER);
    }
    _tableType = tableBuffer.get(getFormat().OFFSET_TABLE_TYPE);
    _maxColumnCount = tableBuffer.getShort(getFormat().OFFSET_MAX_COLS);
    _maxVarColumnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_VAR_COLS);
    short columnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_COLS);
    _logicalIndexCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEX_SLOTS);
    _indexCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEXES);

    int rowNum = ByteUtil.getUnsignedByte(tableBuffer, getFormat().OFFSET_OWNED_PAGES);
    int pageNum = ByteUtil.get3ByteInt(tableBuffer, getFormat().OFFSET_OWNED_PAGES + 1);
    _ownedPages = UsageMap.read(getDatabase(), pageNum, rowNum, false);
    rowNum = ByteUtil.getUnsignedByte(tableBuffer, getFormat().OFFSET_FREE_SPACE_PAGES);
    pageNum = ByteUtil.get3ByteInt(tableBuffer, getFormat().OFFSET_FREE_SPACE_PAGES + 1);
    _freeSpacePages = UsageMap.read(getDatabase(), pageNum, rowNum, false);

    for (int i = 0; i < _indexCount; i++) {
        _indexDatas.add(IndexData.create(this, tableBuffer, i, getFormat()));
    }

    int colOffset = getFormat().OFFSET_INDEX_DEF_BLOCK + _indexCount * getFormat().SIZE_INDEX_DEFINITION;
    int dispIndex = 0;
    for (int i = 0; i < columnCount; i++) {
        Column column = new Column(this, tableBuffer, colOffset + (i * getFormat().SIZE_COLUMN_HEADER),
                dispIndex++);
        _columns.add(column);
        if (column.isVariableLength()) {
            // also shove it in the variable columns list, which is ordered
            // differently from the _columns list
            _varColumns.add(column);
        }
    }
    tableBuffer.position(colOffset + (columnCount * getFormat().SIZE_COLUMN_HEADER));
    for (int i = 0; i < columnCount; i++) {
        Column column = _columns.get(i);
        column.setName(readName(tableBuffer));
    }
    Collections.sort(_columns);
    _autoNumColumns = getAutoNumberColumns(_columns);

    // setup the data index for the columns
    int colIdx = 0;
    for (Column col : _columns) {
        col.setColumnIndex(colIdx++);
    }

    // sort variable length columns based on their index into the variable
    // length offset table, because we will write the columns in this order
    Collections.sort(_varColumns, VAR_LEN_COLUMN_COMPARATOR);

    // read index column information
    for (int i = 0; i < _indexCount; i++) {
        _indexDatas.get(i).read(tableBuffer, _columns);
    }

    // read logical index info (may be more logical indexes than index datas)
    for (int i = 0; i < _logicalIndexCount; i++) {
        _indexes.add(new Index(tableBuffer, _indexDatas, getFormat()));
    }

    // read logical index names
    for (int i = 0; i < _logicalIndexCount; i++) {
        _indexes.get(i).setName(readName(tableBuffer));
    }

    Collections.sort(_indexes);

    // re-sort columns if necessary
    if (getDatabase().getColumnOrder() != ColumnOrder.DATA) {
        Collections.sort(_columns, DISPLAY_ORDER_COMPARATOR);
    }

    for (Column col : _columns) {
        // some columns need to do extra work after the table is completely
        // loaded
        col.postTableLoadInit();
    }
}

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

/**
 * @param database database which owns this table
 * @param tableBuffer Buffer to read the table with
 * @param pageNumber Page number of the table definition
 * @param name Table name/*from   w  w w .  j ava 2s  .  co  m*/
 */
protected TableImpl(DatabaseImpl database, ByteBuffer tableBuffer, int pageNumber, String name, int flags)
        throws IOException {
    _database = database;
    _tableDefPageNumber = pageNumber;
    _name = name;
    _flags = flags;

    // read table definition
    tableBuffer = loadCompleteTableDefinitionBuffer(tableBuffer);
    _rowCount = tableBuffer.getInt(getFormat().OFFSET_NUM_ROWS);
    _lastLongAutoNumber = tableBuffer.getInt(getFormat().OFFSET_NEXT_AUTO_NUMBER);
    if (getFormat().OFFSET_NEXT_COMPLEX_AUTO_NUMBER >= 0) {
        _lastComplexTypeAutoNumber = tableBuffer.getInt(getFormat().OFFSET_NEXT_COMPLEX_AUTO_NUMBER);
    }
    _tableType = tableBuffer.get(getFormat().OFFSET_TABLE_TYPE);
    _maxColumnCount = tableBuffer.getShort(getFormat().OFFSET_MAX_COLS);
    _maxVarColumnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_VAR_COLS);
    short columnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_COLS);
    _logicalIndexCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEX_SLOTS);
    _indexCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEXES);

    tableBuffer.position(getFormat().OFFSET_OWNED_PAGES);
    _ownedPages = UsageMap.read(getDatabase(), tableBuffer, false);
    tableBuffer.position(getFormat().OFFSET_FREE_SPACE_PAGES);
    _freeSpacePages = UsageMap.read(getDatabase(), tableBuffer, false);

    for (int i = 0; i < _indexCount; i++) {
        _indexDatas.add(IndexData.create(this, tableBuffer, i, getFormat()));
    }

    readColumnDefinitions(tableBuffer, columnCount);

    readIndexDefinitions(tableBuffer);

    // read column usage map info
    while (tableBuffer.remaining() >= 2) {

        short umapColNum = tableBuffer.getShort();
        if (umapColNum == IndexData.COLUMN_UNUSED) {
            break;
        }

        int pos = tableBuffer.position();
        UsageMap colOwnedPages = null;
        UsageMap colFreeSpacePages = null;
        try {
            colOwnedPages = UsageMap.read(getDatabase(), tableBuffer, false);
            colFreeSpacePages = UsageMap.read(getDatabase(), tableBuffer, false);
        } catch (IllegalStateException e) {
            // ignore invalid usage map info
            colOwnedPages = null;
            colFreeSpacePages = null;
            tableBuffer.position(pos + 8);
            LOG.warn("Table " + _name + " invalid column " + umapColNum + " usage map definition: " + e);
        }

        for (ColumnImpl col : _columns) {
            if (col.getColumnNumber() == umapColNum) {
                col.setUsageMaps(colOwnedPages, colFreeSpacePages);
                break;
            }
        }
    }

    // re-sort columns if necessary
    if (getDatabase().getColumnOrder() != ColumnOrder.DATA) {
        Collections.sort(_columns, DISPLAY_ORDER_COMPARATOR);
    }

    for (ColumnImpl col : _columns) {
        // some columns need to do extra work after the table is completely
        // loaded
        col.postTableLoadInit();
    }

    _fkEnforcer = new FKEnforcer(this);

    if (!isSystem()) {
        // after fully constructed, allow column validator to be configured (but
        // only for user tables)
        for (ColumnImpl col : _columns) {
            col.setColumnValidator(null);
        }
    }
}

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

/**
 * Reads an index page, populating the correct collection based on the page
 * type (node or leaf).//  w  w w  . j  ava  2s  .  c o  m
 */
protected void readDataPage(DataPage dataPage) throws IOException {
    ByteBuffer buffer = _indexBufferH.getPageBuffer(getPageChannel());
    getPageChannel().readPage(buffer, dataPage.getPageNumber());

    boolean isLeaf = isLeafPage(buffer);
    dataPage.setLeaf(isLeaf);

    // note, "header" data is in LITTLE_ENDIAN format, entry data is in
    // BIG_ENDIAN format
    int entryPrefixLength = ByteUtil.getUnsignedShort(buffer, getFormat().OFFSET_INDEX_COMPRESSED_BYTE_COUNT);
    int entryMaskLength = getFormat().SIZE_INDEX_ENTRY_MASK;
    int entryMaskPos = getFormat().OFFSET_INDEX_ENTRY_MASK;
    int entryPos = entryMaskPos + entryMaskLength;
    int lastStart = 0;
    int totalEntrySize = 0;
    byte[] entryPrefix = null;
    List<Entry> entries = new ArrayList<Entry>();
    TempBufferHolder tmpEntryBufferH = TempBufferHolder.newHolder(TempBufferHolder.Type.HARD, true,
            ENTRY_BYTE_ORDER);

    Entry prevEntry = FIRST_ENTRY;
    for (int i = 0; i < entryMaskLength; i++) {
        byte entryMask = buffer.get(entryMaskPos + i);
        for (int j = 0; j < 8; j++) {
            if ((entryMask & (1 << j)) != 0) {
                int length = (i * 8) + j - lastStart;
                buffer.position(entryPos + lastStart);

                // determine if we can read straight from the index page (if no
                // entryPrefix).  otherwise, create temp buf with complete entry.
                ByteBuffer curEntryBuffer = buffer;
                int curEntryLen = length;
                if (entryPrefix != null) {
                    curEntryBuffer = getTempEntryBuffer(buffer, length, entryPrefix, tmpEntryBufferH);
                    curEntryLen += entryPrefix.length;
                }
                totalEntrySize += curEntryLen;

                Entry entry = newEntry(curEntryBuffer, curEntryLen, isLeaf);
                if (prevEntry.compareTo(entry) >= 0) {
                    throw new IOException("Unexpected order in index entries, " + prevEntry + " >= " + entry);
                }

                entries.add(entry);

                if ((entries.size() == 1) && (entryPrefixLength > 0)) {
                    // read any shared entry prefix
                    entryPrefix = new byte[entryPrefixLength];
                    buffer.position(entryPos + lastStart);
                    buffer.get(entryPrefix);
                }

                lastStart += length;
                prevEntry = entry;
            }
        }
    }

    dataPage.setEntryPrefix(entryPrefix != null ? entryPrefix : EMPTY_PREFIX);
    dataPage.setEntries(entries);
    dataPage.setTotalEntrySize(totalEntrySize);

    int prevPageNumber = buffer.getInt(getFormat().OFFSET_PREV_INDEX_PAGE);
    int nextPageNumber = buffer.getInt(getFormat().OFFSET_NEXT_INDEX_PAGE);
    int childTailPageNumber = buffer.getInt(getFormat().OFFSET_CHILD_TAIL_INDEX_PAGE);

    dataPage.setPrevPageNumber(prevPageNumber);
    dataPage.setNextPageNumber(nextPageNumber);
    dataPage.setChildTailPageNumber(childTailPageNumber);
}

From source file:co.paralleluniverse.galaxy.core.Cache.java

private boolean writeData(CacheLine line, ByteBuffer data) {
    if (data.remaining() > maxItemSize)
        throw new IllegalArgumentException("Data size is " + data.remaining()
                + " bytes and exceeds the limit of " + maxItemSize + " bytes.");

    if (compareBeforeWrite) {
        if (line.data != null && data.remaining() == line.data.remaining()) {
            final int p1 = line.data.position();
            final int p2 = data.position();
            boolean modified = false;
            for (int i = 0; i < data.remaining(); i++) {
                if (line.data.get(p1 + i) != data.get(p2 + i)) {
                    modified = true;/*from  w ww.  jav  a 2  s. com*/
                    break;
                }
            }
            if (!modified)
                return false;
        }
    }

    allocateLineData(line, data.remaining());
    line.data.put(data);
    line.data.flip();
    return true;
}

From source file:com.healthmarketscience.jackcess.Table.java

/**
 * Reads the column data from the given row buffer.  Leaves limit unchanged.
 * Caches the returned value in the rowState.
 *///from  w  w  w .  ja v a 2s . com
private static Object getRowColumn(JetFormat format, ByteBuffer rowBuffer, Column column, RowState rowState,
        Map<Column, byte[]> rawVarValues) throws IOException {
    byte[] columnData = null;
    try {

        NullMask nullMask = rowState.getNullMask(rowBuffer);
        boolean isNull = nullMask.isNull(column);
        if (column.getType() == DataType.BOOLEAN) {
            // Boolean values are stored in the null mask.  see note about
            // caching below
            return rowState.setRowValue(column.getColumnIndex(), Boolean.valueOf(!isNull));
        } else if (isNull) {
            // well, that's easy! (no need to update cache w/ null)
            return null;
        }

        // reset position to row start
        rowBuffer.reset();

        // locate the column data bytes
        int rowStart = rowBuffer.position();
        int colDataPos = 0;
        int colDataLen = 0;
        if (!column.isVariableLength()) {

            // read fixed length value (non-boolean at this point)
            int dataStart = rowStart + format.OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET;
            colDataPos = dataStart + column.getFixedDataOffset();
            colDataLen = column.getType().getFixedSize(column.getLength());

        } else {
            int varDataStart;
            int varDataEnd;

            if (format.SIZE_ROW_VAR_COL_OFFSET == 2) {

                // read simple var length value
                int varColumnOffsetPos = (rowBuffer.limit() - nullMask.byteSize() - 4)
                        - (column.getVarLenTableIndex() * 2);

                varDataStart = rowBuffer.getShort(varColumnOffsetPos);
                varDataEnd = rowBuffer.getShort(varColumnOffsetPos - 2);

            } else {

                // read jump-table based var length values
                short[] varColumnOffsets = readJumpTableVarColOffsets(rowState, rowBuffer, rowStart, nullMask);

                varDataStart = varColumnOffsets[column.getVarLenTableIndex()];
                varDataEnd = varColumnOffsets[column.getVarLenTableIndex() + 1];
            }

            colDataPos = rowStart + varDataStart;
            colDataLen = varDataEnd - varDataStart;
        }

        // grab the column data
        columnData = new byte[colDataLen];
        rowBuffer.position(colDataPos);
        rowBuffer.get(columnData);

        if ((rawVarValues != null) && column.isVariableLength()) {
            // caller wants raw value as well
            rawVarValues.put(column, columnData);
        }

        // parse the column data.  we cache the row values in order to be able
        // to update the index on row deletion.  note, most of the returned
        // values are immutable, except for binary data (returned as byte[]),
        // but binary data shouldn't be indexed anyway.
        return rowState.setRowValue(column.getColumnIndex(), column.read(columnData));

    } catch (Exception e) {

        // cache "raw" row value.  see note about caching above
        rowState.setRowValue(column.getColumnIndex(), Column.rawDataWrapper(columnData));

        return rowState.handleRowError(column, columnData, e);
    }
}

From source file:com.linkedin.databus.core.DbusEventBuffer.java

/**
 * Injects an event in the regular stream of events
 * @return true iff successful/*  ww w  . ja  va2 s  .c o  m*/
 * @throws InvalidEventException
 */
public boolean injectEvent(DbusEventInternalReadable event) throws InvalidEventException {
    final ByteBuffer eventBuf = event.getRawBytes();
    byte[] cpEventBytes = null;
    if (eventBuf.hasArray()) {
        cpEventBytes = eventBuf.array();
    } else {
        cpEventBytes = new byte[event.getRawBytes().limit()];
        eventBuf.get(cpEventBytes);
    }
    ByteArrayInputStream cpIs = new ByteArrayInputStream(cpEventBytes);
    ReadableByteChannel cpRbc = Channels.newChannel(cpIs);
    int ecnt = readEvents(cpRbc);

    return ecnt > 0;
}

From source file:com.linkedin.databus.core.DbusEventBuffer.java

/**
 * Used by readEventsInternal to move the partial event at the end to the beginning of the
 * staging buffer so we can try to read more data.
 *
 * @param readPos/*from w  ww  . j av  a  2  s. c  om*/
 * @param logDebugEnabled
 */
private void compactStgBuffer(ReadEventsReadPosition readPos, boolean logDebugEnabled) {
    final ByteBuffer readBuffer = readPos.getReadBuffer();

    readBuffer.clear();//despite its name, clear() does not remove the data
    if (readPos.hasNext()) {
        if (logDebugEnabled) {
            _log.debug("Copying " + readPos.bytesRemaining() + " bytes to the start of the readBuffer");
        }

        for (int i = 0; i < readPos.bytesRemaining(); ++i) {
            readBuffer.put(readBuffer.get(readPos.getPosition() + i));
        }
        readPos.startIteration();

        if (logDebugEnabled) {
            _log.debug("readBuffer after compaction: " + readBuffer + "; " + readPos);
        }
    }
}

From source file:edu.umass.cs.gigapaxos.paxospackets.RequestPacket.java

/**
 * The weird constant above is to try to avoid mistakes in the painful (but
 * totally worth it) byte'ification method below. Using bytes as opposed to
 * json strings makes a non-trivial difference (~2x over json-smart and >4x
 * over org.json. So we just chuck json libraries and use our own byte[]
 * serializer for select packets./* w w  w  . j a v  a2 s .  c  om*/
 * 
 * The serialization overhead really matters most for RequestPacket and
 * AcceptPacket. Every request, even with batching, must be deserialized by
 * the coordinator and must be serialized back while sending out the
 * AcceptPacket. The critical path is the following at a coordinator and is
 * incurred at least in part even with batching for every request: (1)
 * receive request, (2) send accept, (3) receive accept_replies, (4) send
 * commit Accordingly, we use byteification for {@link RequestPacket},
 * {@link AcceptPacket}, {@link BatchedAcceptReply} and
 * {@link BatchedCommit}.
 * 
 * */

protected byte[] toBytes(boolean instrument) {
    // return cached value if already present
    if ((this.getType() == PaxosPacketType.REQUEST || this.getType() == PaxosPacketType.ACCEPT)
            && this.byteifiedSelf != null && !instrument)
        return this.byteifiedSelf;
    // check if we can use byteification at all; if not, use toString()
    if (!((BYTEIFICATION && IntegerMap.allInt()) || instrument)) {
        try {
            if (this.getType() == PaxosPacketType.REQUEST || this.getType() == PaxosPacketType.ACCEPT)
                return this.byteifiedSelf = this.toString().getBytes(CHARSET); // cache
            return this.toString().getBytes(CHARSET);
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
            return null;
        }
    }

    // else byteify
    try {
        int exactLength = 0;
        byte[] array = new byte[this.lengthEstimate()];
        ByteBuffer bbuf = ByteBuffer.wrap(array);
        assert (bbuf.position() == 0);

        // paxospacket stuff
        super.toBytes(bbuf);
        int ppPos = bbuf.position(); // for assertion
        assert (bbuf.position() == ByteBuffer.wrap(array, SIZEOF_PAXOSPACKET_FIXED - 1, 1).get()
                + SIZEOF_PAXOSPACKET_FIXED) : bbuf.position() + " != "
                        + ByteBuffer.wrap(array, SIZEOF_PAXOSPACKET_FIXED - 1, 1).get()
                        + SIZEOF_PAXOSPACKET_FIXED;
        exactLength += (bbuf.position());

        bbuf.putLong(this.requestID);
        bbuf.put(this.stop ? (byte) 1 : (byte) 0);
        exactLength += (Long.BYTES + 1);

        // addresses
        /* Note: 0 is ambiguous with wildcard address, but that's okay
         * because an incoming packet will never come with a wildcard
         * address. */
        bbuf.put(this.clientAddress != null ? this.clientAddress.getAddress().getAddress() : new byte[4]);
        // 0 (not -1) means invalid port
        bbuf.putShort(this.clientAddress != null ? (short) this.clientAddress.getPort() : 0);
        /* Note: 0 is an ambiguous wildcard address that could also be a
         * legitimate value of the listening socket address. If the request
         * happens to have no listening address, we will end up assuming it
         * was received on the wildcard address. At worst, the matching for
         * the corresponding response back to the client can fail. */
        bbuf.put(this.listenAddress != null ? this.listenAddress.getAddress().getAddress() : new byte[4]);
        // 0 (not -1) means invalid port
        bbuf.putShort(this.listenAddress != null ? (short) this.listenAddress.getPort() : 0);
        exactLength += 2 * (Integer.BYTES + Short.BYTES);

        // other non-final fields
        bbuf.putInt(this.entryReplica);
        bbuf.putLong(this.entryTime);
        bbuf.put(this.shouldReturnRequestValue ? (byte) 1 : (byte) 0);
        bbuf.putInt(this.forwardCount);
        exactLength += (Integer.BYTES + Long.BYTES + 1 + Integer.BYTES);

        // digest related fields: broadcasted, digest
        // whether this request was already broadcasted
        bbuf.put(this.broadcasted ? (byte) 1 : (byte) 0);
        exactLength += 1;
        assert (exactLength ==
        // where parent left us off
        ppPos + SIZEOF_REQUEST_FIXED
        // for the three int fields not yet filled
                - 4 * Integer.BYTES) : exactLength + " != [" + ppPos + " + " + SIZEOF_REQUEST_FIXED + " - "
                        + 4 * Integer.BYTES + "]";
        // digest length and digest iteself
        bbuf.putInt(this.digest != null ? this.digest.length : 0);
        exactLength += Integer.BYTES;
        if (this.digest != null)
            bbuf.put(this.digest);
        exactLength += (this.digest != null ? this.digest.length : 0);
        // /////////// end of digest related fields //////////

        // highly variable length fields
        // requestValue
        byte[] reqValBytes = this.requestValue != null ? this.requestValue.getBytes(CHARSET) : new byte[0];
        bbuf.putInt(reqValBytes != null ? reqValBytes.length : 0);
        bbuf.put(reqValBytes);
        exactLength += (4 + reqValBytes.length);

        // responseValue
        byte[] respValBytes = this.responseValue != null ? this.responseValue.getBytes(CHARSET) : new byte[0];
        bbuf.putInt(respValBytes != null ? respValBytes.length : 0);
        bbuf.put(respValBytes);
        exactLength += (4 + respValBytes.length);

        // batched requests batchSize|(length:batchedReqBytes)+
        bbuf.putInt(this.batchSize());
        exactLength += (4);
        if (this.batchSize() > 0)
            for (RequestPacket req : this.batched) {
                byte[] element = req.toBytes();
                bbuf.putInt(element.length);
                bbuf.put(element);
                exactLength += (4 + element.length);
            }

        // bbuf.array() was a generous allocation
        byte[] exactBytes = new byte[exactLength];
        bbuf.flip();
        assert (bbuf.remaining() == exactLength) : bbuf.remaining() + " != " + exactLength;
        bbuf.get(exactBytes);

        if (this.getType() == PaxosPacketType.REQUEST)
            this.byteifiedSelf = exactBytes;

        return exactBytes;

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}