# # # # get_progress_state_util.cfv # # # include "templates.util.base_util"; # # # # get_expanded_progress_value() # # # subroutine(get_expanded_progress_value( string s), ( # A progress description may contain $lang_stats and i.e. a file path which contains a $. # The $ in the file path would raise an error upon expand(). To handle this we escape all # non-$lang strings before we apply expand(). string the_regexp = ".(lang_admin\.|lang_stats\.)|(\{=(.)+=\})"; if (contains(s, "$lang_stats")) then ( # # Escape the language variable(s) # s = replace_all(s, "$lang_stats", "__HexEsc__24__lang_stats"); # # Escape any other $ character in the string # bool is_non_lang_dollar_char = false; if (contains(s, "$")) then ( s = replace_all(s, "$", "__HexEsc__24__"); is_non_lang_dollar_char = true; ); # # Restore lang variables # s = replace_all(s, "__HexEsc__24__lang_stats", "$lang_stats"); # # Expand the string # s = expand(s); # # Restore any non-language $ # if (is_non_lang_dollar_char) then ( s = replace_all(s, "__HexEsc__24__", "$"); ); ); # return s s; )); # # # # get_progress_info_in_get_progress_state() # # # subroutine(get_progress_info_in_get_progress_state( string task_id), ( delete_node("v.progress_info"); v.progress_info = ""; get_progress_info(task_id, "v.progress_info"); # debug_message("\n#### get_progress_info_in_get_progress_state() - progress_info:\n" . node_as_string("v.progress_info") . "\n"); "v.progress_info"; )); # # # # get_progress_info_check_all_report_elements_done() # # # subroutine(get_progress_info_check_all_report_elements_done( string lai_directory, string profile_name, node report_job), ( debug_message("\n\n\n#### get_progress_info_check_all_report_elements_done() START \n"); # Write debug output to v.temp_debug_report_elements so that we can show any incomplete report elements in # the progress error message. delete_node("v.temp_debug_report_elements"); v.temp_debug_report_elements = ""; # Checks if all report elements exists in the respective output directory, in this case HTML node report_elements_job_node = report_job{"report_elements"}; bool is_ready_report_element; bool is_ready_report = true; node report_element; string report_element_name; string report_element_id; string report_element_html_formatting_id; string html_report_element_id; string report_element_file_name; string report_element_file_path; foreach report_element report_elements_job_node ( report_element_id = @report_element{"report_element_id"}; report_element_html_formatting_id = @report_element{"report_element_html_formatting_id"}; html_report_element_id = get_html_report_element_id(report_element_id, report_element_html_formatting_id); report_element_file_name = html_report_element_id . ".txt"; report_element_file_path = lai_directory . "profiles_cache/" . profile_name . "/html_report_elements/" . report_element_file_name; is_ready_report_element = file_exists(report_element_file_path); if (!is_ready_report_element) then ( is_ready_report = false; ); # Track debug info for error message. report_element_name = node_name(report_element); "v.temp_debug_report_elements." . report_element_name . ".report_element_id" = report_element_id; "v.temp_debug_report_elements." . report_element_name . ".report_element_file_name" = report_element_file_name; "v.temp_debug_report_elements." . report_element_name . ".raw_report_element_exists" = if (?("profiles_cache." . profile_name . ".raw_report_elements." . report_element_id)) then (true) else (false); "v.temp_debug_report_elements." . report_element_name . ".html_report_element_exists" = is_ready_report_element; ); # debug_message("\n\n\n#### is_ready_report: " . is_ready_report . "\n"); debug_message("\n\n\n#### get_progress_info_check_all_report_elements_done() END \n\n"); is_ready_report; )); # # # # get_progress_state_for_reports() # # # subroutine(get_progress_state_for_reports( string profile_name, string session_id, string report_job_id, bool is_active_task, bool progress_exists), ( debug_message("\n\n\n#### get_progress_state_for_reports() START \n"); string progress_state = ""; if (is_active_task and progress_exists) then ( progress_state = "progress"; ) else ( if (is_active_task) then ( # There is no progress, we assume that we are in progress prediction mode progress_state = "progress_prediction"; ) else ( # The task is not anymore active # Check if all report element files exists (we only do that if the task is not anymore active so that we avoid any file conflicts) string session_profile_path = "sessions_cache." . session_id . ".profiles." . profile_name; node report_job = session_profile_path . ".report_jobs." . report_job_id; string lai_directory = LOGANALYSISINFO_DIRECTORY; bool is_ready_report_elements = get_progress_info_check_all_report_elements_done(lai_directory, profile_name, report_job); if (is_ready_report_elements) then ( progress_state = "complete"; ); ); ); progress_state; debug_message("#### get_progress_state_for_reports() END \n\n"); )); # # # # get_active_subtasks_progress_dat() # # # subroutine(get_active_subtasks_progress_dat( node task_item_with_active_subtasks), ( # This gets the label foreach active subtask. # Note, there may be mutiple tasks with the same label, we combine # them and append the number of occurance in braces, i.e.: # Parsing server (multiprocessor log parsing) (2x) string dat = "["; string item_dat; if (task_item_with_active_subtasks?{"active_subtasks"} and num_subnodes(task_item_with_active_subtasks{"active_subtasks"}) > 0) then ( node active_subtasks = task_item_with_active_subtasks{"active_subtasks"}; node item; string subtask_pid; string label; string label_checksum; node active_subtask_labels = new_node(); int number_of_tasks; # # Collect labels in active_subtask_labels # foreach item active_subtasks ( subtask_pid = @item{"pid"}; # Check if there is progress for the subtask_pid delete_node("v.subtask_progress_info"); v.subtask_progress_info = ""; node progress_info = "v.subtask_progress_info"; get_progress_info(subtask_pid, progress_info); # Ignore subtasks which do not have a progress_info label if (progress_info?{"label"} and (@progress_info{"label"} ne "")) then ( label = @progress_info{"label"}; label_checksum = md5_digest(label); if (!active_subtask_labels?{label_checksum}) then ( # item does not yet exist, add it @active_subtask_labels{label_checksum}{"label"} = label; @active_subtask_labels{label_checksum}{"number_of_tasks"} = 1; ) else ( # Lable already exists, just increase the number_of_tasks number_of_tasks = @active_subtask_labels{label_checksum}{"number_of_tasks"}; @active_subtask_labels{label_checksum}{"number_of_tasks"} = number_of_tasks + 1; ); ); ); # # Create the labels json # foreach item active_subtask_labels ( label = @item{"label"}; number_of_tasks = @item{"number_of_tasks"}; item_dat = "{"; item_dat .= add_json("label", label, "string"); item_dat .= add_json("numOfTasks", number_of_tasks, "int"); dat .= close_json(item_dat) . ","; ); ); if (dat ne "[") then ( dat = replace_last(dat, ",", "]"); ) else ( dat .= "]"; ); # Return dat; )); # # # # get_processing_details_dat() # # # subroutine(get_processing_details_dat( node processing_details), ( string dat = "["; string item_dat; node item; string label; foreach item processing_details ( label = get_expanded_label(@item{"label"}); item_dat = "{"; item_dat .= add_json("label", label, "string"); item_dat .= add_json("value", format(@item, @item{"display_format_type"}), "string"); dat .= close_json(item_dat) . ","; ); dat = replace_last(dat, ",", "]"); # debug_message("\n\n#### processing_details dat:\n" . dat . "\n\n"); dat; )); # # # # get_progress_info_warnings_dat() # # # subroutine(get_progress_info_warnings_dat( node progress_info), ( string warnings_dat = "["; if (progress_info?{"warnings"} and (num_subnodes(progress_info{"warnings"}) > 0)) then ( node warnings = progress_info{"warnings"}; node item; string the_warning; foreach item warnings ( the_warning = get_expanded_label(@item); warnings_dat .= '"' . encode_json(the_warning) . '",'; ); warnings_dat = replace_last(warnings_dat, ",", "]"); ) else ( # No warnings warnings_dat .= "]"; ); # Return warnings_dat; )); # # # # get_progress_info_dat() # # # subroutine(get_progress_info_dat( node task_item_with_active_subtasks, node progress_info, bool is_report_progress), ( debug_message("\n#### get_progress_info_dat() \n\n"); # debug_message("\n" . node_as_string(progress_info) . "\n"); int current_step_number = @progress_info{"current_step"}; int number_of_steps = 0; # # Get major progress label # string major_task = @progress_info{"major_task"}; string main_label; if (major_task ne "" and major_task ne "unknown") then ( main_label = get_expanded_label(@progress_info{"label"}); ) else ( # Check if task_item if it has action information and get # the label from the action name if (task_item_with_active_subtasks?{"action"} and @task_item_with_active_subtasks{"action"} ne "") then ( string action_name = @task_item_with_active_subtasks{"action"}; if (?("lang_stats.progress.major_task." . action_name)) then ( main_label = @("lang_stats.progress.major_task." . action_name); ) else ( main_label = action_name; ); ) else ( # Fallback to regular label main_label = get_expanded_label(@progress_info{"label"}); ); ); string active_step_label = '-'; string active_step_description = '-'; # string progress_meter_position = @progress_info{"progress_meter_position"}; string progress_meter_position = 0; # string decimal_point; # The progress_meter_position must be a floating point number for javascript calculation, so # fix it in case that the decimal divider is not a dot (i.e. in German language). # Formatting is done on client side. # 2008-11-03 - GMF - Handled case where progress meter position contains no decimal point (which was causing an error # due to the attempt to use $1 when there was no previous match. Added "if" to do nothing in that case. # bool b = matches_regular_expression(progress_meter_position, "([^0-9])"); # if (b) then ( # string decimal_point = $1; # if (decimal_point ne "." and decimal_point ne "") then ( # progress_meter_position = replace_first(progress_meter_position, decimal_point, "."); # ); # ); # debug_message("\n\n#### progress_meter_position: $progress_meter_position \n"); # debug_message("\n#### decimal_point: $decimal_point \n\n"); # KHP 22/Oct/2013 - Greg added global time_elapsed because steps # do not count elapsed time correctly. int total_time_elapsed = @progress_info{"time_elapsed"}; if (progress_info?{"step"}) then ( node progress_steps = progress_info{"step"}; number_of_steps = num_subnodes(progress_steps); if (number_of_steps > 0) then ( node current_step_node = progress_steps{current_step_number}; # Don't use simple expand because suboperation_description may contain a $ in log directory! # active_step_label = expand(@current_step_node{"label"}); # active_step_description = expand(@current_step_node{"suboperation_description"}); active_step_label = get_expanded_progress_value(@current_step_node{"label"}); active_step_description = get_expanded_progress_value(@current_step_node{"suboperation_description"}); # # Get time elapsed # # node step_item; # foreach step_item progress_steps ( # # total_time_elapsed += @step_item{"time_elapsed"}; # # if (node_name(step_item) eq current_step_number) then ( # last; # ); # ); ); ); # # Get progress info for active subtasks # string active_subtasks_progress_dat = get_active_subtasks_progress_dat(task_item_with_active_subtasks); # # Get processing details # string processing_details_dat; if (!is_report_progress and progress_info?{"details"} and (num_subnodes(progress_info{"details"}) > 0)) then ( processing_details_dat = get_processing_details_dat(progress_info{"details"}); ) else ( processing_details_dat = "[]"; ); # # Get warnings, if any # string warnings_dat = get_progress_info_warnings_dat(progress_info); string dat = "{"; dat .= add_json("meterPosition", progress_meter_position, "float"); dat .= add_json("currentStep", current_step_number + 1, "int"); dat .= add_json("numberOfSteps", number_of_steps, "int"); dat .= add_json("mainLabel", main_label, "string"); dat .= add_json("stepLabel", active_step_label, "string"); dat .= add_json("stepDescription", active_step_description, "string"); dat .= add_json("totalTimeElapsed", format(total_time_elapsed, "duration_compact"), "string"); dat .= add_json("activeSubtasks", active_subtasks_progress_dat, "obj"); dat .= add_json("processingDetails", processing_details_dat, "obj"); dat .= add_json("warnings", warnings_dat, "obj"); dat = close_json(dat); # debug_message("\n\n#### progress_info dat:\n" . total_time_elapsed_display . "\n\n"); dat; )); # # # # get_progress_error_message_via_task_id # # # subroutine(get_progress_error_message_via_task_id( string task_id), ( debug_message("\n#### get_progress_error_message_via_task_id() START \n"); # This returns an error message if one exists for the given task_id, else it returns an empty string debug_message("#### task_id:" . task_id . "\n"); string error_message; if (task_id ne "") then ( # Check for error message in task node task_info = get_task_info(); # debug_message("\n" . node_as_string(task_info) . "\n"); if (task_info{task_id}?{"error_message"}) then ( error_message = @task_info{task_id}{"error_message"}; ); # Clean up delete_node(task_info); ); # Return error_message; debug_message("\n#### get_progress_error_message_via_task_id() END \n"); )); # # # # get_database_progress_error_message() # # # subroutine(get_database_progress_error_message( string task_id, bool is_active_task, bool progress_exists, bool is_real_time_processing, bool database_is_building, bool initial_build_done), ( # # Returns the error message of the task if one exists, else it returns a general error message # string error_message = get_progress_error_message_via_task_id(task_id); if (error_message eq "") then ( # # There is no error for the task reported, so we compose a general error message # error_message = lang_stats.general.background_process_terminated . "\n\n"; error_message .= "Error occured when trying to get database progress in get_progress_state().\n\n"; error_message .= "Database/Progress state:\n"; error_message .= "- task_id: " . task_id . "\n"; error_message .= "- is_active_task: " . is_active_task . "\n"; error_message .= "- progress_exists: " . progress_exists . "\n"; error_message .= "- db_info is_real_time_processing: " . is_real_time_processing . "\n"; error_message .= "- db_info database_is_building: " . database_is_building . "\n"; error_message .= "- db_info initial_build_done: " . initial_build_done . "\n"; ); error_message; )); # # # # get_database_progress_state() # # # subroutine(get_database_progress_state( string profile_name, string task_id, bool is_active_task, bool progress_exists), ( debug_message("\n\n#### get_database_progress_state START \n"); string progress_state; node db_info = get_database_info(profile_name, false); # debug_message("\n" . node_as_string(db_info) . "\n"); bool is_real_time_processing = get_is_real_time_processing(profile_name); bool database_is_building = get_database_is_building(profile_name, db_info); bool initial_build_done = get_initial_build_done(db_info); bool database_is_ready_for_reporting = get_database_is_ready_for_reporting(db_info); debug_message("\n\n#### is_real_time_processing: " . is_real_time_processing . "\n"); debug_message("#### database_is_building: " . database_is_building . "\n"); debug_message("#### initial_build_done: " . initial_build_done . "\n"); debug_message("#### database_is_ready_for_reporting: " . database_is_ready_for_reporting . "\n\n"); if (!is_real_time_processing) then ( if (initial_build_done and !database_is_building) then ( progress_state = "complete"; ) else if (is_active_task) then ( if (progress_exists) then ( progress_state = "progress"; ) else ( progress_state = "progress_prediction"; ); ) else ( # The task just completed or the task crashed. # Wait some time and re-check the db_info. # If the database is not yet done we assumme that the task # crashed and show an error message. debug_message("#### The task just completed or the task crashed, re-check the database_done state \n"); int count = 0; int max_count = 4; bool completed_with_delay = false; while (count < max_count) ( sleep_milliseconds(750); # Get a fresh database_info delete_node(db_info); db_info = get_database_info(profile_name, false); database_is_building = get_database_is_building(profile_name, db_info); initial_build_done = get_initial_build_done(db_info); if (initial_build_done and !database_is_building) then ( count = max_count; completed_with_delay = true; ) else ( count++; ); ); if (completed_with_delay) then ( # debug_message("#### The database build finally completed with a delay \n"); progress_state = "complete"; ) else ( # Show error string error_message = get_database_progress_error_message(task_id, is_active_task, progress_exists, is_real_time_processing, database_is_building, initial_build_done); error(error_message); ); ); ) else ( # Real time processing if (database_is_ready_for_reporting) then ( progress_state = "complete"; ) else if (progress_exists) then ( progress_state = "progress"; ) else ( progress_state = "progress_prediction"; ); ); # Clean up delete_node(db_info); debug_message("#### progress_state: " . progress_state . "\n"); progress_state; debug_message("#### get_database_progress_state END \n"); )); # # # # get_snapon_progress_state() # # # subroutine(get_snapon_progress_state( string profile_name, node active_task_item, string task_id, bool is_active_task, bool progress_exists), ( debug_message("\n\n#### get_snapon_progress_state START \n"); string progress_state; if (is_active_task) then ( if (progress_exists) then ( progress_state = "progress"; ) else ( progress_state = "progress_prediction"; ); ) else ( # We assume the snapon operation completed unless an error message exists string error_message = if (active_task_item?{"error_message"}) then (@active_task_item{"error_message"}) else (""); if (error_message eq "") then ( progress_state = "complete"; ) else ( # Throw an error error(error_message); ); ); debug_message("#### progress_state: " . progress_state . "\n"); progress_state; debug_message("#### get_snapon_progress_state END \n"); ));