if (distributionSpec == null) {
s_logger.info("Unable to work out distribution spec for specification " + specFromClient);
responses.add(buildErrorMessageResponse(specFromClient, LiveDataSubscriptionResult.NOT_PRESENT, "Unable to work out distribution spec"));
continue;
}
final LiveDataSpecification fullyQualifiedSpec = distributionSpec.getFullyQualifiedLiveDataSpecification();
Subscription subscription = getSubscription(fullyQualifiedSpec);
if (subscription != null) {
s_logger.info("Already subscribed to {}", fullyQualifiedSpec);
responses.add(buildSubscriptionResponse(specFromClient, distributionSpec));
} else {
String securityUniqueId = fullyQualifiedSpec.getIdentifier(getUniqueIdDomain());
if (securityUniqueId == null) {
String errorMsg = "Qualified spec " + fullyQualifiedSpec + " does not contain ID of domain " + getUniqueIdDomain();
responses.add(buildErrorMessageResponse(specFromClient, LiveDataSubscriptionResult.INTERNAL_ERROR, errorMsg));
continue;
}
subscription = new Subscription(securityUniqueId, getMarketDataSenderFactory(), getLkvStoreProvider());
securityUniqueId2NewSubscription.put(subscription.getSecurityUniqueId(), subscription);
securityUniqueId2SpecFromClient.put(subscription.getSecurityUniqueId(), specFromClient);
}
subscription.createDistributor(distributionSpec, persistent).setExpiry(distributionExpiryTime);
}
//Allow checks here, before we do the snapshot or the subscribe
checkSubscribe(securityUniqueId2NewSubscription.keySet());
// In some cases, the underlying market data API may not, when the subscription is started,
// return a full image of all fields. If so, we need to get the full image explicitly.
Collection<String> newSubscriptionsForWhichSnapshotIsRequired = new ArrayList<>();
for (Subscription subscription : securityUniqueId2NewSubscription.values()) {
if (snapshotOnSubscriptionStartRequired(subscription)) {
newSubscriptionsForWhichSnapshotIsRequired.add(subscription.getSecurityUniqueId());
}
}
s_logger.info("Subscription snapshot required for {}", newSubscriptionsForWhichSnapshotIsRequired);
Map<String, FudgeMsg> snapshots = doSnapshot(newSubscriptionsForWhichSnapshotIsRequired);
for (Map.Entry<String, FudgeMsg> snapshot : snapshots.entrySet()) {
Subscription subscription = securityUniqueId2NewSubscription.get(snapshot.getKey());
subscription.initialSnapshotReceived(snapshot.getValue());
}
// Setup the subscriptions in the underlying data provider.
for (Subscription subscription : securityUniqueId2NewSubscription.values()) {
// this is necessary so we don't lose any updates immediately after doSubscribe(). See AbstractLiveDataServer#liveDataReceived()
// and how it calls AbstractLiveDataServer#getSubscription()
_securityUniqueId2Subscription.put(subscription.getSecurityUniqueId(), subscription);
}
s_logger.info("Creating underlying market data API subscription to {}", securityUniqueId2NewSubscription.keySet());
Map<String, Object> subscriptionHandles = doSubscribe(securityUniqueId2NewSubscription.keySet());
// Set up data structures
for (Map.Entry<String, Object> subscriptionHandle : subscriptionHandles.entrySet()) {
String securityUniqueId = subscriptionHandle.getKey();
Object handle = subscriptionHandle.getValue();
LiveDataSpecification specFromClient = securityUniqueId2SpecFromClient.get(securityUniqueId);
Subscription subscription = securityUniqueId2NewSubscription.get(securityUniqueId);
subscription.setHandle(handle);
_currentlyActiveSubscriptions.add(subscription);