diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 20:52:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 20:52:35 +0000 |
| commit | 46439007cf417cbd9ac8049bb4122c890097a0fa (patch) | |
| tree | 6fdb25e5f3a2b6d5657eb23b35774b631d4d97e4 /man/2/spree | |
| parent | 37da2899f40661e3e9631e497da8dc59b971cbd0 (diff) | |
20060303-partial
Diffstat (limited to 'man/2/spree')
| -rw-r--r-- | man/2/spree | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/man/2/spree b/man/2/spree new file mode 100644 index 00000000..1cd517b3 --- /dev/null +++ b/man/2/spree @@ -0,0 +1,604 @@ +.TH SPREE 2 +.SH NAME +Spree \- distributed interactive sessions. +.SH SYNOPSIS +.EX +.ps -1 +.vs -1 +include "sys.m"; +include "draw.m"; +include "sets.m"; +include "spree.m"; +spree := load Spree Spree->PATH; +Range, Object, Clique, Member: import spree; +Set: import Sets; +Archive: import Archives; + +Range: adt { + start: int; + end: int; +}; + +Object: adt { + transfer: fn(o: self ref Object, + r: Range, dst: ref Object, i: int); + setvisibility: fn(o: self ref Object, + visibility: Set); + setattrvisibility: fn(o: self ref Object, + name: string, visibility: Set); + setattr: fn(o: self ref Object, + name: string, val: string, vis: Set); + getattr: fn(o: self ref Object, name: string): string; + delete: fn(o: self ref Object); + deletechildren: fn(o: self ref Object, r: Range); + + id: int; + parentid: int; + children: array of ref Object; + objtype: string; + visibility: Set; + # ...private data +}; + +Clique: adt { + new: fn(parent: self ref Clique, archive: ref Archive, + owner: string): (int, string, string); + newobject: fn(clique: self ref Clique, parent: ref Object, + visibility: int, objtype: string): ref Object; + action: fn(clique: self ref Clique, cmd: string, + objs: list of int, rest: string, whoto: int); + member: fn(clique: self ref Clique, id: int): ref Member; + start: fn(clique: self ref Clique); + breakmsg: fn(clique: self ref Clique, whoto: Sets->Set); + members: fn(clique: self ref Clique): list of ref Member; + owner: fn(clique: self ref Clique): string; + hangup: fn(clique: self ref Clique); + notify: fn(clique: self ref Clique, cliqueid: int, msg: string); + + objects: array of ref Object; + cliqueid: int; + # ...private data +}; + +Member: adt { + obj: fn(m: self ref Member, id: int): ref Object; + del: fn(m: self ref Member, suspend: int); + + id: int; + name: string; + # ...private data +}; + +Engine: module { + init: fn(srvmod: Spree, clique: ref Clique, argv: list of string): string; + command: fn(member: ref Member, e: string): string; + join: fn(member: ref Member , e: string, suspended: int): string; + leave: fn(member: ref Member): int; + notify: fn(fromid: int, s: string); + readfile: fn(f: int, offset: big, count: int): array of byte; +}; + +Archives: module { + Archive: adt { + argv: list of string; # how to restart the session. + members: array of string; # members involved. + info: list of (string, string); # any other information. + objects: array of ref Object; + }; + init: fn(mod: Spree); + write: fn(clique: ref Clique, info: list of (string, string), file: string, members: Set): string; + read: fn(file: string): (ref Archive, string); + readheader: fn(file: string): (ref Archive, string); +}; + +rand: fn(n: int): int; +.ps +1 +.vs +1 +.EE +.SH DESCRIPTION +.I Spree +provides a general server interface that allows sets of distributed +clients, +.IR cliques , +to interact in a controlled manner, with the +interaction mediated +by Limbo modules, known as +.IR engines . +Each engine decides on the rules +of its particular clique; the engine interface is described +at the end of this manual page, under +``Module Interface''. +.PP +This manual page describes the +interface as presented to an engine +once it has been loaded by +.IR spree . +A loaded instance of an engine is responsible for a particular +.IR clique , +in which one or more +.I members +participate. Messages sent by members +are interpreted by the engine, which +responds by making changes to the hierarchical +.I object +database held by the clique. +Behind the scenes +.I spree +distributes updates to this database to members +of the clique as appropriate (see +.IR spree (4) +for details). +.SS "Objects and visibility" +Objects hold a clique's visible state. An object +has a unique integer +.IR id , +which is an index into the array +.IB clique .objects\fR;\fP +it also holds a set of attribute-value pairs, a type, and +zero or more child objects. Together, all the objects +in the clique form a hierarchical tree, rooted at +the +.IR "root object" +(id 0), which always exists. +Each attribute and each object also has an associated +.IR "visibility set" , +the set of member that sees updates to the attributes or the children +of the object. Each member has a unique id; +in a visibility set (see +.IR sets (2)), +a member is ``visible'' if the set contains the member's id. +.PP +Note that the visibility set of an object does not alter the visibility +of that object's attributes, but only that of its children (and of +their children: in general an object is visible to a member if the +intersection of all its ancestors' visibility sets contains that +member). +.PP +Objects can be transferred inside the hierarchy from one parent to +another. If an object is moved to a parent whose visibility conceals it +from a member, then it will appear to that member to have been deleted; +if it is later made visible, then it will be recreated for that +member. +A clique engine can almost always ignore this technicality, +except for one thing: the identifier used by a particular member to +identify an object is not necessarily the same as that used by the clique +engine. Thus when an engine receives an object id in a member's +message, it should convert it using the +.IB member .obj() +function. +.SS \fBClique\fP +The +.B Clique +type holds all the objects in a clique. It allows the +creation of new objects, and provides a way of communicating +with members directly. +All data members of a +.B Clique +should be treated as read-only. +.TP 10 +.IB clique .objects +This array holds the objects in the clique. An object with +identifier +.I id +is found at +.IB clique .objects[ id ]\fR.\fP +.TP +.IB clique .new(\fIarchive\fP, \fIowner\fP) +.B New +creates a new clique. +.I Archive +is an archive of the game to be created; +.IB archive \.argv +should be non-nil; its first element should name +the engine to be loaded (as a path relative to the +engine module directory, and without the +.B .dis +extension). +.TP +.IB clique .newobject(\fIparent\fP,\ \fIvisibility\fP,\ \fIobjtype\fP) +.B Newobject +creates a new object at the end +of +.IR parent 's +children; +If +.I parent +is nil, the new object is created under the root object. +The new object has visibility +.IR visibility , +and type +.IR objtype . +An object's type cannot be changed once +it has been created. +.TP +.IB clique .action(\fIcmd\fP,\ \fIobjs\fP,\ \fIrest\fP,\ \fIwhoto\fP) +.B Action +sends a message to some members without affecting +the object hierarchy. It can be used to send transient +events that have no meaning when stored statically +(for example, network latency probes). +The message is sent to the set of members given by +.IR whoto . +.I Objs +is assumed to be a list of object ids, which are +converted appropriately for each member +receiving the message; the final +message is a string built by concatenating +.IR cmd , +the list of object ids, and +.IR rest , +separated by spaces. +.TP +.IB clique .breakmsg(\fIwhoto\fP) +Messages are usually sent to clients in an uninterrupted +stream (as documented in +.IR spree (4)), +with a single read returning a potentially large +set of messages. +.B Breakmsg +arranges that subsequent messages received by the members specified in +.I whoto +will see not be merged with messages sent prior to the call to +.BR breakmsg . +This is used to enable a new client module to be started +without needing to pass it data received in the previous read. +.TP +.IB clique .member(\fIid\fP) +.B Member +yields the member corresponding to identifier +.IR id , +or +.B nil +if there is none. +.TP +.IB clique .membernamed(\fIname\fP) +.B Membernamed +searches for a member of +.I clique +named +.I name +and returns it if it finds it, otherwise +.BR nil . +.TP +.IB clique .members() +.B Members +returns a list of all the members of +.IR clique , +including those that have been suspended. +.TP +.IB clique .owner() +.B Owner +returns the name of the owner of the clique; +i.e. the user that created it. +.TP +.IB clique .hangup() +.B Hangup +terminates a game and informs all the +players of that fact. +.TP +.IB clique .notify(\fIcliqueid\fP, \fImsg\fP) +.B Notify +sends an informational message to another clique. +The clique so referenced must be either the parent +or a child of +.IR clique . +The message is not sent synchronously, +and care should be taken not to send messages that +can cause an indefinite recursion. +.SS Member +The +.B Member +type represents a member of a clique. +.TP 10 +.IB member .id +The member's identifier is an integer unique across all current members +of the clique, +but ids of members that have left the clique will +be reused. +There may not be two members of the same name in the +same clique. +.TP +.IB member .name +.B Name +holds the authenticated name of the member. +This is necessarily unique over the members +of a clique. +.TP +.IB member .obj(\fIid\fP) +.B Obj +converts from a member's external object +identifier to the clique's local +.B Object +that it represents. It returns +.B nil +if there is no such object. +.TP +.IB member .del(\fIsuspend\fP) +.B Del +deletes +.I member +from the clique; +no more requests from +.I member +will be received by the clique engine. +If +.I suspend +is non-zero, if a member of the same name joins again +it will be allocated the same object id, allowing a member +to leave and join again without losing state. +.SS \fBObject\fP +The +.B Object +type is the basic unit of clique engine state. +An object's children can be selectively concealed +from members; it holds a set of +.RI ( attribute ,\ value ) +pairs, each of which can be concealed likewise. +Where an argument +.IR r , +of +.B Range +type is used, it refers to a range of an object's +children starting at index +.IB r .start\fR,\fP +and finishing at +.IB r .end-1\fR.\fP +All the data members of an +.B Object +should be treated as read-only. +.TP 10 +.IB obj .setattr(\fIname\fP,\ \fIval\fP,\ \fIvis\fP) +.B Setattr +sets attribute +.I name +in +.I obj +to +.IR val. +If the attribute is being created for the +first time, then it will be given visibility +.IR vis . +.I Name +should be non-empty, and should not +contain any space characters. +Note that it is not possible for an attribute +to refer directly to an object by its identifier; +if this facility is needed, another identifying +scheme should be used. This also applies +to member identifiers, which will change +if the clique is saved and loaded again. +.TP +.IB obj .getattr(\fIname\fP) +.B Getattr +yields the current value of the +attribute +.I name +in +.IR obj . +If an attribute is not set, it yields +.BR nil . +.TP +.IB obj .delete() +.B Delete +removes +.I obj +from the object +hierarchy. +.TP +.IB obj .deletechildren(\fIr\fP) +.B Deletechildren +deletes children in range +.I r +from +.IR obj . +.TP +.IB obj .transfer(\fIr\fP,\ \fIdst\fP,\ \fIi\fP) +.B Transfer +transfers the children in range +.I r +from +.I obj +to just before the object at index +.I i +in +.IR dst . +It is permissible for +.I obj +and +.I dst +to be the same object. +.TP +.IB obj .setvisibility(\fIvisibility\fP) +.B Setvisibility +allows the set of members +given in +.I visibility +to see the children of +.IR obj , +and denies access to all others. +Members are notified of the change. +.TP +.IB obj .setattrvisibility(\fIname\fP,\ \fIvisibility\fP) +.B Setattrvisibility +allows the set of members +given in +.I visibility +to see the value of +.IR obj 's +attribute +.IR name , +and denies access to all others. +Members are not notified of the change; +if there is a need to communicate +the fact of an attribute becoming invisible to +members, it should be done by using another +(visible) attribute to communicate the change. +.SS "Archives" +The +.B Archives +module provides a means of committing a clique +to permanent storage and retrieving it later. +It should first be initialised by calling +.BR init , +passing the +.B Spree +module in +.IR mod . +.B Write +writes +.I clique +to the file +.IR file . +.I Info +gives a set of attributes and values associated with the clique; +.I members +gives the set of clique members for which visibility information +will be archived; visibility information for other members is forgotten. +.PP +.B Read +opens +.I file +and returns it as an +.B Archive +adt, say +.IR a . +.IB A .argv +holds the command line arguments to the clique module +(including the name of the module, its first element); +.IB a .members +gives the names of all archived members - the id +of an archived member is given by its index in the array; +.IB a .info +gives the list of attributes an values as stored by +.BR write ; +.IB a .objects +holds the clique objects. +.B Readheader +is just like +.B read +except that it parses the header only, so will return an +.B Archive +adt such that +.IB a .objects +is nil. +.SS "Module Interface" +An engine module, +.IR mod , +must implement the +following functions. Where a function returns a string, +it is interpreted as an error response to the member +responsible for the request; an empty string signifies +no error. +.TP +.IB mod ->init(\fIsrvmod\fP, \fIclique\fP, \fIargv\fP) +.B Init +initialises the clique engine. +.I Clique +is the clique that the engine is controlling, +and +.I srvmod +is the +.B Spree +module holding its associated data. +An error response from this function +causes the clique to be aborted. +.I Argv +gives a list of arguments to the engine, starting +with its module name. +.TP +.IB mod ->join(\fImember\fP, \fIe\fP, \fIsuspended\fP) +.I Member +has made a request to join the clique; +an error response causes the request to be +refused, otherwise the member joins the +clique. +.I E +is a message from the client about how it would like to +join the clique (e.g. +.BR join , +.BR watch , +etc). +.I Suspended +is non-zero if the member was previously suspended from the clique. +.TP +.IB mod ->leave(\fImember\fP) +.I Member +has left the clique. +If +.B leave +returns zero, the member will not be deleted from the +clique, but merely suspended until they should join again. +.TP +.IB mod ->command(\fImember\fP,\ \fIe\fP) +.I Member +has sent the command +.IR e . +The command usually follows +the simple message conventions +used in +.IR spree (4), +i.e. simple space-separated tokens. +.TP +.IB mod ->notify(\fIcliqueid\fP, \fIs\fP) +A notification, +.IR s , +has been posted to +the current clique +by the clique identified by +.IR cliqueid . +The posting clique is either a parent or a child of the current clique. +.TP +.IB mod . +.SH EXAMPLE +The following is a small, but working example +of a clique engine that acts as a chat server +(parsing error checking omitted, and white-space +compressed to save paper): +.PP +.EX +.ps -1 +.vs -1 +implement Cliquemodule; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "../spree.m"; + spree: Spree; + Clique, Member: import spree; +clique: ref Clique; +clienttype(): string +{ + return "chat"; +} +init(g: ref Clique, srvmod: Spree): string +{ + (sys, clique, spree) = (load Sys Sys->PATH, g, srvmod); + return nil; +} +join(nil: ref Member): string +{ + return nil; +} +leave(nil: ref Member) +{ +} +command(member: ref Member, cmd: string): string +{ + clique.action("say " + string member.id + " " + cmd, nil, nil, ~0); + return nil; +} +.ps +1 +.vs +1 +.EE +.SH SOURCE +.B /appl/cmd/cliques/spree.b +.SH "SEE ALSO" +.IR spree (4), +.IR spree-objstore (2), +.IR spree-cardlib (2), +.IR spree-allow (2), +.SH BUGS +The reuse of object ids can lead to +problems when objects are deleted and +recreated on the server before clients become +aware of the changes. |
