Package net.sodacan.core.journal


package net.sodacan.core.journal

A Sodacan journal primarily stores Actor state messages which can also be interleaved with other messages. Most of this description covers State Messages.

There is one logical journal for each ActorGroup per Host. A journal contains journal entries. Each entry has a variable length. Journal entries are identified by a monotonic long field. The identifiers are not contiguous. The journal is immutable except for new entries appended.

A journal is composed of one or more journal files. Journal files are "rotated" under several conditions. Taken together, the journal files represent the complete journal for an actor group.

A journal can be read sequentially as follows: Each journal file has a header containing the base journal entry id of that file. The first journal file's header will have a base entry id corresponding to the position in that file. Subsequent journal files will have a base id relative to that file. Using the desired id minus the base id yields the file position in that file.

In practice, journal files are rotated so that no one file grows too large. A journal file might also be rotated if the file format changes.

Each journal file begins with a header record which carries several important fields including the starting id of the file. The file position can be deduced from the id.

Each entry in a journal has two relevant fields: At the beginning of the entry is a long that corresponds to the file position of the entry. This is primarily used as a check on the validity of the entry. Following the payload for an entry, another long is added that carries the logical entry id for the *next* entry in that journal. When the journal file is opened for append, its a simple matter of backing up four bytes from the end of the file to get the next entry id. This field is also used to begin a new follow-on file where the next id at the end of the previous file becomes the starting id of the next journal file.

Each journal has a companion index file. The index file is never rotated. However, it can be recreated by reading the journal file(s). The index is used to locate the most recent journal entry for each actor managed by the ActorGroup.

The journal files are organized as follows:

  • All files for a single host are stored in a directory tree structure.
  • Each host is typically on a separate node and has a unique id which is used to name the host folder under the root folder (from Sodacan Config).
  • A host never shares a journal with other hosts and an ActorGroup journal is never shared with other ActorGroups on the same host or other hosts.
  • ActorGroups also have a unique id which is used to name a folder within the host folder that holds the journal and related files for that ActorGroup.
  • Within an ActorGroup, one subfolder, named journal/, holds all of the journal files for that ActorGroup. The files in this folder hold the source of truth for that Host/ActorGroup. If files are lost from this folder, they must be recovered from another replica on another host.
  • Journals for an inactive (cold) Host/ActorGroup will fall behind as long as the ActorGroup is cold.
  • When an ActorGroup on a Host is inactive, no messages are being queued or processed by the Actors in that cold ActorGroup.
  • When the Coordinator puts an ActorGroup in warm status, its Journal will need to be brought up to date. Another warm (preferably) replica will need to send Journal updates to the cold Journal, and keep the state messages from the warm ActorGroup coming to the cold ActorGroup allow that cold ActorGroup to become and stay synchronized.
  • Once this level of synchronization is achieved, the warm ActorGroup can begin the process of bringing the Actor's local state up to date. A warm ActorGroup does not care about the state of individual Actor's state.
  • Handling a transition from warm to hot status all happens within the ActorGroup. The ActorGroup needs to read its journal and send state update Messages to the Actors in that non-live ActorGroup. This activity has the appearance of imposing on the sanctity of an Actor, but since the ActorGroup is not live, the framework is free to setup the underlying storage used by an Actor.
  • Another folder inside the ActorGroup folder is named index. This folder contains an index into the journal file allowing the journal manager fast access to the most recent state record for actors. This index is used when an actor has not been loaded into memory (or was evicted) and asks the ActorGroup manager to send the actor's state back to the actor. The manager, if needed, can easily reorganize the index since it is owned and used exclusively by the manager.
  • In a warmed up server, it should be rare for an actor to request a state restoration since there is usually no reason for an actor to be evicted except when the whole group is abandoned or when too many actors are in memory.
  • The resulting directory structure is root/hostid/ActorGroupid/journal. And root/hostid/ActorGroupid/index
  • Classes
    Class
    Description
    A journal entry suitable for writing/reading with nio.
    The first 2^16 bytes of a journal file are reserved for header information pertaining to the format of the rest of the file.