]> matita.cs.unibo.it Git - helm.git/blobdiff - components/library/libraryClean.ml
branch for universe
[helm.git] / components / library / libraryClean.ml
diff --git a/components/library/libraryClean.ml b/components/library/libraryClean.ml
new file mode 100644 (file)
index 0000000..9a3b172
--- /dev/null
@@ -0,0 +1,272 @@
+(* Copyright (C) 2005, HELM Team.
+ * 
+ * This file is part of HELM, an Hypertextual, Electronic
+ * Library of Mathematics, developed at the Computer Science
+ * Department, University of Bologna, Italy.
+ * 
+ * HELM is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * HELM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HELM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * For details, see the HELM World-Wide-Web page,
+ * http://helm.cs.unibo.it/
+ *)
+
+(* $Id$ *)
+
+open Printf
+
+let debug = false
+let debug_prerr = if debug then prerr_endline else ignore
+
+module HGT = Http_getter_types;;
+module HG = Http_getter;;
+module UM = UriManager;;
+
+
+let strip_xpointer s = Pcre.replace ~pat:"#.*$" s ;;
+
+let safe_buri_of_suri suri =
+  try
+    UM.buri_of_uri (UM.uri_of_string suri)
+  with
+    UM.IllFormedUri _ -> suri
+
+let one_step_depend cache_of_processed_baseuri suri dbtype dbd =
+  let buri = safe_buri_of_suri suri in
+  if Hashtbl.mem cache_of_processed_baseuri buri then 
+    []
+  else
+    begin
+      Hashtbl.add cache_of_processed_baseuri buri true;
+      let query = 
+        let buri = buri ^ "/" in 
+        let buri = HSql.escape dbtype dbd buri in
+        let obj_tbl = MetadataTypes.obj_tbl () in
+        if HSql.isMysql dbtype dbd then        
+          sprintf ("SELECT source, h_occurrence FROM %s WHERE " 
+            ^^ "h_occurrence REGEXP '"^^
+            "^%s\\([^/]+\\|[^/]+#xpointer.*\\)$"^^"'")
+          obj_tbl buri
+       else
+         begin
+            sprintf ("SELECT source, h_occurrence FROM %s WHERE " 
+            ^^ "REGEXP(h_occurrence, '"^^
+            "^%s\\([^/]+\\|[^/]+#xpointer.*\\)$"^^"')")
+            obj_tbl buri
+            (* implementation with vanilla ocaml-sqlite3
+            HLog.debug "Warning SELECT without REGEXP";
+           sprintf
+              ("SELECT source, h_occurrence FROM %s WHERE " ^^ 
+               "h_occurrence LIKE '%s%%' " ^^ HSql.escape_string_for_like)
+                 obj_tbl buri*)
+         end
+      in
+      try 
+        let rc = HSql.exec dbtype dbd query in
+        let l = ref [] in
+        HSql.iter rc (
+          fun row -> 
+            match row.(0), row.(1) with 
+            | Some uri, Some occ when 
+                Filename.dirname (strip_xpointer occ) = buri -> 
+                  l := uri :: !l
+            | _ -> ());
+        let l = List.sort Pervasives.compare !l in
+        HExtlib.list_uniq l
+      with
+        exn -> raise exn (* no errors should be accepted *)
+    end
+    
+let db_uris_of_baseuri buri =
+ let dbd = LibraryDb.instance () in
+ let dbtype = 
+   if Helm_registry.get_bool "matita.system" then HSql.Library else HSql.User
+ in
+ let query = 
+  let buri = buri ^ "/" in 
+  let buri = HSql.escape dbtype dbd buri in
+  let obj_tbl = MetadataTypes.name_tbl () in
+  if HSql.isMysql dbtype dbd then        
+    sprintf ("SELECT source FROM %s WHERE " 
+    ^^ "source REGEXP '^%s[^/]*(#xpointer.*)?$'") obj_tbl buri
+  else
+   begin
+    sprintf ("SELECT source FROM %s WHERE " 
+      ^^ "REGEXP(source, '^%s[^/]*\\(#xpointer.*\\)?$')") obj_tbl buri
+   end
+ in
+ try 
+  let rc = HSql.exec dbtype dbd query in
+  let l = ref [] in
+  HSql.iter rc (
+    fun row -> 
+      match row.(0) with 
+      | Some uri when Filename.dirname (strip_xpointer uri) = buri -> 
+          l := uri :: !l
+      | _ -> ());
+  let l = List.sort Pervasives.compare !l in
+  HExtlib.list_uniq l
+ with
+  exn -> raise exn (* no errors should be accepted *)
+;;
+
+let close_uri_list cache_of_processed_baseuri uri_to_remove =
+  let dbd = LibraryDb.instance () in
+  let dbtype = 
+    if Helm_registry.get_bool "matita.system" then HSql.Library else HSql.User
+  in
+  (* to remove an uri you have to remove the whole script *)
+  let buri_to_remove = 
+    HExtlib.list_uniq 
+      (List.fast_sort Pervasives.compare 
+        (List.map safe_buri_of_suri uri_to_remove))
+  in
+  (* cleand the already visided baseuris *)
+  let buri_to_remove = 
+    List.filter 
+      (fun buri -> 
+        if Hashtbl.mem cache_of_processed_baseuri buri then false
+        else true)
+      buri_to_remove
+  in
+  (* now calculate the list of objects that belong to these baseuris *)
+  let uri_to_remove = 
+    try
+      List.fold_left 
+        (fun acc buri ->
+          let inhabitants = HG.ls ~local:true (buri ^ "/") in
+          let inhabitants = List.filter 
+              (function HGT.Ls_object _ -> true | _ -> false) 
+            inhabitants
+          in
+          let inhabitants = List.map 
+              (function 
+               | HGT.Ls_object e -> buri ^ "/" ^ e.HGT.uri 
+               | _ -> assert false)
+            inhabitants
+          in
+          inhabitants @ acc)
+      [] buri_to_remove 
+    with HGT.Invalid_URI u -> 
+      HLog.error ("We were listing an invalid buri: " ^ u);
+      exit 1
+  in
+  let uri_to_remove_from_db =
+   List.fold_left 
+     (fun acc buri -> 
+       let dbu = db_uris_of_baseuri buri in
+       dbu @ acc
+     ) [] buri_to_remove 
+  in
+  let uri_to_remove = uri_to_remove @ uri_to_remove_from_db in
+  let uri_to_remove =
+   HExtlib.list_uniq (List.sort Pervasives.compare uri_to_remove) in
+  (* now we want the list of all uri that depend on them *) 
+  let depend = 
+    List.fold_left
+    (fun acc u -> one_step_depend cache_of_processed_baseuri u dbtype dbd @ acc)
+    [] uri_to_remove
+  in
+  let depend = 
+    HExtlib.list_uniq (List.fast_sort Pervasives.compare depend) 
+  in
+  uri_to_remove, depend
+;;
+
+let rec close_db cache_of_processed_baseuri uris next =
+  match next with
+  | [] -> uris
+  | l -> 
+     let uris, next = close_uri_list cache_of_processed_baseuri l in
+     close_db cache_of_processed_baseuri uris next @ uris
+;;
+  
+let cleaned_no = ref 0;;
+
+  (** TODO repellent code ... *)
+let moo_root_dir = lazy (
+  let url =
+    List.assoc "cic:/matita/"
+      (List.map
+        (fun pair ->
+          match
+            Str.split (Str.regexp "[ \t\r\n]+") (HExtlib.trim_blanks pair)
+          with
+          | a::b::_ -> a, b
+          | _ -> assert false)
+        (Helm_registry.get_list Helm_registry.string "getter.prefix"))
+  in
+  String.sub url 7 (String.length url - 7))
+;;
+
+let clean_baseuris ?(verbose=true) buris =
+  let cache_of_processed_baseuri = Hashtbl.create 1024 in
+  let dbd = LibraryDb.instance () in
+  let dbtype = 
+    if Helm_registry.get_bool "matita.system" then HSql.Library else HSql.User
+  in
+  Hashtbl.clear cache_of_processed_baseuri;
+  let buris = List.map Http_getter_misc.strip_trailing_slash buris in
+  debug_prerr "clean_baseuris called on:";
+  if debug then
+    List.iter debug_prerr buris; 
+  let l = close_db cache_of_processed_baseuri [] buris in
+  let l = HExtlib.list_uniq (List.fast_sort Pervasives.compare l) in
+  let l = List.map UriManager.uri_of_string l in
+  debug_prerr "clean_baseuri will remove:";
+  if debug then
+    List.iter (fun u -> debug_prerr (UriManager.string_of_uri u)) l; 
+  List.iter
+   (fun baseuri ->
+     try 
+      let obj_file =
+       LibraryMisc.obj_file_of_baseuri ~must_exist:false ~writable:true ~baseuri
+      in
+       HExtlib.safe_remove obj_file ;
+       HExtlib.safe_remove 
+         (LibraryMisc.lexicon_file_of_baseuri 
+           ~must_exist:false ~writable:true ~baseuri) ;
+       HExtlib.rmdir_descend (Filename.chop_extension obj_file)
+     with Http_getter_types.Key_not_found _ -> ())
+   (HExtlib.list_uniq (List.fast_sort Pervasives.compare
+     (List.map (UriManager.buri_of_uri) l @ buris)));
+  List.iter
+   (let last_baseuri = ref "" in
+    fun uri ->
+     let buri = UriManager.buri_of_uri uri in
+     if buri <> !last_baseuri then
+      begin
+        if not (Helm_registry.get_bool "matita.verbose") then
+            (print_endline ("matitaclean " ^ buri ^ "/");flush stdout)
+          else 
+            HLog.message ("Removing: " ^ buri ^ "/*");
+       last_baseuri := buri
+      end;
+     LibrarySync.remove_obj uri
+   ) l;
+  if HSql.isMysql dbtype dbd then
+   begin
+   cleaned_no := !cleaned_no + List.length l;
+   if !cleaned_no > 30 && HSql.isMysql dbtype dbd then
+    begin
+     cleaned_no := 0;
+     List.iter
+      (function table ->
+        ignore (HSql.exec dbtype dbd ("OPTIMIZE TABLE " ^ table)))
+      [MetadataTypes.name_tbl (); MetadataTypes.rel_tbl ();
+       MetadataTypes.sort_tbl (); MetadataTypes.obj_tbl();
+       MetadataTypes.count_tbl()]
+    end
+   end