Beispiel #1
0
        public void SaveData(Context ctx)
        {
            KpDatabase.UseFileTransactions = _app.GetBooleanPreference(PreferenceKey.UseFileTransactions);
            using (IWriteTransaction trans = _app.GetFileStorage(Ioc).OpenWriteTransaction(Ioc, KpDatabase.UseFileTransactions))
            {
                DatabaseFormat.Save(KpDatabase, trans.OpenFile());

                trans.CommitWrite();
            }
        }
Beispiel #2
0
        public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task <MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish) : base(activity, finish)
        {
            _app               = app;
            _ioc               = ioc;
            _databaseData      = databaseData;
            _compositeKey      = compositeKey;
            _keyfileOrProvider = keyfileOrProvider;


            _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
        }
Beispiel #3
0
        public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish)
            : base(finish)
        {
            _app = app;
            _ioc = ioc;
            _databaseData = databaseData;
            _compositeKey = compositeKey;
            _keyfileOrProvider = keyfileOrProvider;

            _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
        }
Beispiel #4
0
        public static void Copy(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc, IKp2aApp app)
        {
            IFileStorage sourceStorage = app.GetFileStorage(sourceIoc, false);             //don't cache source. file won't be used ever again
            IFileStorage targetStorage = app.GetFileStorage(targetIoc);

            using (
                var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc,
                                                                          app.GetBooleanPreference(
                                                                              PreferenceKey.UseFileTransactions)))
            {
                using (var writeStream = writeTransaction.OpenFile())
                {
                    sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream);
                }
                writeTransaction.CommitWrite();
            }
        }
Beispiel #5
0
        public static void Copy(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc, IKp2aApp app)
        {
            IFileStorage sourceStorage = app.GetFileStorage(sourceIoc, false); //don't cache source. file won't be used ever again
            IFileStorage targetStorage = app.GetFileStorage(targetIoc);

            using (
                var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc,
                                                                          app.GetBooleanPreference(
                                                                              PreferenceKey.UseFileTransactions)))
            {
                using (var writeStream = writeTransaction.OpenFile())
                {
                    sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream);
                }
                writeTransaction.CommitWrite();
            }
        }
Beispiel #6
0
        public override void Run()
        {
            if (!_dontSave)
            {
                try
                {
                    if (_db.CanWrite == false)
                    {
                        //this should only happen if there is a problem in the UI so that the user sees an edit interface.
                        Finish(false, "Cannot save changes. File is read-only!");
                        return;
                    }

                    string message = _app.GetResourceString(UiStringKey.saving_database);

                    if (ShowDatabaseIocInStatus)
                    {
                        message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
                    }

                    StatusLogger.UpdateMessage(message);

                    IOConnectionInfo ioc         = _db.Ioc;
                    IFileStorage     fileStorage = _app.GetFileStorage(ioc);

                    if (_streamForOrigFile == null)
                    {
                        if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) ||
                            (_db.KpDatabase.HashOfFileOnDisk == null))                                //first time saving
                        {
                            PerformSaveWithoutCheck(fileStorage, ioc);
                            Finish(true);
                            return;
                        }
                    }


                    if (
                        (_streamForOrigFile != null) ||
                        fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion) ||                          //first try to use the fast change detection
                        (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed)                            //if that fails, hash the file and compare:
                        )
                    {
                        //ask user...
                        _app.AskYesNoCancel(UiStringKey.TitleSyncQuestion, UiStringKey.MessageSyncQuestion,
                                            UiStringKey.YesSynchronize,
                                            UiStringKey.NoOverwrite,
                                            //yes = sync
                                            (sender, args) =>
                        {
                            Action runHandler = () =>
                            {
                                //note: when synced, the file might be downloaded once again from the server. Caching the data
                                //in the hashing function would solve this but increases complexity. I currently assume the files are
                                //small.
                                MergeIn(fileStorage, ioc);
                                PerformSaveWithoutCheck(fileStorage, ioc);
                                _db.UpdateGlobals();
                                Finish(true);
                            };
                            RunInWorkerThread(runHandler);
                        },
                                            //no = overwrite
                                            (sender, args) =>
                        {
                            RunInWorkerThread(() =>
                            {
                                PerformSaveWithoutCheck(fileStorage, ioc);
                                Finish(true);
                            });
                        },
                                            //cancel
                                            (sender, args) =>
                        {
                            RunInWorkerThread(() => Finish(false));
                        },
                                            _ctx
                                            );
                    }
                    else
                    {
                        PerformSaveWithoutCheck(fileStorage, ioc);
                        Finish(true);
                    }
                }
                catch (Exception e)
                {
                    /* TODO KPDesktop:
                     * catch(Exception exSave)
                     * {
                     * MessageService.ShowSaveWarning(pd.IOConnectionInfo, exSave, true);
                     * bSuccess = false;
                     * }
                     */
                    Kp2aLog.LogUnexpectedError(e);
                    Finish(false, e.Message);
                    return;
                }
            }
            else
            {
                Finish(true);
            }
        }
