Network Values

The purpose of the Network Values service is to update all workstations of a multi-server application when a change to a Network Value variable has occurred. Network Value variables cannot be used in steady state.

If your client is isolated from the server, and changes have occurred to Network Value variables, the client's changes will be overwritten when a reconnection to the server has been made.

Network Value variables are declared within the NetworkValue class,

[(NETWORKVALUE)
    HistoricalLastTS     { UTC Timestamp of last historical data read    };
    NextDailyReportTS    { UTC timestamp of next daily report data read  };
]

and are updated whenever the value for these variables changes on a client or server workstation.

Network Value variables can store any value that you can Pack. (see note) Unlike Retained variables, Network Value variables recognize array element changes, and will update such changes as needed. It should be noted however that Network Value variables won't see changes within multidimensional arrays. Therefore, a subroutine called, "Update" can be called if you have changed a complex data structure like a multidimensional array. During startup, only the Network Value variables whose value changed since the last synchronization are obtained.

If using a multidimensional array with NetworkValues, use only dynamic arrays rather than static. You can store dictionaries, but you must use NetworkValues\Update to update them.

The values for Network Value variables are stored in a folder named, "NetworkValues" within your application's directory. The name and format of these files is identical to that of the Retained variables (see Retained Variables), however, the extension for NetworkValues files is ".NV", whereas the extension for the Retained variable files is ".VAL". Protected retained variable files have the extension ".VLX".

It is not recommended that you use the Network Values service for tag values, or other constantly changing values (e.g. mouse position). A better use for the Network Values service is for updates to other services.

Network Value Service Subroutines and Modules

In order to make use of the Network Values service, you must first start the service, and then call Register(). An example follows.

If \NetworkValues\Started Main;
[\NetworkValues\Register(Self, "MyModule");
   …
]

NetworkValues\Register

Register(Owner, InstanceName)

Where, Owner is the owner of the variables, and InstanceName is the name of the instance. InstanceName must consist of characters that are valid for file names.

The purpose of the Register module is to allow any module with class NetworkValue variables to retain these variables across instantiations of a module and to have values automatically propagated around the network. If two instances of the same module register with the same instance name, then each of these modules will be affected by the other's changes in values.

In the case of network values being used in a tag, the InstanceName should be the tag's name or Unique ID. If using the Unique ID, use code similar to the following:

\NetworkValues\Register(Self, Replace(\UniqueID, 0, StrLen(\UniqueID), "\", "+"));

Register is a subroutine. After returning, the owner's variables will be set to the current server's version of the values. The caller must wait for NetworkValues\Started to become true before calling the Register module.

NetworkValues\Update

Not required for most variables. Use only for values in multi-dimensional arrays, dictionaries, structures of structures or combinations of these. (See earlier notes.)

Update(Owner, VarName)

Where, Owner is the owner instance of the variables and VarName is the name of the variables, provided as a text string.

Network Values Service Scheme

The Network Values service is designed to transfer values for any module around the system, and retain those values between starts for the application and instantiations of the module. The scheme used by the Network Values service follows.

  1. DBSystem is created, containing Registered names concatenated with variable names, which are separated by a plus sign (+). The Registered names are also stored in the same DBSystem. Their value is the head of the list of Monitor modules. The values are saved in packed streams in files by the same name as the concatenated name. The retained registered names array also contains the version number for each value. The revision number is always incremented, and is a retained value.
  2. RPC Synchronization is done, and Started is set.
  3. The host module must wait for NetworkValues\Started.
  4. Register(Obj, Name) is a subroutine that launches Monitor. Register performs a ListVars on Obj to get all class variables that will be distributed through remote procedure calls. It then launches sufficient Monitor modules to handle the number of variables. It also sets current values of variables from DBSystem before returning.
  5. Monitor links itself onto a list wherein the registered name is the name of a variable in the RegisterNamesDB containing the object value of the head of the list. The list is self-repairing, and not ordered.
  6. Monitor watches for changes in simple values and 1 dimensional array of values for the variables and then checks if the current value is different from the DBSystem value. If different, an RPC message to the server is sent to set the new value.
  7. The server sends the SetValues message to all clients and itself.
  8. The persistent values are stored in a directory called NetworkValues. Each value has its own file. Each file is a member of a linked list whose head is NetworkHead, and is sorted by the Revision number. This enables the GetServerChanges to easily get the most recent values.
  9. SetValues sets the value in the DBSystem, writes the value to the corresponding file for the name, walks through the list of Monitor modules for the registered name, and sets the variable in each of the registering modules.
  10. If a registering module stops, the Monitor automatically stops since it has been called from the registering module.