Exemple #1
0
        private static void DoUploads(Library library, bool restricted_metadata_sync, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
        {
            int upload_count = 0;

            StatusManager.Instance.ClearCancelled(StatusCodes.SYNC_META(library));
            foreach (SynchronisationState ss in synchronisation_action.states_to_upload)
            {
                StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), String.Format("Uploading metadata to your Web/Intranet Library ({0} to go)", synchronisation_action.states_to_upload.Count - upload_count), upload_count, synchronisation_action.states_to_upload.Count, true);
                ++upload_count;

                // Has the user cancelled?
                if (StatusManager.Instance.IsCancelled(StatusCodes.SYNC_META(library)))
                {
                    Logging.Info("User has cancelled their metadata upload");
                    break;
                }

                // Only do some filetypes if we are in restricted sync (e.g. they haven't paid for a while)
                {
                    if (restricted_metadata_sync)
                    {
                        string extension = ss.extension;
                        extension = extension.ToLower();
                        if (!SynchronisationFileTypes.extensions_restricted_sync.Contains(extension))
                        {
                            Logging.Info("Not syncing {0} because we are on restricted sync", ss.filename);
                            continue;
                        }
                    }
                }

                // Upload the file
                {
                    Logging.Info("+Uploading {0}", ss.filename);

                    // --- TODO: Replace this with a pretty interface class ------------------------------------------------
                    if (false)
                    {
                    }
                    else if (library.WebLibraryDetail.IsIntranetLibrary)
                    {
                        SynchronisationExecutor_Intranet.DoUpload(library, ss);
                    }
                    else
                    {
                        throw new Exception(String.Format("Did not understand how to upload for library {0}", library.WebLibraryDetail.Title));
                    }
                    // -----------------------------------------------------------------------------------------------------

                    Logging.Info("-Uploading {0}");

                    historical_sync_file[ss.filename] = ss.library_item.md5;
                }
            }

            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), String.Format("Uploaded {0} metadata to your Web/Intranet Library", upload_count));
        }
Exemple #2
0
        internal static SynchronisationAction Build(WebLibraryDetail web_library_detail, SynchronisationStates synchronisation_states)
        {
            SynchronisationAction synchronisation_action = new SynchronisationAction();

            List <SynchronisationState> synchronisation_state_list = new List <SynchronisationState>(synchronisation_states.Values);

            for (int i = 0; i < synchronisation_state_list.Count; ++i)
            {
                SynchronisationState synchronisation_state = synchronisation_state_list[i];

                if (false ||
                    (0 == i % 20 && synchronisation_state_list.Count < 100) ||
                    (0 == i % 100 && synchronisation_state_list.Count < 1000) ||
                    (0 == i % 500)
                    )
                {
                    StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(web_library_detail), "Determining sync action", i, synchronisation_state_list.Count);
                }

                // NB: Ordering of these statements is important so don't reorder them!

                // Not local, not remote: something dodgy in the history file, ignore it
                if (null == synchronisation_state.md5_local && null == synchronisation_state.md5_remote)
                {
                    synchronisation_action.states_dodgy.Add(synchronisation_state);
                }

                // If we don't have it locally but we do remotely
                else if (null == synchronisation_state.md5_local && null != synchronisation_state.md5_remote)
                {
                    synchronisation_action.states_to_download.Add(synchronisation_state);
                }

                // If we don't have it remotely, but we do locally
                else if (null != synchronisation_state.md5_local && null == synchronisation_state.md5_remote)
                {
                    synchronisation_action.states_to_upload.Add(synchronisation_state);
                }

                // If local and remote match, do nothing
                else if (0 == synchronisation_state.md5_local.CompareTo(synchronisation_state.md5_remote))
                {
                    synchronisation_action.states_already_synced.Add(synchronisation_state);
                }

                // If local and remote don't match, but local has not changed
                else if (0 == synchronisation_state.md5_local.CompareTo(synchronisation_state.md5_previous))
                {
                    synchronisation_action.states_to_download.Add(synchronisation_state);
                }

                // If local and remote don't match, but remote has not changed
                else if (0 == synchronisation_state.md5_remote.CompareTo(synchronisation_state.md5_previous))
                {
                    synchronisation_action.states_to_upload.Add(synchronisation_state);
                }

                // If local and remote don't match and neither match the previous value, we have a merge conflict
                else
                {
                    synchronisation_action.states_to_merge.Add(synchronisation_state);
                }
            }

            return(synchronisation_action);
        }
Exemple #3
0
 private static void DoMerges(Library library, bool restricted_metadata_sync, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
 {
     // For now we are going to treat all conflicted files as downloads (i.e. server wins)
     synchronisation_action.states_to_download.AddRange(synchronisation_action.states_to_merge);
     synchronisation_action.states_to_merge.Clear();
 }
Exemple #4
0
        private static void DoNotifyLibraryOfChanges(Library library, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
        {
            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), "Notifying library of changes");

            HashSet <string> fingerprints_that_have_changed = new HashSet <string>();

            foreach (SynchronisationState ss in synchronisation_action.states_to_download)
            {
                fingerprints_that_have_changed.Add(ss.fingerprint);
            }

            foreach (string fingerprint in fingerprints_that_have_changed)
            {
                library.NotifyLibraryThatDocumentHasChangedExternally(fingerprint);
            }

            // Update grid
            library.NotifyLibraryThatDocumentListHasChangedExternally();

            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), "Notified library of changes");
        }
