private static void RefreshContactLinkingDefaultFolderIds(MailboxSession mailboxSession) { foreach (DefaultFolderType folderType in ContactsSearchFolderCriteria.MyContactsExtended.ScopeDefaultFolderTypes) { AutomaticLink.RefreshDefaultFolderWithRetry(mailboxSession, folderType); } }
public void ItemOperation(COWSettings settings, IDumpsterItemOperations dumpster, COWTriggerAction operation, COWTriggerActionState state, StoreSession session, StoreObjectId itemId, CoreItem item, CoreFolder folder, bool onBeforeNotification, OperationResult result, CallbackContext callbackContext) { Util.ThrowOnNullArgument(session, "session"); Util.ThrowOnNullArgument(item, "item"); EnumValidator.ThrowIfInvalid <COWTriggerAction>(operation, "operation"); EnumValidator.ThrowIfInvalid <COWTriggerActionState>(state, "state"); EnumValidator.ThrowIfInvalid <OperationResult>(result, "result"); COWContactLinking.Tracer.TraceDebug <StoreObjectId>((long)this.GetHashCode(), "COWContactLinking.ItemOperation: processing contact linking for item {0}.", itemId); MailboxSession mailboxSession = (MailboxSession)session; MailboxInfoForLinking mailboxInfo = MailboxInfoForLinking.CreateFromMailboxSession(mailboxSession); ContactLinkingPerformanceTracker performanceTracker = new ContactLinkingPerformanceTracker(mailboxSession); DirectoryPersonSearcher directoryPersonSearcher = new DirectoryPersonSearcher(mailboxSession.MailboxOwner); ContactStoreForContactLinking contactStoreForContactLinking = new ContactStoreForCowContactLinking(mailboxSession, performanceTracker); ContactLinkingLogger logger = new ContactLinkingLogger("COWContactLinking", mailboxInfo); AutomaticLink automaticLink = new AutomaticLink(mailboxInfo, logger, performanceTracker, directoryPersonSearcher, contactStoreForContactLinking); automaticLink.LinkNewOrUpdatedContactBeforeSave(item, new Func <ContactInfoForLinking, IContactStoreForContactLinking, IEnumerable <ContactInfoForLinking> >(this.GetOtherContactsEnumeratorForCOW)); if (!onBeforeNotification) { item.SaveFlags |= PropertyBagSaveFlags.ForceNotificationPublish; try { item.Save(SaveMode.NoConflictResolution); } finally { item.SaveFlags &= ~PropertyBagSaveFlags.ForceNotificationPublish; } } callbackContext.ContactLinkingProcessingState = ContactLinkingProcessingState.Processed; }
protected override void UpdateContact(IExtensibleLogger logger, IContactLinkingPerformanceTracker performanceTracker) { ContactInfoForLinking.Tracer.TraceDebug <VersionedId, string>((long)this.GetHashCode(), "ContactInfoForLinkingFromPropertyBag.UpdateContact: setting link properties AND saving contact with id = {0}; given-name: {1}", base.ItemId, base.GivenName); base.RetryOnTransientExceptionCatchObjectNotFoundException(logger, "update of contact Id=" + base.ItemId, delegate { using (Contact contact = Contact.Bind(this.mailboxSession, base.ItemId, new PropertyDefinition[] { ContactSchema.PersonId })) { base.SetLinkingProperties(PropertyBagAdaptor.Create(contact)); AutomaticLink.DisableAutomaticLinkingForItem(contact); contact.Save(SaveMode.NoConflictResolution); } }); performanceTracker.IncrementContactsUpdated(); }
private void LinkTwoContacts(ContactLinkingOperation operation, ContactInfoForLinking contact1, ContactInfoForLinking contact2) { if (!contact1.Linked && contact2.Linked) { this.LogLinkOperation(operation, contact1, contact2); this.UpdatePersonaId(contact1, contact2.PersonId); contact1.Linked = true; } else if (contact1.Linked && !contact2.Linked) { this.LogLinkOperation(operation, contact2, contact1); this.UpdatePersonaId(contact2, contact1.PersonId); contact2.Linked = true; } else if (contact1.Linked && contact2.Linked) { this.LogLinkOperation(operation, contact2, contact1); this.UpdatePersonaId(contact2, contact1.PersonId); } else { if (!contact2.IsNew && contact1.IsNew) { this.LogLinkOperation(operation, contact1, contact2); this.UpdatePersonaId(contact1, contact2.PersonId); } else { this.LogLinkOperation(operation, contact2, contact1); this.UpdatePersonaId(contact2, contact1.PersonId); } contact1.Linked = true; contact2.Linked = true; } contact1.LinkRejectHistory.UnionWith(contact2.LinkRejectHistory); contact2.LinkRejectHistory = contact1.LinkRejectHistory; AutomaticLink.MergeGALLinkState(contact1, contact2); }
internal static void PerformContactLinkingAfterMigration(StoreSession storeSession) { MailboxSession mailboxSession = storeSession as MailboxSession; if (mailboxSession == null) { ContactLink.Tracer.TraceDebug(0L, "AutomaticLink::PerformContactLinkingAfterMigration. Skiping session as it is not a MailboxSession."); return; } ContactLink.Tracer.TraceDebug <MailboxSession>(0L, "StoreSession::PerformContactLinking. Starting linking for {0}.", mailboxSession); ExDateTime exDateTime = ExDateTime.Now.Add(AutomaticLink.AllocatedTimeSlotForLinkingOnMigration.Value); MailboxInfoForLinking mailboxInfoForLinking = MailboxInfoForLinking.CreateFromMailboxSession(mailboxSession); ContactLinkingPerformanceTracker performanceTracker = new ContactLinkingPerformanceTracker(mailboxSession); DirectoryPersonSearcher directoryPersonSearcher = new DirectoryPersonSearcher(mailboxSession.MailboxOwner); ContactStoreForBulkContactLinking contactStoreForBulkContactLinking = new ContactStoreForBulkContactLinking(mailboxSession, performanceTracker); ContactLinkingLogger contactLinkingLogger = new ContactLinkingLogger("PerformContactLinkingAfterMigration", mailboxInfoForLinking); bool flag = false; contactLinkingLogger.LogEvent(new SchemaBasedLogEvent <ContactLinkingLogSchema.MigrationStart> { { ContactLinkingLogSchema.MigrationStart.DueTime, (DateTime)exDateTime } }); try { AutomaticLink.RefreshContactLinkingDefaultFolderIds(mailboxSession); AutomaticLink automaticLink = new AutomaticLink(mailboxInfoForLinking, contactLinkingLogger, performanceTracker, directoryPersonSearcher, contactStoreForBulkContactLinking); automaticLink.LinkAllExistingContactsTimeBound(exDateTime); flag = true; } catch (DefaultFolderNameClashException e) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e); } catch (AccessDeniedException e2) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e2); } catch (ConnectionFailedTransientException e3) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e3); } catch (FolderSaveTransientException e4) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e4); } catch (MailboxUnavailableException e5) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e5); } catch (ObjectNotFoundException e6) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e6); } catch (StorageTransientException e7) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e7); } catch (StoragePermanentException e8) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e8); } catch (Exception e9) { AutomaticLink.TraceAndLogExceptionDuringLinkingPostMigration(mailboxInfoForLinking, contactLinkingLogger, e9); throw; } finally { contactLinkingLogger.LogEvent(new SchemaBasedLogEvent <ContactLinkingLogSchema.MigrationEnd> { { ContactLinkingLogSchema.MigrationEnd.Success, flag } }); ContactLink.Tracer.TraceDebug <MailboxInfoForLinking, bool>(0L, "AutomaticLink::PerformContactLinkingAfterMigration. Done processing {0}. Contact linking completed successfully: {1}", mailboxInfoForLinking, flag); } }
private HashSet <ContactInfoForLinking> LinkWithContacts(ContactInfoForLinking contactBeingSaved, IEnumerable <ContactInfoForLinking> otherContacts, int maxLinkCount, out bool linkedToDirectory) { linkedToDirectory = false; HashSet <ContactInfoForLinking> hashSet = new HashSet <ContactInfoForLinking>(ContactInfoForLinkingComparerByItemId.Instance); PersonId personId = contactBeingSaved.PersonId; HashSet <PersonId> hashSet2 = new HashSet <PersonId>(); ContactInfoForLinkingFromDirectory contactInfoForLinkingFromDirectory = null; if (contactBeingSaved.GALLinkState != GALLinkState.NotAllowed && contactBeingSaved.GALLinkID == null) { this.TryFindDirectoryMatch(contactBeingSaved, out contactInfoForLinkingFromDirectory); } foreach (ContactInfoForLinking contactInfoForLinking in otherContacts) { if (!this.CanContinueProcessingContacts()) { break; } if (!contactInfoForLinking.PersonId.Equals(personId) && !ContactInfoForLinkingComparerByItemId.Instance.Equals(contactInfoForLinking, contactBeingSaved) && !hashSet2.Contains(contactInfoForLinking.PersonId)) { ContactLinkingOperation contactLinkingOperation = AutomaticLinkCriteria.CanLink(contactBeingSaved, contactInfoForLinking); if (contactInfoForLinkingFromDirectory != null && contactInfoForLinking.GALLinkState == GALLinkState.Linked && contactInfoForLinking.GALLinkID == contactInfoForLinkingFromDirectory.GALLinkID) { if (contactLinkingOperation == ContactLinkingOperation.None) { contactLinkingOperation = ContactLinkingOperation.AutoLinkViaGalLinkId; } contactInfoForLinkingFromDirectory = null; } if (AutomaticLink.ShouldLink(contactLinkingOperation)) { hashSet2.Add(contactInfoForLinking.PersonId); HashSet <ContactInfoForLinking> hashSet3 = new HashSet <ContactInfoForLinking>(this.contactStoreForContactLinking.GetPersonContacts(contactInfoForLinking.PersonId)); if (hashSet3.Count + hashSet.Count <= maxLinkCount) { hashSet.UnionWith(hashSet3); this.LinkTwoContacts(contactLinkingOperation, contactBeingSaved, contactInfoForLinking); if (hashSet.Count == maxLinkCount) { string text = string.Format(CultureInfo.InvariantCulture, "Stopping linking iteration for PersonID {0} because we have reached maximum number of contacts for the persona.", new object[] { contactBeingSaved.PersonId }); ContactLink.Tracer.TraceDebug <string>((long)this.GetHashCode(), "AutomaticLinking.LinkWithContacts: {0}", text); base.LogEvent(new SchemaBasedLogEvent <ContactLinkingLogSchema.Warning> { { ContactLinkingLogSchema.Warning.Context, text } }); break; } } else { ContactLink.Tracer.TraceDebug <PersonId, VersionedId>((long)this.GetHashCode(), "AutomaticLinking.LinkWithContacts: Skipping link with PersonID {0} for item {1} because we would be over the maximum number of contacts for the persona.", contactInfoForLinking.PersonId, contactBeingSaved.ItemId); this.LogSkippedContactLinking(contactBeingSaved, hashSet.Count, maxLinkCount, contactInfoForLinking, hashSet3.Count); } } } } if (contactInfoForLinkingFromDirectory != null && contactBeingSaved.GALLinkState != GALLinkState.Linked) { this.LogGALLinkOperation(contactBeingSaved, contactInfoForLinkingFromDirectory); contactBeingSaved.SetGALLink(contactInfoForLinkingFromDirectory); linkedToDirectory = true; } return(hashSet); }