public void decompress(InputStream in, int inLength, byte[] outArray, int outOffset,
      int outLength) throws IOException {
      // Our input is a sequence of bounded byte ranges (call them segments), with
      // BoundedDelegatingInputStream providing a way to switch in a new segment when the
      // previous segment has been fully consumed.

      // Create the input streams here the first time around.
      if (compressedIn == null) {
        lowerIn = new WALDecompressionBoundedDelegatingInputStream();
        if (decompressor == null) {
          decompressor = algorithm.getDecompressor();
        }
        compressedIn = algorithm.createDecompressionStream(lowerIn, decompressor, IO_BUFFER_SIZE);
      }
      if (outLength == 0) {
        // The BufferedInputStream will return earlier and skip reading anything if outLength == 0,
        // but in fact for an empty value, the compressed output still contains some metadata so the
        // compressed size is not 0, so here we need to manually skip inLength bytes otherwise the
        // next read on this stream will start from an invalid position and cause critical problem,
        // such as data loss when splitting wal or replicating wal.
        IOUtils.skipFully(in, inLength);
      } else {
        lowerIn.reset(in, inLength);
        IOUtils.readFully(compressedIn, outArray, outOffset, outLength);
        // if the uncompressed size was larger than the configured buffer size for the codec,
        // the BlockCompressorStream will have left an extra 4 bytes hanging. This represents a size
        // for the next segment, and it should be 0. See HBASE-28390
        if (lowerIn.available() == 4) {
          int remaining = rawReadInt(lowerIn);
          assert remaining == 0;
        }
      }
    }
Encapsulates the compression algorithm and its streams that we will use for value compression
in this WAL.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/CompressionContext.java