Class RecordCappingInputStream

java.lang.Object
java.io.InputStream
java.io.FilterInputStream
org.elasticsearch.xpack.esql.datasources.spi.RecordCappingInputStream
All Implemented Interfaces:
Closeable, AutoCloseable

public abstract class RecordCappingInputStream extends FilterInputStream
Stream wrapper that enforces the max_record_size byte cap on every record without decoding characters or visiting bytes outside the bulk-read fast path. The byte counter starts at zero, accumulates every byte (including line terminators), and resets when an unquoted record terminator is observed: '\n', '\r', or '\r\n'. The cap matches the terminator-inclusive byte length used by record splitters so an oversized record fails at every layer with the same threshold.

Format-specific subclasses provide the exception factory; the rest of the state machine — single-byte / bulk read accounting, CRLF spanning across reads, mark/reset lockout — is shared. This keeps the CSV and NDJSON cap streams from drifting in lockstep when one gets a CRLF or boundary-handling fix.

The hot path is read(byte[], int, int): it delegates a single bulk read to the underlying stream and then sweeps the freshly populated region in one tight loop. read() is wired to the same accounting but is not on the throughput-critical path (the downstream parser buffers in bulk).

mark/reset are disabled to keep the byte counter monotonic with the bytes the downstream parser consumes; a rewind would skew the cap relative to the actual record boundaries.

Semantics under lenient error policies: a thrown IOException from a bulk read leaves the underlying stream in an undefined position (the parser may have buffered partial bytes ahead of the trip), so the wrapper cannot resume after a cap failure. Callers that need row-level recovery under lenient policy must keep this wrapper out of those paths.

  • Constructor Details

    • RecordCappingInputStream

      protected RecordCappingInputStream(InputStream in, int maxRecordBytes)
  • Method Details