/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.rcfile; import io.airlift.slice.Slice; import java.io.IOException; import java.io.OutputStream; import java.util.List; import java.util.function.Supplier; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; public interface RcFileCompressor { CompressedSliceOutput createCompressedSliceOutput(int minChunkSize, int maxChunkSize); // This specialized SliceOutput has direct access buffered output slices to // report buffer sizes and to get he final output. Additionally, a new // CompressedSliceOutput can be created that reuses the underlying output // buffer final class CompressedSliceOutput extends BufferedOutputStreamSliceOutput { private final ChunkedSliceOutput bufferedOutput; private final Supplier<CompressedSliceOutput> resetFactory; private final Runnable onDestroy; private boolean closed; private boolean destroyed; /** * @param compressionStream the compressed output stream to delegate to * @param bufferedOutput the output for the compressionStream * @param resetFactory the function to create a new CompressedSliceOutput that reuses the bufferedOutput * @param onDestroy used to cleanup the compression when done */ public CompressedSliceOutput(OutputStream compressionStream, ChunkedSliceOutput bufferedOutput, Supplier<CompressedSliceOutput> resetFactory, Runnable onDestroy) { super(compressionStream, 4096); this.bufferedOutput = requireNonNull(bufferedOutput, "bufferedOutput is null"); this.resetFactory = requireNonNull(resetFactory, "resetFactory is null"); this.onDestroy = requireNonNull(onDestroy, "onDestroy is null"); } @Override public int getRetainedSize() { return super.getRetainedSize() + bufferedOutput.getRetainedSize(); } public int getCompressedSize() { checkState(closed, "Stream has not been closed"); checkState(!destroyed, "Stream has been destroyed"); return bufferedOutput.size(); } public List<Slice> getCompressedSlices() { checkState(closed, "Stream has not been closed"); checkState(!destroyed, "Stream has been destroyed"); return bufferedOutput.getSlices(); } public CompressedSliceOutput createRecycledCompressedSliceOutput() { checkState(closed, "Stream has not been closed"); checkState(!destroyed, "Stream has been destroyed"); destroyed = true; return resetFactory.get(); } @Override public void close() throws IOException { closed = true; super.close(); } public void destroy() { if (!destroyed) { destroyed = true; onDestroy.run(); } } } }