View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.buffer;
18  
19  import io.netty.util.ResourceLeakDetector;
20  import io.netty.util.ResourceLeakTracker;
21  import io.netty.util.internal.ObjectUtil;
22  
23  import java.nio.ByteOrder;
24  
25  class SimpleLeakAwareByteBuf extends WrappedByteBuf {
26  
27      /**
28       * This object's is associated with the {@link ResourceLeakTracker}. When {@link ResourceLeakTracker#close(Object)}
29       * is called this object will be used as the argument. It is also assumed that this object is used when
30       * {@link ResourceLeakDetector#track(Object)} is called to create {@link #leak}.
31       */
32      private final ByteBuf trackedByteBuf;
33      final ResourceLeakTracker<ByteBuf> leak;
34  
35      SimpleLeakAwareByteBuf(ByteBuf wrapped, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leak) {
36          super(wrapped);
37          this.trackedByteBuf = ObjectUtil.checkNotNull(trackedByteBuf, "trackedByteBuf");
38          this.leak = ObjectUtil.checkNotNull(leak, "leak");
39      }
40  
41      SimpleLeakAwareByteBuf(ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leak) {
42          this(wrapped, wrapped, leak);
43      }
44  
45      @Override
46      public ByteBuf slice() {
47          return newSharedLeakAwareByteBuf(super.slice());
48      }
49  
50      @Override
51      public ByteBuf retainedSlice() {
52          return unwrappedDerived(super.retainedSlice());
53      }
54  
55      @Override
56      public ByteBuf retainedSlice(int index, int length) {
57          return unwrappedDerived(super.retainedSlice(index, length));
58      }
59  
60      @Override
61      public ByteBuf retainedDuplicate() {
62          return unwrappedDerived(super.retainedDuplicate());
63      }
64  
65      @Override
66      public ByteBuf readRetainedSlice(int length) {
67          return unwrappedDerived(super.readRetainedSlice(length));
68      }
69  
70      @Override
71      public ByteBuf slice(int index, int length) {
72          return newSharedLeakAwareByteBuf(super.slice(index, length));
73      }
74  
75      @Override
76      public ByteBuf duplicate() {
77          return newSharedLeakAwareByteBuf(super.duplicate());
78      }
79  
80      @Override
81      public ByteBuf readSlice(int length) {
82          return newSharedLeakAwareByteBuf(super.readSlice(length));
83      }
84  
85      @Override
86      public ByteBuf asReadOnly() {
87          return newSharedLeakAwareByteBuf(super.asReadOnly());
88      }
89  
90      @Override
91      public ByteBuf touch() {
92          return this;
93      }
94  
95      @Override
96      public ByteBuf touch(Object hint) {
97          return this;
98      }
99  
100     @Override
101     public boolean release() {
102         if (super.release()) {
103             closeLeak();
104             return true;
105         }
106         return false;
107     }
108 
109     @Override
110     public boolean release(int decrement) {
111         if (super.release(decrement)) {
112             closeLeak();
113             return true;
114         }
115         return false;
116     }
117 
118     private void closeLeak() {
119         // Close the ResourceLeakTracker with the tracked ByteBuf as argument. This must be the same that was used when
120         // calling DefaultResourceLeak.track(...).
121         boolean closed = leak.close(trackedByteBuf);
122         assert closed;
123     }
124 
125     @Override
126     public ByteBuf order(ByteOrder endianness) {
127         if (order() == endianness) {
128             return this;
129         } else {
130             return newSharedLeakAwareByteBuf(super.order(endianness));
131         }
132     }
133 
134     private ByteBuf unwrappedDerived(ByteBuf derived) {
135         // We only need to unwrap SwappedByteBuf implementations as these will be the only ones that may end up in
136         // the AbstractLeakAwareByteBuf implementations beside slices / duplicates and "real" buffers.
137         ByteBuf unwrappedDerived = unwrapSwapped(derived);
138 
139         if (unwrappedDerived instanceof AbstractPooledDerivedByteBuf) {
140             // Update the parent to point to this buffer so we correctly close the ResourceLeakTracker.
141             ((AbstractPooledDerivedByteBuf) unwrappedDerived).parent(this);
142 
143             // force tracking of derived buffers (see issue #13414)
144             return newLeakAwareByteBuf(derived, AbstractByteBuf.leakDetector.trackForcibly(derived));
145         }
146         return newSharedLeakAwareByteBuf(derived);
147     }
148 
149     @SuppressWarnings("deprecation")
150     private static ByteBuf unwrapSwapped(ByteBuf buf) {
151         if (buf instanceof SwappedByteBuf) {
152             do {
153                 buf = buf.unwrap();
154             } while (buf instanceof SwappedByteBuf);
155 
156             return buf;
157         }
158         return buf;
159     }
160 
161     private SimpleLeakAwareByteBuf newSharedLeakAwareByteBuf(
162             ByteBuf wrapped) {
163         return newLeakAwareByteBuf(wrapped, trackedByteBuf, leak);
164     }
165 
166     private SimpleLeakAwareByteBuf newLeakAwareByteBuf(
167             ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leakTracker) {
168         return newLeakAwareByteBuf(wrapped, wrapped, leakTracker);
169     }
170 
171     protected SimpleLeakAwareByteBuf newLeakAwareByteBuf(
172             ByteBuf buf, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leakTracker) {
173         return new SimpleLeakAwareByteBuf(buf, trackedByteBuf, leakTracker);
174     }
175 }