Exemple #5
0
        internal static void Sync(Library library, bool restricted_metadata_sync, bool is_readonly, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
        {
            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), "Performing metadata transfers");

            // For read only libraries, we need to overwrite any files that have been changed locally since the last sync
            if (is_readonly)
            {
                if (0 < synchronisation_action.states_to_upload.Count)
                {
                    Logging.Info("We are discarding {0} upload items because library is read-only.", synchronisation_action.states_to_upload.Count);
                    synchronisation_action.states_to_download.AddRange(synchronisation_action.states_to_upload);
                    synchronisation_action.states_to_upload.Clear();
                }

                if (0 < synchronisation_action.states_to_merge.Count)
                {
                    Logging.Info("We are discarding {0} merge items because library is read-only.", synchronisation_action.states_to_merge.Count);
                    synchronisation_action.states_to_download.AddRange(synchronisation_action.states_to_merge);
                    synchronisation_action.states_to_merge.Clear();
                }
            }

            DoMerges(library, restricted_metadata_sync, historical_sync_file, synchronisation_action);
            DoUploads(library, restricted_metadata_sync, historical_sync_file, synchronisation_action);
            int download_count = DoDownloads(library, restricted_metadata_sync, historical_sync_file, synchronisation_action);

            if (0 < download_count)
            {
                DoNotifyLibraryOfChanges(library, historical_sync_file, synchronisation_action);
            }

            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), "Finished metadata transfers");
        }
Exemple #6
0
        private static int DoDownloads(Library library, bool restricted_metadata_sync, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
        {
            int download_count = 0;

            StatusManager.Instance.ClearCancelled(StatusCodes.SYNC_META(library));
            foreach (SynchronisationState ss in synchronisation_action.states_to_download)
            {
                StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), String.Format("Downloading metadata from your Web/Intranet Library ({0} to go)", synchronisation_action.states_to_download.Count - download_count), download_count, synchronisation_action.states_to_download.Count, true);
                ++download_count;

                // Has the user cancelled?
                if (StatusManager.Instance.IsCancelled(StatusCodes.SYNC_META(library)))
                {
                    Logging.Info("User has cancelled their metadata download");
                    break;
                }

                try
                {
                    Logging.Info("+Downloading {0}", ss.filename);

                    StoredUserFile stored_user_file = null;

                    // --- TODO: Replace this with a pretty interface class ------------------------------------------------
                    if (false)
                    {
                    }
                    else if (library.WebLibraryDetail.IsIntranetLibrary)
                    {
                        stored_user_file = SynchronisationExecutor_Intranet.DoDownload(library, ss);
                    }
                    else
                    {
                        throw new Exception(String.Format("Did not understand how to download for library {0}", library.WebLibraryDetail.Title));
                    }
                    // -----------------------------------------------------------------------------------------------------

                    Logging.Info("-Downloading {0}", ss.filename);

                    {
                        // Check that the MD5s match, or we have had some issue in the download
                        Logging.Info("Checking content");
                        string md5_metadata    = StreamMD5.FromBytes(stored_user_file.Content);
                        string header_etag     = stored_user_file.Md5;
                        string header_etag_nik = header_etag;
                        if (null != header_etag && !String.IsNullOrEmpty(header_etag) && 0 != String.Compare(md5_metadata, header_etag, true) && 0 != String.Compare(md5_metadata, header_etag_nik, true))
                        {
                            throw new Exception(String.Format("Local and remote MD5s do not match. local={0} remote={1} remote_nik={2}", md5_metadata, header_etag, header_etag_nik));
                        }

                        Logging.Info("Copying content");
                        library.LibraryDB.PutBlob(ss.fingerprint, ss.extension, stored_user_file.Content);

                        // Remember this MD5 for our sync clash detection
                        Logging.Info("Remembering md5");
                        historical_sync_file[ss.filename] = md5_metadata;
                    }
                }

                catch (Exception ex)
                {
                    Logging.Error(ex, "There was a problem downloading one of your sync files");
                }
            }

            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(library), String.Format("Downloaded {0} metadata from your Web/Intranet Library", download_count));

            return(download_count);
        }
Exemple #7
0
        private static void DoUploads(WebLibraryDetail web_library_detail, Dictionary <string, string> historical_sync_file, SynchronisationAction synchronisation_action)
        {
            int upload_count = 0;

            StatusManager.Instance.ClearCancelled(StatusCodes.SYNC_META(web_library_detail));
            foreach (SynchronisationState ss in synchronisation_action.states_to_upload)
            {
                StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(web_library_detail), String.Format("Uploading metadata to your Web/Intranet Library ({0} to go)", synchronisation_action.states_to_upload.Count - upload_count), upload_count, synchronisation_action.states_to_upload.Count, true);
                ++upload_count;

                // Has the user canceled?
                if (StatusManager.Instance.IsCancelled(StatusCodes.SYNC_META(web_library_detail)))
                {
                    Logging.Info("User has canceled their metadata upload");
                    break;
                }

                // Upload the file
                {
                    Logging.Info("+Uploading {0}", ss.filename);

                    // TODO: Replace this with a pretty interface class ------------------------------------------------
                    if (web_library_detail.IsIntranetLibrary)
                    {
                        SynchronisationExecutor_Intranet.DoUpload(web_library_detail, ss);
                    }
                    else
                    {
                        throw new Exception(String.Format("Did not understand how to upload for library {0}", web_library_detail.Title));
                    }
                    // -----------------------------------------------------------------------------------------------------

                    Logging.Info("-Uploading {0}");

                    historical_sync_file[ss.filename] = ss.library_item.md5;
                }
            }

            StatusManager.Instance.UpdateStatus(StatusCodes.SYNC_META(web_library_detail), String.Format("Uploaded {0} metadata to your Web/Intranet Library", upload_count));
        }