Java tutorial
/* * Copyright (c) 2010-2014. Axon Framework * * 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 org.axonframework.eventstore.fs; import org.apache.commons.io.input.CountingInputStream; import org.axonframework.common.io.IOUtils; import org.axonframework.domain.DomainEventMessage; import org.axonframework.eventstore.EventStoreException; import org.axonframework.serializer.SerializedDomainEventData; import org.axonframework.serializer.Serializer; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Writes snapshot events to the given {@link #snapshotEventFile}. * * @author Frank Versnel * @since 2.0 */ public class FileSystemSnapshotEventWriter { private final InputStream eventFile; private final OutputStream snapshotEventFile; private final Serializer eventSerializer; /** * Creates a snapshot event writer that writes any given <code>snapshotEvent</code> to the given * <code>snapshotEventFile</code>. * * @param eventFile used to determine the number of bytes to skip upon reading a snapshot * when using {@link FileSystemSnapshotEventReader#readSnapshotEvent(String, Object)} * @param snapshotEventFile the snapshot file to write to * @param eventSerializer the serializer used to serialize snapshot events */ public FileSystemSnapshotEventWriter(InputStream eventFile, OutputStream snapshotEventFile, Serializer eventSerializer) { this.eventFile = eventFile; this.snapshotEventFile = snapshotEventFile; this.eventSerializer = eventSerializer; } /** * Writes the given snapshotEvent to the {@link #snapshotEventFile}. * Prepends a long value to the event in the file indicating the bytes to skip when reading the {@link #eventFile}. * * @param snapshotEvent The snapshot to write to the {@link #snapshotEventFile} */ public void writeSnapshotEvent(DomainEventMessage snapshotEvent) { try { long offset = calculateOffset(snapshotEvent); DataOutputStream dataOutputStream = new DataOutputStream(snapshotEventFile); dataOutputStream.writeLong(offset); FileSystemEventMessageWriter eventMessageWriter = new FileSystemEventMessageWriter(dataOutputStream, eventSerializer); eventMessageWriter.writeEventMessage(snapshotEvent); } catch (IOException e) { throw new EventStoreException("Error writing a snapshot event due to an IO exception", e); } finally { IOUtils.closeQuietly(snapshotEventFile); } } /** * Calculate the bytes to skip when reading the event file. * * @param snapshotEvent the snapshot event * @return the bytes to skip when reading the event file * * @throws IOException when the {@link #eventFile} was closed unexpectedly */ private long calculateOffset(DomainEventMessage snapshotEvent) throws IOException { CountingInputStream countingInputStream = null; try { countingInputStream = new CountingInputStream(new BufferedInputStream(eventFile)); FileSystemEventMessageReader eventMessageReader = new FileSystemEventMessageReader( new DataInputStream(countingInputStream)); long lastReadSequenceNumber = -1; while (lastReadSequenceNumber < snapshotEvent.getSequenceNumber()) { SerializedDomainEventData entry = eventMessageReader.readEventMessage(); lastReadSequenceNumber = entry.getSequenceNumber(); } return countingInputStream.getByteCount(); } finally { IOUtils.closeQuietly(countingInputStream); } } }