Copyright | MIT |
---|---|
Maintainer | max.voit+hdv@with-eyes.net |
Portability | non-portable (uses GHC extensions) |
Safe Haskell | None |
Language | Haskell2010 |
A replication backend for acid-state that is centered around a Master node. Slave nodes connect to the Master, are synchronized and get updated by the Master continuously. This backend offers two flavors of operation:
Regular operation
- No redundancy guarantees but fast.
Redundant operation
- Guarantees redundant replication on n nodes but slower.
In both cases Slaves' Updates block (and eventually time out) if the Master is unreachable.
Queries operate on the local state with the performance known from acid-state. Note that state on all nodes is eventually consistent, i.e. it might differ shortly (for Queries run concurrently to Updates being serialized).
- openMasterState :: (IsAcidic st, Typeable st) => String -> PortNumber -> st -> IO (AcidState st)
- openMasterStateFrom :: (IsAcidic st, Typeable st) => FilePath -> String -> PortNumber -> st -> IO (AcidState st)
- enslaveState :: (IsAcidic st, Typeable st) => String -> PortNumber -> st -> IO (AcidState st)
- enslaveStateFrom :: (IsAcidic st, Typeable st) => FilePath -> String -> PortNumber -> st -> IO (AcidState st)
- openRedMasterState :: (IsAcidic st, Typeable st) => String -> PortNumber -> Int -> st -> IO (AcidState st)
- openRedMasterStateFrom :: (IsAcidic st, Typeable st) => FilePath -> String -> PortNumber -> Int -> st -> IO (AcidState st)
- enslaveRedState :: (IsAcidic st, Typeable st) => String -> PortNumber -> st -> IO (AcidState st)
- enslaveRedStateFrom :: (IsAcidic st, Typeable st) => FilePath -> String -> PortNumber -> st -> IO (AcidState st)
- type PortNumber = Int
Usage
Open your AcidState using one of the functions below. Take care to use the same initial-state on all nodes. Afterwards the usual interface of acid state is available.
Always make sure to have sensible exception management since naturally a lot
more error sources exist with this backend than do for a Local
AcidState.
Using bracket
is recommended for achieving this
conveniently:
main = bracket (enslaveState ...) closeAcidState $ \acid -> do ...
createCheckpoint
issued on Master is a global operation,
while issued on a Slave it is not. Note that Checkpoints on Master reduce the
amount of Updates to be transferred when a Slave (re-)connects.
createArchive
is an operation local to each node since usually
further action is required. For global Archives see createArchiveGlobally
.
Regular operation
Running Updates on Master works as known from acid-state and with negligible performance loss. On Slaves Updates are delayed by approximately one round trip time (RTT). When no Slaves are connected Updates are only serialized on the Master, i.e. there is no redundancy.
:: (IsAcidic st, Typeable st) | |
=> String | address to bind (useful to listen on specific interfaces only) |
-> PortNumber | port to bind to |
-> st | initial state |
-> IO (AcidState st) |
Open the Master state.
The directory for the local state files is the default one ("state[typeOf state]").
:: (IsAcidic st, Typeable st) | |
=> FilePath | location of the local state files |
-> String | address to bind (useful to listen on specific interfaces only) |
-> PortNumber | port to bind to |
-> st | initial state |
-> IO (AcidState st) |
Open the master state from a specific location.
:: (IsAcidic st, Typeable st) | |
=> String | hostname of the Master |
-> PortNumber | port to connect to |
-> st | initial state |
-> IO (AcidState st) |
Open a local State as Slave for a Master.
The directory for the local state files is the default one ("state/[typeOf state]").
:: (IsAcidic st, Typeable st) | |
=> FilePath | location of the local state files. |
-> String | hostname of the Master |
-> PortNumber | port to connect to |
-> st | initial state |
-> IO (AcidState st) |
Open a local State as Slave for a Master. The directory of the local state files can be specified.
Redundant operation
When Updates are scheduled they are sent out and written to disk on all nodes. However, an Update is visible to Queries (and its result returned) only as soon as at least n nodes are done replicating it. Thus each Update is delayed for at least one RTT.
If less than n-1 Slave nodes are connected, all Updates are blocked until enough nodes are available again. Queries are not affected and operate on the last n-replicated state.
Note: Shutting down and restarting the Master resumes the last state including even Updates that were not n-replicated.
:: (IsAcidic st, Typeable st) | |
=> String | address to bind (useful to listen on specific interfaces only) |
-> PortNumber | port to bind to |
-> Int | guarantee n-redundant replication |
-> st | initial state |
-> IO (AcidState st) |
Open the master state with n-redundant replication.
The directory for the local state files is the default one ("state/[typeOf state]/").
:: (IsAcidic st, Typeable st) | |
=> FilePath | location of the local state files |
-> String | address to bind (useful to listen on specific interfaces only) |
-> PortNumber | port to bind to |
-> Int | guarantee n-redundant replication |
-> st | initial state |
-> IO (AcidState st) |
Open the master state from a specific location with redundant replication.
:: (IsAcidic st, Typeable st) | |
=> String | hostname of the Master |
-> PortNumber | port to connect to |
-> st | initial state |
-> IO (AcidState st) |
Open a local State as Slave for a Master.
The directory for the local state files is the default one ("state/[typeOf state]").
:: (IsAcidic st, Typeable st) | |
=> FilePath | location of the local state files. |
-> String | hostname of the Master |
-> PortNumber | port to connect to |
-> st | initial state |
-> IO (AcidState st) |
Open a local State as Slave for a _redundant_ Master. The directory of the local state files can be specified.
Types
type PortNumber = Int Source
Number of a port for establishing a network connection.