safety commit
[SXSI/xpathcomp.git] / 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
8 open Ata
9 INCLUDE "utils.ml"
10 let () = init_timer();;
11
12 let enabled_gc = Gc.get()
13 let disabled_gc = { Gc.get() with
14                       Gc.max_overhead = 1000000; 
15                       Gc.space_overhead = 100 }
16 let hash x = 131*x/(x-1+1)
17
18 let test_loop tree tag =
19   let t' = Tree.tagged_desc tree tag  Tree.root in
20   let f = Hashtbl.create 4096
21   in
22   let jump t _ =  Tree.tagged_foll_ctx tree tag t Tree.root in
23   let g t ctx = 
24     if t == Tree.nil then 0
25     else 1+ ((Hashtbl.find f (hash 101)) (jump t ctx) ctx)
26   in
27   Hashtbl.add f (hash 101) g;
28   (Hashtbl.find f (hash 101)) t' Tree.root
29
30 let test_full tree = 
31   let root = Tree.root in
32   let fin = Tree.closing tree root in
33   let rec loop t = if t <= fin then
34   let tag = Tree.tag tree t in
35 (*  let _ = Tag.to_string tag in *)
36   if tag == Tag.pcdata then (ignore (Tree.get_text tree t)); 
37   let t = (Obj.magic ((Obj.magic t) + 1)) in
38   loop t
39   in
40   loop root
41
42
43 let test_loop2 tree tag =
44   let t' = Tree.tagged_desc tree tag  Tree.root in
45   let f = Hashtbl.create 4096
46   in
47   let jump t _ =  Tree.tagged_foll_ctx tree tag t Tree.root in
48   let rec g t ctx = 
49     if t == Tree.nil then 0
50     else 1+ (match (Hashtbl.find f (hash 101)) with
51                 `Foo ->g (jump t ctx) ctx
52             ) 
53   in
54   Hashtbl.add f (hash 101) `Foo;
55   g t' Tree.root
56
57 let main v query_string output =
58  
59     let _ = Tag.init (Tree.tag_pool v) in
60       Printf.eprintf "Parsing query : ";    
61       let query = try
62         time
63           XPath.Parser.parse_string query_string
64       with
65           Ulexer.Loc.Exc_located ((x,y),e) -> Printf.eprintf "character %i-%i %s\n" x y (Printexc.to_string e);exit 1
66       in
67 (*      let _ = Printf.eprintf "Timing //keyword :" in
68       let r = time (test_loop v) (Tag.tag "keyword") in
69       let _ = Printf.eprintf "Count is %i\n%!" r in 
70       let _ = Printf.eprintf "Timing //keyword 2:" in
71       let r = time (test_loop2 v) (Tag.tag "keyword") in
72       let _ = Printf.eprintf "Count is %i\n%!" r in  
73       let _ = Printf.eprintf "Timing //node() :" in
74       let _ = time (test_full)  v in      *)
75       XPath.Ast.print Format.err_formatter query;
76       Format.fprintf Format.err_formatter "\n%!";
77       Printf.eprintf "Compiling query : ";
78       let auto,ltags,contains = time (XPath.Compile.compile ~querystring:query_string) query in 
79       let _ = Ata.dump Format.err_formatter auto in
80       let _ = Printf.eprintf "%!" in
81       let jump_to = 
82         match contains with
83            None -> (max_int,`NOTHING)
84           | Some s -> 
85               let r = Tree.count v s 
86               in
87               Printf.eprintf "%i documents in the TextCollection\n" (Tree.text_size v);
88               Printf.eprintf "Global count is %i, using " r;
89               if r < !Options.tc_threshold then begin             
90                 Printf.eprintf "TextCollection contains\nCalling global contains : ";
91                 time (Tree.init_contains v) s;
92               end
93               else begin
94                 Printf.eprintf "Naive contains\nCalling global contains : ";
95                 time (Tree.init_naive_contains v) s
96               end;(r,`CONTAINS(s))
97       in
98       let test_list = jump_to in
99       (*
100         let test_list = 
101         if (!Options.backward) then begin
102         Printf.eprintf "Finding min occurences : ";
103         time 
104         ( List.fold_left (fun ((min_occ,kind)as acc)  (tag,_) ->
105                               let numtags = Tree.subtree_tags v tag Tree.root in
106                                 if  ((numtags < min_occ) && numtags >= 2)
107                                 then (numtags,`TAG(tag))
108                                 else acc) jump_to) ltags
109           end
110           else (max_int,`NOTHING)
111         in*)
112         let _ = if (snd test_list) != `NOTHING then
113           let occ,s1,s2 = match test_list with
114             | (x,`TAG (tag)) -> (x, "tag", (Tag.to_string tag))
115             | (x,`CONTAINS(s)) -> (x, "contains()", s)
116             | _ -> assert false
117           in
118             Printf.eprintf "Will jump to %s %s occuring %i time\n%!" s1 s2 occ
119         in
120           Printf.eprintf "Execution time %s : "
121             (if !Options.count_only then "(counting only)" else if !Options.backward then "(bottomup)" else "");
122           begin
123             let _ = Gc.full_major();Gc.compact() in
124             let _ = Printf.eprintf "%!" in
125 (*          let _ = Gc.set (disabled_gc) in *)
126               if !Options.backward && ((snd test_list) != `NOTHING )then 
127                 
128                 let r = time (bottom_up_count auto v )(snd test_list)  in
129                 let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r 
130                 in ()
131               else
132                 let _ = 
133                   if !Options.backward then Printf.eprintf "WARNING: couldn't find a jumping point, running top-down\n" 
134                 in
135                 if !Options.count_only then
136                   let r = time ( top_down_count auto ) v in 
137                   let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r
138                   in ()
139                 else      
140                 let module GR = Ata.Test(struct let doc = v end) in
141                   let result = time (GR.top_down auto) v in
142                   let _ = Printf.eprintf "Counting results " in
143                   let rcount = time (GR.Results.length) result in
144                     Printf.eprintf "Number of nodes in the result set : %i\n" rcount;
145                     Printf.eprintf "\n%!";
146                     begin
147                       match output with
148                         | None -> ()
149                         | Some f ->                   
150                             Printf.eprintf "Serializing results : ";
151                             time( fun () ->
152                                     (*let oc = open_out f in *)
153                                     let oc = Unix.openfile f [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
154                                       (*output_string oc "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";*)
155                                      GR.Results.iter (fun t -> 
156                                                   Tree.print_xml_fast3 v t oc;
157                                                         (*output_char oc '\n'; *)                               
158                                                ) result) ();
159                     end;
160           end;
161           let _ = Gc.set enabled_gc in
162             Printf.eprintf "Total running time : %fms\n%!" (total_time())
163 ;;
164
165 Options.parse_cmdline();;
166
167 let v =
168   if (Filename.check_suffix !Options.input_file ".srx")
169   then 
170     begin
171       Printf.eprintf "Loading from file : ";
172       time (Tree.load  ~sample:!Options.sample_factor )
173         !Options.input_file;
174         end
175   else 
176     let v = 
177       time (fun () -> let v = Tree.parse_xml_uri !Options.input_file;
178             in Printf.eprintf "Parsing document : %!";v
179            ) () 
180     in
181       if !Options.save_file <> ""
182       then begin
183         Printf.eprintf "Writing file to disk : ";
184         time (Tree.save v) !Options.save_file;
185       end;
186       v
187 in
188   main v !Options.query !Options.output_file;;
189