Query Pattern

Figure: Query Pattern

  • The first example demonstrates the usage of a query server and a query client ports.
  • The query pattern implements a client initiated two-way communication. A client (service requestor) sends a request containing individual parameters and receives an individual result from the server (service provider).
  • The query pattern is also used if a service is needed at a very low rate compared to the cycle time of the service. To save communication bandwidth, it makes more sense to perform a query if new data is needed instead of being overrun by not needed updates. The query pattern is, for example, used to request a particular part of a map where the request specifies the size and the origin of the map patch that is then returned by the answering communication object.
  • The server can handle an arbitrary number of connected clients (see figure below).
  • It provides a member function based interface at the service requestor and a handler based interface at the service provider.
  • The client side interface provides two different access modes. The first one is the standard blocking query which forms a synchronous interface. The second access mode forms an asynchronous interface and supports the deferred reception of answers for previously invoked requests. That access mode provides both, blocking and non-blocking member functions. It is particularly useful for interleaved requests of different queries.
  • At the service provider, each incoming request is forwarded to the registered handler for further processing. The handler at the service provider has to be derived from the abstract handler class to provide an implementation of the handleQuery member function.
  • Due to the handler based approach, no incoming request is lost. All requests of all connected clients are handled in an arbitrary order. However, all requests of a single client are handled in the order of being sent.
  • In case of a passive handler, the processing of incoming requests is driven by the upcalling thread of the query server. Thus, the execution of the next incoming request is blocked until the passive handler returns. A passive handler makes sense if only short and non-blocking activities are involved. It avoids the overhead of thread generation inside the query server. It is allowed to call the answer method from inside a passive handler.
  • The query server implements an asynchronous upcall interface. That is, the answer to be returned is provided by a separate answer method and not as return value of the upcall. The reason for this structure becomes obvious in case of active handlers. The upcall can deliver the incoming request and can immediately return without being forced to wait until the returned result is available. The asynchronous upcall interface allows to provide the answer even from a completely different thread, for example, that one at the end of a processing chain.
  • Any kind of active handler can be used to decouple the processing of incoming requests from the query server. The advantage of a user side threading model is that one is free to implement any kind of needed threading model (thread per incoming communication object, thread pool etc.). The passive handler just hands over the incoming communication object but does not process it. Since there is no separate thread created inside the server to handle the upcall, there is no waste of resources in case of using an active handler (it makes no sense to have a separate thread per upcall in case of an active handler).
  • An already implemented example of an active handler is given by the Queue Query Server Handler. All incoming requests are stored in a queue and another thread is handling one request after the next (independently of the upcall of the query server).

Figure: Several query clients