Repository node serialization

From HEWIKI
Jump to: navigation, search

Contents

Note: Node serialization to the repository is only one way to transfer data chunks to the client. Another is to use the freeform text storage, described at Repository Data Storage.

Overview

Repository Node Serialization is the process of taking a node and storing it in a file in the repository. The Repository can be accessed by both clients and servers. The nodes that have been stored into the repository can then be loaded later and used as needed.

The intended use for this system is to allow for the transmission of data to the client along a different path. By using the Repository as a cache for the data, the server does not need to retransmit chunks of data to each client that logs in. It is also vaguely possible that this might be useful in transmitting data between servers.

What problem(s) does this solve?

What problem(s) does this not solve?

Concepts

Accessing data stored in the Repository is an asynchronous operation

Accessing the repository is always an asynchronous operation, which upon completion will call a specifically named function to a script passed in as a part of the request. The response will contain a requestID tag that may be used to match request with response as well as any information retrieved.

Only persisted nodes should be saved to the Repository

While it is possible to save a non-persisted node, we strongly recommend only persisted nodes should be saved to the repository using this functionality. The reason for this recommendation is that the node must still exist in order for you to make subsequent changes to the data.

If you use a non-persisted node which is subsequently lost because the area shuts down, you will never be able to change the data that you stored.

Not a replacement for prototypes for data shared by servers

While you could use this system to store data that you want to share between servers, Prototypes already support that functionality and are significantly easier to use. Prototypes also load on demand and will eventually be subject to garbage collection to unload them from memory in area servers that have not needed them for a period of time.

Not a replacement for the Spec System

The Spec System uses the related functionality of storing an arbitrary string to a repository file to leverage the bandwidth friendly nature of storage in the repository, but beyond that is a much more robust technology with loads of additional functionality that make it ideal for storing game data that is shared between servers and/or the client.

Class/Field definitions must be identical between source and destination DOMs

It is important that the definitions used for the node be identically defined in the source and destination DOMs, this can ONLY be done using World Publish to copy the definitions between the server(source) and client(destination). It is not possible to create identical DOM definitions using the DOM Editor because each has its own unique ID when created that way.

If the definitions are not in sync, because they have been edited by one of the GOMs, the node will fail to load properly.

Usage

Create a persisted server node

All nodes that are saved will need to be created initially on the server. This will establish a valid unique ID for each node, which is used when loading or saving the data for the node from/to the repository.

var n = CreatePersistedNodeFromClass( <className> )

or via the CLI

\cnfc <className>; +persistent

While it is technically possible to save a non-persistent node from the server, it would only be able to be updated by the client. If the node saved to the repository is persistent, then the area that owns the node can update it in the repository at any time.

Save a node to the Repository

Serialization of a node to the repository is accomplished through one of two external functions based on the location (server or client) in which the operation is to take place. Once a node is serialized to a file in the repository, it may subsequently be loaded by servers or clients as needed.

On the Server

Saving a node to the repository is accomplished through the use of the external function SaveNodeToRepository().


As with the other external functions working with nodes saved to the repository this is an asynchronous operation. The external function returns a requestID so that your script systems can match request with the later response.


external function SaveNodeToRepository(nodeToSave as NodeRef, callbackScript as ScriptRef) as ID


Which performs a callback to the specified callback script at the function:


function RepositoryNodeSaved(nodeSaved as ID, requestTag as ID, success as Boolean)


Sample code

// Assume for this example that we have created a systemNode $SAVEHANDLER 
//   to handle our save requests and the following code is located in the saveHandlerClassMethods script
//
//   field requestIDToSystemNameMap as lookuplist indexed by id of string
 
method saveNodeToRepositoryForSystem( nodeToSave as noderef, SystemName as string )
  requestID as id = SaveNodeToRepository( nodeToSave, SYSTEM.EXEC.THISSCRIPT )
 
  // Store the requestID in a lookuplist as the key to name of the system that requested the save
  me.requestIDToSystemNameMap[requestID] = systemName
.
 
// Handle the response
function RepositoryNodeSaved(nodeSaved as ID, requestTag as ID, success as Boolean)
  if success
    println( "Successfully saved the node(" + nodeSaved + ") for the system(" + $SAVEHANDLER.requestIDToSystemNameMap[requestID] + ")" )
  else
    println( "ERROR: Was not able to save the node(" + nodeSaved + ") for the system(" + $SAVEHANDLER.requestIDToSystemNameMap[requestID] + ")" )
  .
.

On the client

This functionality is restricted by the Permissions system, and generally restricted to your development teams.

