1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.PlatformDependent;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.nio.channels.ClosedChannelException;
26 import java.nio.channels.GatheringByteChannel;
27 import java.nio.channels.ScatteringByteChannel;
28
29
30
31
32
33
34 public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf {
35
36 private final ByteBufAllocator alloc;
37
38 private ByteBuffer tmpNioBuf;
39 private int capacity;
40 private boolean doNotFree;
41 ByteBuffer buffer;
42 long memoryAddress;
43
44
45
46
47
48
49
50 public UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
51 super(maxCapacity);
52 if (alloc == null) {
53 throw new NullPointerException("alloc");
54 }
55 if (initialCapacity < 0) {
56 throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
57 }
58 if (maxCapacity < 0) {
59 throw new IllegalArgumentException("maxCapacity: " + maxCapacity);
60 }
61 if (initialCapacity > maxCapacity) {
62 throw new IllegalArgumentException(String.format(
63 "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
64 }
65
66 this.alloc = alloc;
67 setByteBuffer(allocateDirect(initialCapacity), false);
68 }
69
70
71
72
73
74
75 protected UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) {
76
77
78
79
80
81
82
83
84
85 this(alloc, initialBuffer.slice(), maxCapacity, false);
86 }
87
88 UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity, boolean doFree) {
89 super(maxCapacity);
90 if (alloc == null) {
91 throw new NullPointerException("alloc");
92 }
93 if (initialBuffer == null) {
94 throw new NullPointerException("initialBuffer");
95 }
96 if (!initialBuffer.isDirect()) {
97 throw new IllegalArgumentException("initialBuffer is not a direct buffer.");
98 }
99 if (initialBuffer.isReadOnly()) {
100 throw new IllegalArgumentException("initialBuffer is a read-only buffer.");
101 }
102
103 int initialCapacity = initialBuffer.remaining();
104 if (initialCapacity > maxCapacity) {
105 throw new IllegalArgumentException(String.format(
106 "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
107 }
108
109 this.alloc = alloc;
110 doNotFree = !doFree;
111 setByteBuffer(initialBuffer.order(ByteOrder.BIG_ENDIAN), false);
112 writerIndex(initialCapacity);
113 }
114
115
116
117
118 protected ByteBuffer allocateDirect(int initialCapacity) {
119 return ByteBuffer.allocateDirect(initialCapacity);
120 }
121
122
123
124
125 protected void freeDirect(ByteBuffer buffer) {
126 PlatformDependent.freeDirectBuffer(buffer);
127 }
128
129 final void setByteBuffer(ByteBuffer buffer, boolean tryFree) {
130 if (tryFree) {
131 ByteBuffer oldBuffer = this.buffer;
132 if (oldBuffer != null) {
133 if (doNotFree) {
134 doNotFree = false;
135 } else {
136 freeDirect(oldBuffer);
137 }
138 }
139 }
140 this.buffer = buffer;
141 memoryAddress = PlatformDependent.directBufferAddress(buffer);
142 tmpNioBuf = null;
143 capacity = buffer.remaining();
144 }
145
146 @Override
147 public boolean isDirect() {
148 return true;
149 }
150
151 @Override
152 public int capacity() {
153 return capacity;
154 }
155
156 @Override
157 public ByteBuf capacity(int newCapacity) {
158 checkNewCapacity(newCapacity);
159
160 int readerIndex = readerIndex();
161 int writerIndex = writerIndex();
162
163 int oldCapacity = capacity;
164 if (newCapacity > oldCapacity) {
165 ByteBuffer oldBuffer = buffer;
166 ByteBuffer newBuffer = allocateDirect(newCapacity);
167 oldBuffer.position(0).limit(oldBuffer.capacity());
168 newBuffer.position(0).limit(oldBuffer.capacity());
169 newBuffer.put(oldBuffer);
170 newBuffer.clear();
171 setByteBuffer(newBuffer, true);
172 } else if (newCapacity < oldCapacity) {
173 ByteBuffer oldBuffer = buffer;
174 ByteBuffer newBuffer = allocateDirect(newCapacity);
175 if (readerIndex < newCapacity) {
176 if (writerIndex > newCapacity) {
177 writerIndex(writerIndex = newCapacity);
178 }
179 oldBuffer.position(readerIndex).limit(writerIndex);
180 newBuffer.position(readerIndex).limit(writerIndex);
181 newBuffer.put(oldBuffer);
182 newBuffer.clear();
183 } else {
184 setIndex(newCapacity, newCapacity);
185 }
186 setByteBuffer(newBuffer, true);
187 }
188 return this;
189 }
190
191 @Override
192 public ByteBufAllocator alloc() {
193 return alloc;
194 }
195
196 @Override
197 public ByteOrder order() {
198 return ByteOrder.BIG_ENDIAN;
199 }
200
201 @Override
202 public boolean hasArray() {
203 return false;
204 }
205
206 @Override
207 public byte[] array() {
208 throw new UnsupportedOperationException("direct buffer");
209 }
210
211 @Override
212 public int arrayOffset() {
213 throw new UnsupportedOperationException("direct buffer");
214 }
215
216 @Override
217 public boolean hasMemoryAddress() {
218 return true;
219 }
220
221 @Override
222 public long memoryAddress() {
223 ensureAccessible();
224 return memoryAddress;
225 }
226
227 @Override
228 protected byte _getByte(int index) {
229 return UnsafeByteBufUtil.getByte(addr(index));
230 }
231
232 @Override
233 protected short _getShort(int index) {
234 return UnsafeByteBufUtil.getShort(addr(index));
235 }
236
237 @Override
238 protected int _getUnsignedMedium(int index) {
239 return UnsafeByteBufUtil.getUnsignedMedium(addr(index));
240 }
241
242 @Override
243 protected int _getInt(int index) {
244 return UnsafeByteBufUtil.getInt(addr(index));
245 }
246
247 @Override
248 protected long _getLong(int index) {
249 return UnsafeByteBufUtil.getLong(addr(index));
250 }
251
252 @Override
253 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
254 UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
255 return this;
256 }
257
258 @Override
259 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
260 UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
261 return this;
262 }
263
264 @Override
265 public ByteBuf getBytes(int index, ByteBuffer dst) {
266 UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
267 return this;
268 }
269
270 @Override
271 public ByteBuf readBytes(ByteBuffer dst) {
272 int length = dst.remaining();
273 checkReadableBytes(length);
274 getBytes(readerIndex, dst);
275 readerIndex += length;
276 return this;
277 }
278
279 @Override
280 protected void _setByte(int index, int value) {
281 UnsafeByteBufUtil.setByte(addr(index), value);
282 }
283
284 @Override
285 protected void _setShort(int index, int value) {
286 UnsafeByteBufUtil.setShort(addr(index), value);
287 }
288
289 @Override
290 protected void _setMedium(int index, int value) {
291 UnsafeByteBufUtil.setMedium(addr(index), value);
292 }
293
294 @Override
295 protected void _setInt(int index, int value) {
296 UnsafeByteBufUtil.setInt(addr(index), value);
297 }
298
299 @Override
300 protected void _setLong(int index, long value) {
301 UnsafeByteBufUtil.setLong(addr(index), value);
302 }
303
304 @Override
305 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
306 UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
307 return this;
308 }
309
310 @Override
311 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
312 UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
313 return this;
314 }
315
316 @Override
317 public ByteBuf setBytes(int index, ByteBuffer src) {
318 UnsafeByteBufUtil.setBytes(this, addr(index), index, src);
319 return this;
320 }
321
322 @Override
323 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
324 UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
325 return this;
326 }
327
328 @Override
329 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
330 return getBytes(index, out, length, false);
331 }
332
333 private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
334 ensureAccessible();
335 if (length == 0) {
336 return 0;
337 }
338
339 ByteBuffer tmpBuf;
340 if (internal) {
341 tmpBuf = internalNioBuffer();
342 } else {
343 tmpBuf = buffer.duplicate();
344 }
345 tmpBuf.clear().position(index).limit(index + length);
346 return out.write(tmpBuf);
347 }
348
349 @Override
350 public int readBytes(GatheringByteChannel out, int length) throws IOException {
351 checkReadableBytes(length);
352 int readBytes = getBytes(readerIndex, out, length, true);
353 readerIndex += readBytes;
354 return readBytes;
355 }
356
357 @Override
358 public int setBytes(int index, InputStream in, int length) throws IOException {
359 return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
360 }
361
362 @Override
363 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
364 ensureAccessible();
365 ByteBuffer tmpBuf = internalNioBuffer();
366 tmpBuf.clear().position(index).limit(index + length);
367 try {
368 return in.read(tmpBuf);
369 } catch (ClosedChannelException ignored) {
370 return -1;
371 }
372 }
373
374 @Override
375 public int nioBufferCount() {
376 return 1;
377 }
378
379 @Override
380 public ByteBuffer[] nioBuffers(int index, int length) {
381 return new ByteBuffer[] { nioBuffer(index, length) };
382 }
383
384 @Override
385 public ByteBuf copy(int index, int length) {
386 return UnsafeByteBufUtil.copy(this, addr(index), index, length);
387 }
388
389 @Override
390 public ByteBuffer internalNioBuffer(int index, int length) {
391 checkIndex(index, length);
392 return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
393 }
394
395 private ByteBuffer internalNioBuffer() {
396 ByteBuffer tmpNioBuf = this.tmpNioBuf;
397 if (tmpNioBuf == null) {
398 this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
399 }
400 return tmpNioBuf;
401 }
402
403 @Override
404 public ByteBuffer nioBuffer(int index, int length) {
405 checkIndex(index, length);
406 return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice();
407 }
408
409 @Override
410 protected void deallocate() {
411 ByteBuffer buffer = this.buffer;
412 if (buffer == null) {
413 return;
414 }
415
416 this.buffer = null;
417
418 if (!doNotFree) {
419 freeDirect(buffer);
420 }
421 }
422
423 @Override
424 public ByteBuf unwrap() {
425 return null;
426 }
427
428 long addr(int index) {
429 return memoryAddress + index;
430 }
431
432 @Override
433 protected SwappedByteBuf newSwappedByteBuf() {
434 if (PlatformDependent.isUnaligned()) {
435
436 return new UnsafeDirectSwappedByteBuf(this);
437 }
438 return super.newSwappedByteBuf();
439 }
440
441 @Override
442 public ByteBuf setZero(int index, int length) {
443 checkIndex(index, length);
444 UnsafeByteBufUtil.setZero(addr(index), length);
445 return this;
446 }
447
448 @Override
449 public ByteBuf writeZero(int length) {
450 ensureWritable(length);
451 int wIndex = writerIndex;
452 UnsafeByteBufUtil.setZero(addr(wIndex), length);
453 writerIndex = wIndex + length;
454 return this;
455 }
456 }