PreviousNext

Execution Semantics

Before we begin to discuss the RPC data types themselves, a slight digression is necessary. Whatever data you pass, all RPCs must deal with the unreliable nature of remote network connections. A call may not complete due to a network failure, possibly leaving the call operations in an indeterminate state. For this reason, the IDL provides execution semantics attributes that applications can use to request certain (limited) guarantees about call completeness.

Ideally, in order for an application to behave in a determinate fashion, each operation needs to be invoked exactly once each time it is invoked. This requirement can be relaxed somewhat for idempotent operations: those which have the same effect when they are invoked one or more times. In this case, an application can settle for at-least-once semantics.

Unfortunately, with a remote procedure call, there is no way to guarantee either exactly once or at-least-once call semantics. Instead, RPC provides at-most-once and idempotent semantics. When a call completes and returns to the client, then at-most-once semantics is equivalent to exactly-once semantics, and idempotent semantics is equivalent to at-least-once. When a call fails to return to the client - either because of a server or communications failure - the semantics make the following guarantees:

at-most-once
The call was invoked on the server either 0 or 1 times. If the call was invoked, it may or may not have completed execution.

idempotent
The call was invoked on the server 0 or more times. If the call was invoked, it may or may not have completed execution for any invocation.

In reality, idempotent semantics provides no guarantee for calls that fail to return to the client. In fact, DCE provides no guarantee about how idempotent semantics are actually implemented. It is perfectly correct to implement idempotency by using at-most-once semantics, and depending on protocol and implementation, this may be the case. Idempotent semantics is therefore really a hint from the application that a call is a candidate to be retried if the implementation uses a retry strategy.

These characteristics lead to two kinds of policy guidelines for call semantics. The first has to do with the behavior required of idempotent operations. An operation is a good candidate for idempotent semantics if it either changes no state on the server (such as, a read operation), or if the server state will be the same even if the same call is invoked more than once (such as, a call that writes the same record) with the same [in] data. Note that in either of these cases, the result returned by a call may not be the same on each retry, since some other thread or process may have modified server state. A server that allows simultaneous reads and writes provides a good example. However, the runtime does guarantee commutativity of operations on the same association: an idempotent call will not be retried if a later call on the same association has been invoked.

The second policy issue has to do with how applications respond to call failures. The issues are the same for idempotent and at-most-once calls. In neither case can the client know whether the server manager operation was invoked, and, if it was invoked, whether it was completed. This leads to three possible failure states:

1. The manager operation was not invoked.

2. The manager operation was invoked but did not complete.

3. The manager operation was invoked and completed, but failed to return to the client.

The burden of determining which state applies, and implementing recovery actions rests almost entirely with the application. The RPC mechanism provides limited support for cleanup in the case of applications that use context handles to maintain state between calls. Application provided context rundown routines will be called on behalf of the application if a communications failure is detected. Beyond this rather elementary mechanism, DCE RPC does not provide any internal support for transaction processing, roll-back, or other recovery mechanisms. For applications where error recovery and maintainance of consistent state is essential, these must be implemented by the application programmer. The topic is beyond the realm of this policy guide.

IDL also provides two execution semantic attributes of somewhat more limited use: broadcast and maybe. Broadcast semantics may be used with connectionless transports when there are multiple servers on the local network that can handle a call. The client broadcasts the call request to all servers, and completes the call with one of them. Maybe semantics provides a calling style that may be used when a call has no [out] or [in, out] parameters. The call is attempted once, and no response is returned. Both broadcast and maybe semantics implicitly require that the operation be idempotent.