Saving a node to the repository from the client uses the external function UploadNodeToRepository(). Unlike the other functions no callback is currently made to report success or failure.


external function UploadNodeToRepository(nodeToUpload as NodeRef, callbackScript as ScriptRef) as ID


This functionality would typically be used to upload changes made by a developer on the client using some GUI to the repository directly rather than having to request the area server perform the save operation.

Sample code

// While a callback script is passed in and a requestID returned, no callback is currently made
var requestID = UploadNodeToRepository(nodeToUpload, SYSTEM.EXEC.THISSCRIPT)

Load a node from the Repository

On the Server

Loading a copy of a node from the repository on the server uses the external function LoadNodeCopyFromRepository(). Due to the possibility that the source node may already be loaded into a GOM a non-persistent copy of the node is created with a new unique ID.

As with the other external functions working nodes saved to the repository this is an asynchronous operation. The external function returns a requestID so that your script systems can match request with the later response.


external function LoadNodeCopyFromRepository(nodeToLoad as ID, callbackScript as ScriptRef) as ID


Which upon completion of the operation will perform a callback to the specified script in the function:


function RepositoryNodeCopyLoaded(sourceNode as ID, nodeCopy as NodeRef, requestTag as ID, success as Boolean )


Sample code

// Assume you have created a systemNode $LOADHANDLER to handle loading nodes from the repository
//   and the following code is located in the loadHandlerClassMethods script
//  
//   field requestIDToSystemNameMap as lookuplist indexed by id of string
 
method LoadNodeFromRepositoryForSystem( nodeID as id, systemName as string )
  var requestID = LoadNodeCopyFromRepository( nodeID, SYSTEM.EXEC.THISSCRIPT )
 
  //  Store a mapping between requestID and the system that requested the node 
  me.requestIDToSystemNameMap[requestID] = systemName
.
 
// Handle the response
function RepositoryNodeCopyLoaded(sourceNodeID as ID, nodeCopy as NodeRef, requestTag as ID, success as Boolean)
  if success
    println("Successfully loaded a copy(" + nodeCopy + ") for the source(" + sourceNodeID + ") for the system(" + $LOADHANDLER.requestIDToSystemNameMap[requestID] + ")" )
  else
    println("ERROR unable to load a copy of the source(" + sourceNodeID + ") from the repository for the system(" + $LOADHANDLER.requestIDToSystemNameMap[requestID] + ")" )
  .
.

On the Client

Loading a copy of a node from the repository on the client uses the external function DownloadNodeFromRepository(). As a copy of the server node, the client's node will have the same ID as the server node's id.

As with the other external functions working nodes saved to the repository this is an asynchronous operation. The external function returns a requestID so that your script systems can match request with the later response.


external function DownloadNodeFromRepository(nodeToLoad as ID, callbackScript as ScriptRef) as ID


Which upon completion of the operation will perform a callback to the specified script in the function:


function RepositoryNodeDownloaded(downloadedNodeID as ID, requestTag as ID, success as Boolean) as Boolean


This download callback differs from the others in that it requires the script to return a Boolean indicating whether or not it wishes notification of future updates. A return value of true signifies that should the file containing the node is updated in the Repository, the new values should be loaded and the node in memory replaced with those values. The callback function will then be called again after the replacement. If false is returned, then nothing special will happen on the client if the Repository file is updated.

Sample code

// Assume you have created a systemNode $LOADHANDLER to handle loading nodes from the repository
//   and the following code is located in the loadHandlerClassMethods script
//  
//   field requestIDToSystemNameMap as lookuplist indexed by id of string
 
method DownloadNodeFromRepositoryForSystem( nodeID as id, systemName as string )
  var requestID = DownloadNodeFromRepository( nodeID, SYSTEM.EXEC.THISSCRIPT )
 
  // store a mapping of requestID to the system that requested the node
  me.requestIDToSystemNameMap[requestID] = systemName
.
 
 
// Handle the Response
function RepositoryNodeDownloaded(downloadedNodeID as ID, requestTag as ID, success as Boolean) as Boolean
  if success
    println( "Successfully Downloaded node(" + downloadedNodeID + ") for system(" +  $LOADHANDLER.requestIDToSystemNameMap[requestID] + ")" )
  else
    println( "ERROR: Unable to download the node(" + downloadedNodeID + ") for the system(" + $LOADHANDLER.requestIDToSystemNameMap[requestID] + ")" )
 
 
    // returning false to indicate we do not want to receive additional callbacks
    return false
  .
 
 
  // returning true to indicate that this script should get another callback should the
  //   repository detect that the file has been updated.
  return true
.

More information

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox