public IFileStorage GetFileStorage(IOConnectionInfo iocInfo, bool allowCache) { IFileStorage fileStorage; if (iocInfo.IsLocalFile()) { fileStorage = new LocalFileStorage(this); } else { IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo); if (DatabaseCacheEnabled && allowCache) { fileStorage = new CachingFileStorage(innerFileStorage, Application.Context, this); } else { fileStorage = innerFileStorage; } } if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; } return(fileStorage); }
private void SetupFileStorage() { _testFileStorage = new TestFileStorage(new TestKp2aApp()); _testCacheSupervisor = new TestCacheSupervisor(); //_fileStorage = new CachingFileStorage(_testFileStorage, Application.Context.CacheDir.Path, _testCacheSupervisor); _fileStorage = new CachingFileStorage(_testFileStorage, "/mnt/sdcard/kp2atest_cache", _testCacheSupervisor); _fileStorage.ClearCache(); File.WriteAllText(CachingTestFile, _defaultCacheFileContents); }
private Stream GetStreamForBaseFile(IFileStorage fileStorage, IOConnectionInfo ioc) { //if we have the original file already available: use it if (_streamForOrigFile != null) { return(_streamForOrigFile); } //if the file storage caches, it might return the local data in case of a conflict. This would result in data loss // so we need to ensure we get the data from remote (only if the remote file is available. if not, we won't overwrite anything) CachingFileStorage cachingFileStorage = fileStorage as CachingFileStorage; if (cachingFileStorage != null) { return(cachingFileStorage.OpenRemoteForReadIfAvailable(ioc)); } return(fileStorage.OpenFileForRead(ioc)); }
public byte[] HashOriginalFile(IOConnectionInfo iocFile) { if (iocFile == null) { Debug.Assert(false); return(null); } // Assert only Stream sIn; try { IFileStorage fileStorage = _app.GetFileStorage(iocFile); CachingFileStorage cachingFileStorage = fileStorage as CachingFileStorage; if (cachingFileStorage != null) { string hash; cachingFileStorage.GetRemoteDataAndHash(iocFile, out hash); return(MemUtil.HexStringToByteArray(hash)); } else { sIn = fileStorage.OpenFileForRead(iocFile); } if (sIn == null) { throw new FileNotFoundException(); } } catch (Exception) { return(null); } byte[] pbHash; try { SHA256Managed sha256 = new SHA256Managed(); pbHash = sha256.ComputeHash(sIn); } catch (Exception) { Debug.Assert(false); sIn.Close(); return(null); } sIn.Close(); return(pbHash); }
public override void Run() { try { IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (!(fileStorage is CachingFileStorage)) { throw new Exception("Cannot sync a non-cached database!"); } StatusLogger.UpdateMessage(UiStringKey.SynchronizingCachedDatabase); CachingFileStorage cachingFileStorage = (CachingFileStorage)fileStorage; //download file from remote location and calculate hash: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); string hash; MemoryStream remoteData; try { remoteData = cachingFileStorage.GetRemoteDataAndHash(ioc, out hash); } catch (FileNotFoundException) { StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.RestoringRemoteFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); return; } //check if remote file was modified: if (cachingFileStorage.GetBaseVersionHash(ioc) != hash) { //remote file is modified if (cachingFileStorage.HasLocalChanges(ioc)) { //conflict! need to merge _saveDb = new SaveDb(_context, _app, new ActionOnFinish((success, result) => { if (!success) { Finish(false, result); } else { Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } _saveDb = null; }), false, remoteData); _saveDb.Run(); _app.GetDb().MarkAllGroupsAsDirty(); } else { //only the remote file was modified -> reload database. //note: it's best to lock the database and do a complete reload here (also better for UI consistency in case something goes wrong etc.) _app.TriggerReload(_context); Finish(true); } } else { //remote file is unmodified if (cachingFileStorage.HasLocalChanges(ioc)) { //but we have local changes -> upload: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.UploadingFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); StatusLogger.UpdateSubMessage(""); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } else { //files are in sync: just set the result Finish(true, _app.GetResourceString(UiStringKey.FilesInSync)); } } } catch (Exception e) { Finish(false, e.Message); } }