2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package io.atomix.storage.journal;
18 import static java.util.Objects.requireNonNull;
20 import io.netty.buffer.AbstractReferenceCountedByteBuf;
21 import io.netty.buffer.ByteBuf;
22 import io.netty.buffer.ByteBufAllocator;
23 import io.netty.buffer.ByteBufUtil;
24 import io.netty.util.internal.PlatformDependent;
25 import java.io.Flushable;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.io.UncheckedIOException;
30 import java.nio.ByteBuffer;
31 import java.nio.ByteOrder;
32 import java.nio.MappedByteBuffer;
33 import java.nio.channels.FileChannel;
34 import java.nio.channels.FileChannel.MapMode;
35 import java.nio.channels.GatheringByteChannel;
36 import java.nio.channels.ScatteringByteChannel;
37 import org.eclipse.jdt.annotation.NonNullByDefault;
40 * A {@link ByteBuf} backed by a {@link MappedByteBuffer}.
42 final class MappedByteBuf extends AbstractReferenceCountedByteBuf implements Flushable {
43 private final ByteBufAllocator alloc;
45 private MappedByteBuffer byteBuffer;
46 private ByteBuffer internalNio;
48 private MappedByteBuf(final ByteBufAllocator alloc, final MappedByteBuffer byteBuffer) {
49 super(byteBuffer.limit());
50 this.alloc = requireNonNull(alloc);
51 this.byteBuffer = requireNonNull(byteBuffer);
55 static MappedByteBuf of(final JournalSegmentFile file) throws IOException {
56 return new MappedByteBuf(file.allocator(), file.channel().map(MapMode.READ_WRITE, 0, file.maxSize()));
60 @SuppressWarnings("checkstyle:avoidHidingCauseException")
61 public void flush() throws IOException {
65 } catch (UncheckedIOException e) {
71 protected void deallocate() {
72 final var local = byteBuffer;
75 PlatformDependent.freeDirectBuffer(local);
80 public ByteBufAllocator alloc() {
85 public boolean isContiguous() {
90 public boolean hasArray() {
95 public byte[] array() {
96 throw new UnsupportedOperationException();
100 public int arrayOffset() {
101 throw new UnsupportedOperationException();
105 public boolean hasMemoryAddress() {
110 public long memoryAddress() {
111 throw new UnsupportedOperationException();
115 public int capacity() {
116 return maxCapacity();
120 public ByteBuf capacity(final int newCapacity) {
121 throw new UnsupportedOperationException("capacity cannot be set");
126 public ByteOrder order() {
127 return ByteOrder.BIG_ENDIAN;
131 public ByteBuf unwrap() {
136 public ByteBuf copy(final int index, final int length) {
138 return alloc.heapBuffer(length).writeBytes(byteBuffer.slice(index, length));
142 public boolean isDirect() {
147 public int nioBufferCount() {
152 public ByteBuffer nioBuffer(final int index, final int length) {
153 checkIndex(index, length);
154 return byteBuffer.slice(index, length);
158 public ByteBuffer internalNioBuffer(final int index, final int length) {
159 checkIndex(index, length);
160 return internalNio().position(index).limit(index + length);
163 private ByteBuffer internalNio() {
164 var local = internalNio;
166 internalNio = local = byteBuffer.duplicate();
172 public ByteBuffer[] nioBuffers(final int index, final int length) {
173 return new ByteBuffer[] { nioBuffer(index, length) };
177 public byte getByte(final int index) {
179 return _getByte(index);
183 protected byte _getByte(final int index) {
184 return byteBuffer.get(index);
188 public short getShort(final int index) {
190 return _getShort(index);
194 protected short _getShort(final int index) {
195 return byteBuffer.getShort(index);
199 protected short _getShortLE(final int index) {
200 return ByteBufUtil.swapShort(byteBuffer.getShort(index));
204 public int getUnsignedMedium(final int index) {
206 return _getUnsignedMedium(index);
210 protected int _getUnsignedMedium(final int index) {
211 return (_getByte(index) & 0xff) << 16 | (_getByte(index + 1) & 0xff) << 8 | _getByte(index + 2) & 0xff;
215 protected int _getUnsignedMediumLE(final int index) {
216 return _getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8 | (_getByte(index + 2) & 0xff) << 16;
220 public int getInt(final int index) {
222 return _getInt(index);
226 protected int _getInt(final int index) {
227 return byteBuffer.getInt(index);
231 protected int _getIntLE(final int index) {
232 return ByteBufUtil.swapInt(byteBuffer.getInt(index));
236 public long getLong(final int index) {
238 return _getLong(index);
242 protected long _getLong(final int index) {
243 return byteBuffer.getLong(index);
247 protected long _getLongLE(final int index) {
248 return ByteBufUtil.swapLong(byteBuffer.getLong(index));
252 public ByteBuf setByte(final int index, final int value) {
254 _setByte(index, value);
259 protected void _setByte(final int index, final int value) {
260 byteBuffer.put(index, (byte) value);
264 public ByteBuf setShort(final int index, final int value) {
266 _setShort(index, value);
271 protected void _setShort(final int index, final int value) {
272 byteBuffer.putShort(index, (short) value);
276 protected void _setShortLE(final int index, final int value) {
277 byteBuffer.putShort(index, ByteBufUtil.swapShort((short) value));
281 public ByteBuf setMedium(final int index, final int value) {
283 _setMedium(index, value);
288 protected void _setMedium(final int index, final int value) {
289 setByte(index, (byte) (value >>> 16));
290 setByte(index + 1, (byte) (value >>> 8));
291 setByte(index + 2, (byte) value);
295 protected void _setMediumLE(final int index, final int value) {
296 setByte(index, (byte) value);
297 setByte(index + 1, (byte) (value >>> 8));
298 setByte(index + 2, (byte) (value >>> 16));
302 public ByteBuf setInt(final int index, final int value) {
304 _setInt(index, value);
309 protected void _setInt(final int index, final int value) {
310 byteBuffer.putInt(index, value);
314 protected void _setIntLE(final int index, final int value) {
315 byteBuffer.putInt(index, ByteBufUtil.swapInt(value));
319 public ByteBuf setLong(final int index, final long value) {
321 _setLong(index, value);
326 protected void _setLong(final int index, final long value) {
327 byteBuffer.putLong(index, value);
331 protected void _setLongLE(final int index, final long value) {
332 byteBuffer.putLong(index, ByteBufUtil.swapLong(value));
336 public ByteBuf getBytes(final int index, final ByteBuf dst, final int dstIndex, final int length) {
337 checkDstIndex(index, length, dstIndex, dst.capacity());
338 if (dst.hasArray()) {
339 byteBuffer.get(index, dst.array(), dst.arrayOffset() + dstIndex, length);
341 dst.setBytes(dstIndex, this, index, length);
347 public ByteBuf getBytes(final int index, final byte[] dst, final int dstIndex, final int length) {
348 checkDstIndex(index, length, dstIndex, dst.length);
349 byteBuffer.get(index, dst, dstIndex, length);
354 public ByteBuf getBytes(final int index, final ByteBuffer dst) {
355 final var remaining = dst.remaining();
356 checkIndex(index, remaining);
357 dst.put(byteBuffer.slice(index, remaining));
362 public ByteBuf getBytes(final int index, final OutputStream out, final int length) throws IOException {
363 throw new UnsupportedOperationException();
367 public int getBytes(final int index, final GatheringByteChannel out, final int length) throws IOException {
368 throw new UnsupportedOperationException();
372 public int getBytes(final int index, final FileChannel out, final long position, final int length)
374 throw new UnsupportedOperationException();
378 public ByteBuf setBytes(final int index, final ByteBuf src, final int srcIndex, final int length) {
379 checkSrcIndex(index, length, srcIndex, src.capacity());
380 src.getBytes(srcIndex, this, index, length);
385 public ByteBuf setBytes(final int index, final byte[] src, final int srcIndex, final int length) {
386 checkSrcIndex(index, length, srcIndex, src.length);
387 byteBuffer.put(index, src, srcIndex, length);
392 public ByteBuf setBytes(final int index, final ByteBuffer src) {
394 byteBuffer.put(index, src, src.position(), src.remaining());
399 public int setBytes(final int index, final InputStream in, final int length) throws IOException {
400 throw new UnsupportedOperationException();
404 public int setBytes(final int index, final ScatteringByteChannel in, final int length) throws IOException {
405 throw new UnsupportedOperationException();
409 public int setBytes(final int index, final FileChannel in, final long position, final int length)
411 throw new UnsupportedOperationException();