Name

stasher — Interactive object repository client

Synopsis

stasher [ --connect=directory | --admin=directory ] [--alarm=seconds] [command]

Description

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.

Starting and connecting to an object repository server

The following commands connect to an object repository server that's already running, or start a server process.

CONNECT [directory]

The CONNECT command makes a regular, non-administrative connection to an object repository server running in a directory. 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 /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 directory parameter is required.

$ 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.

ADMIN [directory]

The ADMIN command makes an administrative connection to an object repository server running in a directory. 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 /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 directory parameter is required.

START {directory}

The START command starts a child process that runs an object repository server in the directory, 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.

DISCONNECT

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.

Administrative commands

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.

GETPROPS

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.

SETPROP {name} {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.

RESETPROP {name}

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.

SETLIMITS {maxobjects} {maxobjectsize}

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 nMb, 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).

STATUS

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.

STOP

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.

RESIGN

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

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.

EDITCLUSTER [FORCE] [NEW] [command]*

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 [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:

ADDNODE {name}

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.

DELNODE {name}

Removes the specified node from the list of nodes in the object repository.

UPDATE {name}

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.

SET {name[=value]}

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.

UNSET {name}

Any existing settings with this name are removed.

ADD {name=value}

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.

REORDER name (BEFORE|AFTER) anchor

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 and ENCRYPTION 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.

SAVECLUSTER [FORCE]?

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.

NAMESPACE {command}*

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.

NAMESPACE (RW|RO) [command]*

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.

NAMESPACE (RW|RO) ADD [selector]* [rule]*

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:

USER {username}

The following rules apply only to connections from a process running with the given effective username.

GROUP {groupname}

The following rules apply only to connections from a process running with the given effective groupname.

PATH {pathname}

The following rules apply only to connections from a process running the given binary executable. pathname must be an absolute pathname.

HOST {node}

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 {hierarchy} {path}

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.

SETROOT {hierarchy}

Set the connection's namespace root to this hierarchy within the object repository's namespace.

UNADD {hierarchy}

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.

UNSETROOT

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.

SETLABEL {label}

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.

NAMESPACE (RW|RO) MODIFY [selector]* [rule]*

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:

UNSETLABEL

Remove the existing label from the selected rules. Alternatively, specifying another LABEL rule replaces the existing label; this would be essentially a rename operation.

DELSETROOT

Remove any SETROOT or UNSETROOT from the selected rules. Alternatively, specifying another SETROOT UNSETROOT replaces the existing one in the selected rule.

DELADD {hierarchy}

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 ADDs and UNADDs, and DELSETROOT any SETROOT or UNSETROOT.

Write access to etc considered harmful

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.

NAMESPACE (RW|RO) MOVE [selector]* (BEFORE | AFTER) [selector]*

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.

Regular commands

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.

PUT ( (DEL name:uuid | NEW name | UPD name:uuid) (VALUE literal | FILE filename) )+

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.

NEW name

Adds a new object to the repository. The PUT command fails if the object already exists.

DEL name:uuid

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.

UPD name:uuid

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 UPDated objects may be specified in two ways, immediately after the NEW or the UPDate 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.

DIR [hierarchy]

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.

UIDS {object}+

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 {hierarchy}*

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.

GET {object}+

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.

SAVE ({object} {filename})+

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.

SUB {object}+

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.

UNSUB {object}+

The UNSUB command cancels the subscription for the specified objects.

Application namespace rules

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/domain (actual directory location depends on stasher's configuration options) that typically contains the following two commands:

PATH pathname
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.