public void DeleteLinksFromAssociation(FolderAssociation association) { using (var query = Connection.Prepare($"delete from LinkStatus where AssociationId='{association.Id}'")) { query.Step(); } }
private async Task CreateFolder(FolderAssociation association, BaseItem localItem, string name) { //adds the folder and if necessesary the parent folder var uri = new Uri(Configuration.ServerUrl); var remoteBaseFolder = uri.LocalPath; var path = _BuildRemoteFolderPath(association, localItem.EntityId); path = WebUtility.UrlDecode(path.Replace(remoteBaseFolder, "").TrimEnd('/')); var folders = path.Split('/'); if (localItem.IsCollection) { folders = (path + "/" + name).Split('/'); } var currentFolder = remoteBaseFolder.TrimEnd('/'); foreach (string f in folders) { string folderName = Uri.EscapeDataString(f); if (_existingFolders.Contains(currentFolder + '/' + folderName))//this should speed up the inital sync { currentFolder += '/' + folderName; continue; } //var folderContent = await _davClient.ListFolder(new Uri(currentFolder, UriKind.RelativeOrAbsolute)); if (!await _davClient.Exists(new Uri(currentFolder + '/' + folderName, UriKind.RelativeOrAbsolute))) { await _davClient.CreateFolder(new Uri(currentFolder + '/' + folderName, UriKind.RelativeOrAbsolute)); } _existingFolders.Add(currentFolder + '/' + folderName); currentFolder += '/' + folderName; } }
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); }
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); }
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); }
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 override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association) { List <BaseItem> items = new List <BaseItem>(); var item = GetAssociatedItem(association.LocalFolderId); StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(item.EntityId); await _GetChangesFromSearchIndex(folder, association.Id, items); //await _CheckLocalFolderRecursive(folder, association.Id, items); return(items); }
private string _BuildRemoteFilePath(FolderAssociation association, string path) { var localFolder = GetAssociatedItem(association.LocalFolderId); Uri baseUri = new Uri(localFolder.EntityId); Uri fileUri = new Uri(path); Uri relativeUri = baseUri.MakeRelativeUri(fileUri); string uri = relativeUri.ToString(); var relativeString = uri.Substring(uri.IndexOf('/') + 1); var remoteFolder = GetAssociatedItem(association.RemoteFolderId); return(remoteFolder.EntityId + (relativeString)); }
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); }
public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association) { if (Configuration.Configuration.DoNotUseSearchIndex) { var list = await GetDeletedItemsRecursiveAsync(association); return(list); } else { return(await GetDeletedItemsFromIndexAsync(association)); } }
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); }
public ObservableCollection <LinkStatus> GetAllItems(FolderAssociation association) { var items = new ObservableCollection <LinkStatus>(); using (var query = Connection.Prepare(GetSelectAllQuery() + " WHERE AssociationId = ?")) { query.Bind(1, association.Id); while (query.Step() == SQLiteResult.ROW) { var item = CreateInstance(query); items.Add(item); } } return(items); }
//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); } } }
private string _BuildRemoteFolderPath(FolderAssociation association, string path) { var localFolder = GetAssociatedItem(association.LocalFolderId); Uri baseUri = new Uri(localFolder.EntityId); Uri fileUri = new Uri(path); var relative = fileUri.ToString().Replace(baseUri.ToString(), ""); if (relative != "" && relative != "/") { relative = relative.Remove(relative.LastIndexOf('/')).TrimStart('/'); } var remoteFolder = GetAssociatedItem(association.RemoteFolderId); var result = remoteFolder.EntityId + (relative); return(result); }
public override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association) { List <BaseItem> items = new List <BaseItem>(); var item = GetAssociatedItem(association.LocalFolderId); StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(item.EntityId); if (Configuration.Configuration.DoNotUseSearchIndex) { await _GetChangedFilesRecursive(folder, association, items); } else { await _GetChangesFromSearchIndex(folder, association.Id, items); } return(items); }
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); }
public void RemoveFromSyncedFolders(FolderAssociation association) { ItemTableModel.GetDefault().DeleteItemsFromAssociation(association); LinkStatusTableModel.GetDefault().DeleteLinksFromAssociation(association); FolderAssociationTableModel.GetDefault().DeleteItem(association.Id); }
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); }