(* log.ml - Don Yang (uguu.org) 10/02/07 *) (* Special events *) let start_marker = "{{{";; let end_marker = "}}}";; (* Regular expressions for parsing input lines *) let re_dictionary_def = Str.regexp "^ *# *\\([^ ]+\\) *= *\\([^ ].*\\)$";; let re_event_line = Str.regexp ("^ *\\([0-9][^ ]+ [0-9]+:[0-9][^ ]+\\|[0-9][^ ]+\\) " ^ "+\\([^ ].*\\)$");; (* Append block to file *) let append_block_to_file block file = let out_channel = open_out_gen [Open_wronly; Open_append; Open_creat; Open_binary] 0o600 file in output_string out_channel block; close_out out_channel;; (* Read a single log line from file *) let read_log_line in_channel line_number reverse_log reference_time dict = incr line_number; let line = input_line in_channel in if (Str.string_match re_dictionary_def line 0) then ( let key = Str.matched_group 1 line in let value = Strutil.clean_string (Str.matched_group 2 line) in Hashtbl.replace dict key value ) else if (Str.string_match re_event_line line 0) then ( let event = Strutil.clean_string (Str.matched_group 2 line) in let time = Time.decode_time !reference_time (Str.matched_group 1 line) in if time < 0.0 || (!reference_time > 0.0 && time < !reference_time) then ( Printf.printf "Ignored line %d due to invalid timestamp\n" !line_number ) else ( reverse_log := (time, event) :: !reverse_log; reference_time := time ) ) else ();; (* Load file to list *) let read_file_to_log in_channel = let reverse_log = ref [] in let reference_time = ref 0.0 in let dictionary = Hashtbl.create 128 in let line_number = ref 0 in while try (read_log_line in_channel line_number reverse_log reference_time dictionary; true) with End_of_file -> false do () done; (!reverse_log, !reference_time, dictionary);; (* Load stdin to list *) let read_stdin_to_log () = let (reverse_log, _, _) = read_file_to_log stdin in reverse_log;; (* Find first event in reverse log that contains the specified prefix *) let find_last_event_prefix reverse_log prefix = let prefix_length = String.length prefix in let predicate event = try (String.sub (snd event) 0 prefix_length) = prefix with Invalid_argument "String.sub" -> false in snd (List.find predicate reverse_log);; (* Find first event in reverse log that contains the specified substring *) let find_last_event_substr reverse_log key = let pattern = Str.regexp_string key in let predicate event = try (ignore (Str.search_forward pattern (snd event) 0); true) with Not_found -> false in snd (List.find predicate reverse_log);;