/**
* Copyright 2013 Netflix, Inc.
*
* 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.netflix.aegisthus.io.sstable;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.commons.io.input.CountingInputStream;
import javax.annotation.Nonnull;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
/**
* This class reads an SSTable index file and returns the offset for each key.
*/
public class IndexDatabaseScanner implements Iterator<IndexDatabaseScanner.OffsetInfo>, Closeable {
private final CountingInputStream countingInputStream;
private final DataInputStream input;
public IndexDatabaseScanner(@Nonnull InputStream is) {
this.countingInputStream = new CountingInputStream(is);
this.input = new DataInputStream(this.countingInputStream);
}
@Override
public void close() {
try {
input.close();
} catch (IOException ignored) {
}
}
@Override
public boolean hasNext() {
try {
return input.available() != 0;
} catch (IOException e) {
throw new IOError(e);
}
}
@Override
@Nonnull
public OffsetInfo next() {
try {
long indexOffset = countingInputStream.getByteCount();
int keysize = input.readUnsignedShort();
input.skipBytes(keysize);
Long dataOffset = input.readLong();
skipPromotedIndexes();
return new OffsetInfo(dataOffset, indexOffset);
} catch (IOException e) {
throw new IOError(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
void skipPromotedIndexes() throws IOException {
int size = input.readInt();
if (size <= 0) {
return;
}
FileUtils.skipBytesFully(input, size);
}
public static class OffsetInfo {
private final long dataFileOffset;
private final long indexFileOffset;
public OffsetInfo(long dataFileOffset, long indexFileOffset) {
this.dataFileOffset = dataFileOffset;
this.indexFileOffset = indexFileOffset;
}
public long getDataFileOffset() {
return dataFileOffset;
}
@SuppressWarnings("unused")
public long getIndexFileOffset() {
return indexFileOffset;
}
}
}