PDA

View Full Version : Shared Database Nodes/Combat Tracker



Foen
August 12th, 2008, 07:21
This isn't specifically a Combat Tracker post, but it does apply to shared combat tracker development.

I have been working on a shared player facility (shared Notes pages, in fact) using databasenode.addHolder, and have come across a feature of that functionality which has an impact on how I test this stuff going forward.

The addHolder(name,ownerflag) method is supposed to allow you to assign a holder to a node, so the holder can read and receive events on the node, but if the ownerflag is set to false they won't be able to edit it.

It seems, however, that editing is still enabled (and the holder receives 'ownership' status) even if the flag is false, if they are the most recent client holder of the node.

So, the host always has edit access, clients usually don't, but the most recent client holder does.

While not particularly surprising on reflection (it is good to know a node wouldn't be orphaned), it means that any development testing on shared data nodes needs at least two client sessions plus the host to simulate the live environment.

This is essential development information, not least because it is difficult to run the host and two independent client sessions on the same machine: the client sessions share one cached view of the campaign, which causes data conflicts and is also a poor simulation of the live environment.

I have now reverted to host+one test client on one machine, and a second test client on a second machine. Of course, this means you need two licences to do such development work, and two connected PCs.

Just thought some of you might find it useful to know this.

Stuart

Foen
August 14th, 2008, 15:23
When working with a shared list (such as the Notes list) which isn't published by the host invoking a Share/Shareas command but uses addHolder, there are a number of issues to be aware of.

Shared Parent, Owned Child Nodes

To gain access to the onChildUpdate event when other players edit their entries, all clients must be holders of the parent (list) database node, and owners of their list entry nodes. As they don't own the parent node (only one owner is allowed at a time) they cannot create new nodes of their own, but must request the nodes from the host using Interface.requestNewClientWindow on some containing windowlist.

However, this returns asynchronously and does not pass a reference to the new node back to the caller. It also doesn't seem to allow the host to intervene in the creation process. This means it isn't useful if properties must be set on the new node at creation. The documentation says "If any further processing is required, other means to process the created window are required." :confused:

There seems to be no way around this from the client side, so a separate mechanism is needed to pass node-creation requests to the host that will allow the host to set the newly-formed node properties.

onChildUpdate

As a node holder, clients receive information on changes to the node made by other clients and the host. They do not, however, receive the initial node contents when they first log on. The amount of information passed when changes occur is very restricted (I guess it keeps bandwidth usage down), so that if only one sub-node changes (for example the text of a Note), only that change gets cascaded and not the whole node (so the name of the Note wouldn't be passed through). This means that shared items created during a session are visible to all clients, but not those which were created in a previous session.

As there is no way for a client to request a download of the existing database information, another mechanism is needed to allow this.

Sharable/ShareAs

The preceding issues can be largely avoided using the <sharable> and <shareas> tags for a window class, and I guess this is the most obvious way for something like a combat tracker. I have been looking for alternative mechanisms because the window class sharing functionality needs to be pushed from the host and needs to be re-shared when clients disconnect and reconnect. For shared Notes, the emphasis should be on client-side control and ownership, which is inconsistent with the window class sharing approach. Furthermore, the windows are intrusive when pushed onto client desktops, whereas the existing Notes list is only opened on client demand.

Solution One: Requesting New Nodes

The only mechanism I could implement for client-side requests for new database nodes, with server-side intervention in setting initial properties (like ownership), was to pass messages through the chat system using deliverMessage(cmd) and onReceiveMessage(cmd).

The cmd parameter is a specially-formatted chat message from the client which cannot be generated from normal operation, and the host intercepts them before they are processed by the chat window. If the command is 'request new database node', the host creates the node and sets the initial properties.

No return value is sent back, because the client is a holder of the parent node and is notified via onChildUpdate as soon as the new node is created.

Solution Two: Populating the Initial Node Data

As the system does not push existing node data to the clients when they connect, it only publishes incremental changes, it was necessary to build a re-share routine on the host. Although very basic, the re-sharing is achieved by iterating over the shared db structure (in this case the Notes list) and setting each value equal to itself: node.setValue(node.getValue()). Although no data is actually changed, the host sends the refreshed nodes to the clients.

For clients to instigate this re-sharing (soon after connecting), I used the chat-message mechanism to send a re-share request from clients to host. This only needs to be done once per client, per session, as subsequent changes are propogated automatically.

I hope this helps others using shared/common resources, as it isn't otherwise well documented.

Stuart