private void ProcessSyncStateFolders(Folder deviceFolder, ISyncLogger syncLogger) { using (QueryResult queryResult = deviceFolder.FolderQuery(FolderQueryFlags.None, null, null, DeviceSyncStateMetadata.NullSyncPropertiesFolders)) { for (;;) { IStorePropertyBag[] propertyBags = queryResult.GetPropertyBags(100); if (propertyBags == null || propertyBags.Length == 0) { break; } foreach (IStorePropertyBag propertyBag in propertyBags) { SyncStateMetadata metadataFromPropertyBag = this.GetMetadataFromPropertyBag(deviceFolder.Session as MailboxSession, propertyBag, syncLogger); if (metadataFromPropertyBag != null) { syncLogger.TraceDebug <SyncStateMetadata>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.ProcessSyncStateFolders] Found SyncState: {0}", metadataFromPropertyBag); this.syncStateMap.TryAdd(metadataFromPropertyBag.Name, metadataFromPropertyBag); } else { syncLogger.TraceDebug <DeviceIdentity>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.ProcessSyncStateFolders] Discovered unusable sync state for device {0}", this.Id); } } } } }
private void ProcessSyncStateItems(Folder deviceFolder, ISyncLogger syncLogger) { using (QueryResult queryResult = deviceFolder.ItemQuery(ItemQueryType.None, null, null, DeviceSyncStateMetadata.NullSyncPropertiesItems)) { for (;;) { IStorePropertyBag[] propertyBags = queryResult.GetPropertyBags(100); if (propertyBags == null || propertyBags.Length == 0) { break; } foreach (IStorePropertyBag storePropertyBag in propertyBags) { string displayName = (string)storePropertyBag.TryGetProperty(ItemSchema.Subject); SyncStateMetadata metadataFromPropertyBag = this.GetMetadataFromPropertyBag(storePropertyBag, displayName, syncLogger); if (metadataFromPropertyBag != null) { StoreObjectId objectId = ((VersionedId)storePropertyBag.TryGetProperty(ItemSchema.Id)).ObjectId; metadataFromPropertyBag.FolderSyncStateId = null; metadataFromPropertyBag.ItemSyncStateId = objectId; syncLogger.TraceDebug <SyncStateMetadata>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.ProcessSyncStateItems] Found Item SyncState: {0}", metadataFromPropertyBag); this.syncStateMap.TryAdd(metadataFromPropertyBag.Name, metadataFromPropertyBag); } else { syncLogger.TraceDebug <DeviceIdentity>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.ProcessSyncStateItems] Discovered unusable sync state for device {0}", this.Id); } } } } }
private SyncStateMetadata GetSyncStateItemMetadata(MailboxSession mailboxSession, Folder parentFolder, string displayName, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } using (QueryResult queryResult = parentFolder.ItemQuery(ItemQueryType.None, null, new SortBy[] { new SortBy(ItemSchema.Subject, SortOrder.Ascending) }, DeviceSyncStateMetadata.NullSyncPropertiesItems)) { if (queryResult.SeekToCondition(SeekReference.OriginBeginning, new ComparisonFilter(ComparisonOperator.Equal, ItemSchema.Subject, displayName))) { IStorePropertyBag storePropertyBag = queryResult.GetPropertyBags(1)[0]; StoreObjectId objectId = ((VersionedId)storePropertyBag.TryGetProperty(ItemSchema.Id)).ObjectId; syncLogger.TraceDebug <string, SmtpAddress, string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncStateItemMetadata] Sync state '{0}' for mailbox '{1}' is stored on item id '{2}'", displayName, mailboxSession.MailboxOwner.MailboxInfo.PrimarySmtpAddress, objectId.ToBase64String()); SyncStateMetadata metadataFromPropertyBag = this.GetMetadataFromPropertyBag(storePropertyBag, displayName, syncLogger); metadataFromPropertyBag.FolderSyncStateId = parentFolder.Id.ObjectId; metadataFromPropertyBag.ItemSyncStateId = objectId; return(metadataFromPropertyBag); } } syncLogger.TraceDebug <string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncStateItemMetadata] Did not find child item with name {0}", displayName); return(null); }
private static FolderSyncStateMetadata GetFolderSyncStateMetadata(SyncStateStorage syncStateStorage, MailboxSession mailboxSession, string name, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } SyncStateMetadata syncState = syncStateStorage.DeviceMetadata.GetSyncState(mailboxSession, name, syncLogger); FolderSyncStateMetadata folderSyncStateMetadata = syncState as FolderSyncStateMetadata; if (folderSyncStateMetadata == null) { syncLogger.TraceDebug <SmtpAddress, string>(ExTraceGlobals.SyncProcessTracer, 0L, "[FolderSyncState.GetFolderSyncStateMetadata] SyncStateMetadata in place of FolderSyncStateMetadata for Mailbox: {0}, State: {1}. Trying re-read...", mailboxSession.MailboxOwner.MailboxInfo.PrimarySmtpAddress, name); syncStateStorage.DeviceMetadata.TryRemove(name, syncLogger); syncState = syncStateStorage.DeviceMetadata.GetSyncState(mailboxSession, name, syncLogger); folderSyncStateMetadata = (syncState as FolderSyncStateMetadata); if (folderSyncStateMetadata == null) { syncStateStorage.DeleteFolderSyncState(name); syncStateStorage.DeviceMetadata.TryRemove(name, null); throw new CorruptSyncStateException(ServerStrings.ExSyncStateCorrupted(name), new InvalidOperationException("SyncStateMetadata in place of FolderSyncStateMetadata")); } syncLogger.TraceDebug <string>(ExTraceGlobals.SyncProcessTracer, 0L, "[FolderSyncState.GetFolderSyncStateMetadata] Re-read of sync state {0} was successful.", name); } return(folderSyncStateMetadata); }
internal static FolderHierarchySyncState GetSyncState(SyncStateStorage syncStateStorage, Folder syncStateParentFolder, StoreObjectId storeObjectId, ISyncLogger syncLogger = null) { SyncStateInfo syncStateInfo = new FolderHierarchySyncStateInfo(); StoreObject syncStateStoreObject = SyncState.GetSyncStateStoreObject(syncStateStorage, syncStateParentFolder, syncStateInfo, syncLogger, new PropertyDefinition[0]); if (syncStateStoreObject == null) { return(null); } SyncStateMetadata syncState = syncStateStorage.DeviceMetadata.GetSyncState(syncStateParentFolder.Session as MailboxSession, syncStateInfo.UniqueName, syncLogger); return(new FolderHierarchySyncState(syncStateStorage, syncStateStoreObject, syncState, syncStateInfo, false, syncLogger)); }
internal static CustomSyncState GetSyncState(SyncStateStorage syncStateStorage, Folder syncStateParentFolder, SyncStateInfo syncStateInfo, ISyncLogger syncLogger, params PropertyDefinition[] propertiesToFetch) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } SyncStateMetadata syncStateMetadata = null; StoreObject syncStateStoreObject = SyncState.GetSyncStateStoreObject(syncStateStorage, syncStateParentFolder, syncStateInfo, syncLogger, out syncStateMetadata, propertiesToFetch); if (syncStateStoreObject == null) { return(null); } return(new CustomSyncState(syncStateStorage, syncStateStoreObject, syncStateMetadata, syncStateInfo, false)); }
internal static CustomSyncState CreateSyncState(SyncStateStorage syncStateStorage, SyncStateInfo syncStateInfo, Folder syncStateParentFolder, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } StoreObject storeObject = SyncState.CreateSyncStateStoreObject(syncStateStorage, syncStateInfo, syncStateParentFolder, null, null, syncLogger); if (syncStateStorage.DeviceMetadata.TryRemove(syncStateInfo.UniqueName, syncLogger) != null) { syncLogger.TraceDebug <DeviceIdentity, string>(ExTraceGlobals.SyncTracer, 0L, "[CustomSyncState.CreateSyncState] Removed stale cached sync state metadata for device {0}, sync state {1}", syncStateStorage.DeviceMetadata.Id, syncStateInfo.UniqueName); } SyncStateMetadata syncStateMetadata = (storeObject is Item) ? new SyncStateMetadata(syncStateStorage.DeviceMetadata, syncStateInfo.UniqueName, syncStateStorage.SaveOnDirectItems ? null : storeObject.ParentId, storeObject.Id.ObjectId) : new SyncStateMetadata(syncStateStorage.DeviceMetadata, syncStateInfo.UniqueName, storeObject.Id.ObjectId, null); return(new CustomSyncState(syncStateStorage, storeObject, syncStateMetadata, syncStateInfo, true)); }
private static void GetSyncStateBlob(MailboxSession session, SyncStateMetadata syncStateMetadata, SyncStateFolderData data) { switch (syncStateMetadata.StorageType) { case StorageType.Folder: using (Folder folder = Folder.Bind(session, syncStateMetadata.FolderSyncStateId, new PropertyDefinition[] { ItemSchema.SyncCustomState })) { object obj = folder.TryGetProperty(ItemSchema.SyncCustomState); byte[] array = obj as byte[]; data.SyncStateBlob = Convert.ToBase64String(array); data.SyncStateSize = array.Length; data.Created = (DateTime)folder.CreationTime; return; } break; case StorageType.Item: case StorageType.DirectItem: break; default: return; } using (Item item = Item.Bind(session, syncStateMetadata.ItemSyncStateId, new PropertyDefinition[] { ItemSchema.SyncCustomState })) { using (MemoryStream memoryStream = new MemoryStream()) { using (Stream stream = item.OpenPropertyStream(ItemSchema.SyncCustomState, PropertyOpenMode.ReadOnly)) { byte[] data2 = new byte[1024]; Util.StreamHandler.CopyStreamData(stream, memoryStream, null, 0, data2); memoryStream.Flush(); } data.Created = (DateTime)item.CreationTime; data.SyncStateSize = (int)memoryStream.Position; string syncStateBlob = Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Position, Base64FormattingOptions.None); data.SyncStateBlob = syncStateBlob; } } }
private AggregateOperationResult InternalDeleteSyncState(string name) { this.CheckDisposed("DeleteCustomSyncState"); this.syncLogger.Information <int>(ExTraceGlobals.SyncTracer, (long)this.GetHashCode(), "SyncStateStorage::InternalDeleteSyncState. Hashcode = {0}", this.GetHashCode()); ArgumentValidator.ThrowIfNullOrEmpty("name", name); SyncStateMetadata syncState = this.DeviceMetadata.GetSyncState(this.folder.Session as MailboxSession, name, this.syncLogger); this.DeviceMetadata.TryRemove(name, this.syncLogger); AggregateOperationResult result = null; if (syncState != null) { if (syncState.FolderSyncStateId == null && syncState.ItemSyncStateId != null) { this.syncLogger.Information <string>(ExTraceGlobals.SyncTracer, (long)this.GetHashCode(), "[SyncStateStorage.InternalDeleteSyncState] Deleting direct item sync state {0}", name); result = this.folder.DeleteObjects(DeleteItemFlags.SoftDelete, new StoreId[] { syncState.ItemSyncStateId }); } else if (syncState.FolderSyncStateId != null) { this.syncLogger.Information <string>(ExTraceGlobals.SyncTracer, (long)this.GetHashCode(), "[SyncStateStorage.InternalDeleteSyncState] Deleting sync folder for sync state {0}", name); result = this.folder.DeleteObjects(DeleteItemFlags.SoftDelete, new StoreId[] { syncState.FolderSyncStateId }); } else { this.syncLogger.Information <string>(ExTraceGlobals.SyncTracer, (long)this.GetHashCode(), "[SyncStateStorage.InternalDeleteSyncState] Metadata had null for both item and folder id. Weird - not deleting anything. Sync State: {0}", name); } StoreObjectId storeObjectId = (syncState.FolderSyncStateId != null) ? syncState.FolderSyncStateId : syncState.ItemSyncStateId; if (storeObjectId != null) { this.TraceAggregateOperationResultFromDelete(result, name, storeObjectId); } } return(result); }
public SyncStateMetadata TryAdd(SyncStateMetadata syncStateMetadata, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } SyncStateMetadata syncStateMetadata2 = this.syncStateMap.GetOrAdd(syncStateMetadata.Name, syncStateMetadata); if (syncStateMetadata.GetType().IsSubclassOf(syncStateMetadata2.GetType())) { syncLogger.TraceDebug <string, string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.TryAdd] New sync state metadata instance ({0}) is subclass of cached one ({1}). Replacing.", syncStateMetadata.GetType().Name, syncStateMetadata2.GetType().Name); this.syncStateMap[syncStateMetadata.Name] = syncStateMetadata; syncStateMetadata2 = syncStateMetadata; } FolderSyncStateMetadata folderSyncStateMetadata = syncStateMetadata2 as FolderSyncStateMetadata; if (folderSyncStateMetadata != null && folderSyncStateMetadata.IPMFolderId != null) { syncLogger.TraceDebug <string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.TryAdd] Encountered FolderSyncStateMetadata instance for '{0}'. Adding source key to reverse mapping.", syncStateMetadata.Name); this.ipmToFolderSyncStateMap[folderSyncStateMetadata.IPMFolderId] = folderSyncStateMetadata; } return(syncStateMetadata2); }
protected FolderHierarchySyncState(SyncStateStorage syncStateStorage, StoreObject storeObject, SyncStateMetadata syncStateMetadata, SyncStateInfo syncStateInfo, bool newSyncState, ISyncLogger syncLogger = null) : base(syncStateStorage, storeObject, syncStateMetadata, syncStateInfo, newSyncState, syncLogger) { }
public SyncStateMetadata GetSyncState(MailboxSession mailboxSession, string name, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } SyncStateMetadata result; if (this.syncStateMap.TryGetValue(name, out result)) { syncLogger.TraceDebug <string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Cache hit for sync state: {0}", name); return(result); } syncLogger.TraceDebug <string>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Cache MISS for sync state: {0}", name); using (Folder folder = Folder.Bind(mailboxSession, this.DeviceFolderId, new PropertyDefinition[] { FolderSchema.ItemCount, FolderSchema.ChildCount })) { int itemCount = folder.ItemCount; syncLogger.TraceDebug <string, int, bool>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] deviceFolder {0} has {1} items and subfolders? {2}", folder.DisplayName, itemCount, folder.HasSubfolders); SyncStateMetadata syncStateMetadata = null; if (itemCount > 0) { syncStateMetadata = this.GetSyncStateItemMetadata(mailboxSession, folder, name, syncLogger); if (syncStateMetadata != null) { syncLogger.TraceDebug <SyncStateMetadata>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Retrieved DIRECT item sync state: {0}", syncStateMetadata); syncStateMetadata.FolderSyncStateId = null; } } if (syncStateMetadata == null && folder.HasSubfolders) { using (QueryResult queryResult = folder.FolderQuery(FolderQueryFlags.None, null, new SortBy[] { new SortBy(FolderSchema.DisplayName, SortOrder.Ascending) }, DeviceSyncStateMetadata.NullSyncPropertiesFolders)) { if (queryResult.SeekToCondition(SeekReference.OriginBeginning, new ComparisonFilter(ComparisonOperator.Equal, FolderSchema.DisplayName, name))) { IStorePropertyBag propertyBag = queryResult.GetPropertyBags(1)[0]; syncStateMetadata = this.GetMetadataFromPropertyBag(mailboxSession, propertyBag, syncLogger); if (syncStateMetadata != null) { syncLogger.TraceDebug <SyncStateMetadata>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Retrieved sub folder sync state: {0}", syncStateMetadata); } } } } if (syncStateMetadata != null) { SyncStateMetadata syncStateMetadata2 = this.syncStateMap.GetOrAdd(syncStateMetadata.Name, syncStateMetadata); if (syncStateMetadata2.StorageType != syncStateMetadata.StorageType) { syncLogger.TraceDebug <StorageType, StorageType>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Metadata was already cached but had store type: {0}. New instance was: {1}. Using new instance.", syncStateMetadata2.StorageType, syncStateMetadata.StorageType); this.syncStateMap[syncStateMetadata.Name] = syncStateMetadata; syncStateMetadata2 = syncStateMetadata; } return(syncStateMetadata2); } syncLogger.TraceDebug <string, Guid>(ExTraceGlobals.SyncProcessTracer, (long)this.GetHashCode(), "[DeviceSyncStateMetadata.GetSyncState] Cache miss for sync state {0}, Mailbox {1}, but search did not find it.", name, mailboxSession.MailboxGuid); } return(null); }
internal static FolderSyncState GetSyncState(SyncStateStorage syncStateStorage, Folder deviceFolder, ISyncProviderFactory syncProviderFactory, Func <SyncStateStorage, StoreObject, FolderSyncStateMetadata, SyncStateInfo, ISyncProviderFactory, bool, ISyncLogger, FolderSyncState> creator, ISyncLogger syncLogger = null) { if (syncLogger == null) { syncLogger = TracingLogger.Singleton; } ArgumentValidator.ThrowIfNull("syncStateStorage", syncStateStorage); ArgumentValidator.ThrowIfNull("deviceFolder", deviceFolder); ArgumentValidator.ThrowIfNull("syncProviderFactory", syncProviderFactory); byte[] collectionIdBytes = syncProviderFactory.GetCollectionIdBytes(); if (collectionIdBytes == null || collectionIdBytes.Length == 0) { throw new ArgumentException("SyncProviderFactory CollectionId bytes cannot be null or empty."); } StoreObjectId storeObjectId = null; try { storeObjectId = StoreObjectId.Deserialize(collectionIdBytes); } catch (ArgumentException innerException) { syncLogger.TraceError <string>(ExTraceGlobals.SyncTracer, 0L, "[FolderSyncState.GetSyncState(syncProviderFactory)] The IPMFolderBytes that the provider gave us are invalid for folder {0}", deviceFolder.DisplayName); throw new CorruptSyncStateException(ServerStrings.ExSyncStateCorrupted(deviceFolder.DisplayName), innerException); } FolderSyncStateMetadata folderSyncStateMetadata = null; if (!syncStateStorage.DeviceMetadata.SyncStatesByIPMFolderId.TryGetValue(storeObjectId, out folderSyncStateMetadata)) { syncLogger.TraceDebug <DeviceIdentity, string>(ExTraceGlobals.SyncTracer, 0L, "[FolderSyncState.GetSyncState(syncProviderFactory)] Cache miss for device {0}, IPM folder Id {1}", syncStateStorage.DeviceMetadata.Id, storeObjectId.ToBase64String()); return(null); } SyncStateMetadata syncStateMetadata = folderSyncStateMetadata; StoreObject storeObject = SyncState.GetSyncStateStoreObject(deviceFolder, ref syncStateMetadata, syncLogger, new PropertyDefinition[] { InternalSchema.SyncFolderSourceKey }); if (!object.ReferenceEquals(folderSyncStateMetadata, syncStateMetadata)) { FolderSyncStateMetadata folderSyncStateMetadata2 = syncStateMetadata as FolderSyncStateMetadata; if (folderSyncStateMetadata2 == null) { syncLogger.TraceDebug <string, string>(ExTraceGlobals.SyncProcessTracer, 0L, "[FolderSyncState.GetSyncState] Device {0} has non-folder sync state for {1}. Returning null.", deviceFolder.DisplayName, folderSyncStateMetadata.Name); if (storeObject != null) { storeObject.Dispose(); storeObject = null; } } else { syncLogger.TraceDebug <string, string>(ExTraceGlobals.SyncProcessTracer, 0L, "[FolderSyncState.GetSyncState] Device {0} had state folder sync state metadata for {1}. Replacing.", deviceFolder.DisplayName, folderSyncStateMetadata.Name); folderSyncStateMetadata = folderSyncStateMetadata2; } } if (storeObject == null) { return(null); } SyncStateInfo syncStateInfo = new FolderSyncStateInfo(folderSyncStateMetadata.Name); if (creator == null) { return(new FolderSyncState(syncStateStorage, storeObject, folderSyncStateMetadata, syncStateInfo, syncProviderFactory, false, syncLogger)); } return(creator(syncStateStorage, storeObject, folderSyncStateMetadata, syncStateInfo, syncProviderFactory, false, syncLogger)); }
protected CustomSyncState(SyncStateStorage syncStateStorage, StoreObject storeObject, SyncStateMetadata syncStateMetadata, SyncStateInfo syncStateInfo, bool syncStateIsNew) : base(syncStateStorage, storeObject, syncStateMetadata, syncStateInfo, syncStateIsNew, null) { }