/* Copyright 2012. Bloomberg Finance L.P.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: The above
* copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
// blpapi_providersession.h -*-C++-*-
#ifndef INCLUDED_BLPAPI_PROVIDERSESSION
#define INCLUDED_BLPAPI_PROVIDERSESSION
//@PURPOSE: Provide a session that can be used for providing services
//
//@CLASSES:
// blpapi::ProviderSession: Session with providing(publishing) services.
// blpapi::ProviderEventHandler: Event handler for ProviderSession
// blpapi::ServiceRegistrationOptions: Container holding registration options.
//
//@DESCRIPTION: ProviderSession inherits from AbstractSession. In addition to
// AbstractSession functionality, ProviderSession provides functions that are
// needed to support publishing like 'registerService', 'createTopics' and
// 'publish'.
//
// Topic Life Cycle
// ----------------
// A provider wishing to publish subscription data must explicitly open each
// topic on which they publish using 'ProviderSession::createTopics' (or
// 'ProviderSession::createTopicsAsync'). Creating a topic prepares the
// distribution and caching infrastructure for new data associated with the
// topic's resolved identifier. (Note that several different topics could
// resolve to the same ID.) Independent of a topic's creation status is its
// subscription status, i.e. whether there are subscribers ready to receive
// the data published. A topic that is both created and subscribed is
// *activated*.
//
// There are two models for managing topic creation: broadcast and
// interactive. Broadcast publishers proactively call
// 'ProviderSession::createTopic*' for each topic on which they intend to
// publish, while interactive publishers wait to receive a
// 'TopicSubscribed' message (within an 'Event' of type 'Event::TOPIC_STATUS')
// before calling 'ProviderSession::createTopic*' in response. Topics are
// resolved before they are created---it is possible that multiple different
// topic strings will map to the same underlying topic. See below for the
// behavior of the SDK when the same topic is created multiple times.
//
// After 'ProviderSession::createTopic*' is called, the publisher will receive
// a 'TopicCreated' message (within an 'Event::TOPIC_STATUS' event), and when
// there is at least one subscriber to the topic the publisher will then
// receive a 'TopicActivated' message (also within an 'Event::TOPIC_STATUS'
// event). As subscribers come and go, additional 'TopicSubscribed',
// 'TopicActivated', 'TopicUnsubscribed', and 'TopicDeactivated' messages may
// be received by the publisher. A 'Topic' object can be retrieved from each of
// these messages using the 'ProviderSession::getTopic' method, and this
// object can be used for subsequent calls to 'EventFormatter::appendMessage'
// and 'ProviderSession::deleteTopic'. In the case that the same resolved
// topic is created multiple times by a publisher using different names, it is
// unspecified which of those names will be returned by 'Message::topicName'
// for these (or other) messages.
//
// If a publisher no longer intends to publish data on a topic, it can call
// 'ProviderSession::deleteTopic*' to free the internal caching and
// distribution resources associated with the topic. When a resolved topic has
// been deleted the same number of times that it has been created,
// a 'TopicDeleted' message will be delivered, preceded by 'TopicUnsubscribed'
// and 'TopicDeactivated' messages if the topic was still subscribed (and
// activated). No further messages can be published on a deleted topic.
//
// Deregistering a service deletes all topics associated with that service.
//
// Note that 'TopicActivated' and 'TopicDeactivated' messages are entirely
// redundant with 'TopicCreated', 'TopicSubscribed', 'TopicDeleted', and
// 'TopicUnsubscribed' messages, and are provided only for the convenience
// of publishers that do not maintain per-topic state.
#ifndef INCLUDED_BLPAPI_ABSTRACTSESSION
#include <blpapi_abstractsession.h>
#endif
#ifndef INCLUDED_BLPAPI_CALL
#include <blpapi_call.h>
#endif
#ifndef INCLUDED_BLPAPI_CORRELATIONID
#include <blpapi_correlationid.h>
#endif
#ifndef INCLUDED_BLPAPI_DEFS
#include <blpapi_defs.h>
#endif
#ifndef INCLUDED_BLPAPI_EVENT
#include <blpapi_event.h>
#endif
#ifndef INCLUDED_BLPAPI_EVENTDISPATCHER
#include <blpapi_eventdispatcher.h>
#endif
#ifndef INCLUDED_BLPAPI_IDENTITY
#include <blpapi_identity.h>
#endif
#ifndef INCLUDED_BLPAPI_REQUEST
#include <blpapi_request.h>
#endif
#ifndef INCLUDED_BLPAPI_RESOLUTIONLIST
#include <blpapi_resolutionlist.h>
#endif
#ifndef INCLUDED_BLPAPI_SERVICE
#include <blpapi_service.h>
#endif
#ifndef INCLUDED_BLPAPI_SESSIONOPTIONS
#include <blpapi_sessionoptions.h>
#endif
#ifndef INCLUDED_BLPAPI_SUBSCRIPTIONLIST
#include <blpapi_subscriptionlist.h>
#endif
#ifndef INCLUDED_BLPAPI_TOPIC
#include <blpapi_topic.h>
#endif
#ifndef INCLUDED_BLPAPI_TOPICLIST
#include <blpapi_topiclist.h>
#endif
#ifndef INCLUDED_BLPAPI_TYPES
#include <blpapi_types.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct blpapi_ServiceRegistrationOptions;
typedef struct blpapi_ServiceRegistrationOptions
blpapi_ServiceRegistrationOptions_t;
typedef void(*blpapi_ProviderEventHandler_t)(blpapi_Event_t *event,
blpapi_ProviderSession_t *session,
void *userData);
BLPAPI_EXPORT
blpapi_ProviderSession_t *blpapi_ProviderSession_create(
blpapi_SessionOptions_t *parameters,
blpapi_ProviderEventHandler_t handler,
blpapi_EventDispatcher_t *dispatcher,
void *userData);
BLPAPI_EXPORT
void blpapi_ProviderSession_destroy(
blpapi_ProviderSession_t *session);
BLPAPI_EXPORT
int blpapi_ProviderSession_start(
blpapi_ProviderSession_t *session);
BLPAPI_EXPORT
int blpapi_ProviderSession_startAsync(
blpapi_ProviderSession_t *session);
BLPAPI_EXPORT
int blpapi_ProviderSession_stop(
blpapi_ProviderSession_t *session);
BLPAPI_EXPORT
int blpapi_ProviderSession_stopAsync(
blpapi_ProviderSession_t *session);
BLPAPI_EXPORT
int blpapi_ProviderSession_nextEvent(
blpapi_ProviderSession_t *session,
blpapi_Event_t **eventPointer,
unsigned int timeoutInMilliseconds);
BLPAPI_EXPORT
int blpapi_ProviderSession_tryNextEvent(
blpapi_ProviderSession_t *session,
blpapi_Event_t **eventPointer);
BLPAPI_EXPORT
int blpapi_ProviderSession_registerService(
blpapi_ProviderSession_t *session,
const char *serviceName,
const blpapi_Identity_t *identity,
blpapi_ServiceRegistrationOptions_t *registrationOptions);
BLPAPI_EXPORT
int blpapi_ProviderSession_activateSubServiceCodeRange(
blpapi_ProviderSession_t *session,
const char* serviceName,
int begin,
int end,
int priority);
BLPAPI_EXPORT
int blpapi_ProviderSession_deactivateSubServiceCodeRange(
blpapi_ProviderSession_t *session,
const char* serviceName,
int begin,
int end);
BLPAPI_EXPORT
int blpapi_ProviderSession_registerServiceAsync(
blpapi_ProviderSession_t *session,
const char *serviceName,
const blpapi_Identity_t *identity,
blpapi_CorrelationId_t *correlationId,
blpapi_ServiceRegistrationOptions_t *registrationOptions);
BLPAPI_EXPORT
int blpapi_ProviderSession_deregisterService(
blpapi_ProviderSession_t *session,
const char *serviceName);
BLPAPI_EXPORT
int blpapi_ProviderSession_resolve(
blpapi_ProviderSession_t *session,
blpapi_ResolutionList_t *resolutionList,
int resolveMode,
const blpapi_Identity_t *identity);
BLPAPI_EXPORT
int blpapi_ProviderSession_resolveAsync(
blpapi_ProviderSession_t *session,
const blpapi_ResolutionList_t *resolutionList,
int resolveMode,
const blpapi_Identity_t *identity);
BLPAPI_EXPORT
int blpapi_ProviderSession_createTopics(
blpapi_ProviderSession_t *session,
blpapi_TopicList_t *topicList,
int resolveMode,
const blpapi_Identity_t *identity);
BLPAPI_EXPORT
int blpapi_ProviderSession_createTopicsAsync(
blpapi_ProviderSession_t *session,
const blpapi_TopicList_t *topicList,
int resolveMode,
const blpapi_Identity_t *identity);
BLPAPI_EXPORT
int blpapi_ProviderSession_getTopic(
blpapi_ProviderSession_t *session,
const blpapi_Message_t *message,
blpapi_Topic_t **topic);
BLPAPI_EXPORT
int blpapi_ProviderSession_createTopic(
blpapi_ProviderSession_t *session,
const blpapi_Message_t *message,
blpapi_Topic_t **topic);
BLPAPI_EXPORT
int blpapi_ProviderSession_createServiceStatusTopic(
blpapi_ProviderSession_t *session,
const blpapi_Service_t *service,
blpapi_Topic_t **topic);
BLPAPI_EXPORT
int blpapi_ProviderSession_deleteTopics(
blpapi_ProviderSession_t* session,
const blpapi_Topic_t** topics,
size_t numTopics);
BLPAPI_EXPORT
int blpapi_ProviderSession_publish(
blpapi_ProviderSession_t *session,
blpapi_Event_t *event);
BLPAPI_EXPORT
int blpapi_ProviderSession_sendResponse(
blpapi_ProviderSession_t *session,
blpapi_Event_t *event,
int isPartialResponse);
BLPAPI_EXPORT
blpapi_AbstractSession_t *blpapi_ProviderSession_getAbstractSession(
blpapi_ProviderSession_t *session);
// ServiceRegistrationOptions
BLPAPI_EXPORT
blpapi_ServiceRegistrationOptions_t*
blpapi_ServiceRegistrationOptions_create(void);
BLPAPI_EXPORT
blpapi_ServiceRegistrationOptions_t*
blpapi_ServiceRegistrationOptions_duplicate(
const blpapi_ServiceRegistrationOptions_t *parameters);
BLPAPI_EXPORT
void blpapi_ServiceRegistrationOptions_destroy(
blpapi_ServiceRegistrationOptions_t *parameters);
BLPAPI_EXPORT
void blpapi_ServiceRegistrationOptions_copy(
blpapi_ServiceRegistrationOptions_t *lhs,
const blpapi_ServiceRegistrationOptions_t *rhs);
// SUBSERVICE CODES
BLPAPI_EXPORT
int blpapi_ServiceRegistrationOptions_addActiveSubServiceCodeRange(
blpapi_ServiceRegistrationOptions_t *parameters,
int start, int end, int priority);
BLPAPI_EXPORT
void blpapi_ServiceRegistrationOptions_removeAllActiveSubServiceCodeRanges(
blpapi_ServiceRegistrationOptions_t *parameters);
BLPAPI_EXPORT
void blpapi_ServiceRegistrationOptions_setGroupId(
blpapi_ServiceRegistrationOptions_t *parameters,
const char *groupId,
unsigned int groupIdLength);
BLPAPI_EXPORT
int blpapi_ServiceRegistrationOptions_setServicePriority(
blpapi_ServiceRegistrationOptions_t *parameters,
int priority);
BLPAPI_EXPORT
void blpapi_ServiceRegistrationOptions_setPartsToRegister(
blpapi_ServiceRegistrationOptions_t *parameters,
int parts);
BLPAPI_EXPORT
int blpapi_ServiceRegistrationOptions_getGroupId(
blpapi_ServiceRegistrationOptions_t *parameters,
char *groupdIdBuffer,
int *groupIdLength);
BLPAPI_EXPORT
int blpapi_ServiceRegistrationOptions_getServicePriority(
blpapi_ServiceRegistrationOptions_t *parameters);
BLPAPI_EXPORT
int blpapi_ServiceRegistrationOptions_getPartsToRegister(
blpapi_ServiceRegistrationOptions_t *parameters);
#ifdef __cplusplus
}
namespace BloombergLP {
namespace blpapi {
static void providerEventHandlerProxy(blpapi_Event_t *event,
blpapi_ProviderSession_t *session,
void *userData);
class ProviderSession;
// ==========================
// class ProviderEventHandler
// ==========================
class ProviderEventHandler {
public:
virtual ~ProviderEventHandler() {}
virtual bool processEvent(const Event& event,
ProviderSession *session) = 0;
};
// ================================
// class ServiceRegistrationOptions
// ================================
class ServiceRegistrationOptions {
// Contains the options which the user can specify when registering
// a service
//
// To use non-default options to registerService, create a
// ServiceRegistrationOptions instance and set the required options and
// then supply it when using the registerService interface.
blpapi_ServiceRegistrationOptions_t *d_handle_p;
public:
enum ServiceRegistrationPriority {
PRIORITY_LOW = BLPAPI_SERVICEREGISTRATIONOPTIONS_PRIORITY_LOW,
PRIORITY_MEDIUM = BLPAPI_SERVICEREGISTRATIONOPTIONS_PRIORITY_MEDIUM,
PRIORITY_HIGH = BLPAPI_SERVICEREGISTRATIONOPTIONS_PRIORITY_HIGH
};
enum RegistrationParts {
// constants for specifying which part(s) of a service should be
// registered
PART_PUBLISHING = BLPAPI_REGISTRATIONPARTS_PUBLISHING,
// register to receive subscribe and unsubscribe messages
PART_OPERATIONS = BLPAPI_REGISTRATIONPARTS_OPERATIONS,
// register to receive the request types corresponding to each
// "operation" defined in the service metadata
PART_SUBSCRIBER_RESOLUTION
= BLPAPI_REGISTRATIONPARTS_SUBSCRIBER_RESOLUTION,
// register to receive resolution requests (with message type
// 'PermissionRequest') from subscribers
PART_PUBLISHER_RESOLUTION
= BLPAPI_REGISTRATIONPARTS_PUBLISHER_RESOLUTION,
// register to receive resolution requests (with message type
// 'PermissionRequest') from publishers (via
// 'ProviderSession::createTopics')
PART_DEFAULT = BLPAPI_REGISTRATIONPARTS_DEFAULT
// register the parts of the service implied by options
// specified in the service metadata
};
ServiceRegistrationOptions();
// Create ServiceRegistrationOptions with default options.
ServiceRegistrationOptions(const ServiceRegistrationOptions& original);
// Copy Constructor
~ServiceRegistrationOptions();
// Destroy this ServiceRegistrationOptions.
// MANIUPLATORS
ServiceRegistrationOptions& operator=(
const ServiceRegistrationOptions& rhs);
// Assign to this object the value of the specified 'rhs' object.
void setGroupId(const char *groupId, unsigned int groupIdLength);
// Set the Group ID for the service to be registered to the specified
// char array beginning at groupId with size groupIdLength.
// If groupIdLength > MAX_GROUP_ID_SIZE (=64) only the first
// MAX_GROUP_ID_SIZE chars are considered as Group Id.
int setServicePriority(int priority);
// Set the priority with which a service will be registered to
// the non-negative value specified in priority.
// This call returns with a non-zero value indicating error when
// a negative priority is specified.
// Any non-negative priority value, other than the one
// pre-defined in ServiceRegistrationPriority can be used.
// Default value is PRIORITY_HIGH
void setPartsToRegister(int parts);
// Set the parts of the service to be registered to the specified
// 'parts', which must be a bitwise-or of the options provided in
// 'RegistrationParts', above. This option defaults to
// 'RegistrationParts::PARTS_DEFAULT'.
void addActiveSubServiceCodeRange(int begin, int end, int priority);
// Advertise the service to be registered to receive, with the
// specified 'priority', subscriptions that the resolver has mapped to
// a service code between the specified 'begin' and the specified 'end'
// values, inclusive. The behavior of this function is undefined unless
// '0 <= begin <= end < (1 << 24)', and 'priority' is non-negative.
void removeAllActiveSubServiceCodeRanges();
// Remove all previously added sub-service code ranges.
// ACCESSORS
blpapi_ServiceRegistrationOptions_t *handle() const;
int getGroupId(char *groupId, int *groupIdLength) const;
// Copy the previously specified groupId at the memory location
// specified by groupId and the set the size of the groupId returned at
// groupIdLength. A Non-zero value indicates an error.
// The behavior is undefined if there is not enough space to copy the
// group Id to the specified buffer.
// Note that the groupId is not null terminated and buffer for groupId
// needs to be at most MAX_GROUP_ID_SIZE.
int getServicePriority() const;
// Return the value of the service priority in this
// ServiceRegistrationOptions instance.
int getPartsToRegister() const;
// Return the parts of the service to be registered. See
// 'RegistrationParts', above for additional details.
};
// =====================
// class ProviderSession
// =====================
class ProviderSession : public AbstractSession {
// This class provides a session that can be used for providing services.
//
// It inherits from AbstractSession. In addition to the AbstractSession
// functionality a ProviderSession provides the following
// functions to applications.
//
// A provider can register to provide services using
// 'ProviderSession::registerService*'. Before registering to provide a
// service the provider must have established its identity. Then
// the provider can create topics and publish events on topics. It also
// can get requests from the event queue and send back responses.
//
// After users have registered a service they will start receiving
// subscription requests ('TopicSubscribed' message in 'TOPIC_STATUS') for
// topics which belong to the service. If the resolver has specified
// 'subServiceCode' for topics in 'PermissionResponse', then only providers
// who have activated the 'subServiceCode' will get the subscription
// request. Where multiple providers have registered the same service and
// sub-service code (if any), the provider that registered the highest
// priority for the sub-service code will receive subscription requests; if
// multiple providers have registered the same sub-service code with the
// same priority (or the resolver did not set a sub-service code for the
// subscription), the subscription request will be routed to one of the
// providers with the highest service priority.
blpapi_ProviderSession_t *d_handle_p;
ProviderEventHandler *d_eventHandler_p;
private:
friend void providerEventHandlerProxy(blpapi_Event_t *event,
blpapi_ProviderSession_t *session,
void *userData);
void dispatchEvent(const Event& event);
private:
// NOT IMPLEMENTED
ProviderSession(const ProviderSession&);
ProviderSession& operator=(const ProviderSession&);
public:
enum ResolveMode {
AUTO_REGISTER_SERVICES = BLPAPI_RESOLVEMODE_AUTO_REGISTER_SERVICES,
// Try to register services found in ResolutionList if necessary.
DONT_REGISTER_SERVICES = BLPAPI_RESOLVEMODE_DONT_REGISTER_SERVICES
// Fail to resolve a topic if the service has not already been
// registered.
};
ProviderSession(const SessionOptions& options = SessionOptions(),
ProviderEventHandler *eventHandler=0,
EventDispatcher *eventDispatcher=0);
// Construct a Session using the optionally specified
// 'options', the optionally specified 'eventHandler' and the
// optionally specified 'eventDispatcher'.
//
// See the SessionOptions documentation for details on what
// can be specified in the 'options'.
//
// If 'eventHandler' is not 0 then this Session will operation
// in asynchronous mode, otherwise the Session will operate in
// synchronous mode.
//
// If 'eventDispatcher' is 0 then the Session will create a
// default EventDispatcher for this Session which will use a
// single thread for dispatching events. For more control over
// event dispatching a specific instance of EventDispatcher
// can be supplied. This can be used to share a single
// EventDispatcher amongst multiple Session objects.
//
// If an 'eventDispatcher' is supplied which uses more than
// one thread the Session will ensure that events which should
// be ordered are passed to callbacks in a correct order. For
// example, partial response to a request or updates to a
// single subscription.
//
// If 'eventHandler' is 0 and the 'eventDispatcher' is not
// 0 an exception is thrown.
//
// Each EventDispatcher uses its own thread or pool of
// threads so if you want to ensure that a session which
// receives very large messages and takes a long time to
// process them does not delay a session that receives small
// messages and processes each one very quickly then give each
// one a separate EventDispatcher.
explicit ProviderSession(blpapi_ProviderSession_t *handle);
virtual ~ProviderSession();
// Destructor.
// MANIPULATORS
virtual bool start();
// See AbstractSession::start().
virtual bool startAsync();
// See AbstractSession::startAsync().
virtual void stop();
// See AbstractSession::stop().
virtual void stopAsync();
// See AbstractSession::stopAsync().
virtual Event nextEvent(int timeout=0);
// See AbstractSession::nextEvent().
virtual int tryNextEvent(Event *event);
// See AbstractSession::tryNextEvent()
bool registerService(
const char *serviceName,
const Identity& providerIdentity
= Identity(),
const ServiceRegistrationOptions& registrationOptions
= ServiceRegistrationOptions());
// Attempt to register the service identified by the specified
// 'serviceName' and block until the service is either registered
// successfully or has failed to be registered. The optionally
// specified 'providerIdentity' is used to verify permissions
// to provide the service being registered. The optionally
// specified 'registrationOptions' is used to specify the
// group ID and service priority of the service being registered.
// Returns 'true' if the service is registered successfully and
// 'false' if the service cannot be registered successfully.
//
// The 'serviceName' must be a full qualified service name. That is it
// must be of the form '//<namespace>/<local-name>'.
//
// This function does not return until a SERVICE_STATUS event has been
// generated. Note that if the session was created in asynchronous
// mode, the event may be processed before the function returns.
void activateSubServiceCodeRange(const char *serviceName,
int begin,
int end,
int priority);
// Register to receive, with the specified 'priority', subscriptions
// for the specified 'service' that the resolver has mapped to a
// service code between the specified 'begin' and the specified 'end'
// values, inclusive. The behavior of this function is undefined unless
// 'service' has already been successfully registered,
// '0 <= begin <= end < (1 << 24)', and 'priority' is non-negative.
void deactivateSubServiceCodeRange(const char *serviceName,
int begin,
int end);
// De-register to receive subscriptions for the specified 'service'
// that the resolver has mapped to a service code between the specified
// 'begin' and the specified 'end' values, inclusive. The behavior of
// this function is undefined unless 'service' has already been
// successfully registered and '0 <= begin <= end < (1 << 24)'.
CorrelationId registerServiceAsync(
const char *serviceName,
const Identity& providerIdentity
= Identity(),
const CorrelationId& correlationId
= CorrelationId(),
const ServiceRegistrationOptions& registrationOptions
= ServiceRegistrationOptions());
// Begin the process of registering the service identified by
// the specified 'serviceName' and return immediately. The optionally
// specified 'providerIdentity' is used to verify permissions
// to provide the service being registered. The optionally
// specified 'correlationId' is used to track 'Event' objects generated
// as a result of this call. Return the actual 'CorrelationId' object
// that will identify 'Event' objects. The optionally specified
// 'registrationOptions' is used to specify the group ID and service
// priority of the service being registered.
//
// The 'serviceName' must be a full qualified service name. That is it
// must be of the form '//<namespace>/<local-name>'.
//
// The application must monitor events for a SERVICE_STATUS
// Event which will be generated once the service has been
// successfully registered or registration has failed.
bool deregisterService(const char *serviceName);
// Deregister the service, including all registered parts, identified
// by the specified 'serviceName'. The identity in the service
// registration is reused to verify permissions for deregistration. If
// the service is not registered nor in pending registration, return
// false; return true otherwise. If the service is in pending
// registration, cancel the pending registration. If the service is
// registered, send a deregistration request; generate TOPIC_STATUS
// events containing a TopicUnsubscribed message for each subscribed
// topic, a TopicDeactivated message for each active topic and a
// TopicDeleted for each created topic; generate REQUEST_STATUS events
// containing a RequestFailure message for each pending incoming
// request; and generate a SERVICE_STATUS Event containing a
// ServiceDeregistered message. All published events on topics created
// on this service will be ignored after this method returns.
void resolve(ResolutionList *resolutionList,
ResolveMode resolveMode=DONT_REGISTER_SERVICES,
Identity providerIdentity=Identity());
// Resolves the topics in the specified 'resolutionList' and
// updates the 'resolutionList' with the results of the
// resolution process. If the specified 'resolveMode' is
// DONT_REGISTER_SERVICES (the default) then all the services
// referenced in the topics in the 'resolutionList' must
// already have been registered using registerService(). If
// 'resolveMode' is AUTO_REGISTER_SERVICES then the specified
// 'providerIdentity' should be supplied and ProviderSession
// will automatically attempt to register any services
// reference in the topics in the 'resolutionList' that have
// not already been registered. Once resolveSync() returns
// each entry in the 'resolutionList' will have been updated
// with a new status.
//
// Before resolveSync() returns one or more RESOLUTION_STATUS
// events and, if 'resolveMode' is AUTO_REGISTER_SERVICES,
// zero or more SERVICE_STATUS events are generated. If this
// is an asynchronous ProviderSession then these Events may be
// processed by the registered EventHandler before resolve()
// has returned.
void resolveAsync(const ResolutionList& resolutionList,
ResolveMode resolveMode=DONT_REGISTER_SERVICES,
const Identity& providerIdentity=Identity());
// Begin the resolution of the topics in the specified
// 'resolutionList'. If the specified 'resolveMode' is
// DONT_REGISTER_SERVICES (the default) then all the services
// referenced in the topics in the 'resolutionList' must
// already have been registered using registerService(). If
// 'resolveMode' is AUTO_REGISTER_SERVICES then the specified
// 'providerIdentity' should be supplied and ProviderSession
// will automatically attempt to register any services
// reference in the topics in the 'resolutionList' that have
// not already been registered.
//
// One or more RESOLUTION_STATUS events will be delivered with
// the results of the resolution. These events may be
// generated before or after resolve() returns. If
// AUTO_REGISTER_SERVICES is specified SERVICE_STATUS events
// may also be generated before or after resolve() returns.
Topic createTopic(const Message& message);
// DEPRECATED
// Create a topic from the specified 'message', which must be of type
// 'ResolutionSuccess'. This method is deprecated; use 'createTopics'
// or 'createTopicsAsync', which handle resolution automatically.
Topic getTopic(const Message& message);
// Finds a previously created Topic object based on the specified
// 'message'. The 'message' must be one of the following
// types: TopicCreated, TopicActivated, TopicDeactivated,
// TopicSubscribed, TopicUnsubscribed, TopicRecap.
// If the 'message' is not valid then invoking isValid() on the
// returned Topic will return false.
Topic createServiceStatusTopic(const Service& service);
// Creates a Service Status Topic which is to be used to provide
// service status. On success invoking isValid() on the returned Topic
// will return false.
void publish(const Event& event);
// Publish messages contained in the specified 'event'.
void sendResponse(const Event& event, bool isPartialResponse = false);
// Send the response event for previously received request
void createTopics(TopicList *topicList,
ResolveMode resolveMode=DONT_REGISTER_SERVICES,
Identity providerIdentity=Identity());
// Creates the topics in the specified 'topicList' and
// updates the 'topicList' with the results of the
// creation process. If service needs to be registered,
// 'providerIdentity' should be supplied.
// Once a call to this function returns,
// each entry in the 'topicList' will have been updated
// with a new topic creation status.
//
// Before createTopics() returns one or more RESOLUTION_STATUS
// events, zero or more SERVICE_STATUS events and one or more
// TOPIC_STATUS events are generated.
// If this is an asynchronous ProviderSession then these
// Events may be processed by the registered EventHandler
// before createTopics() has returned.
void createTopicsAsync(const TopicList& topicList,
ResolveMode resolveMode=DONT_REGISTER_SERVICES,
const Identity& providerIdentity=Identity());
// Creates the topics in the specified 'topicList' and
// updates the 'topicList' with the results of the
// creation process. If service needs to be registered,
// 'providerIdentity' should be supplied.
//
// One or more RESOLUTION_STATUS events, zero or more
// SERVICE_STATUS events and one or more TOPIC_STATUS
// events are generated.
// If this is an asynchronous ProviderSession then these
// Events may be processed by the registered EventHandler
// before createTopics() has returned.
void deleteTopic(const Topic& topic);
// Remove one reference from the specified 'topic'. If this function
// has been called the same number of times that 'topic' was created
// by 'createTopics', then 'topic' is deleted: a 'TopicDeleted'
// message is delivered, preceded by 'TopicUnsubscribed' and
// 'TopicDeactivated' if 'topic' was subscribed. (See "Topic
// Life Cycle", above, for additional details.) The behavior of this
// function is undefined if 'topic' has already been deleted the same
// number of times that it has been created. Further, the behavior is
// undefined if a provider attempts to publish a message on a deleted
// topic.
void deleteTopics(const std::vector<Topic>& topics);
// Delete each topic in the specified 'topics'. See
// 'deleteTopic(const Topic&)' for additional details.
void deleteTopics(const Topic* topics,
size_t numTopics);
// Delete the first 'numTopics' elements of the specified 'topics'
// array. See 'deleteTopic(const Topic&)' for additional details.
blpapi_ProviderSession_t *handle() const;
// Return the handle to this provider session
};
//=============================================================================
// INLINE FUNCTION DEFINITIONS
//=============================================================================
// ---------------------
// class ProviderSession
// ---------------------
inline
ProviderSession::ProviderSession(const SessionOptions& parameters,
ProviderEventHandler *handler,
EventDispatcher *dispatcher)
: d_eventHandler_p(handler)
{
d_handle_p = blpapi_ProviderSession_create(parameters.handle(),
handler ? (blpapi_ProviderEventHandler_t)providerEventHandlerProxy : 0,
dispatcher ? dispatcher->impl() : 0,
this);
initAbstractSessionHandle(
blpapi_ProviderSession_getAbstractSession(d_handle_p));
}
inline
ProviderSession::ProviderSession(blpapi_ProviderSession_t *newHandle)
: d_handle_p(newHandle)
{
initAbstractSessionHandle(
blpapi_ProviderSession_getAbstractSession(d_handle_p));
}
inline
ProviderSession::~ProviderSession()
{
blpapi_ProviderSession_destroy(d_handle_p);
}
inline
bool ProviderSession::start()
{
return blpapi_ProviderSession_start(d_handle_p) ? false : true;
}
inline
bool ProviderSession::startAsync()
{
return blpapi_ProviderSession_startAsync(d_handle_p) ? false : true;
}
inline
void ProviderSession::stop()
{
blpapi_ProviderSession_stop(d_handle_p);
}
inline
void ProviderSession::stopAsync()
{
blpapi_ProviderSession_stopAsync(d_handle_p);
}
inline
Event ProviderSession::nextEvent(int timeout)
{
blpapi_Event_t *event;
ExceptionUtil::throwOnError(
blpapi_ProviderSession_nextEvent(d_handle_p, &event, timeout));
return Event(event);
}
inline
int ProviderSession::tryNextEvent(Event *event)
{
blpapi_Event_t *impl;
int ret = blpapi_ProviderSession_tryNextEvent(
d_handle_p, &impl);
if(0 == ret) {
*event = Event(impl);
}
return ret;
}
inline
bool ProviderSession::registerService(
const char *serviceName,
const Identity& identity,
const ServiceRegistrationOptions& registrationOptions)
{
return blpapi_ProviderSession_registerService(
d_handle_p,
serviceName,
identity.handle(),
registrationOptions.handle()) ? false : true;
}
inline
void ProviderSession::activateSubServiceCodeRange(const char *serviceName,
int begin, int end, int priority)
{
ExceptionUtil::throwOnError(
BLPAPI_CALL_PROVIDERSESSION_ACTIVATESUBSERVICECODERANGE(d_handle_p,
serviceName,
begin,
end,
priority));
}
inline
void ProviderSession::deactivateSubServiceCodeRange(const char *serviceName,
int begin, int end)
{
ExceptionUtil::throwOnError(
BLPAPI_CALL_PROVIDERSESSION_DEACTIVATESUBSERVICECODERANGE(d_handle_p,
serviceName,
begin,
end));
}
inline
CorrelationId ProviderSession::registerServiceAsync(
const char *serviceName,
const Identity& identity,
const CorrelationId& correlationId,
const ServiceRegistrationOptions& registrationOptions)
{
blpapi_CorrelationId_t retv = correlationId.impl();
ExceptionUtil::throwOnError(
blpapi_ProviderSession_registerServiceAsync(
d_handle_p, serviceName, identity.handle(),
&retv, registrationOptions.handle())
);
return retv;
}
inline
bool ProviderSession::deregisterService(const char *serviceName)
{
return BLPAPI_CALL_PROVIDERSESSION_DEREGISTERSERVICE(
d_handle_p,
serviceName) == 0 ? true : false;
}
inline
void ProviderSession::resolve(ResolutionList* resolutionList,
ResolveMode resolveMode,
Identity identity)
{
ExceptionUtil::throwOnError(blpapi_ProviderSession_resolve(
d_handle_p,
resolutionList->impl(),
resolveMode,
identity.handle()));
return;
}
inline
void ProviderSession::resolveAsync(const ResolutionList& resolutionList,
ResolveMode resolveMode,
const Identity& identity)
{
ExceptionUtil::throwOnError(blpapi_ProviderSession_resolveAsync(
d_handle_p,
resolutionList.impl(),
resolveMode,
identity.handle()));
return;
}
inline
Topic ProviderSession::createTopic(const Message& message)
{
blpapi_Topic_t* topic;
ExceptionUtil::throwOnError(
blpapi_ProviderSession_createTopic(
d_handle_p, message.impl(), &topic));
return Topic(topic);
}
inline
Topic ProviderSession::getTopic(const Message& message)
{
blpapi_Topic_t* topic;
ExceptionUtil::throwOnError(
blpapi_ProviderSession_getTopic(
d_handle_p, message.impl(), &topic));
return Topic(topic);
}
inline
Topic ProviderSession::createServiceStatusTopic(const Service& service)
{
blpapi_Topic_t* topic;
ExceptionUtil::throwOnError(
blpapi_ProviderSession_createServiceStatusTopic(
d_handle_p, service.handle(), &topic));
return Topic(topic);
}
inline
void ProviderSession::createTopics(TopicList* topicList,
ResolveMode resolveMode,
Identity identity)
{
ExceptionUtil::throwOnError(blpapi_ProviderSession_createTopics(
d_handle_p,
topicList->impl(),
resolveMode,
identity.handle()));
return;
}
inline
void ProviderSession::createTopicsAsync(const TopicList& topicList,
ResolveMode resolveMode,
const Identity& identity)
{
ExceptionUtil::throwOnError(blpapi_ProviderSession_createTopicsAsync(
d_handle_p,
topicList.impl(),
resolveMode,
identity.handle()));
return;
}
inline
void ProviderSession::deleteTopic(const Topic& topic)
{
const blpapi_Topic_t* topicImpl = topic.impl();
ExceptionUtil::throwOnError(BLPAPI_CALL_PROVIDERSESSION_DELETETOPICS(
d_handle_p,
&topicImpl,
1));
}
inline
void ProviderSession::deleteTopics(const std::vector<Topic>& topics)
{
if (topics.size() == 0) {
return;
}
std::vector<const blpapi_Topic_t *> topicImplList;
topicImplList.reserve(topics.size());
for (std::vector<Topic>::const_iterator it = topics.begin();
it != topics.end();
++it) {
topicImplList.push_back(it->impl());
}
ExceptionUtil::throwOnError(BLPAPI_CALL_PROVIDERSESSION_DELETETOPICS(
d_handle_p,
&topicImplList[0],
topicImplList.size()));
}
inline
void ProviderSession::deleteTopics(const Topic* topics,
size_t numTopics)
{
if (numTopics == 0) {
return;
}
std::vector<const blpapi_Topic_t *> topicImplList;
topicImplList.reserve(numTopics);
for (size_t i = 0; i < numTopics; ++i) {
topicImplList.push_back(topics[i].impl());
}
ExceptionUtil::throwOnError(BLPAPI_CALL_PROVIDERSESSION_DELETETOPICS(
d_handle_p,
&topicImplList[0],
topicImplList.size()));
}
inline
void ProviderSession::publish(const Event& event)
{
ExceptionUtil::throwOnError(
blpapi_ProviderSession_publish(d_handle_p, event.impl()));
return;
}
inline
void ProviderSession::sendResponse(
const Event& event,
bool isPartialResponse)
{
ExceptionUtil::throwOnError(
blpapi_ProviderSession_sendResponse(
d_handle_p, event.impl(), isPartialResponse));
return;
}
inline
blpapi_ProviderSession_t* ProviderSession::handle() const
{
return d_handle_p;
}
inline
void ProviderSession::dispatchEvent(const Event& event)
{
d_eventHandler_p->processEvent(event, this);
}
// --------------------------------
// class ServiceRegistrationOptions
// --------------------------------
inline
ServiceRegistrationOptions::ServiceRegistrationOptions()
{
d_handle_p = blpapi_ServiceRegistrationOptions_create();
}
inline
ServiceRegistrationOptions::ServiceRegistrationOptions(
const ServiceRegistrationOptions& original)
{
d_handle_p = blpapi_ServiceRegistrationOptions_duplicate(
original.handle());
}
inline
ServiceRegistrationOptions::~ServiceRegistrationOptions()
{
blpapi_ServiceRegistrationOptions_destroy(d_handle_p);
}
inline
ServiceRegistrationOptions& ServiceRegistrationOptions::operator=(
const ServiceRegistrationOptions& rhs)
{
blpapi_ServiceRegistrationOptions_copy(this->handle(), rhs.handle());
return *this;
}
// SUBSERVICE CODES
inline
void ServiceRegistrationOptions::addActiveSubServiceCodeRange(int begin,
int end,
int priority)
{
ExceptionUtil::throwOnError(
BLPAPI_CALL_SERVICEREGISTRATIONOPTIONS_ADDACTIVATESUBSERVICECODERANGE(
d_handle_p,
begin,
end,
priority));
}
inline
void ServiceRegistrationOptions::removeAllActiveSubServiceCodeRanges()
{
BLPAPI_CALL_SERVICEREGISTRATIONOPTIONS_REMOVEALLACTIVESUBSERVICECODERANGES(
d_handle_p);
}
inline
void ServiceRegistrationOptions::setGroupId(const char* groupId,
unsigned int groupIdLength)
{
blpapi_ServiceRegistrationOptions_setGroupId(d_handle_p, groupId,
groupIdLength);
}
inline
int ServiceRegistrationOptions::setServicePriority(int priority)
{
return blpapi_ServiceRegistrationOptions_setServicePriority(
d_handle_p, priority);
}
inline
void ServiceRegistrationOptions::setPartsToRegister(int parts)
{
BLPAPI_CALL_SERVICEREGISTRATIONOPTIONS_SETPARTSTOREGISTER(d_handle_p,
parts);
}
inline
int ServiceRegistrationOptions::getGroupId(char *groupIdBuffer,
int *groupIdLength) const
{
return blpapi_ServiceRegistrationOptions_getGroupId(d_handle_p,
groupIdBuffer,
groupIdLength);
}
inline
int ServiceRegistrationOptions::getServicePriority() const
{
return blpapi_ServiceRegistrationOptions_getServicePriority(d_handle_p);
}
inline
int ServiceRegistrationOptions::getPartsToRegister() const
{
return BLPAPI_CALL_SERVICEREGISTRATIONOPTIONS_GETPARTSTOREGISTER(
d_handle_p);
}
inline
blpapi_ServiceRegistrationOptions_t* ServiceRegistrationOptions::handle() const
{
return d_handle_p;
}
// --------------------------
// class ProviderEventHandler
// --------------------------
static void providerEventHandlerProxy(blpapi_Event_t *event,
blpapi_ProviderSession_t *,
void *userData)
{
reinterpret_cast<ProviderSession*>(userData)->dispatchEvent(Event(event));
}
} // close namespace blpapi
} // close namespace BloombergLP
#endif // #ifdef __cplusplus
#endif // #ifndef INCLUDED_BLPAPI_PROVIDERSESSION