org.elasticsearch.index.snapshots.blobstore.SlicedInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :distribution:archives:integ-test-zip
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.index.snapshots.blobstore;
import org.elasticsearch.core.internal.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
/**
* A {@link SlicedInputStream} is a logical
* concatenation one or more input streams. In contrast to the JDKs
* {@link java.io.SequenceInputStream} this stream doesn't require the instantiation
* of all logical sub-streams ahead of time. Instead, {@link #openSlice(int)} is called
* if a new slice is required. Each slice is closed once it's been fully consumed or if
* close is called before.
*/
public abstract class SlicedInputStream extends InputStream {
private int slice = 0;
private InputStream currentStream;
private final int numSlices;
private boolean initialized = false;
/**
* Creates a new SlicedInputStream
* @param numSlices the number of slices to consume
*/
protected SlicedInputStream(final int numSlices) {
this.numSlices = numSlices;
}
private InputStream nextStream() throws IOException {
assert initialized == false || currentStream != null;
initialized = true;
IOUtils.close(currentStream);
if (slice < numSlices) {
currentStream = openSlice(slice++);
} else {
currentStream = null;
}
return currentStream;
}
/**
* Called for each logical slice given a zero based slice ordinal.
*/
protected abstract InputStream openSlice(int slice) throws IOException;
private InputStream currentStream() throws IOException {
if (currentStream == null) {
return initialized ? null : nextStream();
}
return currentStream;
}
@Override
public final int read() throws IOException {
InputStream stream = currentStream();
if (stream == null) {
return -1;
}
final int read = stream.read();
if (read == -1) {
nextStream();
return read();
}
return read;
}
@Override
public final int read(byte[] buffer, int offset, int length) throws IOException {
final InputStream stream = currentStream();
if (stream == null) {
return -1;
}
final int read = stream.read(buffer, offset, length);
if (read <= 0) {
nextStream();
return read(buffer, offset, length);
}
return read;
}
@Override
public final void close() throws IOException {
IOUtils.close(currentStream);
initialized = true;
currentStream = null;
}
@Override
public final int available() throws IOException {
InputStream stream = currentStream();
return stream == null ? 0 : stream.available();
}
}