Jemmac Software
OPCFailover logo. Restrictions for Use

There are three known (and rare) ways in which an OPC Client can be implemented such that it would be unable to take advantage of OPCFailover. For this reason we recommend the download of the trial to verify the behaviour of your OPC Clients.

The restrictions apply when the OPC Client does one or more of the following:

  • does not attempt to reconnect to an OPC Server when a communications problem is detected.
  • does not re-resolve the CLSID from the OPC Server name (ProgID) before a reconnection attempt.
  • passes remote server information when connecting to locally registered OPC Servers.

Below is a more detailed explanation of each of these conditions and some suggestions for resolving them.

1. No reconnect attempt

If an OPC Client does not have any coded logic to perform a reconnection when it encounters a communications problem it can be fixed by simply adding this logic to the OPC Client.

2. No attempt to re resolve the CLSID from the ProgID

OPC server names are DCOM ProgIDs, human readable names for components that have numeric names (CLSID's) in Windows. The CLSID is what is used by the OPC Client when it actually tries to connect to an OPC Server. For example resolving the OPC Server name (ProgID) OpcTestLab.OpcAnalyzer may return a CLSID of {B8AADBA5-382F-45DA-AA0A-D7BB21E4AE97}.

Some OPC Clients perform this lookup only once and then always use the returned CLSID whenever it tries to reconnect to the OPC server. OPCFailover does some remapping of these ProgID/CLSID relationships when a failover is needed. This means that the ProgID may point to a different CLSID. If an OPC Client is not re-resolving the CLSID from the ProgID it will not attempt to reconnect to an alternate OPC Server.

Coding this is a very simple task and just a matter of adding a call to re-resolve the ProgID to CLSID mapping. E.g., connecting to an OPCFailover Group named "OPCTest" could be done as follows (C++):

// Perform the lookup
CLSID clsid;
HRESULT hr = CLSIDFromProgID(A2W("OPCTest"), &clsid);

// Now connect - can pass CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
// MQI is information about interface requested and returned pointer

hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_LOCAL_SERVER, NULL, 1, &MQI);

3. Passing remote server information

One of the options when making a connection to an OPC Server is specifying remote server information. If you wish to explicitly connect to a remote OPC Server then this information is required and should be filled in. For local OPC Servers or remote OPC Servers that have been locally registered it should be omitted. This is because if it is passed then any DCOM configuration, as specified in DCOMCNFG, will be ignored. This is true even if the remote machine name is given as "localhost".

OPCFailover Groups are in essence locally registered remote OPC Servers and so passing server information in the connect call will result in the wiring performed by OPCFailover to be ignored. If "localhost" is set then you are directing DCOM to try to connect to the given CLSID that resides on the local machine. In reality the OPC Server does not exist on the local machine and because the lookup is ignored the connection fails, usually with an error code of 0x80040154 (class not registered).

This is documented by Microsoft for calls:

as follows:

pServerInfo [in]

A pointer to computer on which to instantiate the class object. If this parameter is NULL, the class object is instantiated on the current computer or at the computer specified under the class's RemoteServerName key, according to the interpretation of the dwClsCtx parameter. See COSERVERINFO.

Again the solution to this is very simple, if the server requested is for the localhost then don't pass server information and let the DCOM subsystem perform any necessary lookups based on the local DCOM configuration.

For example (pseudocode)

COSERVERINFO *pServerInfo = NULL;
if (nodename != "localhost" && nodename != GetComputerName()) {
// server isn't local or locally registered so set up COSERVERINFO
...
}

HRESULT hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_LOCAL_SERVER, pServerInfo, 1, &MQI);

Note that this is what is done in the OPC Foundation supplied .NET API wrappers in it's underlying calls to DCOM, as discussed here http://www.opcfoundation.org/forum/viewtopic.php?t=3433

If you have any questions relating to the restrictions for use of OPCFailover, please contact the OPCFailover Product Manager Mark Fisher for advice.