1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import io.netty.util.IllegalReferenceCountException;
20 import io.netty.util.ResourceLeakDetector;
21 import io.netty.util.ResourceLeakTracker;
22 import io.netty.util.internal.ObjectUtil;
23
24 import java.nio.ByteOrder;
25
26 class SimpleLeakAwareByteBuf extends WrappedByteBuf {
27
28
29
30
31
32
33 private final ByteBuf trackedByteBuf;
34 final ResourceLeakTracker<ByteBuf> leak;
35
36 SimpleLeakAwareByteBuf(ByteBuf wrapped, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leak) {
37 super(wrapped);
38 this.trackedByteBuf = ObjectUtil.checkNotNull(trackedByteBuf, "trackedByteBuf");
39 this.leak = ObjectUtil.checkNotNull(leak, "leak");
40 }
41
42 SimpleLeakAwareByteBuf(ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leak) {
43 this(wrapped, wrapped, leak);
44 }
45
46 @Override
47 public ByteBuf slice() {
48 return newSharedLeakAwareByteBuf(super.slice());
49 }
50
51 @Override
52 public ByteBuf retainedSlice() {
53 return unwrappedDerived(super.retainedSlice());
54 }
55
56 @Override
57 public ByteBuf retainedSlice(int index, int length) {
58 return unwrappedDerived(super.retainedSlice(index, length));
59 }
60
61 @Override
62 public ByteBuf retainedDuplicate() {
63 return unwrappedDerived(super.retainedDuplicate());
64 }
65
66 @Override
67 public ByteBuf readRetainedSlice(int length) {
68 return unwrappedDerived(super.readRetainedSlice(length));
69 }
70
71 @Override
72 public ByteBuf slice(int index, int length) {
73 return newSharedLeakAwareByteBuf(super.slice(index, length));
74 }
75
76 @Override
77 public ByteBuf duplicate() {
78 return newSharedLeakAwareByteBuf(super.duplicate());
79 }
80
81 @Override
82 public ByteBuf readSlice(int length) {
83 return newSharedLeakAwareByteBuf(super.readSlice(length));
84 }
85
86 @Override
87 public ByteBuf asReadOnly() {
88 return newSharedLeakAwareByteBuf(super.asReadOnly());
89 }
90
91 @Override
92 public ByteBuf touch() {
93 return this;
94 }
95
96 @Override
97 public ByteBuf touch(Object hint) {
98 return this;
99 }
100
101 @Override
102 public boolean release() {
103 try {
104 if (super.release()) {
105 closeLeak();
106 return true;
107 }
108 return false;
109 } catch (IllegalReferenceCountException irce) {
110 Throwable trace = leak.getCloseStackTraceIfAny();
111 if (trace != null) {
112 irce.addSuppressed(trace);
113 }
114 throw irce;
115 }
116 }
117
118 @Override
119 public boolean release(int decrement) {
120 try {
121 if (super.release(decrement)) {
122 closeLeak();
123 return true;
124 }
125 return false;
126 } catch (IllegalReferenceCountException irce) {
127 Throwable trace = leak.getCloseStackTraceIfAny();
128 if (trace != null) {
129 irce.addSuppressed(trace);
130 }
131 throw irce;
132 }
133 }
134
135 private void closeLeak() {
136
137
138 boolean closed = leak.close(trackedByteBuf);
139 assert closed;
140 }
141
142 @Override
143 public ByteBuf order(ByteOrder endianness) {
144 if (order() == endianness) {
145 return this;
146 } else {
147 return newSharedLeakAwareByteBuf(super.order(endianness));
148 }
149 }
150
151 private ByteBuf unwrappedDerived(ByteBuf derived) {
152
153
154 ByteBuf unwrappedDerived = unwrapSwapped(derived);
155
156 if (unwrappedDerived instanceof AbstractPooledDerivedByteBuf) {
157
158 ((AbstractPooledDerivedByteBuf) unwrappedDerived).parent(this);
159
160
161 return newLeakAwareByteBuf(derived, AbstractByteBuf.leakDetector.trackForcibly(derived));
162 }
163 return newSharedLeakAwareByteBuf(derived);
164 }
165
166 @SuppressWarnings("deprecation")
167 private static ByteBuf unwrapSwapped(ByteBuf buf) {
168 if (buf instanceof SwappedByteBuf) {
169 do {
170 buf = buf.unwrap();
171 } while (buf instanceof SwappedByteBuf);
172
173 return buf;
174 }
175 return buf;
176 }
177
178 private SimpleLeakAwareByteBuf newSharedLeakAwareByteBuf(
179 ByteBuf wrapped) {
180 return newLeakAwareByteBuf(wrapped, trackedByteBuf, leak);
181 }
182
183 private SimpleLeakAwareByteBuf newLeakAwareByteBuf(
184 ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leakTracker) {
185 return newLeakAwareByteBuf(wrapped, wrapped, leakTracker);
186 }
187
188 protected SimpleLeakAwareByteBuf newLeakAwareByteBuf(
189 ByteBuf buf, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leakTracker) {
190 return new SimpleLeakAwareByteBuf(buf, trackedByteBuf, leakTracker);
191 }
192 }