예제 #1
0
        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);
            }
        }