protected async Task _UpdateFileIndexes(FolderAssociation association, List <BaseItem> items)
        {
            await SetExecutionStatus(ExecutionStatus.UpdatingIndex);

            var itemTableModel = ItemTableModel.GetDefault();

            foreach (BaseItem t in items)
            {
                t.Association = association;
                var foundItem = itemTableModel.GetItem(t);
                if (foundItem == null)
                {
                    itemTableModel.InsertItem(t);
                    t.Id = itemTableModel.GetLastInsertItem().Id;
                }
                else
                {
                    if (foundItem.ChangeKey != t.ChangeKey)
                    {
                        t.ChangeNumber = foundItem.ChangeNumber + 1;
                        itemTableModel.UpdateItem(t, foundItem.Id);
                    }
                    t.Id = foundItem.Id;
                }
            }
            association.LastSync = DateTime.Now;
            FolderAssociationTableModel.GetDefault().UpdateItem(association, association.Id);
        }
        private void AfterUpdate(BaseItem sourceItem, BaseItem targetItem)
        {
            if (targetItem.Association == null)
            {
                targetItem.Association = sourceItem.Association;
            }
            targetItem.ChangeNumber = sourceItem.ChangeNumber;
            var link = LinkStatusTableModel.GetDefault().GetItem(sourceItem);

            if (link != null)
            {
                link.ChangeNumber = sourceItem.ChangeNumber;
                LinkStatusTableModel.GetDefault().UpdateItem(link, link.Id);
                targetItem.Id = link.TargetItemId;
                ItemTableModel.GetDefault().UpdateItem(sourceItem, sourceItem.Id);
                ItemTableModel.GetDefault().UpdateItem(targetItem, targetItem.Id);
            }
            var historyEntry = new SyncHistoryEntry();

            historyEntry.CreateDate   = DateTime.Now;
            historyEntry.SourceItemId = sourceItem.Id;
            historyEntry.TargetItemId = targetItem.Id;
            historyEntry.Result       = sourceItem.AdapterType == _sourceEntityAdapter.GetType()
                ? SyncResult.Sent
                : SyncResult.Received;
            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
        }
        public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association)
        {
            List <BaseItem> result = new List <BaseItem>();
            //get the storagefolder
            var           localFolderItem = GetAssociatedItem(association.LocalFolderId);
            StorageFolder sFolder         = await StorageFolder.GetFolderFromPathAsync(localFolderItem.EntityId);

            var sItems  = new List <IStorageItem>();
            var options = new QueryOptions();

            options.FolderDepth   = FolderDepth.Deep;
            options.IndexerOption = IndexerOption.UseIndexerWhenAvailable;
            var itemQuery = sFolder.CreateItemQueryWithOptions(options);
            var queryTask = itemQuery.GetItemsAsync();

            //get all the files and folders from the db that were inside the folder at the last time
            var existingItems = ItemTableModel.GetDefault().GetFilesForFolder(association, this.GetType());

            sItems.AddRange(await queryTask);

            var storageItems = new List <BaseItem>();

            foreach (var storageItem in sItems)
            {
                storageItems.Add(new BaseItem {
                    EntityId = storageItem.Path
                });
            }
            var missingItems = existingItems.Except(storageItems, new EnityIdComparer()).ToList();

            //var fixedPath = sFolder.Path.Replace("USERS", "Users");
            foreach (var missingItem in missingItems)
            {
                if (missingItem.EntityId == sFolder.Path)
                {
                    continue;
                }
                //additional check if the file really does not exist
                //for some reason the query seems to return wrong results sometimes
                if (!missingItem.IsCollection)
                {
                    FileInfo fInfo = new FileInfo(missingItem.EntityId);
                    if (!fInfo.Exists)
                    {
                        result.Add(missingItem);
                    }
                }
                else
                {
                    DirectoryInfo dInfo = new DirectoryInfo(missingItem.EntityId);
                    if (!dInfo.Exists)
                    {
                        result.Add(missingItem);
                    }
                }
            }
            return(result);
        }
예제 #4
0
        public override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association)
        {
            List <BaseItem> items  = new List <BaseItem>();
            var             folder = ItemTableModel.GetDefault().GetItem(association.RemoteFolderId);

            await _CheckRemoteFolderRecursive(folder, items);

            return(items);
        }
