private void ProcessNotificationLinkConfirmation( string objectUrl, string linkID, NotificationLinkConfirmation notificationLinkConfirmation) { if (2 != Interlocked.Increment(ref notificationLinkConfirmation.NumItemsRecieved)) // Not ready for processing return; // Remove old NotificationLinkConfirmation from RAM ThreadPool.QueueUserWorkItem(delegate(object state) { try { NotificationLinkConfirmationLock.EnterUpgradeableReadLock(); try { Dictionary<string, NotificationLinkConfirmation> objectUrlDictionary; if (NotificationLinkConfirmationsByObjectUrlByLinkID.TryGetValue(objectUrl, out objectUrlDictionary)) lock (objectUrlDictionary) { objectUrlDictionary.Remove(linkID); if (0 == objectUrlDictionary.Count) { NotificationLinkConfirmationLock.EnterWriteLock(); try { NotificationLinkConfirmationsByObjectUrlByLinkID.Remove(objectUrl); } finally { NotificationLinkConfirmationLock.ExitWriteLock(); } } } } finally { NotificationLinkConfirmationLock.ExitUpgradeableReadLock(); } } catch (Exception e) { log.Error("Exception cleaning " + objectUrl + " from the cached link notifications", e); } }); if (!notificationLinkConfirmation.NotificationLinkInfo.Equals( notificationLinkConfirmation.ConfirmationLinkInfo)) { log.Warn("Notification confirmation mismatch on a link: " + JsonWriter.Serialize(notificationLinkConfirmation)); return; } HashSet<string> recipients = new HashSet<string>(notificationLinkConfirmation.NotificationLinkInfo.RecipientIdentities); recipients.IntersectWith(notificationLinkConfirmation.ConfirmationLinkInfo.RecipientIdentities); // Start handling the result for each recipient foreach (string recipient in recipients) ThreadPool.QueueUserWorkItem(delegate(object recipientObj) { try { ReceiveNotification( notificationLinkConfirmation.SenderIdentity, recipientObj.ToString(), objectUrl, notificationLinkConfirmation.SummaryView, notificationLinkConfirmation.DocumentType, "link", notificationLinkConfirmation.ChangeData, notificationLinkConfirmation.ConfirmationLinkInfo.OwnerIdentity); } catch (Exception e) { log.Warn("Exception processing a confirmed link notification", e); } }, recipient); }
private NotificationLinkConfirmation GetNotificationLinkConfirmation(string objectUrl, string linkID) { // Make sure the timer is created if (null == NotificationLinkConfirmationTimer) { Timer timer = new Timer(NotificationLinkConfirmationCleanup, null, 600000, 600000); if (null != Interlocked.CompareExchange<Timer>(ref NotificationLinkConfirmationTimer, timer, null)) timer.Dispose(); } // Get the dictionary for the the object url Dictionary<string, NotificationLinkConfirmation> forObjectUrl; NotificationLinkConfirmationLock.EnterUpgradeableReadLock(); try { // If there's no dictionary, aquire a write lock, re-check, and then create it if (!NotificationLinkConfirmationsByObjectUrlByLinkID.TryGetValue(objectUrl, out forObjectUrl)) { NotificationLinkConfirmationLock.EnterWriteLock(); try { if (!NotificationLinkConfirmationsByObjectUrlByLinkID.TryGetValue(objectUrl, out forObjectUrl)) { forObjectUrl = new Dictionary<string, NotificationLinkConfirmation>(); NotificationLinkConfirmationsByObjectUrlByLinkID[objectUrl] = forObjectUrl; } } finally { NotificationLinkConfirmationLock.ExitWriteLock(); } } // Manipulation of the dictionary needs to happen within the read lock because NotificationLinkConfirmationsByObjectUrlByLinkID // is also cleaned within a lock lock (forObjectUrl) { NotificationLinkConfirmation toReturn; if (!forObjectUrl.TryGetValue(linkID, out toReturn)) { toReturn = new NotificationLinkConfirmation(); forObjectUrl[linkID] = toReturn; } return toReturn; } } finally { NotificationLinkConfirmationLock.ExitUpgradeableReadLock(); } }