stasher — Interactive object repository client
stasher
[ --connect=directory
| --admin=directory
] [--alarm=seconds
] [command]
stasher provides an interactive interface to an object repository server. This is mostly an administrative tool, but it's also available as a crude object repository client, running in a “sandbox” for demonstration purposes. It connects to an object repository server running on the same machine. The server is typically configured so that unknown non-administrative connections are confined to a sandbox area, where random objects can be placed and/or retrieved, and stasher implements an interactive interface shell for doing so.
stasher issues a prompt, and waits for a command. Each command gets parsed into white-space-delimited words, in a similar manner as bash(1), including quoting. Input continues if the last character on a typed line is a backslash. stasher removes the backslash, saves the first line, repeats the prompt and waits for another line to be entered, which gets logically appended to the first line, before broken up into individual words using bash(1) rules. Lines are combined in this manner, consecutively, until a typed line does not end in a backslash, then the collected input gets split into words, and executed.
If stasher receives any non-option parameters, the pre-parsed parameters get interpreted as individual words that make up a single command, which then gets executed, and stasher exits. Otherwise, stasher repeatedly prompts for, and executes commands until it reads an end-of-file (usually “CTRL-D” from the keyboard).
Passing a single command to execute, to stasher, on the command line, enables some rudimentary scripting using the following options:
--connect=directory
stasher executes the command “CONNECT directory” before executing the command it receives as an argument.
--admin=directory
stasher executes the command “ADMIN directory” before executing the command it receives as an argument.
--alarm=seconds
Sets an alarm clock for the prescribed number of seconds. If the command executed by stasher does not finish in the prescribed time, the stasher command dies with a signal.
Input to stasher can also be piped in, which stasher reads and acts upon as if it was typed in. stasher does not issue interactive prompts if its input is piped in; and suppresses some interactive output; but otherwise produces the same messages that it would, when used interactively.
The following documentation specifies the syntax of each command as a list of separate words. Except where noted otherwise "{parameter}" refers to a single parsed word, that's required by the command; "[parameter]" refers to a single optional word. Uppercase specifies literal keywords, a lowercase name designates a replaceable parameter value.
Parenthesis designates a sequence, or a list of words. The "*" suffix denotes an optional sequence of words. The "+" suffix denotes a required sequence, at least one word is required, and may be repeated.
The following commands connect to an object repository server that's already running, or start a server process.
The CONNECT
command makes
a regular, non-administrative connection to an object repository
server running
in a
.
The connection usually gets placed into a sandbox area, according to
the namespace rules defined for the given object repository.
directory
is optional
when there's exactly one object repository server node
directory installed in
the default installation directory, which is usually
directory
/var/stasher/nodes
or
/usr/local/var/stasher/nodes
.
If there's more than one node directory, or if it's not in the
default location, the
parameter
is required.
directory
$ stasher > connect nodekey.dir Connected to example, node nodea.example. Maximum 10 objects, 32 Mb aggregate object size, per transaction. Maximum 10 concurrent subscriptions. nodea>
This example makes a connection to an object repository cluster node
running from nodekey.dir
.
stasher prompts with a “>” when
its not connected to any server. When connected the node's name
is included with the prompt.
stasher can connect to only one server
at a time.
After connecting, stasher reports the
server's limits. In this example, the server will accept a maximum
of ten objects per transaction, with their total aggregate
size not exceeding a megabyte; and the server accepts a maximum of ten
object subscriptions at a time.
The ADMIN
command makes
an administrative connection to an object repository server running
in a
.
The directory
must
be owned by the same user-id that's running stasher
otherwise the connection fails.
directory
is optional
when there's exactly one object repository server node
directory installed in
the default installation directory, which is usually
directory
/var/stasher/nodes
or
/usr/local/var/stasher/nodes
.
If there's more than one node directory, or if it's not in the
default location, the
parameter
is required.
directory
The START
command
starts a child process that runs an object repository server in the
, which must've
been previously created by
stashermg --nodekey --generate.
An administrative connection gets immediately established with the
newly started server process, as if by the “ADMIN” command.
directory
The DISCONNECT
command drops the connection with
the server. stasher can only connect to one server
at a time, and an existing connection must be dropped before
another CONNECT
or ADMIN
command.
The following commands require an administrative connection with an
object repository server created by the
ADMIN
command.
stasher does not itself check that an administrative
connection was established; this is checked by the server, and the
imposed penalty is the disconnection of a non-administrative connection,
and a nasty message in the server's logs.
This command displays a list of current server property settings.
Server property settings are low level configuration settings that
control the server's operation.
The GETPROPS
command displays a list of property
settings, and each setting's current value.
The SETPROP
command changes an internal server
property setting name
to value. Generally,
the setting takes effect immediately, and is permanent. The new
setting remains in effect when the server gets restarted.
The RESETPROP
command resets a property setting to
its default value the next time the server restarts. The default
property setting value does not take effect immediately. It's necessary
to stop and restart the server for the property to revert to its
default value.
Set a maximum limit of maxobjects
objects
updated per transaction, with the total aggregate size of all objects
in the transaction no more than
maxobjectsize
.
maxobjectsize
can be given as
“n
Mb”, in megabytes.
These limits take effect for new client connections only, and do not affect existing connections. In order to effectively manage the object repository's available space, all client connections must have the same uniform limit, so this command gets typically used when creating a new object repository cluster. If the limits of an existing cluster get changed, all object repository nodes should be restarted in an orderly fashion, to enforce consistent limits for all client connections.
Specifying “default
” for
maxobjects
or
maxobjectsize
resets the correspoding
limit to its “factory default” setting (10 objects,
32 megabytes).
The STATUS
command displays the connected node's
current status. The result is a long report on the node's state,
with mind-numbing detail.
The STOP
command stops the repository cluster node
and terminates the daemon process. The stoppage is immediate, and the
administrative connection with the server gets dropped.
Stopping a slave cluster node generally has little impact, as long as the majority of nodes in the cluster remain in quorum. If the stopped node was a master node, the remaining nodes must elect a new master. This is a disruptive event and should be avoided, if possible. Once a new master gets elected, each slave has to synchronize its copy of the object repository with the master, before regular operations can resume. Depending on the size of the object repository, this can take a long time.
Use the “STATUS” command to verify which node is the current master node, and that there's sufficient number of nodes for the cluster to remain in quorum (the majority of nodes in the cluster are up, connected and synchronized with each other). If this node is a repository master node, use the “RESIGN” command to make another node a master, in an orderly fashion.
If this node is the current master of the cluster, another node takes its place. This is an orderly transition that does not require each node to re-synchronize itself with the new master.
The RESIGN
command has no effect if the connected
node is not the current master.
Halt the entire cluster. All nodes in the cluster get stopped. This command requires a full quorum (all nodes in the cluster are up, connected and synchronized with each other), and can only be issued when connected to the cluster's master node.
Use STATUS
to show the cluster's master node
and its quorum status. This is the safest way to stop an
entire cluster and have any connected clients receive a
reliable indication whether their last transaction succeeded,
or not.
The EDITCLUSTER
command loads the list of
cluster nodes, for editing by the CLUSTER
command. The cluster list is a list of nodes in the repository,
the machines they run on, and their individual configurations.
It's stored as an object in the repository itself, named
“etc/cluster”.
EDITCLUSTER
loads this list.
The CLUSTER
command makes changes to the list,
and SAVECLUSTER
installs a new
“etc/cluster” object.
Since the list of cluster nodes is saved as an object in the repository, changes made to the cluster configuration using an administrative connection on any node get automatically replicated to all nodes in the cluster.
In marginal situations it may be necessary to use
EDITCLUSTER
with the "force" or "new" option
to recover from fatal errors that
prevent normal object repository cluster operations.
The object repository cluster node configuration is stored as an
object in its own repository. If the repository cluster is not in
quorum, attempts to read or update objects hang, until the
repository quorum gets established, and the
EDITCLUSTER
and
SAVECLUSTER
commands wait until
quorum (the majority of nodes in the cluster are up, connected and synchronized with each other) gets
established.
There are situations where a quorum can never be established. This can occur, for example, if: a node in the repository permanently disappears for some reason; the node is not yet removed from the cluster's configuration; and the remaining operational nodes are insufficient for a minimum quorum. The former node has to be deleted from the configuration, before the total number of nodes in the repository falls and the remaining nodes now comprise a majority quorum. So the cluster configuration cannot be loaded until a quorum is formed, and the quorum cannot be formed until a node gets removed from the cluster's configuration.
To recover from this situation, a new administrative connection must
be established, and the “force” parameter specified to
the EDITCLUSTER
command. “force”
loads “etc/cluster” from the node's copy of the
object repository, even if the cluster is not in quorum. This
permits editing to proceed.
If the “etc/cluster” object itself is corrupted or damaged, and cannot be parsed, the “new” parameter (which can be used together with “force”) ignores the contents of “etc/cluster”, and starts editing with an empty list.
Any additional words given to EDITCLUSTER
,
“[command]*”,
if present,
get processed as if they were given to the CLUSTER
command.
CLUSTER
changes the list of nodes in the cluster and their
configuration. A CLUSTER
by itself shows the current
list. If followed by a command
, the command
updates the list of nodes, and SHOW
shows the changed
list.
The list of individual cluster commands follows. They are
typically combined into a single
CLUSTER
directive, since they often must follow in
a specific order, as described:
Add a new node to the list of nodes in the object repository
cluster, named name
.
name
must match the name given to
stashermg(1)'s
--name
parameter which created the node's
certificate. Each node in the cluster must have a unique name.
The SET
,
UNSET
,
and ADD
directives that follow, in the
same CLUSTER
directive, get applied to the
newly created node.
Removes the specified node from the list of nodes in the object repository.
Make changes to an existing node's configuration.
The SET
,
UNSET
,
and ADD
directives that follow, in the
same CLUSTER
directive, get applied to the
selected node.
Sets the node's configuration setting named “name” to the specified value. “name=value” is specified as a single word.
Either uppercase or lowercase may be used to give a setting's
name. Setting names are case-insensitive.
The SET
directive removes any setting with
the same name, and replaces it with the new
value
.
Some options are flags, and do not have a value, so the “=value” part is omitted. The list of options is given below.
Any existing settings with this name are removed.
This is similar to the SET
command except
that any existing setting with this name remains, and this
value is added as another setting with the same name.
Depending on the setting, the same setting may have multiple
values.
Changes the listed order of nodes in the cluster by moving
one node, “name” before another “anchor”
node in the cluster. The order in which the nodes in the cluster
appear is mostly cosmetic, but it's used by the
RESIGN
command, which sets the next available
node, in the cluster, as the new master.
Examples:
CLUSTER ADDNODE nodea SET host=ip1.nodea.example.com ADD host=ip2.nodea.example.com SET nomaster
Define a new node named “nodea” in the cluster, with the
the setting “host” containing two values,
“ip1.nodea.example.com” and
“ip2.nodea.example.com”. The SET
directive sets the first value for “host”, and
ADD
adds the second value (if it was also a
SET
the second SET
replaces the
value from the first one).
Additionally, the “nomaster” setting, that takes no value, is given.
CLUSTER UPDATE nodea UNSET nomaster
This example removes the “nomaster” setting from “nodea”.
CLUSTER REORDER nodea AFTER nodeb
Move node “nodea” after “nodeb” in the node list.
Node configuration settings Setting Description HOST=
hostname
The name of the server the node runs on. The server's name does not have to be the same as the given name of the node, in its certificate. The
HOST
option must be specified for every node in the repository. Multiple HOST settings are permitted for nodes running on multi-homed servers.NOMASTER
This node should never be elected the repository's cluster master. The
RESIGN
command will not consider this node. The only situation where this node assumes a master role would be if all connected nodes have this setting, and there are no other choices. As soon as a node connects that does not have this setting, it becomes the repository's master.ENCRYPTION
Connections with this node should be fully encrypted over the network. Without this setting, encryption is only used briefly to authenticate connections with this node and verify the node's certificate. Once a connection gets established, it remains encrypted if this setting is present, otherwise the encryption gets dropped. The encryption gets dropped only if the nodes on both sides of the connection do not have this flag set. If either node has this setting, the connection remains encrypted.
Changes to the
HOST
andENCRYPTION
options have no effect on existing connections with the affected nodes. They take their respective effect when the next connection between the nodes gets established, after any existing connection gets dropped, for some reason.
All changes specified by previous CLUSTER
command
take effect. A new “etc/cluster” objects is installed in
the object repository, and distributed to all nodes in the cluster.
SAVECLUSTER
fails with an error message
if the list of nodes in the repository was independently updated,
by another stasher on the same node, or another
node in the cluster, after the initial EDITCLUSTER
command.
The FORCE
option should only be specified for the
same reason that its given to EDITCLUSTER
, and its
full implication must be fully understood.
FORCE
updates the “etc/cluster”
object, with the new cluster configuration, on the connected node only.
It's meant to be used as an emergency repair tool, to bring up the
repository cluster under dire circumstances:
The first node in the cluster gets started. On the node, the cluster node list configuration gets force-edited, updated, and force-save, in order to recover from whatever condition prevents the quorum from getting established.
The next node in the cluster get started. If it is unable to connect with the first node, the secon node's cluster list gets forcibly edited in the same manner, using whatever changes are needed for it to be able to connect with first node.
Once a connection is made, the two nodes should be able to re-synchronize their copies of the object repository, including “etc/cluster” with the cluster's official node list.
The process gets repeated, until a quorum forms. Once a quorum forms, it might be possible to bring up the remaining nodes without force-editing their copy of “etc/cluster”, as long as they connect with the quorum's master. The quorum's state should prevent any possibility of them becoming the cluster's master, pushing their bad “etc/cluster” to other nodes, and undo-ing the rebuilt cluster list.
Make changes to global object repository namespace rules. An administrative connection has full read/write access to the entire object repository namespace. A non-administrative connection typically has read/write and read-only access to a subset of the entire object repository namespace. The namespace rules define the subset.
The namespace rules are processed when a non-administrative connection gets established. This defines the connection's view of the object repository namespace. Changes to the namespace rules take effect for new connections only, and do not affect existing connections.
Global namespace rules are stored in the “etc/namespaces” object in the repository itself, so changes are immediately replicated to all nodes, and take effect on all nodes. Global namespace rules get overridden by application namespace rules, see the section called “Application namespace rules”. The global namespce rules described here take effect only when application namespace rules are not in effect.
The “etc/namespaces” object
gets updated by the NAMESPACE
command
in the same way that all objects are. The repository must be
in quorum. If not, NAMESPACE
waits until the
repository is in quorum, before proceeding.
The primary namespace setting is the namespace root. This restricts the connection's view to the specified subset of the object repository hierarchy.
Example: the namespace root is “apps/acct”. This is the top-level hierarchy from the connection's view. If the connection accesses an object named “index” it actually ends up with “apps/acct/index”. Objects in the repository outside of “apps/acct” are inaccessible, except through an auxiliary namespace mapping.
The namespace rules may also define auxiliary namespace mappings, which act as a virtual pointer from the connection's namespace root. Example: a connection whose root is “apps/acct”, and an auxiliary mapping of “system” to “etc”. A connection accesses “system/cluster”. Instead of “apps/acct/system/cluster”, the actual object accessed is “etc/cluster”. An auxiliary mapping is like a pointer from the connection's namespace root to some other part of the object repository's hierarchy. From the connection's view, the “system” hierarchy provides access to anything in “etc” in the object repository namespace, notwithstanding that the connection's namespace root is “apps/acct”.
Typically, applications create and use objects in a top-level namespace, and namespace rules separate applications' objects from each other.
The namespace rules specify each connection's root, and any auxiliary mappings. The rules define them based on the user-id and the group-id of the process that connected to a repository node, the filename of the binary that the process is running, and on the name of the node itself.
The namespace command with no arguments displays the current list of
namespace rules. Otherwise the first argument must be either
RW
or RO
.
There are two separate lists of namespace rules, the read/write rules and the read-only rules. In order to define a namespace view for a connection, the read-only rules gets processed first. The namespace they specify gets defined as a read-only namespace, where the connection can access objects, but not modify them.
Afterwords, the read-write rules modify the read-only view, and specify which parts of the namespace may be modified. If an auxiliary mapping gets initially defined by read-only rules, accessing objects through that mapping is restricted to reading them, and the objects cannot be modified. If an auxiliary mapping gets defined by read-write rules, objects in that auxiliary mapping are modifiable by the connection.
An auxiliary mapping defined by read-write rules does not require that the mapping must be defined by read-only rules, first. The read-write rules simply supersede the read-only ones. The auxiliary mapping may or may not be defined in the read-only list. If the read-write list does not redefine the mapping, it gets left as it is, otherwise the read-write mapping supersedes, and the read-write mapping can specify a different part of the entire object repository namespace for the read-write mapping, than the read-only one.
The connection's name root setting can appear in either the read-only or the read-write list. If specified by a read-write rule, the application may access and modify objects under the specified namespace. If specified by a read-only rule, and not overridden by a read-write rule, the application may access any existing objects, but not modify them. If the application has any read-write auxiliary mappings, the application can still modify objects through the read-write mapping.
If a top-level namespace root does not get specified by either read-only or read-write rules, the top-level namespace gets set to “sandbox”.
The ADD
commands adds a new namespace read-write or
read-only rule. One or more following clauses follow
the ADD
command:
ADD
is followed by a list of selectors, then
by a list of rules. The selectors restrict the following rules to
be applicable only to connections that meet a specified criteria.
If no selectors are given, the rules apply to all connections:
The following rules apply only to connections from a process running with the given effective username.
The following rules apply only to connections from a process running with the given effective groupname.
The following rules apply only to connections from a process
running the given binary executable.
pathname
must be an absolute pathname.
The following rules apply only to connections on the given
node
in the object repository cluster.
Essentially, only the specified node processes this rule, all
others ignore it.
One or more of the following rules follow the selectors:
Add an auxiliary mapping from hierarchy
to path
.
hierarchy
must be a single name,
not hierarchical. path
is the
path in the overall object repository hierarchy where the mapping
points to.
Note that this ADD
clause is different, and
in addition to ADD
that follows
the NAMESPACE (RW|RO)
, which indicates an
addition of a new rule, that contains this clause.
Set the connection's namespace root to this
hierarchy
within the object
repository's namespace.
Remove any previous auxiliary mapping for
hierarchy
that's set by any previous
rule. All namespace rules are processed in sequence, and
an auxiliary mapping set by one rule can be removed by another
rule. A rule can also define its own ADD
,
for the same hierarchy, that replaces the previous rule's.
Remove any top level hierarchy specification that's set by any
previous rule in the namespace rule list. All namespace rules are
processed in sequence, and a namespace root specified by a rule
an auxiliary mapping set by one rule can be overridden by another
rule, or removed altogether by UNSETROOT
, so
if not specified by some subsequent rule it defaults to the
“sandbox”.
Assign a label
to these rules.
It's an arbitrary name that labels these rules, and provides a
convenient way to MODIFY
them.
The same label cannot be specified for more than one set of rules.
This is similar to ADD
except that this modifies
an existing read-write or a read-only rule definition.
The first read-write or read-only rule that matches the list of
selector gets modified according to the rules given by
MODIFY
. Alternatively, “LABEL {label}”
selects a rule that has the specified label.
This is more convenient than
having to laboriously repeat the existing selectors, exactly.
MODIFY
's rules are the same as
ADD
, but may also include the following:
Remove the existing label from the selected rules. Alternatively,
specifying another LABEL
rule replaces the
existing label; this would be essentially a rename operation.
Remove any SETROOT
or
UNSETROOT
from the selected rules.
Alternatively, specifying another SETROOT
UNSETROOT
replaces the existing one in the
selected rule.
Remove any ADD
or
UNADD
for the same hierarchy
from the selected rules.
Alternatively, specifying another SETROOT
UNSETROOT
replaces the existing one in the
selected rule.
To remove a namespace entry completely, DELADD
all
of its ADD
s and UNADD
s,
and DELSETROOT
any
SETROOT
or UNSETROOT
.
An ADD
to the “etc”
hierarchy in the RW
list means that anyone that
gets that rule
can remove anything in “etc”. With
stasher itself, a single RMRF
command will destroy the entire object cluster repository.
Examples:
nodea> NAMESPACE RW ADD PATH /usr/sbin/distreboot SETROOT \ apps/distreboot.objrepo.example.com SETLABEL distreboot NAMESPACE RW ADD PATH /usr/sbin/distreboot SETLABEL distreboot \ SETROOT apps/distreboot.objrepo.example.com
This command sets the read-write namespace root for /usr/sbin/distreboot to “apps/distreboot.objrepo.example.com”, and assigns the “distreboot” label to this rule.
The NAMESPACE
command responds with the list of
currently defined namespace rules, in the form of the commands
necessary to recreate them. In the above example, there were no
other namespace rules defined before, and the output consists of the
same command.
nodea> NAMESPACE RO ADD PATH /usr/bin/distreboot SETLABEL distreboot-etc ADD etc etc NAMESPACE RO ADD PATH /usr/bin/distreboot SETLABEL distreboot-etc \ ADD etc etc NAMESPACE RW ADD PATH /usr/bin/distreboot SETLABEL distreboot \ SETROOT apps/distreboot.objrepo.courier-mta.com
An auxiliary namespace mapping gets added, with the assigned label of “distreboot-etc”. The mapping links “etc” from within the same program's namespace root to the real “etc” within the overall object repository hierarchy, read-only.
As stated previously, the read-only and read-write rules are separate
lists, and the read-only list gets processed first, followed by the
read-write list, and the output of the NAMESPACE
command reflects that. However, after processing both lists, the
auxiliary namespace mappings take effect with respect to the derived
namespace root, so the above example works as described.
The order of rules often matters with a complex namespace configuration.
The MOVE
command
rearranges the order of the existing rules.
The MOVE
command takes two lists of selectors.
Each list selects an existing rule, the same way
that the ADD
and MODIFY
,
preferably using an existing label to make this operation easier.
The rule selected by the first list of selectors gets moved before or after the rule selected by the second list, as specified. The read-write and read-only rules are separate from each other, and a read-write rule can be re-positioned only relative to another read-write rule, and a read-only rule can be repositioned only relative to another read-only rule.
The regular commands generally require the object repository to be in quorum (the majority of nodes in the cluster are up, connected and synchronized with each other). If not, these commands wait until a quorum forms, before proceeding.
The PUT
command adds, modifies, or removes
objects in the object repository. More than one object can be
processed at the same time.
If the PUT
fails for any reason, as described below,
none of the changes take effect; otherwise all objects get updated
atomically.
Another
process doing a PUT
, GET
, or
another command at the same time
will either use the previous contents of the modified objects, or
the contents as updated by this PUT
.
Atomicity is guaranteed only as long as the object repository cluster
remains in quorum. Like all other commands, PUT
waits until the repository cluster is in quorum before proceeding.
If the repository cluster loses quorum in the middle of a
PUT
, the command waits until a quorum gets
reestablished, before resuming, but the results of the command,
when it's reported to succeed, or to fail, are undefined. The command
may report a failure, but some of its objects might still get
updated, as the contents of the object repository get re-synchronized
between all the nodes in the quorum.
The maximum number of objects in a PUT
, and the
maximum aggregate sizes of new object values, are limited by the
server. These limits are reported when stasher
connects to its object repository node server.
PUT
takes a list of objects to process, as follows.
Each object's name is interpreted according to the
NAMESPACE
rules, in force.
Adds a new object to the repository. The PUT
command fails if the object already exists.
Removes an object from the repository.
The existing object's name must
be followed by a colon, and the existing object's
uuid
. The PUT
command fails if the object does not exist or its
uuid
is different.
Updates an existing object's value.
The existing object's name must
be followed by a colon, and the existing object's
uuid
. The UPD
command fails if the object does not exist or its
uuid
is different.
The value of NEW
or
UPD
ated objects may be specified in two ways,
immediately after the NEW
or the
UPD
ate command:
“VALUE literal” gives the new value for the object
explicitly, as a single word;
“FILE filename” reads the value from the specified file.
The entire contents of the given file are taken as the new value of
the object.
If successful, the UPD
command responds with the
uuid
of all objects added or updated by
the command. A uuid
is an opaque serial
number or a timestamp. Each time an object gets updated, it gets
a new uuid
, which is shown as a list of
meaningless letters, numbers, and some symbols. The actual value is
unimportant, except that it's always unique, and each update to an
object changes its uuid
.
The UPD
and DEL
operation
require a matching uuid
. If the affected
objects get updated by someone else, since the objects'
uuid
were obtained, they'll have a different
uuid
, and PUT
fails.
Example:
nodea> put new pi value "3.1415926" new e value "2.718281828" New object uuid: PjGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS
This example creates two objects, named “pi” and “e”, with explicit values. The new objects did not exist, and the new objects' uuid is “PjGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS”. All objects updated by a transaction have the same uuid.
nodea> put upd pi:PjGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS file /tmp/pi New object uuid: RDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS
The “pi” objects gets replaced, and its new contents are
taken from the file /tmp/pi
. This object now has
a different uuid.
nodea> put del pi:PjGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS Collision detected - object uuid mismatch
The “pi” object cannot be deleted, since the specified uuid no longer matches.
nodea> put del pi:RDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS New object uuid: TDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS
Specifying the pi
object's correct uuid succeeds in
deleting the object. This PUT
transaction did not
update or create any new objects, so the new uuid value is meaningless.
The DIR
command lists objects at the
specified hierarchy level, or at the top level if a hierarchy
is not specified.
nodea> dir etc/ pi
This example shows that the top level hierarchy contains an object named “pi” and a sub-hierarchy named “etc”. A trailing “/” designates a hierarchy level, not an object.
nodea> dir etc etc/namespaces etc/rootcerts
There are two objects in the “etc” hierarchy, whose names are shown. Object names are shown with their full hierarchy, as in this example.
The UIDS
command shows the uuids of listed objects:
nodea> uids etc/namespaces pi e etc/namespaces:ODGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS pi:UDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS e:
Each object's name is affixed with “:” and its current uuid value. In this example the object “e” did not exist, and its uuid shows empty.
RMRF
run the DIR
,
UIDS
and PUT
commands to remove
all objects in the listed hierarchies.
If no parameters are given, everything in the connecting client's
sandbox gets removed. Since this would be a disaster if the client
had an administrative connection, an RMRF
reports
an error if no arguments are provided, and the connection is an
administrative connection.
This is typically used to clean up a generic, shared, sandbox hierarchy.
Retrieve and display the contents of the selected objects:
nodea> get pi e pi:UDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS e:XzGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS 3.1415926 2.718281828
The output of GET
is similar to
UIDS
's output, and includes the value of each
object.
Objects may contain any data, and it's not necessarily human-readable,
so the GET
is not very useful if an object contains
binary data.
The SAVE
command is similar to GET
except that the value of each object is saved in a file, rather than
shown. Each object's name is followed by the filename where the
object's value is saved to:
nodea> save pi /tmp/pi e /tmp/e e:XzGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS pi:UDGKSOqwW7MxIG00Y4SSJm000028Tm800318n4AS
/tmp/pi
and /tmp/e
now
contain the values of the corresponding objects.
After subscribing to one or more objects, the server sends a “push”-type notification every time the object's value changes. The maximum number of concurrent subscription is limited by the server. stasher shows how many concurrent subscription the server accepts, after connecting to the server.
The subscription facility is mostly useful when using the C++ API for accessing the object repository. Here, with stasher it's implemented for demonstrative purposes, mostly. Each time stasher reads a command and executes it, it reports the names of any objects that the server, in the meantime, has pushed to stasher:
nodea> sub pi e Subscribed to pi Subscribed to e nodea> nodea> nodea> e updated pi updated nodea> uids e pi e: pi:HX2RF2zlQsLwIm00MAKSJm000000T0C00318n4AS
After reporting that both subscribed objects have been updated, the
UIDS
command returns “pi”'s new uuid,
and shows that the “e” object was deleted.
Append a trailing "/" to the object name to subscribe to all changes in a hierarchy. A notification gets sent when any object in the hierarchy changes. Note that the subscription is for the immediate objects in the hierarchy, and won't cover any nested hierarchies.
The UNSUB
command cancels the subscription for the
specified objects.
The namespace rules defined by
the NAMESPACE
command are stored in a repository object, and take effect for all
cluster nodes. An application namespace rule file is an alternative
namespace specification mechanism that's easier to use with
installable application packages. It avoids the need to have an
installation script update the namespace rules stored in the object
repository.
This section describes the application namespace rule file, and defines the naming convention for application namespaces.
Application namespaces are named according to the application's domain name. For example, a distributed rebooter that comes with stasher might use the domain "distreboot.courier-mta.com". This does not have to be a real, existing hostname. As long as an organization or a group controls a domain name, the organization or a group can use that domain name to name its applications, without conflicting with other applications.
Applications should use "apps/domain
"
hierarchy as their root namespace, where domain
is the controlling organization or group's domain or a subdomain.
An application package installs a namespace file named
@localstatedir@/stasher/apps/
(actual directory location depends on stasher's configuration options)
that typically contains the following two commands:
domain
PATHpathname
ROOT apps/domain
This is equivalent to the following namespace configuration
(see the section called “NAMESPACE {command}*”):
“NAMESPACE RW ADD PATH pathname
HOST host
SETROOT apps/domain
”,
where “host
” is the host where
the application namespace rules file gets installed.
The net effect is that pathname
's read/write
namespace root gets set to apps/domain
.
The PATH
command must always be the first command
in the application namespace rule file. When a non-administrative
client connection gets established, all files in
@localstatedir@/stasher/apps
get searched
(except files whose names contain the characters # or ~, which are
presumed to be backup or lock files from various editors).
If the connecting client's PATH
is found, the
following commands specify the namespace that take effect for the
non-administrative connection.
If the connecting client's PATH
is not found, the
global object repository namespace rules get processed
(see the section called “NAMESPACE {command}*”).
Each line in an application namespace rule file gets parsed into whitespace-delimited words, which may be quoted using the double-quote character. The available commands are:
PATH
filename
All following commands in the file define the namespace rules
for connections from filename
.
PATH
may appear more than once in an application
namespace rule file.
ROOT
hierarchy
Equivalent to
“NAMESPACE RW ADD PATH path
HOST host
SETROOT hierarchy
”,
where host
is
path
's host.
ROROOT
hirearchy
Equivalent to
“NAMESPACE RO ADD PATH path
HOST host
SETROOT hierarchy
”,
where host
is
path
's host.
RW
alias
hierarchy
Equivalent to
“NAMESPACE RW ADD PATH path
HOST host
ADD alias
hierarchy
”,
where host
is
path
's host.
RO
alias
hierarchy
Equivalent to
“NAMESPACE RO ADD PATH path
HOST host
ADD alias
hierarchy
”,
where host
is
path
's host.
Note the application namespace rule files are known only to the node that's running on the same server. Presumably, the application that uses the distributed object repository gets installed on multiple repository nodes. The application package installs the same namespace rule file on each node, so every application installation, on different nodes, ends up connecting to the same namespace; but it's possible to install the same application in a different application directory, on one node, and adjust the application namespace rule file so that it sees the same object namespace as its peers on other nodes.