/** * Remove all the local of a context (but keep global). * * @param context a counter context * @return a version of {@code context} where no shards are local. */ public ByteBuffer clearAllLocal(ByteBuffer context) { int count = Math.abs(context.getShort(context.position())); if (count == 0) return context; // no local or global shards present. List<Short> globalShardIndexes = new ArrayList<>(count); for (int i = 0; i < count; i++) { short elt = context.getShort(context.position() + HEADER_SIZE_LENGTH + i * HEADER_ELT_LENGTH); if (elt < 0) globalShardIndexes.add(elt); } if (count == globalShardIndexes.size()) return context; // no local shards detected. // allocate a smaller BB for the cleared context - with no local header elts. ByteBuffer cleared = ByteBuffer.allocate( context.remaining() - (count - globalShardIndexes.size()) * HEADER_ELT_LENGTH); cleared.putShort(cleared.position(), (short) globalShardIndexes.size()); for (int i = 0; i < globalShardIndexes.size(); i++) cleared.putShort( cleared.position() + HEADER_SIZE_LENGTH + i * HEADER_ELT_LENGTH, globalShardIndexes.get(i)); int origHeaderLength = headerLength(context); ByteBufferUtil.arrayCopy( context, context.position() + origHeaderLength, cleared, cleared.position() + headerLength(cleared), context.remaining() - origHeaderLength); return cleared; }
/** * Mark context to delete local references afterward. Marking is done by multiply #elt by -1 to * preserve header length and #elt count in order to clear all local refs later. * * @param context a counter context * @return context that marked to delete local refs */ public ByteBuffer markLocalToBeCleared(ByteBuffer context) { short count = context.getShort(context.position()); if (count <= 0) return context; // already marked or all are remote. boolean hasLocalShards = false; for (int i = 0; i < count; i++) { if (context.getShort(context.position() + HEADER_SIZE_LENGTH + i * HEADER_ELT_LENGTH) >= 0) { hasLocalShards = true; break; } } if (!hasLocalShards) return context; // all shards are global or remote. ByteBuffer marked = ByteBuffer.allocate(context.remaining()); marked.putShort(marked.position(), (short) (count * -1)); ByteBufferUtil.arrayCopy( context, context.position() + HEADER_SIZE_LENGTH, marked, marked.position() + HEADER_SIZE_LENGTH, context.remaining() - HEADER_SIZE_LENGTH); return marked; }
@Override public final void readFully(byte[] bytes) throws IOException { ByteBufferUtil.arrayCopy(buffer, buffer.position() + position, bytes, 0, bytes.length); position += bytes.length; }