/// <summary>
/// Publishes a subscription.
/// </summary>
public NotificationMessage GetNextMessage(
OperationContext context,
SessionPublishQueue queue,
AsyncPublishOperation operation,
out uint subscriptionId,
out UInt32Collection availableSequenceNumbers,
out bool moreNotifications)
{
subscriptionId = 0;
availableSequenceNumbers = null;
moreNotifications = false;
NotificationMessage message = null;
try
{
Utils.Trace("Publish #{0} ReceivedFromClient", context.ClientHandle);
// check for status messages.
lock (m_statusMessages)
{
Queue<StatusMessage> statusQueue = null;
if (m_statusMessages.TryGetValue(context.SessionId, out statusQueue))
{
if (statusQueue.Count > 0)
{
StatusMessage status = statusQueue.Dequeue();
subscriptionId = status.SubscriptionId;
return status.Message;
}
}
}
bool requeue = false;
do
{
// wait for a subscription to publish.
Subscription subscription = queue.Publish(
context.ClientHandle,
context.OperationDeadline,
requeue,
operation);
if (subscription == null)
{
Utils.Trace("Publish #{0} Timeout", context.ClientHandle);
return null;
}
subscriptionId = subscription.Id;
moreNotifications = false;
// publish notifications.
try
{
requeue = false;
message = subscription.Publish(
context,
out availableSequenceNumbers,
out moreNotifications);
// a null message indicates a false alarm and that there were no notifications
// to publish and that the request needs to be requeued.
if (message != null)
{
break;
}
Utils.Trace("Publish False Alarm - Request #{0} Requeued.", context.ClientHandle);
requeue = true;
}
finally
{
queue.PublishCompleted(subscription, moreNotifications);
}
}
while (requeue);
}
finally
{
// update diagnostics.
if (context.Session != null)
{
lock (context.Session.DiagnosticsLock)
{
SessionDiagnosticsDataType diagnostics = context.Session.SessionDiagnostics;
diagnostics.CurrentPublishRequestsInQueue--;
}
}
}
return message;
}