Archive Files
When Aeron Archive records a Publication, it stores the messages in a Recording. Each Publication that is recorded has its own Recording, and each Recording has a recordingId (just a number starting at 0).
A Recording is not one large file; it is split up into multiple files known as Segment files. Each Segment file has a predetermined fixed length and once it is full, another one is created. Having separate files makes the Recording easier to manage, e.g. old Segment files can be deleted while the latest Segment file is still being written to.
Aeron Archive maintains a Catalog file archive.catalog
, which is like a contents page that keeps track of all the
Recordings and their Segment files. The Catalog contains metadata about each Recording, such as the start and stop
position, start and stop timestamp, Term Length of the Publication, streamId, sessionId, etc.
You can think of a Recording as a DVD box set and Segment files as the individual DVDs. The Archive Catalog is your contents page - your list of box sets. Aeron Archive supports querying the Catalog, so you can find a Recording based on various criteria.
Segment Files
Segment files contain the raw data copied straight from the Terms in the Log Buffer of the Publication being recorded. Data is copied unchanged (with a small caveat if checksums are enabled - see later), so if you were to compare messages within the Log Buffer with the corresponding section of a Segment file, they would be identical. The first and last bytes in a Segment file are from the first and last bytes of a Term buffer - there is no additional layering of data formats, no such thing as a Segment file header or Segment metadata, etc. Any additional data is in the Catalog.
All the Segment files for a particular Recording have the same fixed length. The length must be a power of 2 between 64 KB and 1 GB inclusive (the same criteria as Term Length) and must hold at least one Term from the Publication being recorded (the default length is 128 MB). This means each Segment file will be able to hold exactly a power of 2 number of Terms worth of data (1, 2, 4, 8, 16, etc.).
Unlike Log Buffers, Segment files do not have Term boundaries internally, but given that their length is dictated by Term Length, it's useful to draw Term lengths on Segment files in a diagram. In the diagram below, the Segment file length is 4 * Term Length and Term Length is 64 KB, so the file would be 262,144 bytes long exactly.
Use the tabs above to step through the animation.
As messages are published and written to the first Term in the Log Buffer, Aeron Archive copies them into the start of the Segment file. Again, Segment files do not contain Terms, but it's easier to visualise what's happening if we mark Term Lengths on the Segment file in the diagram.
As messages are written to the second Term, they continue to be copied to the Segment file. This Segment file can hold exactly 4 Terms worth of messges.
Messages continue to be copied. The purpose of this diagram is to show where Term data is copied to in the Segment file. It does not mean to imply that messages are copied in large batches - they are copied piecemeal, as and when they are written to the Log Buffer.
The Publication wraps around the Log Buffer and starts to use Term 0 again. This is copied to the end of the Segment file, which leaves the Segment file full.
As more messages are published to the Log Buffer, Aeron Archive creates a new Segment file and copies new messages to the start of it. Segment filenames are discussed more below, but the second number in the filename is the position in the Publication that the first byte in the Segment file represents. Here, you can see the first Segment file started from the beginning of the Publication and the second one started 262,144 bytes (256 KB) into it.
Aeron Archive continues to copy data, creating new Segment files as necessary.
If the Recording didn't start until halfway through Term 1, the start of the Segment file would look like this. The first Term in the file would be Term 1 and the messages would start at an offset in the Segment file matching the offset of the recording start position in Term 1. Also notice that the Segment file's filename reflects the position at the start of Segment file (which matches the position at the start of Term 1). The position that the Recording started at (98,304) would be recorded in the Catalog file.
Segment Filenames
Segment filenames follow the format: <recordingId>-<segmentFileBasePosition>.rec
All Segment files for the same Recording will obviously start with the same recordingId. The diagram above was for recordingId 0.
The second part of the filename is the position in the Publication that the start of the file represents. This is
referred to as segmentFileBasePosition
in
AeronArchive.
In the diagram above, the Recording started from the start of the Publication, so the start of the first Segment file
is for position 0 in the Publication. It was for recordingId 0, so the filename is 0-0.rec
.
In the diagram, Term Length is 64 KB and each Segment file holds 4 Terms, so the length of 0-0.rec
is 256 KB, or
262,144 bytes. That means the start of the second Segment file is for position 262144 in the Publication, so
the second Segment file is named 0-262144.rec
.
Step 7 in the diagram demonstrated starting a Recording halfway through Term 1. Segment files always hold whole
Terms, so the Segment file started at the start of Term 1, even though no messages were recorded until halfway
through it (the first half of the file would contain zeros). The segmentFileBasePosition
is thus 64 KB, or 65536,
so the filename is 0-65536.rec
.
Checksums
For a reminder of the format of the data in a Log Buffer, see Message Formats.
Aeron Archive can be configured to add a checksum to each DATA frame as it records it in a Segment file. When the Recording is replayed, the checksum is verified.
The checksum is written in each DATA frame header, overwriting the sessionId field. When a Recording is replayed, the sessionId and streamId fields are overwritten anyway, to be those of the replay Publication, so it doesn't matter that the original sessionId is lost. Reusing an existing field like this means the Segment file does not need to be any larger when checksums are enabled, so very little is affected by them.
Other than this difference, the data recorded in a Segment file is exactly the same as the data that passed through the Log Buffer.
Catalog file
The Catalog file archive.catalog
essentially contains a series of RecordingDescriptor records.
RecordingDescriptor is defined in the SBE schema aeron-archive-codecs.xml. As well as being used to encode data in the Catalog, RecordingDescriptor is also used on the wire, to return information about Recordings on the Control Response Channel in response to a list recordings request. The first two fields controlSessionId and correlationId are used on the wire, but left unset (zero) when used in the Catalog.
Here's what's in a RecordingDescriptor:
Field | Description |
---|---|
controlSessionId | Not used in the Catalog, only used on the wire |
correlationId | Not used in the Catalog, only used on the wire |
recordingId | Integer id of this Recording (0, 1, 2...) |
startTimestamp | Epoch time millis |
stopTimestamp | Epoch time millis (-1 if not set) |
startPosition | Position in the Publication that Recording started at |
stopPosition | Position in the Publication that Recording stopped at (-1 if still active) |
initialTermId | Copied from the Publication |
segmentFileLength | Fixed length of each Segment file in this Recording (other Recordings can have a different segmentFileLength) |
termBufferLength | Copied from the Publication |
mtuLength | Copied from the Publication |
sessionId | Copied from the Publication |
streamId | Copied from the Publication |
strippedChannel | The same as originalChannel, but with unnecessary fields stripped off. Used by Aeron Archive when it creates the Subscription to record |
originalChannel | The channel parameter from the StartRecording request (not updated if the Recording is Extended) |
sourceIdentity | aeron:ipc or host:port |
Catalog Refresh
When Aeron Archive starts, there will be no active Recordings, so every RecordingDescriptor in the Catalog should have a stopPosition. This might not be the case if Aeron Archive did not shut down cleanly, so on startup, Aeron Archive scans the Catalog looking for missing stop positions. For any that it finds, it opens the last Segment file for that Recording and walks through all the fragments until it finds the last one (where the next Frame header's length field is zero). It sets the stopPosition in the Catalog to the end of that Fragment and sets the stopTimestamp to the current time.
Mark file
As well as Segment files and the Catalog file, Aeron Archive creates a mark file archive-mark.dat
. This is used to
guard the archive directory so that only one instance of Aeron Archive can use it at a time. The mark file contains a
timestamp, which Aeron Archive updates once per second. If a second instance of Aeron Archive starts, using the same
archive directory, then if the timestamp in the mark file is less than 10 seconds old, the second instance exits with
an error.
Example files
Here's an example set of files created by Aeron Archive. The location of these files is configurable and defaults to
an aeron-archive
directory, which would be created below the working directory when Aeron Archive starts.
0-0.rec
0-131072.rec
0-262144.rec
0-393216.rec
0-524288.rec
0-655360.rec
1-65536.rec
1-196608.rec
1-327680.rec
archive.catalog
archive-mark.dat
There are two Recordings here, which means two different Publications have been recorded. The first Recording is
stored in the files named 0-*.rec
and the second Recording stored in 1-*.rec
.