Merge branch 'handle-stdout'
[SXSI/xpathcomp.git] / src / main.ml
1 (******************************************************************************)
2 (*  SXSI : XPath evaluator                                                    *)
3 (*  Kim Nguyen (Kim.Nguyen@nicta.com.au)                                      *)
4 (*  Copyright NICTA 2008                                                      *)
5 (*  Distributed under the terms of the LGPL (see LICENCE)                     *)
6 (******************************************************************************)
7 INCLUDE "utils.ml"
8
9 open Ata
10
11 let () = init_timer();;
12
13
14 let default_gc = Gc.get()
15 let tuned_gc = { default_gc with
16   Gc.minor_heap_size = 32*1024*1024;
17   Gc.major_heap_increment = 8*1024*1024;
18   Gc.max_overhead = 1000000;
19   Gc.space_overhead = 100;
20 }
21
22 let mk_runtime run auto doc arg count print outfile =
23   fun () ->
24     if !Config.do_perf then start_perf ();
25     let r = Utils.time ~count:!Config.repeat ~msg:"Execution time" (run auto doc) arg in
26     if !Config.do_perf then stop_perf ();
27     Logger.start_msg Format.err_formatter "[Debug] Number of results: ";
28     Logger.msg Format.err_formatter "%i" (count r);
29     Logger.end_msg Format.err_formatter "\n";
30     match outfile with
31         None -> ()
32       | Some file ->
33         Utils.time ~count:1 ~msg:"Serialization time" (print file !Config.no_wrap_results doc) r
34 ;;
35
36 let main v query_string output =
37   Tag.init (Tree.tag_operations v);
38   if !Config.docstats then Tree.stats v;
39   let query =
40     Utils.time ~msg:"Parsing query" XPath.parse query_string
41   in
42   Logger.start_msg Format.err_formatter "[Debug]";
43   Logger.msg Format.err_formatter " Parsed query: @\n @[<v 0> {";
44   Logger.msg Format.err_formatter " %a }@]" XPath.Ast.print query;
45   Logger.end_msg Format.err_formatter "\n\n";
46   let auto, bu_info =
47     Utils.time ~msg:"Compiling query" Compile.compile query
48   in
49   Logger.start_msg Format.err_formatter "[Debug] Automaton: ";
50   Logger.msg Format.err_formatter "@\n     @[<v 0>";
51   Logger.msg Format.err_formatter "%a" Ata.print auto;
52   Logger.end_msg Format.err_formatter "\n\n";
53   Gc.full_major();
54   Gc.compact();
55   Gc.set (tuned_gc);
56   let runtime =
57     match !Config.bottom_up, bu_info with
58
59     | true, Some [ (query, pattern) ] ->
60       if !Config.count_only then
61         let module R = ResJIT.Count in
62         let module M = Runtime.Make(R) in
63         mk_runtime M.bottom_up_run auto v (query, pattern) R.NS.length R.NS.serialize !Config.output_file
64       else
65         let module R = ResJIT.Mat in
66         let module M = Runtime.Make(R) in
67         mk_runtime M.bottom_up_run auto v (query, pattern) R.NS.length R.NS.serialize !Config.output_file
68
69     | _ ->
70       (* run the query top_down *)
71
72       if !Config.bottom_up then
73         Logger.verbose Format.err_formatter "Cannot run the query in bottom-up mode, using top-down evaluator@\n@?";
74       if !Config.count_only then
75         let module R = ResJIT.Count in
76         let module M = Runtime.Make(R) in
77         if !Config.twopass then
78           mk_runtime M.twopass_top_down_run auto v Tree.root R.NS.length R.NS.serialize None
79         else
80           mk_runtime M.top_down_run auto v Tree.root R.NS.length R.NS.serialize !Config.output_file
81       else
82         let module R = ResJIT.Mat in
83         let module M = Runtime.Make(R) in
84         mk_runtime M.top_down_run auto v Tree.root R.NS.length R.NS.serialize !Config.output_file
85   in
86   runtime ()
87 ;;
88
89 let () = Options.parse_cmdline()
90 ;;
91 let _ =
92   try
93     Printexc.record_backtrace true;
94     let document =
95       if Filename.check_suffix !Config.input_file ".srx"
96       then
97         Utils.time
98           ~msg:"Loading Index file"
99           (Tree.load
100              ~sample:!Config.sample_factor
101              ~load_text:(not !Config.disable_text_collection))
102           !Config.input_file
103       else
104         let v =
105           Utils.time
106             ~msg:"Loading XML file"
107             (Tree.parse_xml_uri)
108             !Config.input_file
109         in
110         let () =
111           if !Config.save_file <> ""
112           then
113             Utils.time
114               ~msg:"Writing file to disk"
115               (Tree.save v)
116               !Config.save_file;
117         in
118         v
119     in
120     main document !Config.query !Config.output_file;
121 IFDEF PROFILE
122   THEN
123     Profile.summary Format.err_formatter
124   ELSE ()
125 END
126   with
127   | Ulexer.Loc.Exc_located ((x,y),e) ->
128     Logger.print Format.err_formatter "character %i-%i %s@\n" x y (Printexc.to_string e);
129     exit 1
130
131   | e ->
132     Logger.print Format.err_formatter "BACKTRACE: %s@\n@?" (Printexc.get_backtrace());
133     Logger.print Format.err_formatter "FATAL ERROR: %s@\n@?" (Printexc.to_string e);
134     exit 2