/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (DesignMode) { return; } // Use the version immediately after the live version _version = ManagerSettings.Instance.LiveVersion + 1; lblVersion.Text = _version.ToString(); try { // Load the filters from the previous version and use that for the default filter var prevVersionPath = VersionHelper.GetVersionFileListPath(_version - 1); if (File.Exists(prevVersionPath)) { var pv = VersionFileList.CreateFromFile(prevVersionPath); var sb = new StringBuilder(); foreach (var f in pv.Filters) { sb.AppendLine(f); } txtIgnoreFilter.Text = sb.ToString(); } } catch (Exception ex) { Debug.Fail(ex.ToString()); txtIgnoreFilter.Text = string.Empty; } }
/// <summary> /// When overridden in the derived class, handles synchronizing the given version. /// </summary> /// <param name="fu">The <see cref="IFileUploader"/> to use.</param> /// <param name="v">The version to synchronize.</param> /// <param name="reEnqueue">True if the <paramref name="v"/> should be re-enqueued so it can be re-attempted. /// If the method throws an <see cref="Exception"/>, the <paramref name="v"/> will be re-enqueued no matter what.</param> /// <returns>The error string, or null if the synchronization was successful.</returns> protected override string DoSync(IFileUploader fu, int v, out bool reEnqueue) { fu.SkipIfExists = false; reEnqueue = false; var remoteFileListFilePath = PathHelper.GetVersionString(v) + ".txt"; var remoteFileListHashFilePath = PathHelper.GetVersionString(v) + ".hash"; // Ensure the live version is written. This is a very small but very important file, so just write it during // every synchronization. fu.UploadAsync(_settings.LiveVersionFilePath, MasterServerReader.CurrentVersionFilePath); // Also ensure the master server and file server lists are up-to-date. Again, we will just do this every time we // check to sync since they are relatively small lists but very important to keep up-to-date. fu.UploadAsync(_settings.FileServerListFilePath, MasterServerReader.CurrentDownloadSourcesFilePath); fu.UploadAsync(_settings.MasterServerListFilePath, MasterServerReader.CurrentMasterServersFilePath); // Load the VersionFileList for the version to check var vflPath = VersionHelper.GetVersionFileListPath(v); if (!File.Exists(vflPath)) { // Version doesn't exist at all while (fu.IsBusy) { Thread.Sleep(500); } return(null); } // Test the creation of the VersionFileList to ensure its valid VersionFileList.CreateFromFile(vflPath); // Try to download the version's file list hash var vflHash = fu.DownloadAsString(remoteFileListHashFilePath); // Check if the hash file exists on the server if (vflHash != null) { // Check if the hash matches the current version's hash var expectedVflHash = File.ReadAllText(VersionHelper.GetVersionFileListHashPath(v)); if (vflHash != expectedVflHash) { // We don't need to delete anything since we make the MasterServer overwrite instead } else { // Hash existed and was correct - good enough for us! But first, wait for uploads to finish... while (fu.IsBusy) { Thread.Sleep(500); } return(null); } } else { // Hash didn't exist at all, so we will have to update. As long as SkipIfExists is set to true, files // that already exist will be skipped, so we will only end up uploading the new files. In any case, its // the same process either way. } // Upload the files fu.UploadAsync(VersionHelper.GetVersionFileListPath(v), remoteFileListFilePath); fu.UploadAsync(VersionHelper.GetVersionFileListHashPath(v), remoteFileListHashFilePath); // Wait for uploads to finish while (fu.IsBusy) { Thread.Sleep(1000); } // All done! return(null); }
/// <summary> /// Handles the Click event of the btnChangeLiveVersion control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> static void btnChangeLiveVersion_Click(object sender, EventArgs e) { // Check that the next version even exists var nextVersion = _settings.LiveVersion + 1; if (!Directory.Exists(VersionHelper.GetVersionPath(nextVersion)) || !File.Exists(VersionHelper.GetVersionFileListPath(nextVersion))) { MessageBox.Show( "Cannot change the live version since you are already at the latest version." + Environment.NewLine + "If you want to change the live version, create a new version first.", "Error", MessageBoxButtons.OK); return; } // Ensure the next version's contents are valid try { VersionFileList.CreateFromFile(VersionHelper.GetVersionFileListPath(nextVersion)); } catch (Exception ex) { const string errmsg = "The file listing file for the next version exists, but it is corrupt." + " Please use Create New Version to recreate the next version then try again.{0}Inner Exception:{0}{1}"; MessageBox.Show(string.Format(errmsg, Environment.NewLine, ex), "Corrupt file listing file", MessageBoxButtons.OK); return; } // Confirm change if ( MessageBox.Show("Are you sure you wish to update the live version?", "Update live version?", MessageBoxButtons.YesNo) == DialogResult.No) { return; } // If the new version is still being uploaded to the servers, warn the user var areServersBusy = _settings.FileServers.Any(x => x.IsBusySyncing); if (areServersBusy) { const string msg = "Are you sure you wish to update the live version? One or more servers (either file or master servers)" + " are still synchronizing. Updating the live version now may leave you in a state where not all of the files" + " are available on all of the servers. It is highly recommended you wait until all synchronization finishes." + "{0}{0}Do you wish to continue? (Canceling is highly recommended!)"; if (MessageBox.Show(msg, "Continue updating live version?", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { return; } } // Update the version number on the master servers _settings.TrySetLiveVersion(_settings.LiveVersion + 1); // Done! const string doneMsg = "The live version has been successfully updated!" + " The master servers will automatically start to update with the new live version number."; MessageBox.Show(doneMsg, "Done!", MessageBoxButtons.OK); }
/// <summary> /// When overridden in the derived class, handles synchronizing the given version. /// </summary> /// <param name="fu">The <see cref="IFileUploader"/> to use.</param> /// <param name="v">The version to synchronize.</param> /// <param name="reEnqueue">True if the <paramref name="v"/> should be re-enqueued so it can be re-attempted. /// If the method throws an <see cref="Exception"/>, the <paramref name="v"/> will be re-enqueued no matter what.</param> /// <returns> /// The error string, or null if the synchronization was successful. /// </returns> protected override string DoSync(IFileUploader fu, int v, out bool reEnqueue) { reEnqueue = false; // Load the VersionFileList for the version to check var vflPath = VersionHelper.GetVersionFileListPath(v); if (!File.Exists(vflPath)) { // Version doesn't exist at all return(null); } var vfl = VersionFileList.CreateFromFile(vflPath); // Try to download the version's file list hash var fileListHashPath = GetVersionRemoteFilePath(v, PathHelper.RemoteFileListHashFileName); var vflHash = fu.DownloadAsString(fileListHashPath); // Check if the hash file exists on the server if (vflHash != null) { // Check if the hash matches the current version's hash var expectedVflHash = File.ReadAllText(VersionHelper.GetVersionFileListHashPath(v)); if (vflHash != expectedVflHash) { // Delete the whole version folder first fu.DeleteDirectory(GetVersionRemoteFilePath(v, null)); } else { // Hash existed and was correct - good enough for us! return(null); } } else { // Hash didn't exist at all, so we will have to update. As long as SkipIfExists is set to true, files // that already exist will be skipped, so we will only end up uploading the new files. In any case, its // the same process either way. } // Check the hashes of the local files foreach (var f in vfl.Files) { // Get the local file path var localPath = VersionHelper.GetVersionFile(v, f.FilePath); // Confirm the hash of the file var fileHash = Hasher.GetFileHash(localPath); if (fileHash != f.Hash) { const string errmsg = "The cached hash ({0}) of file `{1}` does not match the real hash ({2}) for version {3}." + " Possible version corruption."; return(string.Format(errmsg, f.Hash, f.FilePath, fileHash, v)); } } // Hashes check out, start uploading foreach (var f in vfl.Files) { // Get the local file path var localPath = VersionHelper.GetVersionFile(v, f.FilePath); var remotePath = GetVersionRemoteFilePath(v, f.FilePath); fu.UploadAsync(localPath, remotePath); } // Wait for uploads to finish while (fu.IsBusy) { Thread.Sleep(1000); } // All uploads have finished, so upload the VersionFileList hash fu.UploadAsync(VersionHelper.GetVersionFileListHashPath(v), fileListHashPath); // All done! That was easy enough, eh? *sigh* return(null); }