src/Tools/cache_io.ML
changeset 40538 b8482ff0bc92
parent 40425 c9b5e0fcee31
child 40578 2b098a549450
equal deleted inserted replaced
40516:516a367eb38c 40538:b8482ff0bc92
     7 signature CACHE_IO =
     7 signature CACHE_IO =
     8 sig
     8 sig
     9   (*IO wrapper*)
     9   (*IO wrapper*)
    10   val with_tmp_file: string -> (Path.T -> 'a) -> 'a
    10   val with_tmp_file: string -> (Path.T -> 'a) -> 'a
    11   val with_tmp_dir: string -> (Path.T -> 'a) -> 'a
    11   val with_tmp_dir: string -> (Path.T -> 'a) -> 'a
    12   val run: (Path.T -> Path.T -> string) -> string ->
    12   type result = {
    13     {output: string list, redirected_output: string list, return_code: int}
    13     output: string list,
       
    14     redirected_output: string list,
       
    15     return_code: int}
       
    16   val run: (Path.T -> Path.T -> string) -> string -> result
    14 
    17 
    15   (*cache*)
    18   (*cache*)
    16   type cache
    19   type cache
    17   val make: Path.T -> cache
    20   val make: Path.T -> cache
    18   val cache_path_of: cache -> Path.T
    21   val cache_path_of: cache -> Path.T
    19   val lookup: cache -> string -> (string list * string list) option * string
    22   val lookup: cache -> string -> result option * string
    20   val run_and_cache: cache -> string -> (Path.T -> Path.T -> string) ->
    23   val run_and_cache: cache -> string -> (Path.T -> Path.T -> string) ->
    21     string -> string list * string list
    24     string -> result
    22   val run_cached: cache -> (Path.T -> Path.T -> string) -> string ->
    25   val run_cached: cache -> (Path.T -> Path.T -> string) -> string -> result
    23     string list * string list
       
    24 end
    26 end
    25 
    27 
    26 structure Cache_IO : CACHE_IO =
    28 structure Cache_IO : CACHE_IO =
    27 struct
    29 struct
    28 
    30 
    42     val path = File.tmp_path (Path.explode (name ^ serial_string ()))
    44     val path = File.tmp_path (Path.explode (name ^ serial_string ()))
    43     val _ = File.mkdir path
    45     val _ = File.mkdir path
    44     val x = Exn.capture f path
    46     val x = Exn.capture f path
    45     val _ = try File.rm_tree path
    47     val _ = try File.rm_tree path
    46   in Exn.release x end
    48   in Exn.release x end
       
    49 
       
    50 type result = {
       
    51   output: string list,
       
    52   redirected_output: string list,
       
    53   return_code: int}
    47 
    54 
    48 fun run make_cmd str =
    55 fun run make_cmd str =
    49   with_tmp_file cache_io_prefix (fn in_path =>
    56   with_tmp_file cache_io_prefix (fn in_path =>
    50   with_tmp_file cache_io_prefix (fn out_path =>
    57   with_tmp_file cache_io_prefix (fn out_path =>
    51     let
    58     let
    96     fun load line (i, xsp) =
   103     fun load line (i, xsp) =
    97       if i < p then (i+1, xsp)
   104       if i < p then (i+1, xsp)
    98       else if i < p + len1 then (i+1, apfst (cons line) xsp)
   105       else if i < p + len1 then (i+1, apfst (cons line) xsp)
    99       else if i < p + len2 then (i+1, apsnd (cons line) xsp)
   106       else if i < p + len2 then (i+1, apsnd (cons line) xsp)
   100       else (i, xsp)
   107       else (i, xsp)
   101   in pairself rev (snd (File.fold_lines load cache_path (1, ([], [])))) end
   108     val (out, err) =
       
   109       pairself rev (snd (File.fold_lines load cache_path (1, ([], []))))
       
   110   in {output=err, redirected_output=out, return_code=0} end
   102 
   111 
   103 fun lookup (Cache {path=cache_path, table}) str =
   112 fun lookup (Cache {path=cache_path, table}) str =
   104   let val key = SHA1.digest str
   113   let val key = SHA1.digest str
   105   in
   114   in
   106     (case Symtab.lookup (snd (Synchronized.value table)) key of
   115     (case Symtab.lookup (snd (Synchronized.value table)) key of
   108     | SOME pos => (SOME (load_cached_result cache_path pos), key))
   117     | SOME pos => (SOME (load_cached_result cache_path pos), key))
   109   end
   118   end
   110 
   119 
   111 fun run_and_cache (Cache {path=cache_path, table}) key make_cmd str =
   120 fun run_and_cache (Cache {path=cache_path, table}) key make_cmd str =
   112   let
   121   let
   113     val {output=err, redirected_output=out, ...} = run make_cmd str
   122     val {output=err, redirected_output=out, return_code} = run make_cmd str
   114     val res = (out, err)
   123     val (l1, l2) = pairself length (out, err)
   115     val (l1, l2) = pairself length res
       
   116     val header = key ^ " " ^ string_of_int l1 ^ " " ^ string_of_int l2
   124     val header = key ^ " " ^ string_of_int l1 ^ " " ^ string_of_int l2
   117     val lines = map (suffix "\n") (header :: out @ err)
   125     val lines = map (suffix "\n") (header :: out @ err)
   118 
   126 
   119     val _ = Synchronized.change table (fn (p, tab) =>
   127     val _ = Synchronized.change table (fn (p, tab) =>
   120       if Symtab.defined tab key then (p, tab)
   128       if Symtab.defined tab key then (p, tab)
   121       else
   129       else
   122         let val _ = File.append_list cache_path lines
   130         let val _ = File.append_list cache_path lines
   123         in (p+l1+l2+1, Symtab.update (key, (p+1, l1, l2)) tab) end)
   131         in (p+l1+l2+1, Symtab.update (key, (p+1, l1, l2)) tab) end)
   124   in res end
   132   in {output=err, redirected_output=out, return_code=return_code} end
   125 
   133 
   126 fun run_cached cache make_cmd str =
   134 fun run_cached cache make_cmd str =
   127   (case lookup cache str of
   135   (case lookup cache str of
   128     (NONE, key) => run_and_cache cache key make_cmd str
   136     (NONE, key) => run_and_cache cache key make_cmd str
   129   | (SOME output, _) => output)
   137   | (SOME output, _) => output)