Beispiel #7
0
        public override void Run()
        {
            if (!_dontSave)
            {
                try
                {
                    if (_db.CanWrite == false)
                    {
                        //this should only happen if there is a problem in the UI so that the user sees an edit interface.
                        Finish(false, "Cannot save changes. File is read-only!");
                        return;
                    }

                    string message = _app.GetResourceString(UiStringKey.saving_database);

                    if (ShowDatabaseIocInStatus)
                    {
                        message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
                    }

                    StatusLogger.UpdateMessage(message);

                    IOConnectionInfo ioc         = _db.Ioc;
                    IFileStorage     fileStorage = _app.GetFileStorage(ioc);

                    if (_streamForOrigFile == null)
                    {
                        if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) ||
                            (_db.KpDatabase.HashOfFileOnDisk == null))                                //first time saving
                        {
                            PerformSaveWithoutCheck(fileStorage, ioc);
                            Finish(true);
                            return;
                        }
                    }


                    bool hasStreamForOrigFile = (_streamForOrigFile != null);
                    bool hasChangeFast        = hasStreamForOrigFile ||
                                                fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion); //first try to use the fast change detection;
                    bool hasHashChanged = hasChangeFast ||
                                          (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) ==
                                           FileHashChange.Changed); //if that fails, hash the file and compare:

                    if (hasHashChanged)
                    {
                        Kp2aLog.Log("Conflict. " + hasStreamForOrigFile + " " + hasChangeFast + " " + hasHashChanged);

                        bool alwaysMerge = (PreferenceManager.GetDefaultSharedPreferences(Application.Context)
                                            .GetBoolean("AlwaysMergeOnConflict", false));

                        if (alwaysMerge)
                        {
                            MergeAndFinish(fileStorage, ioc);
                        }
                        else
                        {
                            //ask user...
                            _app.AskYesNoCancel(UiStringKey.TitleSyncQuestion, UiStringKey.MessageSyncQuestion,
                                                UiStringKey.YesSynchronize,
                                                UiStringKey.NoOverwrite,
                                                //yes = sync
                                                (sender, args) =>
                            {
                                Action runHandler = () => { MergeAndFinish(fileStorage, ioc); };
                                RunInWorkerThread(runHandler);
                            },
                                                //no = overwrite
                                                (sender, args) =>
                            {
                                RunInWorkerThread(() =>
                                {
                                    PerformSaveWithoutCheck(fileStorage, ioc);
                                    Finish(true);
                                });
                            },
                                                //cancel
                                                (sender, args) =>
                            {
                                RunInWorkerThread(() => Finish(false));
                            },
                                                _ctx
                                                );
                        }
                    }
                    else
                    {
                        PerformSaveWithoutCheck(fileStorage, ioc);
                        Finish(true);
                    }
                }
                catch (Exception e)
                {
                    /* TODO KPDesktop:
                     * catch(Exception exSave)
                     * {
                     * MessageService.ShowSaveWarning(pd.IOConnectionInfo, exSave, true);
                     * bSuccess = false;
                     * }
                     */
                    Kp2aLog.LogUnexpectedError(e);
                    Finish(false, e.Message);
                    return;
                }
            }
            else
            {
                Finish(true);
            }
        }
Beispiel #8
0
            public override void Run()
            {
                StatusLogger.UpdateMessage(UiStringKey.exporting_database);
                var          pd     = _app.CurrentDb.KpDatabase;
                PwExportInfo pwInfo = new PwExportInfo(pd.RootGroup, pd, true);

                try
                {
                    var fileStorage = _app.GetFileStorage(_targetIoc);
                    if (fileStorage is IOfflineSwitchable)
                    {
                        ((IOfflineSwitchable)fileStorage).IsOffline = false;
                    }
                    using (var writeTransaction = fileStorage.OpenWriteTransaction(_targetIoc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)))
                    {
                        Stream sOut = writeTransaction.OpenFile();
                        _fileFormat.Export(pwInfo, sOut, new NullStatusLogger());

                        if (sOut != null)
                        {
                            sOut.Close();
                        }

                        writeTransaction.CommitWrite();
                    }
                    if (fileStorage is IOfflineSwitchable)
                    {
                        ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode;
                    }

                    Finish(true);
                }
                catch (Exception ex)
                {
                    Finish(false, ex.Message);
                }
            }
        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);
            }
        }