Skip to content

Commit cb44ae6

Browse files
committed
Additional DataBuffer hints
See gh-26230
1 parent 01fb4db commit cb44ae6

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory,
223223
byte[] bytes = byteBuilder.toByteArray();
224224
DataBuffer buffer = bufferFactory.allocateBuffer(bytes.length);
225225
buffer.write(bytes);
226+
Hints.touchDataBuffer(buffer, hints, logger);
226227

227228
return buffer;
228229
}
@@ -267,6 +268,7 @@ private DataBuffer encodeStreamingValue(Object value, DataBufferFactory bufferFa
267268
DataBuffer buffer = bufferFactory.allocateBuffer(length + separator.length);
268269
buffer.write(bytes, offset, length);
269270
buffer.write(separator);
271+
Hints.touchDataBuffer(buffer, hints, logger);
270272

271273
return buffer;
272274
}

spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,18 @@ public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
211211
// We must resolve value first however, for a chance to handle potential error.
212212
if (body instanceof Mono) {
213213
return ((Mono<? extends DataBuffer>) body)
214-
.flatMap(buffer ->
215-
doCommit(() -> {
216-
try {
217-
return writeWithInternal(Mono.fromCallable(() -> buffer)
218-
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
219-
}
220-
catch (Throwable ex) {
221-
return Mono.error(ex);
222-
}
223-
}).doOnError(ex -> DataBufferUtils.release(buffer)))
214+
.flatMap(buffer -> {
215+
touchDataBuffer(buffer);
216+
return doCommit(() -> {
217+
try {
218+
return writeWithInternal(Mono.fromCallable(() -> buffer)
219+
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
220+
}
221+
catch (Throwable ex) {
222+
return Mono.error(ex);
223+
}
224+
}).doOnError(ex -> DataBufferUtils.release(buffer));
225+
})
224226
.doOnError(t -> getHeaders().clearContentHeaders());
225227
}
226228
else {
@@ -323,4 +325,13 @@ else if (this.state.compareAndSet(State.COMMIT_ACTION_FAILED, State.COMMITTING))
323325
*/
324326
protected abstract void applyCookies();
325327

328+
/**
329+
* Allow sub-classes to associate a hint with the data buffer if it is a
330+
* pooled buffer and supports leak tracking.
331+
* @param buffer the buffer to attach a hint to
332+
* @since 5.3.2
333+
*/
334+
protected void touchDataBuffer(DataBuffer buffer) {
335+
}
336+
326337
}

spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpResponse.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
import java.util.List;
2121

2222
import io.netty.buffer.ByteBuf;
23+
import io.netty.channel.ChannelId;
24+
import org.apache.commons.logging.Log;
25+
import org.apache.commons.logging.LogFactory;
2326
import org.reactivestreams.Publisher;
2427
import reactor.core.publisher.Flux;
2528
import reactor.core.publisher.Mono;
2629
import reactor.netty.http.server.HttpServerResponse;
2730

2831
import org.springframework.core.io.buffer.DataBuffer;
2932
import org.springframework.core.io.buffer.DataBufferFactory;
33+
import org.springframework.core.io.buffer.DataBufferUtils;
3034
import org.springframework.core.io.buffer.NettyDataBufferFactory;
3135
import org.springframework.http.HttpHeaders;
3236
import org.springframework.http.HttpStatus;
@@ -43,6 +47,9 @@
4347
*/
4448
class ReactorServerHttpResponse extends AbstractServerHttpResponse implements ZeroCopyHttpOutputMessage {
4549

50+
private static final Log logger = LogFactory.getLog(ReactorServerHttpResponse.class);
51+
52+
4653
private final HttpServerResponse response;
4754

4855

@@ -115,4 +122,14 @@ private Publisher<ByteBuf> toByteBufs(Publisher<? extends DataBuffer> dataBuffer
115122
Flux.from(dataBuffers).map(NettyDataBufferFactory::toByteBuf);
116123
}
117124

125+
@Override
126+
protected void touchDataBuffer(DataBuffer buffer) {
127+
if (logger.isDebugEnabled()) {
128+
this.response.withConnection(connection -> {
129+
ChannelId id = connection.channel().id();
130+
DataBufferUtils.touch(buffer, "Channel id: " + id.asShortText());
131+
});
132+
}
133+
}
134+
118135
}

0 commit comments

Comments
 (0)