Skip to content

C API Node Functions

Jiri Hnidek edited this page Aug 26, 2014 · 5 revisions

Node Functions

Node commands are used to create and destroy nodes. These functions are used for sending and receiving data stored in nodes.

Basic Node Functions

When we want to create new nodes, then it is necessary to call following function:

 int32_t vrs_send_node_create(const uint8_t session_id,
      const int8_t prio,
      const uint16_t custom_type);

The session_id is the unique identifier of session, where we want to create new node. We can specify custom_type of the node. This can help us with implementation and subscribing to the content of the node. Nodes are unnamed, but developer can specify several types (e.g. #define OBJECT_NODE 35) of nodes to distinguish node types. The custom_type is used for this purpose.

Important Note: The function vrs_send_node_create() could be called with custom_type that is in range 32-65535. Lower values are reserved for special nodes created by Verse server (e.g. User Node, Avatar Node, etc.).

Previous function has corresponding registration of callback function. It means, that this function will be executed, when the client received node_create command.

 void vrs_register_receive_node_create((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint32_t parent_id,
      const uint16_t user_id,
      const uint16_t custom_type));

When we receive node_create command, then we know id assigned to the new node by the verse server. If parent_id is the same as avatar_id of our client, then we know, that our client is author of this node. When parent_id is different from avatar_id, then somebody else just created new node and parent we know parent of this node.

Important Note: Avatar node is temporary node created and owned by server. When the client is logged out from server or connection is broken, then server automatically destroy this node and all child nodes of this avatar node. When we want to keep our data on server, then it is important to link node to some other node in the scene branch.

When the node does not have any children node, then it is possible to destroy it with following function:

 int32_t vrs_send_node_destroy(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id);

Verse server ignores node_destroy commands for non-existing nodes and nodes with children nodes.

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_destroy((*func)(const uint8_t session_id,
      const uint32_t node_id));

When we want to subscribe to the node and receive information about the node, then it is necessary to call following function:

 int32_t vrs_send_node_subscribe(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint32_t version,
      const uint32_t crc32);

When server received node_subscribe command with valid id and the node includes some tag group, children nodes or data layers, then server sends create commands to the client. When some other tag group or whatever is created or delete in this group, then server will send appropriate command to the subscribed client.

When client wants to subscribe to some version of data, because it has local copy of this version at local disk, then it can send command node_subscribe with version and corresponding checksum (crc32) . When server receives this command and version match with crc32, then server will node_subscribe command with version and crc32. When client acknowledge receiving node_subscribe command, then server sends only 'diff' create or destroy commands.

When client doesn't have any local version of data, then it has to subscribe to version = 0.

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_subscribe((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint32_t version,
      const uint32_t crc32));

Note: Computing of crc32 will be described in Verse specification.

When client is not interested in this node anymore, then it can unsubscribe from the node with following function:

 uint32_t vrs_send_node_unsubscribe(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint32_t version);

When this node has child nodes, then client is automatically unsubscribed from these child nodes too. When client sends command node_unsubscribe with version = -1, then it requests versing from Verse server. When it sends version = 0, then versing is not requested.

Note: When previous function is called, then Verse library guarantee that corresponding command is called, when all commands related to the node are already sent.

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_unsubscribe((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint32_t version,
      const uint32_t crc32));

When server receives node_unsubscribe command, then it stop sending any commands related to the client. When sending history (of this client) does not contain any commands related to this node, then server creates new version number, saves data to the disk, compute crc32 and sends node_unsubscribe to the client.

Important note: The client must not send any command related to the node between calling node_unsubscribe and receiving node_unsubscribe (callback function of node_unsubscribe is called). Otherwise the versing will be broken and Verse server will cancel versing. Server will send node_unsubscribe with version = 0 to the client in this case.

Priority of Nodes

When Verse server or Verse client call some vrs_send_ command, then appropriate command is added to the sending queues. When sending thread pops commands from queues, then modified Weighted Fair Queueing algorithm is used for scheduling of commands. There is 256 queues. Each command is added to the queue according its priority. It means, that node with priority equal to the 120 is added to the queue 120. Some priorities are reserved for special commands.

When client wants to change priority of node, then it has to call following function.

 int32_t vrs_send_node_priority(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint8_t priority);

It sends appropriate command to the server, where priority is changed.

Links between Nodes

When client wants to change parent of the node with ID equal to the child_node_id, then it has to send following command to the server, where parent_node_id is the ID of the new parent

 int32_t vrs_send_link_set(const uint8_t session_id,
      const int8_t prio,
      const uint32_t parent_node_id,
      const uint32_t child_node_id);

When server is able to change parent of the node (client has permission for it, new parent node still exists), then server sends the same command back to the client and all clients, that know about this child node. When server is not able to change parent of this child node, then server sends back to the client link_set command with old parent node.

When client wants to be informed about changes of links between nodes, then it has to register following callback function:

 void vrs_register_receive_link_set((*func)(const uint8_t session_id,
      const uint32_t parent_node_id,
      const uint32_t child_node_id));

Access Permissions

An access permissions are evaluated at nodes. User of node can do all operations (send and receive node commands). It is possible to grant access permissions to all user or for each user with following command

 int32_t vrs_send_node_perm(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint16_t user_id,
      const uint8_t perm);

If user_id is equal to the 0xFFFF, then permissions are granted to all other users. Two permissions could be granted (receive node commands and send node commands)

  • no permissions: 00000000
  • receive node commands permission: 00000001
  • send node commands permission: 00000010
  • receive and send node commands permission: 00000011

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_perm((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint16_t user_id,
      const uint8_t perm));

When owner of the node wants to pass property of the node to other user, then verse client has to call following function:

 int32_t vrs_send_node_owner(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint16_t user_id);

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_owner((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint16_t user_id));

Locks

This function could be used for locking the node. Client has to have write permission for the node. Important note: the locking is atomic operation. Two ore more clients can not lock one node at once. When node_lock command is received, then check, what avatar is locker of the node.

 int32_t vrs_send_node_lock(const uint8_t session_id,
      const int8_t prio,
      const uint32_t node_id)

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_lock((*func)(const uint8_t session_id,
      const uint32_t node_id,
      const uint32_t avatar_id))

When client doesn't need to have the node locked, then the node could be unlocked with following function.

 int32_t vrs_send_node_unlock(const uint32_t session_id,
      const int8_t prio,
      const uint32_t node_id,
      const uint32_t version)

When client request versing after unlocking, then it has to send command node_unlock with version = -1.

Previous function has corresponding registration of callback function:

 void vrs_register_receive_node_unlock((*func)(const uint32_t session_id,
      const uint32_t node_id,
      const uint32_t avatar_id,
      const uint32_t version,
      const uint32_t crc32))
Clone this wiki locally