예제 #5
0
        public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association)
        {
            List <BaseItem> items         = new List <BaseItem>();
            var             folder        = ItemTableModel.GetDefault().GetItem(association.RemoteFolderId);
            var             existingItems = ItemTableModel.GetDefault().GetFilesForFolder(association, this.GetType()).ToList();

            await _GetDeletedItemsAsync(folder, existingItems, items);

            return(items);
        }
 public void RemoveInstantUploadAssociations()
 {
     foreach (var association in GetInstantUploadAssociations())
     {
         FolderAssociationTableModel.GetDefault().DeleteItem(association.Id);
         LinkStatusTableModel.GetDefault().DeleteLinksFromAssociation(association);
         ItemTableModel.GetDefault().DeleteItem(association.RemoteFolderId);
         ItemTableModel.GetDefault().DeleteItem(association.LocalFolderId);
         ItemTableModel.GetDefault().DeleteItemsFromAssociation(association);
     }
 }
        public async Task <FolderAssociation> AddFolderToSyncAsync(StorageFolder folder, DavItem remoteFolderItem, bool allowInstantUpload = false)
        {
            StorageApplicationPermissions.FutureAccessList.Add(folder);
            var properties = await folder.Properties.RetrievePropertiesAsync(new List <string> {
                "System.DateModified"
            });

            FolderAssociation fa = new FolderAssociation
            {
                IsActive       = true,
                LocalFolderId  = 0,
                RemoteFolderId = 0,
                SyncDirection  = SyncDirection.FullSync,
                LastSync       = DateTime.MinValue
            };

            if (allowInstantUpload)
            {
                fa.SyncDirection         = SyncDirection.UploadOnly;
                fa.SupportsInstantUpload = true;
            }
            FolderAssociationTableModel.GetDefault().InsertItem(fa);
            fa = FolderAssociationTableModel.GetDefault().GetLastInsertItem();

            BaseItem li = new LocalItem
            {
                IsCollection = true,
                LastModified = ((DateTimeOffset)properties["System.DateModified"]).LocalDateTime,
                EntityId     = folder.Path,
                Association  = fa,
            };
            var testFolder = await StorageFolder.GetFolderFromPathAsync(folder.Path);

            if (testFolder.Path != folder.Path)
            {
                li.EntityId = testFolder.Path;
            }
            ItemTableModel.GetDefault().InsertItem(li);
            li = ItemTableModel.GetDefault().GetLastInsertItem();

            remoteFolderItem.Association = fa;
            ItemTableModel.GetDefault().InsertItem(remoteFolderItem);
            var ri = ItemTableModel.GetDefault().GetLastInsertItem();

            fa.RemoteFolderId = ri.Id;
            fa.LocalFolderId  = li.Id;
            FolderAssociationTableModel.GetDefault().UpdateItem(fa, fa.Id);
            var link = new LinkStatus(li, ri);

            LinkStatusTableModel.GetDefault().InsertItem(link);
            return(fa);
        }
예제 #8
0
        private async Task <List <BaseItem> > GetDeletedItemsRecursiveAsync(FolderAssociation association, List <BaseItem> result = null, StorageFolder folder = null)
        {
            if (result is null)
            {
                result = new List <BaseItem>();
            }
            if (folder is null)
            {
                var localFolderItem = GetAssociatedItem(association.LocalFolderId);
                folder = await StorageFolder.GetFolderFromPathAsync(localFolderItem.EntityId);
            }
            var queryItems    = ItemTableModel.GetDefault().GetFilesForFolder(folder.Path + "\\");
            var dataBaseItems = new List <BaseItem>();

            //remove the items from subfolders
            foreach (var item in queryItems)
            {
                if (item.EntityId == folder.Path)
                {
                    continue;
                }
                var path = item.EntityId.Replace(folder.Path, "").Substring(1);
                if (!path.Contains('\\'))
                {
                    dataBaseItems.Add(item);
                }
            }

            var folderContent = await folder.GetItemsAsync();

            foreach (var item in folderContent)
            {
                if (item.IsOfType(StorageItemTypes.Folder) && item.Path != folder.Path)
                {
                    result = await GetDeletedItemsRecursiveAsync(association, result, item as StorageFolder);
                }
            }

            var folderItems = new List <BaseItem>();

            foreach (var storageItem in folderContent)
            {
                folderItems.Add(new BaseItem {
                    EntityId = storageItem.Path
                });
            }
            var missingItems = dataBaseItems.Except(folderItems, new EnityIdComparer()).ToList();

            result.AddRange(missingItems);
            return(result);
        }
