package org.eclipse.buckminster.p2.remote.server; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.RandomAccessFile; import java.util.List; import org.eclipse.buckminster.p2.remote.change.RepositoryChange; import org.eclipse.buckminster.p2.remote.change.SynchronizationBlock; import org.eclipse.buckminster.runtime.Buckminster; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.IOUtils; import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException; public class ChangeLog { private static final long CHANGELOG_MAGIC = 0x4368616E654C6F67L; private final File m_logFile; public ChangeLog(File logFile, long sequenceStart, RepositoryServer server) throws ProvisionException { ObjectInputStream input = null; try { input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(logFile), 0x8000)); assertMagic(input); } catch(FileNotFoundException e) { ObjectOutputStream output = null; try { output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(logFile), 26)); output.writeLong(CHANGELOG_MAGIC); output.writeLong(sequenceStart); output.writeInt(0); } catch(IOException e2) { throw new ProvisionException(BuckminsterException.createStatus(e2)); } finally { IOUtils.close(output); } } catch(IOException e) { throw new ProvisionException(BuckminsterException.createStatus(e)); } finally { IOUtils.close(input); } m_logFile = logFile; } public void addChange(RepositoryChange change) { try { ObjectOutputStream output = null; try { change.setTimestamp(System.currentTimeMillis()); output = new ObjectOutputStream(new BufferedOutputStream( new FileOutputStream(m_logFile, true), 0x8000)) { @Override protected void writeStreamHeader() throws IOException { super.reset(); } }; output.writeObject(change); } finally { IOUtils.close(output); } // Bump sequence number RandomAccessFile updater = null; try { updater = new RandomAccessFile(m_logFile, "rw"); updater.seek(22); int entryCount = updater.readInt(); updater.seek(22); updater.writeInt(entryCount + 1); } finally { IOUtils.close(updater); } } catch(RuntimeException e) { throw e; } catch(Exception e) { Buckminster.getLogger().error(e, e.getMessage()); } } public SynchronizationBlock getChangesSince(long sequenceNumber) throws ProvisionException { ObjectInputStream input = null; try { input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(m_logFile), 0x8000)); assertMagic(input); long sequenceStart = input.readLong(); int entryCount = input.readInt(); SynchronizationBlock syncBlock = new SynchronizationBlock(); if(sequenceStart + entryCount < sequenceNumber) { syncBlock.setLastChangeNumber(sequenceStart + entryCount); return syncBlock; } List<RepositoryChange> changes = syncBlock.getChanges(); long currentNumber; for(currentNumber = sequenceStart;; ++currentNumber) { try { RepositoryChange change = (RepositoryChange)input.readObject(); if(currentNumber > sequenceNumber) changes.add(change); } catch(EOFException e) { break; } catch(ClassNotFoundException e) { throw new ProvisionException(BuckminsterException.createStatus(e)); } } syncBlock.setLastChangeNumber(currentNumber); return syncBlock; } catch(IOException e) { throw new ProvisionException(BuckminsterException.createStatus(e)); } finally { IOUtils.close(input); } } public long getLastChangeNumber() throws IOException, ProvisionException { ObjectInputStream input = null; try { input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(m_logFile), 0x8000)); assertMagic(input); final long sequenceStart = input.readLong(); final int entryCount = input.readInt(); return sequenceStart + entryCount; } catch(FileNotFoundException e) { return 0L; } finally { IOUtils.close(input); } } private void assertMagic(ObjectInputStream input) throws ProvisionException, IOException { if(input.readLong() != CHANGELOG_MAGIC) throw new ProvisionException(BuckminsterException.createStatus("Not a changelog file: %s", m_logFile)); } }