private void ManageDownload(BundleLibraryManifest manifest) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); string url = manifest.BaseUrl + @"/" + manifest.Id + Common.EXT_BUNDLE; using (UrlDownloader.DownloadAsyncTracker download_async_tracker = UrlDownloader.DownloadWithNonBlocking(url)) { string STATUS_TOKEN = "BundleDownload-" + manifest.Version; StatusManager.Instance.ClearCancelled(STATUS_TOKEN); while (!download_async_tracker.DownloadComplete) { if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling download of Bundle Library due to signaled application shutdown"); StatusManager.Instance.SetCancelled(STATUS_TOKEN); } if (StatusManager.Instance.IsCancelled(STATUS_TOKEN)) { download_async_tracker.Cancel(); break; } StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Downloading Bundle Library...", download_async_tracker.ProgressPercentage, 100, true); ShutdownableManager.Sleep(3000); } // Check the reason for exiting if (download_async_tracker.DownloadDataCompletedEventArgs.Cancelled) { StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Cancelled download of Bundle Library."); } else if (null != download_async_tracker.DownloadDataCompletedEventArgs.Error) { MessageBoxes.Error(download_async_tracker.DownloadDataCompletedEventArgs.Error, "There was an error during the download of your Bundle Library. Please try again later or contact {0} for more information.", manifest.SupportEmail); StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Error during download of Bundle Library."); } else if (null == download_async_tracker.DownloadDataCompletedEventArgs.Result) { MessageBoxes.Error(download_async_tracker.DownloadDataCompletedEventArgs.Error, "There was an error during the download of your Bundle Library. Please try again later or contact {0} for more information.", manifest.SupportEmail); StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Error during download of Bundle Library."); } else { StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Completed download of Bundle Library."); if (MessageBoxes.AskQuestion("The Bundle Library named '{0}' has been downloaded. Do you want to install it now?", manifest.Title)) { LibraryBundleInstaller.Install(manifest, download_async_tracker.DownloadDataCompletedEventArgs.Result); } else { MessageBoxes.Warn("Not installing Bundle Library."); } } } }
public void WaitForAtLeastOneIteration() { if (!have_iterated_at_least_once) { for (int i = 0; i < 20 && !have_iterated_at_least_once; ++i) { Logging.Info("Waiting for the InCite thread to iterate once."); ShutdownableManager.Sleep(250); if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling WordConnector due to signaled application shutdown"); return; } } } }
private static void TailZIPProcess(BundleLibraryManifest manifest, string parameters) { using (Process zip_process = Process.Start(ConfigurationManager.Instance.Program7ZIP, parameters)) { using (ProcessOutputReader process_output_reader = new ProcessOutputReader(zip_process)) { string STATUS_TOKEN = "Bundle-" + manifest.Version; StatusManager.Instance.ClearCancelled(STATUS_TOKEN); int iteration = 0; while (true) { ++iteration; if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling creation of Bundle Library due to signaled application shutdown"); StatusManager.Instance.SetCancelled(STATUS_TOKEN); } if (StatusManager.Instance.IsCancelled(STATUS_TOKEN)) { zip_process.Kill(); zip_process.WaitForExit(5000); Logging.Error("Canceled creation of Bundle Library:\n--- Parameters: {0}\n{1}", parameters, process_output_reader.GetOutputsDumpStrings()); StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Canceled creation of Bundle Library."); return; } if (zip_process.HasExited) { Logging.Info("Completed creation of Bundle Library:\n--- Parameters: {0}\n{1}", parameters, process_output_reader.GetOutputsDumpStrings()); StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Completed creation of Bundle Library."); return; } StatusManager.Instance.UpdateStatus(STATUS_TOKEN, "Creating Bundle Library...", cancellable: true); ShutdownableManager.Sleep(3000); } } } }
public static void DoInterestingAnalysis(PDFReadingControl pdf_reading_control, PDFRendererControl pdf_renderer_control, PDFDocument pdf_document) { pdf_reading_control.OnlineDatabaseLookupControl.PDFDocument = pdf_document; ShutdownableManager.Sleep(1000); if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling DoInterestingAnalysis due to signaled application shutdown"); return; } SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_DuplicatesAndCitations(pdf_reading_control, pdf_document)); // Only bother Google Scholar with a query when we want to: if (ConfigurationManager.IsEnabled(nameof(DoInterestingAnalysis_GoogleScholar))) { SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_GoogleScholar(pdf_reading_control, pdf_document)); } SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_TagCloud(pdf_reading_control, pdf_document)); SafeThreadPool.QueueUserWorkItem(o => DoInterestingAnalysis_SimilarAuthors(pdf_reading_control, pdf_document)); }
private void FlushDocuments(bool force_flush_no_matter_what) { // use a lock to ensure the time-delayed flush doesn't ever collide with the // end-of-execution-run flush initiated by ShutdownableManager. ForcedFlushRequested = force_flush_no_matter_what; if (!force_flush_no_matter_what) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); } int done_count_for_status = 0; Stopwatch breathing_time = Stopwatch.StartNew(); while (true) { int count_to_go = PendingQueueCount; int todo_count_for_status = done_count_for_status + count_to_go; if (0 < count_to_go) { StatusManager.Instance.UpdateStatus("DocumentQueuedStorer", String.Format("{0}/{1} documents still to flush", count_to_go, todo_count_for_status), done_count_for_status, todo_count_for_status); } else { StatusManager.Instance.ClearStatus("DocumentQueuedStorer"); return; } if (!ForcedFlushRequested) { // No flushing while still adding... unless we're quitting the executable already. if (Library.IsBusyAddingPDFs) { return; } if (breathing_time.ElapsedMilliseconds > FolderWatcher.MAX_SECONDS_PER_ITERATION) { ShutdownableManager.Sleep(FolderWatcher.SECONDS_TO_RELAX_PER_ITERATION); // reset: breathing_time.Restart(); } } PDFDocument pdf_document_to_flush = null; // grab one PDF to save/flush: // Utilities.LockPerfTimer l2_clk = Utilities.LockPerfChecker.Start(); lock (documents_to_store_lock) { // l2_clk.LockPerfTimerStop(); foreach (var pair in documents_to_store) { pdf_document_to_flush = pair.Value; documents_to_store.Remove(pair.Key); break; } } if (null != pdf_document_to_flush) { pdf_document_to_flush.SaveToMetaData(ForcedFlushRequested); done_count_for_status++; } } }
public static PDFDocument AddNewPDFDocumentsToLibraryWithMetadata_SYNCHRONOUS(WebLibraryDetail web_library_detail, bool suppress_notifications, FilenameWithMetadataImport[] filename_with_metadata_imports) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); Stopwatch clk = Stopwatch.StartNew(); Stopwatch breathing_time = Stopwatch.StartNew(); // Notify if there is just a single doc suppress_notifications = suppress_notifications || (filename_with_metadata_imports.Length > 1); StatusManager.Instance.ClearCancelled("BulkLibraryDocument"); PDFDocument last_added_pdf_document = null; int successful_additions = 0; for (int i = 0; i < filename_with_metadata_imports.Length; ++i) { if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Debug特("ImportingIntoLibrary: Breaking out of outer processing loop due to application termination"); break; } if (StatusManager.Instance.IsCancelled("BulkLibraryDocument")) { Logging.Warn("User chose to stop bulk adding documents to the library"); break; } StatusManager.Instance.UpdateStatus("BulkLibraryDocument", String.Format("Adding document {0} of {1} to your library", i + 1, filename_with_metadata_imports.Length), i, filename_with_metadata_imports.Length, true); FilenameWithMetadataImport filename_with_metadata_import = filename_with_metadata_imports[i]; try { string filename = filename_with_metadata_import.filename; string bibtex = filename_with_metadata_import.bibtex; PDFDocument pdf_document = web_library_detail.Xlibrary.AddNewDocumentToLibrary_SYNCHRONOUS(filename, web_library_detail, filename, filename, bibtex, filename_with_metadata_import.tags, filename_with_metadata_import.notes, suppress_notifications); if (null != pdf_document) { ++successful_additions; } last_added_pdf_document = pdf_document; } catch (Exception ex) { Logging.Warn(ex, "There was a problem adding a document to the library:\n{0}", filename_with_metadata_import); // if the problem report file doesn't exist yet, we have to create it: // Utilities.LockPerfTimer l2_clk = Utilities.LockPerfChecker.Start(); lock (problematic_import_documents_lock) { // l2_clk.LockPerfTimerStop(); if (null == problematic_import_documents_filename) { problematic_import_documents_filename = TempFile.GenerateTempFilename("qiqqa-import-problem-report.txt"); } } // then always append the entire report chunk at once as multiple threads MAY // be appending to the report simultaneously! // Utilities.LockPerfTimer l3_clk = Utilities.LockPerfChecker.Start(); lock (problematic_import_documents_lock) { // l3_clk.LockPerfTimerStop(); File.AppendAllText( problematic_import_documents_filename, "The following files caused problems while being imported into Qiqqa:\r\n\r\n" ); File.AppendAllText( problematic_import_documents_filename, String.Format( "----------\r\n{0}\r\n{1}\r\n{2}\r\n----------\r\n" , ex.Message , ex.StackTrace , filename_with_metadata_import ) ); } } if (breathing_time.ElapsedMilliseconds >= FolderWatcher.MAX_SECONDS_PER_ITERATION) { Logging.Info("AddNewPDFDocumentsToLibraryWithMetadata_SYNCHRONOUS: Taking a nap due to MAX_SECONDS_PER_ITERATION: {0} seconds consumed", breathing_time.ElapsedMilliseconds / 1E3); ShutdownableManager.Sleep(FolderWatcher.SECONDS_TO_RELAX_PER_ITERATION); breathing_time.Restart(); } } if (filename_with_metadata_imports.Length > 0) { StatusManager.Instance.UpdateStatus("BulkLibraryDocument", String.Format("Added {0} of {1} document(s) to your library", successful_additions, filename_with_metadata_imports.Length)); } else { StatusManager.Instance.ClearStatus("BulkLibraryDocument"); } // If there have been some import problems, report them to the user. // However, we should not wait for the user response! // Utilities.LockPerfTimer l1_clk = Utilities.LockPerfChecker.Start(); lock (problematic_import_documents_lock) { // l1_clk.LockPerfTimerStop(); if (null != problematic_import_documents_filename) { problematic_import_documents_alert_showing++; // only show a single alert, not a plethora of 'em! if (1 == problematic_import_documents_alert_showing) { // once the user has ack'ed or nack'ed the message, that handler // will RESET the 'showing' counter and the party can start all over again! SafeThreadPool.QueueUserWorkItem(o => AlertUserAboutProblematicImports()); } } } Logging.Debug特("AddNewPDFDocumentsToLibraryFromFolder_SYNCHRONOUS: time spent: {0} ms", clk.ElapsedMilliseconds); return(last_added_pdf_document); }
internal void RepopulateFromCSLProcessor_SUCCESS(CSLProcessorOutputConsumer ip, CSLProcessor.BrowserThreadPassThru passthru) { int MAX_DODGY_PASTE_RETRY_COUNT = 5; int DODGY_PASTE_RETRY_SLEEP_TIME_MS = 200; int dodgy_paste_retry_count = 0; try { // Suppress screen updates (for performance reasons) repopulating_clusters = true; word_application.ScreenUpdating = false; Document document = word_application.Selection.Document; // Get all the fields out there Logging.Info("+Enumerating all fields"); List <Field> fields = GetDocumentFields(document); Logging.Info("-Enumerating all fields"); StatusManager.Instance.ClearCancelled("InCite"); for (int f = 0; f < fields.Count; ++f) { if (StatusManager.Instance.IsCancelled("InCite")) { Logging.Info("Updating of citations in Word has been canceled by the user."); break; } if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling citation update in Word due to signaled Qiqqa application shutdown"); break; } Field field = fields[f]; StatusManager.Instance.UpdateStatus("InCite", "Updating InCite fields in Word", f, fields.Count, true); word_application.StatusBar = String.Format("Updating InCite field {0} of {1}...", f, fields.Count); try { // Do we have a citation that we can fill? CitationCluster citation_cluster = GenerateCitationClusterFromField(field); if (null != citation_cluster) { string text_for_cluster = ip.GetTextForCluster(citation_cluster.cluster_id); string rtf_hash = GenerateRTFHash(passthru.is_note_format, text_for_cluster); // Update this citation cluster only if it needs updating (if it has changed from what is currently stored in it) if (!String.IsNullOrEmpty(text_for_cluster)) { bool needs_update = false; if (!needs_update) { if (rtf_hash != citation_cluster.rtf_hash) { needs_update = true; } } if (!needs_update) { string current_field_contents = field.Result.Text; if (current_field_contents.Contains("QIQQA")) { needs_update = true; } } if (needs_update) { // Update the field with the new hash citation_cluster.rtf_hash = rtf_hash; PopulateFieldWithRawCitationCluster(field, citation_cluster); // Remember the font string font_name = field.Result.Font.Name; float font_size = field.Result.Font.Size; string rtf = RTF_START + text_for_cluster + RTF_END; ClipboardTools.SetText(rtf, TextDataFormat.Rtf); if (passthru.is_note_format) { field.Result.Text = ""; Footnote footnote = field.Result.Footnotes.Add(field.Result); footnote.Range.Text = " "; Range range = footnote.Range; range.Collapse(WdCollapseDirection.wdCollapseStart); range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF); footnote.Range.Font.Name = font_name; footnote.Range.Font.Size = font_size; } else { field.Result.Text = " "; Range range = field.Result; range.Collapse(WdCollapseDirection.wdCollapseStart); range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF); field.Result.Text = field.Result.Text.Trim(); field.Result.Font.Name = font_name; field.Result.Font.Size = font_size; } } } else { citation_cluster.rtf_hash = rtf_hash; PopulateFieldWithRawCitationCluster(field, citation_cluster); field.Result.Text = String.Format("ERROR: Unable to find key {0} in the CSL output.", citation_cluster.cluster_id); } // If we get here, it must have worked! dodgy_paste_retry_count = 0; continue; } // Do we have a bibliography that we can fill? if (IsFieldBibliography(field)) { // Remember the font string font_name = field.Result.Font.Name; float font_size = field.Result.Font.Size; string formatted_bibliography_section = ip.GetFormattedBibliographySection(); if (String.IsNullOrEmpty(formatted_bibliography_section)) { formatted_bibliography_section = "Either this CSL citation style does not produce a bibliography section or you have not yet added any citations to this document, so this bibliography is empty."; } string formatted_bibliography_section_wrapped = CSLProcessorOutputConsumer.RTF_START + formatted_bibliography_section + CSLProcessorOutputConsumer.RTF_END; ClipboardTools.SetText(formatted_bibliography_section_wrapped, TextDataFormat.Rtf); field.Result.Text = " "; Range range = field.Result; range.Collapse(WdCollapseDirection.wdCollapseStart); range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF); field.Result.Font.Name = font_name; field.Result.Font.Size = font_size; // If we get here, it must have worked! dodgy_paste_retry_count = 0; continue; } // Do we have a CSL stats region? if (IsFieldCSLStats(field)) { StringBuilder sb = new StringBuilder(); sb.Append(RTF_START); { sb.AppendFormat("maxoffset={0}\\line\n", ip.max_offset); sb.AppendFormat("entryspacing={0}\\line\n", ip.entry_spacing); sb.AppendFormat("linespacing={0}\\line\n", ip.line_spacing); sb.AppendFormat("hangingindent={0}\\line\n", ip.hanging_indent); sb.AppendFormat("second_field_align={0}\\line\n", ip.second_field_align); } sb.Append(RTF_END); Clipboard.SetText(sb.ToString(), TextDataFormat.Rtf); field.Result.Text = " "; Range range = field.Result; range.Collapse(WdCollapseDirection.wdCollapseStart); range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF); // If we get here, it must have worked! dodgy_paste_retry_count = 0; continue; } } catch (Exception ex) { ++dodgy_paste_retry_count; if (dodgy_paste_retry_count < MAX_DODGY_PASTE_RETRY_COUNT) { Logging.Warn(ex, "Will try again (try {0}) because there was a problem updating a citation field: {1}", dodgy_paste_retry_count, field.Result.Text); // Back up one field so we can try again ShutdownableManager.Sleep(DODGY_PASTE_RETRY_SLEEP_TIME_MS); --f; continue; } else { Logging.Error(ex, "Giving up because there was a problem updating a citation field: {0}", field.Result.Text); dodgy_paste_retry_count = 0; continue; } } } } finally { // Restore the screen updates repopulating_clusters = false; word_application.ScreenUpdating = true; word_application.StatusBar = "Updated InCite fields."; } }
private static void BackgroundRenderImages_BACKGROUND(FlowDocument flow_document, List <AnnotationWorkGenerator.AnnotationWork> annotation_works, AnnotationReportOptions annotation_report_options) { WPFDoEvents.AssertThisCodeIs_NOT_RunningInTheUIThread(); ShutdownableManager.Sleep(annotation_report_options.InitialRenderDelayMilliseconds); PDFDocument last_pdf_document = null; StatusManager.Instance.ClearCancelled("AnnotationReportBackground"); for (int j = 0; j < annotation_works.Count; ++j) { if (ShutdownableManager.Instance.IsShuttingDown) { Logging.Error("Canceling creation of Annotation Report due to signaled application shutdown"); StatusManager.Instance.SetCancelled("AnnotationReportBackground"); } StatusManager.Instance.UpdateStatus("AnnotationReportBackground", "Building annotation report image", j, annotation_works.Count, true); if (StatusManager.Instance.IsCancelled("AnnotationReportBackground")) { Logging.Warn("User canceled annotation report generation"); break; } AnnotationWorkGenerator.AnnotationWork annotation_work = annotation_works[j]; PDFDocument pdf_document = annotation_work.pdf_document; // Clear down our previously caches pages if (null != last_pdf_document && last_pdf_document != pdf_document) { if (last_pdf_document.DocumentExists) { last_pdf_document.FlushCachedPageRenderings(); } } // Remember this PDF document so we can flush it if necessary last_pdf_document = pdf_document; // Now render each image PDFAnnotation pdf_annotation = annotation_work.pdf_annotation; if (null != pdf_annotation) { try { // Clear the waiting for processing text WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.processing_error.Text = ""; }); if (pdf_document.DocumentExists) { // Fill in the paragraph text if (null != annotation_work.annotation_paragraph) { WPFDoEvents.InvokeAsyncInUIThread(() => { BuildAnnotationWork_FillAnnotationText(pdf_document, pdf_annotation, annotation_work); }); } if (null != annotation_work.report_floater) { try { System.Drawing.Image annotation_image = PDFAnnotationToImageRenderer.RenderAnnotation(pdf_document, pdf_annotation, 80); BitmapSource cropped_image_page = BitmapImageTools.FromImage(annotation_image); WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.report_image.Source = cropped_image_page; annotation_work.report_floater.Width = new FigureLength(cropped_image_page.PixelWidth / 1); }); } catch (Exception ex) { Logging.Warn(ex, "There was a problem while rendering an annotation."); WPFDoEvents.InvokeAsyncInUIThread(() => { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); annotation_work.processing_error.Text = "There was a problem while rendering this annotation."; }); } } } else { WPFDoEvents.InvokeAsyncInUIThread(() => { if (null != annotation_work.report_image) { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); } annotation_work.processing_error.Text = "Can't show image: The PDF does not exist locally."; }); } } catch (Exception ex) { Logging.Error(ex, "There was an error while rendering page {0} for document {1} for the annotation report", pdf_annotation.Page, pdf_annotation.DocumentFingerprint); WPFDoEvents.InvokeAsyncInUIThread(() => { if (null != annotation_work.report_image) { annotation_work.report_image.Source = Icons.GetAppIcon(Icons.AnnotationReportImageError); } annotation_work.processing_error.Text = "Can't show image: There was an error rendering the metadata image."; }); } } } // And flush the rendering cache of the last document if (null != last_pdf_document) { if (last_pdf_document.DocumentExists) { last_pdf_document.FlushCachedPageRenderings(); } } StatusManager.Instance.ClearStatus("AnnotationReportBackground"); }