예제 #9
0
        //some users reported that the sync does not find any files
        //this workaround is used if the SearchIndexer does not yield any results, but it's quite slow
        private async Task _GetChangedFilesRecursive(StorageFolder folder, FolderAssociation association, List <BaseItem> result)
        {
            var items = await folder.GetItemsAsync();

            foreach (var storageItem in items)
            {
                Debug.WriteLine(storageItem.Path);
                BasicProperties propertyResult = null;
                if (storageItem.IsOfType(StorageItemTypes.File))
                {
                    propertyResult =
                        await((StorageFile)storageItem).GetBasicPropertiesAsync();
                }
                else if (storageItem.IsOfType(StorageItemTypes.Folder))
                {
                    propertyResult =
                        await((StorageFolder)storageItem).GetBasicPropertiesAsync();
                }

                var      existingItem = ItemTableModel.GetDefault().GetItemFromEntityId(storageItem.Path);
                DateTime date;
                if (existingItem != null && DateTime.TryParse(existingItem.ChangeKey, out date))
                {
                    int i = date.CompareTo(propertyResult.DateModified.UtcDateTime);
                    if (i <= 0)
                    {
                        if (propertyResult.Size != existingItem.Size)
                        {
                            var item = new LocalItem(association, storageItem, propertyResult);
                            result.Add(item);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else if (existingItem == null)
                {
                    var item = new LocalItem(association, storageItem, propertyResult);
                    result.Add(item);
                }
                if (storageItem.IsOfType(StorageItemTypes.Folder))
                {
                    await _GetChangedFilesRecursive((StorageFolder)storageItem, association, result);
                }
            }
        }
        protected override async Task ProcessItems()
        {
            if (Configuration.Configuration.UploadViaWifiOnly)
            {
                var internetConnectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                if (internetConnectionProfile != null && !internetConnectionProfile.IsWlanConnectionProfile)
                {
                    return;
                }
            }
            List <dynamic> itemsToUpdate = new List <dynamic>();

            if (_itemsToUpdate.Count != 0)
            {
                var links = LinkStatusTableModel.GetDefault().GetAllItems();
                foreach (var baseItem in _itemsToUpdate)
                {
                    var existingItem = ItemTableModel.GetDefault().GetItem(baseItem);
                    if (existingItem == null)
                    {
                        _itemsToAdd.Add(baseItem);
                    }
                    else
                    {
                        var itemsToProcess = (from link in links
                                              .Where(x => x.SourceItemId == existingItem.Id || x.TargetItemId == existingItem.Id)
                                              .DefaultIfEmpty()
                                              select new { LinkStatus = link, BaseItem = existingItem }).ToList();

                        _itemsToAdd.AddRange((from item in itemsToProcess
                                              where item.LinkStatus == null
                                              select item.BaseItem).ToList());

                        itemsToUpdate.AddRange((from item in itemsToProcess
                                                where item.LinkStatus != null
                                                select item).ToList());
                    }
                }
            }

            await ProcessAdds(_itemsToAdd);
            await ProcessUpdates(itemsToUpdate);
        }
        public async Task <FolderAssociation> AddFolderToSyncAsync(StorageFolder folder, DavItem remoteFolderItem, SyncDirection direction = SyncDirection.FullSync)
        {
            StorageApplicationPermissions.FutureAccessList.Add(folder);
            var properties = await folder.Properties.RetrievePropertiesAsync(new List <string> {
                "System.DateModified"
            });

            FolderAssociation fa = new FolderAssociation
            {
                IsActive       = true,
                LocalFolderId  = 0,
                RemoteFolderId = 0,
                SyncDirection  = direction,
                LastSync       = DateTime.MinValue
            };

            FolderAssociationTableModel.GetDefault().InsertItem(fa);
            fa = FolderAssociationTableModel.GetDefault().GetLastInsertItem();
            var      path = folder.Path.Replace("\\USERS\\", "\\Users\\");
            BaseItem li   = new LocalItem
            {
                IsCollection = true,
                LastModified = ((DateTimeOffset)properties["System.DateModified"]).LocalDateTime,
                EntityId     = path,
                Association  = fa,
            };

            ItemTableModel.GetDefault().InsertItem(li);
            li = ItemTableModel.GetDefault().GetLastInsertItem();

            remoteFolderItem.Association = fa;
            ItemTableModel.GetDefault().InsertItem(remoteFolderItem);
            var ri = ItemTableModel.GetDefault().GetLastInsertItem();

            fa.RemoteFolderId = ri.Id;
            fa.LocalFolderId  = li.Id;
            FolderAssociationTableModel.GetDefault().UpdateItem(fa, fa.Id);
            var link = new LinkStatus(li, ri);

            LinkStatusTableModel.GetDefault().InsertItem(link);
            return(fa);
        }
예제 #12
0
        public override async Task DeleteItem(BaseItem item)
        {
            long fileId;
            var  link = LinkStatusTableModel.GetDefault().GetItem(item);

            if (link == null)
            {
                await LogHelper.Write($"LinkStatus could not be found: EntityId: {item.EntityId} Id: {item.Id}");

                return;
            }
            fileId = item.Id == link.SourceItemId ? link.TargetItemId : link.SourceItemId;
            var fileItem = ItemTableModel.GetDefault().GetItem(fileId);

            if (fileItem == null)
            {
                return;
            }

            if (item.IsCollection)
            {
                if (new DirectoryInfo(fileItem.EntityId).Exists)
                {
                    var folder = await StorageFolder.GetFolderFromPathAsync(fileItem.EntityId);

                    await folder.DeleteAsync(StorageDeleteOption.PermanentDelete);
                }
            }
            else
            {
                if (new FileInfo(fileItem.EntityId).Exists)
                {
                    var file = await StorageFile.GetFileFromPathAsync(fileItem.EntityId);

                    await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
                }
            }
        }
예제 #13
0
        public override async Task DeleteItem(BaseItem item)
        {
            var link = LinkStatusTableModel.GetDefault().GetItem(item);

            if (link == null)
            {
                await LogHelper.Write($"LinkStatus could not be found: EntityId: {item.EntityId} Id: {item.Id}");

                return;
            }
            var davId = item.Id == link.SourceItemId ? link.TargetItemId : link.SourceItemId;

            var davItem = ItemTableModel.GetDefault().GetItem(davId);

            if (davItem == null)
            {
                return;
            }
            if (await _davClient.Exists(new Uri(davItem.EntityId, UriKind.RelativeOrAbsolute)))
            {
                await _davClient.Delete(new Uri(davItem.EntityId, UriKind.RelativeOrAbsolute));
            }
        }
        private void AfterInsert(BaseItem sourceItem, BaseItem targetItem)
        {
            if (targetItem.Association == null)
            {
                targetItem.Association = sourceItem.Association;
            }
            //check if item with same path already exists
            var existingItem = ItemTableModel.GetDefault().GetItem(targetItem);

            if (existingItem != null)
            {
                ItemTableModel.GetDefault().UpdateItem(targetItem, existingItem.Id);
                targetItem.Id = existingItem.Id;
            }
            else
            {
                ItemTableModel.GetDefault().InsertItem(targetItem);
                targetItem = ItemTableModel.GetDefault().GetLastInsertItem();
            }

            if (LinkStatusTableModel.GetDefault().GetItem(sourceItem) == null)
            {
                var link = new LinkStatus(sourceItem, targetItem);
                LinkStatusTableModel.GetDefault().InsertItem(link);
            }

            var historyEntry = new SyncHistoryEntry();

            historyEntry.CreateDate   = DateTime.Now;
            historyEntry.SourceItemId = sourceItem.Id;
            historyEntry.TargetItemId = targetItem.Id;
            historyEntry.Result       = sourceItem.AdapterType == _sourceEntityAdapter.GetType()
                ? SyncResult.Sent
                : SyncResult.Received;
            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
        }
        protected virtual async Task ProcessItems()
        {
            await LogHelper.Write($"Starting Sync.. BackgroundTask: {_isBackgroundTask}");

            await SetExecutionStatus(ExecutionStatus.Active);

            var items = ItemTableModel.GetDefault().GetAllItems().ToList();
            var links = LinkStatusTableModel.GetDefault().GetAllItems().ToList();

            var itemsToProcess =
                (from baseItem in items
                 .Where(i =>
                        i.Association.SyncDirection == SyncDirection.DownloadOnly &&
                        i.AdapterType == _targetEntityAdapter.GetType() ||
                        i.Association.SyncDirection == SyncDirection.UploadOnly &&
                        i.AdapterType == _sourceEntityAdapter.GetType() ||
                        i.Association.SyncDirection == SyncDirection.FullSync)
                 from link in links
                 .Where(x => x.SourceItemId == baseItem.Id || x.TargetItemId == baseItem.Id)
                 .DefaultIfEmpty()
                 select new { LinkStatus = link, BaseItem = baseItem }).ToList();

            var itemsToAdd =
                (from item in itemsToProcess
                 where item.LinkStatus == null
                 select item.BaseItem).ToList();

            var itemsToUpdate =
                (from item in itemsToProcess
                 where item.BaseItem.ChangeNumber > item.LinkStatus?.ChangeNumber
                 select item).ToList();

            _totalCount += itemsToUpdate.Count + itemsToAdd.Count;
            await ProcessAdds(itemsToAdd);
            await ProcessUpdates(itemsToUpdate);
        }
        protected override async Task ProcessItems()
        {
            List <dynamic> itemsToUpdate = new List <dynamic>();

            if (_itemsToUpdate.Count != 0)
            {
                var links = LinkStatusTableModel.GetDefault().GetAllItems();
                foreach (var baseItem in _itemsToUpdate)
                {
                    var existingItem = ItemTableModel.GetDefault().GetItem(baseItem);
                    if (existingItem == null)
                    {
                        _itemsToAdd.Add(baseItem);
                    }
                    else
                    {
                        var itemsToProcess = (from link in links
                                              .Where(x => x.SourceItemId == existingItem.Id || x.TargetItemId == existingItem.Id)
                                              .DefaultIfEmpty()
                                              select new { LinkStatus = link, BaseItem = existingItem }).ToList();

                        _itemsToAdd.AddRange((from item in itemsToProcess
                                              where item.LinkStatus == null
                                              select item.BaseItem).ToList());

                        itemsToUpdate.AddRange((from item in itemsToProcess
                                                where item.LinkStatus != null
                                                select item).ToList());
                    }
                }
            }


            await ProcessAdds(_itemsToAdd);
            await ProcessUpdates(itemsToUpdate);
        }
예제 #17
0
        public async Task <List <BaseItem> > GetChangesFromChangeTracker(KnownLibraryId libraryId, FolderAssociation association, List <StorageLibraryChangeType> supportedChangeTypes)
        {
            var result  = new List <BaseItem>();
            var library = await StorageLibrary.GetLibraryAsync(libraryId);

            library.ChangeTracker.Enable();
            _changeReader = library.ChangeTracker.GetChangeReader();
            var changes = await _changeReader.ReadBatchAsync();

            foreach (var change in changes)
            {
                if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
                {
                    await LogHelper.Write($"Changetracking lost: {change.Path}");

                    library.ChangeTracker.Reset();
                    return(null);
                }
                try
                {
                    if (supportedChangeTypes.Contains(change.ChangeType))
                    {
                        Debug.WriteLine($"File: {change.Path} ChangeType: {change.ChangeType}");
                        if (change.Path.EndsWith("thumb"))
                        {
                            continue;
                        }
                        var file = await change.GetStorageItemAsync();

                        if (file == null && change.ChangeType == StorageLibraryChangeType.Deleted)
                        {
                            var localItem = new LocalItem();
                            localItem.Association = association;
                            localItem.EntityId    = change.Path;
                            result.Add(localItem);
                        }
                        else if (file == null || file.IsOfType(StorageItemTypes.Folder))
                        {
                            await LogHelper.Write($"Skipping {change.Path}");
                        }
                        else
                        {
                            try
                            {
                                //check if the file is currently in use, for example a video currently being recorded
                                var stream = await((StorageFile)file).OpenStreamForWriteAsync();
                                stream.Dispose();
                            }
                            catch (Exception)
                            {
                                continue;
                            }
                            var props = await file.GetBasicPropertiesAsync();

                            var item = new LocalItem(association, file, props);

                            if (change.ChangeType == StorageLibraryChangeType.ContentsChanged)
                            {
                                //for some reason something is writing to the files after the upload, but without making changes
                                var existingItem = ItemTableModel.GetDefault().GetItem(item);
                                if (existingItem?.Size == item.Size)
                                {
                                    continue;
                                }
                            }
                            result.Add(item);
                        }
                    }
                }
                catch (Exception e)
                {
                    await LogHelper.Write($"InstantUpload: {e.Message} File: {change.Path} ChangeType: {change.ChangeType}");

                    await LogHelper.Write(e.StackTrace);
                }
            }
            return(result);
        }
        protected async Task ProcessAdds(IEnumerable <BaseItem> itemsToAdd)
        {
            var baseItems = itemsToAdd as IList <BaseItem> ?? itemsToAdd.ToList();

            foreach (var item in baseItems)
            {
                try
                {
                    await SetExectuingFileName(item.EntityId);

                    if (ExecutionContext.Instance.Status == ExecutionStatus.Stopped)
                    {
                        break;
                    }

                    //the root item of an association should not be created again
                    if (item.Id == item.Association.LocalFolderId || item.Id == item.Association.RemoteFolderId)
                    {
                        continue;
                    }
                    //skip files bigger than 50MB, these will have to be synced manually
                    //otherwise the upload/download could take too long and task would be terminated
                    //TODO make this configurable
                    if (item.Size > (50 * 1024 * 1024) & _isBackgroundTask)
                    {
                        item.SyncPostponed = true;
                        ItemTableModel.GetDefault().UpdateItem(item, item.Id);
                        continue;
                    }

                    string targetEntitiyId = null;

                    if (item.AdapterType == _targetEntityAdapter.GetType())
                    {
                        targetEntitiyId = _sourceEntityAdapter.BuildEntityId(item);
                    }

                    if (item.AdapterType == _sourceEntityAdapter.GetType())
                    {
                        targetEntitiyId = _targetEntityAdapter.BuildEntityId(item);
                    }

                    //if a new item is added which already exists on the other side we just assume
                    //that they both have the same content and just create a link but do not upload/download anything
                    //this the could be the case at the initial sync. The initial sync should never update
                    //items on one side because we can not compare the contents of files
                    var foundItem = ItemTableModel.GetDefault().GetItemFromEntityId(targetEntitiyId);
                    var result    = foundItem ?? await Insert(item);

                    AfterInsert(item, result);
                    if (await TimeIsOver())
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    ToastHelper.SendToast(string.Format("Message: {0}, EntitityId: {1}", e.Message, item.EntityId));
                    await
                    LogHelper.Write(string.Format("Message: {0}, EntitityId: {1} StackTrace:\r\n{2}", e.Message,
                                                  item.EntityId, e.StackTrace));
                }
            }
        }
        protected async Task ProcessUpdates(IEnumerable <dynamic> itemsToUpdate)
        {
            var toUpdate = itemsToUpdate as IList <dynamic> ?? itemsToUpdate.ToList();
            await LogHelper.Write($"{toUpdate.Count} items to update");

            foreach (var item in toUpdate)
            {
                try
                {
                    await SetExectuingFileName(item.BaseItem.EntityId);

                    if (ExecutionContext.Instance.Status == ExecutionStatus.Stopped)
                    {
                        break;
                    }

                    //the root item of an association should not be created again
                    if (item.BaseItem.Id == item.BaseItem.Association.LocalFolderId || item.BaseItem.Id == item.BaseItem.Association.RemoteFolderId)
                    {
                        continue;
                    }
                    //skip files bigger than 50MB, these will have to be synced manually
                    //otherwise the upload/download could take too long and task would be terminated
                    //TODO make this configurable
                    if (item.BaseItem.Size > (50 * 1024 * 1024) & _isBackgroundTask)
                    {
                        item.BaseItem.SyncPostponed = true;
                        ItemTableModel.GetDefault().UpdateItem(item.BaseItem, item.BaseItem.Id);
                        continue;
                    }

                    //get the linked item
                    var linkedItem =
                        ItemTableModel.GetDefault()
                        .GetItem(item.BaseItem.Id == item.LinkStatus.SourceItemId
                                ? item.LinkStatus.TargetItemId
                                : item.LinkStatus.SourceItemId);
                    //if both (item and the linkedItem) have a higher changenum than the link we have a conflict.
                    //That means both item have been updated since the last time we checked.
                    //so we check which one has the latest change and if it is the current item we update ititem.LinkStatus
                    if (linkedItem != null && item.BaseItem.ChangeNumber > item.LinkStatus.ChangeNumber &&
                        linkedItem.ChangeNumber > item.LinkStatus.ChangeNumber)
                    {
                        if (item.BaseItem.LastModified > linkedItem.LastModified)
                        {
                            var result = await Update(item.BaseItem);

                            AfterUpdate(item.BaseItem, result);
                        }
                    }
                    else
                    {
                        var result = await Update(item.BaseItem);

                        AfterUpdate(item.BaseItem, result);
                    }
                    if (await TimeIsOver())
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    var historyEntry = new SyncHistoryEntry();
                    historyEntry.CreateDate   = DateTime.Now;
                    historyEntry.SourceItemId = item.BaseItem.Id;
                    historyEntry.Result       = SyncResult.Failed;
                    historyEntry.Message      = e.Message;
                    SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
                    ToastHelper.SendToast(string.Format("Message: {0}, EntitityId: {1}", e.Message, item.BaseItem.EntityId));
                    await
                    LogHelper.Write(string.Format("Message: {0}, EntitityId: {1} StackTrace:\r\n{2}", e.Message,
                                                  item.BaseItem.EntityId, e.StackTrace));
                }
            }
        }
 public void RemoveFromSyncedFolders(FolderAssociation association)
 {
     ItemTableModel.GetDefault().DeleteItemsFromAssociation(association);
     LinkStatusTableModel.GetDefault().DeleteLinksFromAssociation(association);
     FolderAssociationTableModel.GetDefault().DeleteItem(association.Id);
 }
예제 #21
0
        private bool ChangekeyHasChanged(BaseItem item)
        {
            var i = ItemTableModel.GetDefault().GetItem(item);

            return(i == null || i.ChangeKey != item.ChangeKey);
        }
예제 #22
0
 private BaseItem GetAssociatedItem(long id)
 {
     return(ItemTableModel.GetDefault().GetItem(id));
 }
        protected async Task ProcessDeletions(List <BaseItem> deletedItems)
        {
            await SetExecutionStatus(ExecutionStatus.Deletions);

            foreach (var item in deletedItems)
            {
                try
                {
                    if (item.AdapterType == _targetEntityAdapter.GetType() &&
                        item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        await _sourceEntityAdapter.DeleteItem(item);
                    }

                    if (item.AdapterType == _sourceEntityAdapter.GetType() &&
                        item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        await _targetEntityAdapter.DeleteItem(item);
                    }

                    var link = LinkStatusTableModel.GetDefault().GetItem(item);
                    if (link != null && item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        //the linked item should only be deleted from the database if its a full sync
                        //otherwise changes might not be tracked anymore if the user makes changes to the sync direction
                        var linkedItem = ItemTableModel.GetDefault().GetItem(link.TargetItemId);
                        if (linkedItem != null)
                        {
                            if (linkedItem.IsCollection)
                            {
                                var childItems = ItemTableModel.GetDefault().GetFilesForFolder(linkedItem.EntityId);
                                foreach (var childItem in childItems)
                                {
                                    var childLink = LinkStatusTableModel.GetDefault().GetItem(childItem);
                                    if (childLink != null)
                                    {
                                        LinkStatusTableModel.GetDefault().DeleteItem(childLink.Id);
                                    }
                                    ItemTableModel.GetDefault().DeleteItem(childItem.Id);
                                }
                            }
                            ItemTableModel.GetDefault().DeleteItem(linkedItem.Id);
                            var historyEntry = new SyncHistoryEntry();
                            historyEntry.CreateDate         = DateTime.Now;
                            historyEntry.Result             = SyncResult.Deleted;
                            historyEntry.OldItemDisplayName = item.DisplayName;
                            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
                        }
                    }

                    if (link != null)
                    {
                        LinkStatusTableModel.GetDefault().DeleteItem(link.Id);
                    }

                    if (item.IsCollection)
                    {
                        var childItems = ItemTableModel.GetDefault().GetFilesForFolder(item.EntityId);
                        foreach (var childItem in childItems)
                        {
                            ItemTableModel.GetDefault().DeleteItem(childItem.Id);
                            _deletedCount++;
                        }
                    }
                    ItemTableModel.GetDefault().DeleteItem(item.Id);
                    _deletedCount++;
                }
                catch (Exception e)
                {
                    ToastHelper.SendToast(string.Format("Message: {0}, EntitityId: {1}", e.Message, item.EntityId));
                    await
                    LogHelper.Write(string.Format("Message: {0}, EntitityId: {1} StackTrace:\r\n{2}", e.Message,
                                                  item.EntityId, e.StackTrace));
                }
            }
        }
예제 #24
0
        private async Task _GetChangesFromSearchIndex(StorageFolder folder, long associationId,
                                                      List <BaseItem> result)
        {
            var association = FolderAssociationTableModel.GetDefault().GetItem(associationId);
            var files       = new List <IStorageItem>();
            var options     = new QueryOptions();

            options.FolderDepth   = FolderDepth.Deep;
            options.IndexerOption = IndexerOption.UseIndexerWhenAvailable;
            //details about filesystem queries using the indexer
            //https://msdn.microsoft.com/en-us/magazine/mt620012.aspx
            string timeFilter = "System.Search.GatherTime:>=" + association.LastSync;

            options.ApplicationSearchFilter = timeFilter;
            var prefetchedProperties = new List <string> {
                "System.DateModified", "System.Size"
            };

            options.SetPropertyPrefetch(PropertyPrefetchOptions.BasicProperties, prefetchedProperties);
            if (!folder.AreQueryOptionsSupported(options))
            {
                throw new Exception($"Windows Search Index has to be enabled for {folder.Path}");
            }

            var queryResult = folder.CreateItemQueryWithOptions(options);

            queryResult.ApplyNewQueryOptions(options);
            files.AddRange(await queryResult.GetItemsAsync());

            foreach (var file in files)
            {
                try
                {
                    IDictionary <string, object> propertyResult = null;
                    if (file.IsOfType(StorageItemTypes.File))
                    {
                        propertyResult =
                            await((StorageFile)file).Properties.RetrievePropertiesAsync(prefetchedProperties);
                    }
                    else if (file.IsOfType(StorageItemTypes.Folder))
                    {
                        propertyResult =
                            await((StorageFolder)file).Properties.RetrievePropertiesAsync(prefetchedProperties);
                    }
                    var item = new LocalItem(new FolderAssociation {
                        Id = associationId
                    }, file, propertyResult);

                    var existingItem = ItemTableModel.GetDefault().GetItem(item);
                    if (existingItem != null)
                    {
                        if (!item.IsCollection)
                        {
                            //additional check if the file has changed:
                            //even though the size not the best way to make sure if a file has changed
                            //its very unlikely that after a change they have the exact same byte count
                            //so its the best option we have
                            if ((ulong)propertyResult["System.Size"] == existingItem.Size)
                            {
                                continue;
                            }
                        }
                    }
                    result.Add(item);
                }
                catch (Exception)
                {
                    Debug.WriteLine(file);
                    throw;
                }
            }

            if (files.Count == 0)
            {
                await _GetChangedFilesRecursive(folder, association, result);
            }

            if (!IsBackgroundSync)
            {
                var unsynced =
                    ItemTableModel.GetDefault()
                    .GetPostponedItems()
                    .Where(x => x.AdapterType == typeof(FileSystemAdapter));
                foreach (var abstractItem in unsynced)
                {
                    abstractItem.SyncPostponed = false;
                }
                result.AddRange(unsynced);
            }
        }