package org.rhq.cassandra.schema;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* An append only log that stores schedule ids in binary format. When data is successfully migrated, the schedule id
* is written to the log.
*
* @author John Sanda
*/
public class MigrationLog {
private File logFile;
private DataOutputStream outputStream;
public MigrationLog(File logFile) throws IOException {
this.logFile = logFile;
outputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(logFile, true), 2048));
}
/**
* Sequentially reads the log into a set. If the log is empty or does not yet exist, an empty set is returned.
* This method does not support concurrent access.
*
* @throws IOException
*/
@SuppressWarnings("unchecked")
public Set<Integer> read() throws IOException {
if (logFile.length() == 0) {
return Collections.emptySet();
}
Set<Integer> scheduleIds = new HashSet<Integer>();
DataInputStream inputStream = null;
try {
inputStream = new DataInputStream(new FileInputStream(logFile));
long bytesRead = 0;
while (bytesRead < logFile.length()) {
scheduleIds.add(inputStream.readInt());
bytesRead += 4;
}
return scheduleIds;
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
/**
* Appends <code>scheduleId</code> to the log. Writes go to an internal buffer and are not immediately flushed to
* disk. When the buffer fills up, it is automatically flushed. This method supports concurrent access.
*
* @throws IOException
*/
public void write(int scheduleId) throws IOException {
// Note that this method assumes concurrent writers. This is ok because
// BufferedOutputStream.write is synchronized.
outputStream.writeInt(scheduleId);
}
/**
* Flushes any buffered writes and then closes the underlying output stream.
*
* @throws IOException
*/
public void close() throws IOException {
outputStream.flush();
outputStream.close();
}
}