/*
* Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved
* http://www.griddynamics.com
*
* This library is free software; you can redistribute it and/or modify it under the terms of
* the Apache License; either
* version 2.0 of the License, or any later version.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.griddynamics.jagger.storage.fs.logging;
import com.google.common.base.Throwables;
import com.griddynamics.jagger.storage.FileStorage;
import com.griddynamics.jagger.storage.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Queue;
import static com.google.common.collect.Lists.newLinkedList;
public abstract class BufferedLogReader implements LogReader {
private static final Logger log = LoggerFactory.getLogger(BufferedLogReader.class);
private FileStorage fileStorage;
@Override
public <T> FileReader<T> read(String sessionId, String logOwner, String kernelId, Class<T> clazz) {
Namespace path = Namespace.of(sessionId, logOwner, kernelId);
return read(path.toString(), clazz);
}
public <T> FileReader<T> read(String path, Class<T> clazz) {
InputStream in;
try {
if (!fileStorage.exists(path.toString())) {
throw new IllegalArgumentException("Path " + path + " doesn't exist");
}
in = new BufferedInputStream(fileStorage.open(path.toString()));
} catch (IOException e) {
throw Throwables.propagate(e);
}
return read(in, clazz);
}
public <T> FileReader<T> read(InputStream in, Class<T> clazz) {
LogReaderInput input = getInput(in);
final IteratorImpl<T> iterator = new IteratorImpl<T>(input, clazz);
return new FileReaderImpl<T>(iterator, in);
}
public void setFileStorage(FileStorage fileStorage) {
this.fileStorage = fileStorage;
}
protected interface LogReaderInput {
Object readObject() throws IOException;
}
protected abstract LogReaderInput getInput(InputStream in);
/*package*/ static class IteratorImpl<T> implements Iterator<T> {
public static final int BUF_SIZE = 1;
private final LogReaderInput input;
private final Class clazz;
private Queue<T> buffer = newLinkedList();
private boolean loaded = false;
public IteratorImpl(LogReaderInput input, Class clazz) {
this.input = input;
this.clazz = clazz;
}
@Override
public boolean hasNext() {
return !getBuffer().isEmpty();
}
@Override
public T next() {
return getBuffer().poll();
}
private Queue<T> getBuffer() {
if (buffer.isEmpty()) {
update();
}
return buffer;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Read only iterator!");
}
private void update() {
if (loaded) {
return;
}
while(buffer.size()<BUF_SIZE) {
try {
Object entry = input.readObject();
if (entry == null) {
continue; // TODO some bug with JBoss reader
}
if (!clazz.isInstance(entry)) {
throw new IllegalStateException("entry " + entry + " is not instance of class " + clazz);
}
buffer.add((T) entry);
} catch (EOFException e) {
loaded = true;
break;
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}
}
private static class FileReaderImpl<T> implements FileReader<T> {
private final Iterator<T> iterator;
private final InputStream inputStream;
private FileReaderImpl(Iterator<T> iterator, InputStream inputStream) {
this.iterator = iterator;
this.inputStream = inputStream;
}
@Override
public void close() {
try {
inputStream.close();
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
@Override
public Iterator<T> iterator() {
return iterator;
}
}
}