About data storage
All the protocols have their own data storage that is identified by the ProtocolSession. When a ListenSession is created a new data storage will be created for every protocol active in this ListenSession. This data storage is initiated empty, or with data passed through during the binding request. If the protocol requires data that doesn't exist in the ListenSession storage, but does exist in the ProtocolSession storage, it will return the data from the ProtocolSession. The same rules applies for the ClientSession, except this will return data from the ListenSession in favor of the ProtocolSession. Data storage exist out of two different kinds of storages.
Storage indexed by string the data saved is identified by an utf-8 string (called name). A hash is created out this name and is placed in a list. This hash identifies yet another list. This is a list with the names that have the same hash. Every name points to a different data pointer with the saved data.
The way the list will look in memory:
Storage indexed by integer the data saved is identified by an integer. This integer is 32 bits long in x86 and 64 bits long in x64. This integer is placed in a list and points to a pointer that holds the saved data.
The data storage is made multithreading and multi-core safe by internally locking the list for write access or fully lock the list to be used by one thread only.
Control panel options
When the requested data does not exist in the client-, listen- and protocolsession, it will look for default data set by the SetControlPanelOptions function. All data will exactly be returned the way it was passed in the UserValueOption structure, with the MultiColumn list as exception. When you request a ControlPaneloption that is set as type MultiColumn list, the GetPluginData function will return a pointer to a list. This list can be edited with the functions CountListRows, GetListItem, GetListItemSize, RemoveListRow and SetListItem. These functions will edit the list in memory, however, these will not save the list on disk. To save the edited list on disk (and make it possible to restore on a reboot) you need to call SavePluginData with the pointer to the list passed in the data parameter (a pointer that points to a data location with the pointer to the list).
Protocol Data structure
The ListenSession and Clientsession both have a member named data, this is a pointer to a list of ProtocolData structures. All the protocols, binded in the Listen- and ClientSession, have their own memory space in this member, this space is identified by the psess member. The size of this memory space is set during the initialization of the protocol by member extraSize from SetProtocolInformation function. This data is always accessible and is meant to be for quick access, like storage for pointers or handles. The difference between the data storage described above is that this memory is always read- and writeable, you don't have to request a copy since you have direct access to the memory. It is possible, but not a required, to find the ProtocolData structure that belongs to a protocol by using the FindProtocolDataStruct function. The data member is copied from the Listensession to the Clientsession on creation and it is therefor possible to initiate recourses when the ListenSession is being binded, save them in the ProtocolData structure and use them from the ClientSession.
When the server reboots it will try to recover the ListenSessions that where active before the reboot. The data member from the ListenSession will not be restored and will be initialized with zero bytes. The ClientSessions will not be recoverd since it is impossible to recover a connection initiated by a client. All data saved by the SavePluginData function will be saved on disk (except if flag GDPD_MEMORY_ONLY is set or if the data is saved in the ClientSession's data storage). The data saved in the ProtocolSession data storage will be restored at the moment the protocol calls the function AcceptProtocol during the initialization. The data saved in the ListenSession data storage will be recovered before the protocols are requested to start binding.
On Windows, the data saved on disk is not saved in a file, but in the Registry. The registry key where all data is saved is: HKEY_LOCAL_MACHINE\SOFTWARE\TV's software\TV's server v3 (x86 and x64) or HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\TV's software\TV's server v3 (if you run the x86 version on a x64 system). On Linux, the data is saved in the directory /etc/tvs-server-x64 or /etc/tvs-server-x86. The same data structure is used as described below, but keys are directories and values are files. This key or directory can be changed using the -r switch. This key has the following sub-keys:
BlockedProtocols This sub-key contains names of protocols that are blocked (not allowed to initiate), this is done by function CloseProtocolSession. The name of the value is set to the modulename and the protocolname in format modulename + ":" + protocolname and the value is set to the protocol name;
Modules This sub-key contains plug-ins that need to be loaded at startup. The name of the value is not important, the value should be set to the path of a DLL-file;
Protocols This sub-key contains data set in the protocol data storage. There are sub-keys with name protocolname. Theses sub-keys can contain the sub-key 'listById', which contains the data set in the storage indexed by integer and sub-key 'listByString', which contains the data set in the storage indexed by string. The data will be saved as value represented as type binary, with multi column list as exception. The name of this list will be another sub-key. This sub-key contains one value, named ItemsPerRow containing the amount of items per row and has some sub-keys. Every sub-key has a number as name and represents one row. Every row has ItemsPerRow Every row has ItemsPerRow amount of values, named by a number starting at one, each representing one item in the row;
ListenSessions This sub-key contains data set in the listensession data storage. There are sub-keys with a number as name, these numbers are unique and assigned at time of creation (in memory this number can be found in member id from structure InternalListenStructure). This key has one value named BindedToProtocols that is saved as type MULTI_SZ and contains the names of the protocols that are binded in this ListenSession. Every protocol has its own sub-key, which have the same structure as the Protocols sub-key.