@@ -79,6 +79,30 @@ let format config name filenames =
7979 return () in
8080 Lwt_main. run t
8181
82+ let dump config filenames =
83+ let t =
84+ let module Vg_IO = Vg. Make (Log )(Block )(Time )(Clock ) in
85+ let open Xenvm_interface in
86+ Lwt_list. map_s
87+ (fun filename ->
88+ Block. connect filename
89+ >> = function
90+ | `Error _ -> fail (Failure (Printf. sprintf " Failed to open %s" filename))
91+ | `Ok x -> return x
92+ ) filenames
93+ >> = fun blocks ->
94+ Vg_IO. connect blocks `RO
95+ >> |= fun vg ->
96+ let md = Vg_IO. metadata_of vg in
97+ let buf = Cstruct. create (64 * 1024 * 1024 ) in
98+ let next = Vg. marshal md buf in
99+ let buf = Cstruct. (sub buf 0 ((len buf) - (len next))) in
100+ let txt = Cstruct. to_string buf in
101+ output_string Pervasives. stdout txt;
102+ output_string Pervasives. stdout " \n " ;
103+ return () in
104+ Lwt_main. run t
105+
82106let host_create copts (vg_name ,_ ) host =
83107 let t =
84108 get_vg_info_t copts vg_name >> = fun info ->
@@ -140,37 +164,79 @@ let shutdown copts (vg_name,_) =
140164 lwt_while (fun () -> is_alive pid) (fun () -> Lwt_unix. sleep 1.0 )
141165 in Lwt_main. run t
142166
143- let benchmark copts (vg_name ,_ ) =
167+ let benchmark copts (vg_name ,_ ) volumes threads =
144168 let t =
145169 let creation_host = Unix. gethostname () in
146170 get_vg_info_t copts vg_name >> = fun info ->
147171 set_uri copts info;
148172 let mib = Int64. mul 1048576L 4L in
149- let number = 1000 in
150- let start = Unix. gettimeofday () in
151- let rec fori test_name acc f = function
152- | 0 -> return acc
153- | n ->
154- f n
155- >> = fun () ->
156- ( if ((n * 100 ) / number) <> (((n + 1 ) * 100 ) / number)
157- then stderr " %s %d %% complete\n %!" test_name (100 - (n * 100 ) / number)
158- else return () ) >> = fun () ->
159- fori test_name ((number - n, Unix. gettimeofday () -. start) :: acc) f (n - 1 ) in
160- fori " Creating volumes" [] (fun i -> Client. create ~name: (Printf. sprintf " test-lv-%d" i) ~size: mib ~creation_host ~creation_time: (Unix. gettimeofday () |> Int64. of_float) ~tags: [] ) number
161- >> = fun creates ->
162- let time = Unix. gettimeofday () -. start in
173+
174+ let start = ref (Unix. gettimeofday () ) in
175+ let n_pending = ref volumes in
176+ let m = Lwt_mutex. create () in
177+ let n_complete = ref 0 in
178+ let times = ref [] in
179+ let on_complete () =
180+ incr n_complete;
181+ let n = ! n_complete in
182+ times := (n, Unix. gettimeofday () -. ! start) :: ! times;
183+ if ((n * 100 ) / volumes) <> (((n + 1 ) * 100 ) / volumes)
184+ then stderr " %d %% complete" ((n * 100 ) / volumes)
185+ else return () in
186+ let rec worker f =
187+ Lwt_mutex. with_lock m
188+ (fun () ->
189+ if ! n_pending > 0 then begin
190+ decr n_pending;
191+ return (Some (volumes - ! n_pending))
192+ end else return None )
193+ >> = function
194+ | Some n ->
195+ f n
196+ >> = fun () ->
197+ on_complete ()
198+ >> = fun () ->
199+ worker f
200+ | None ->
201+ return () in
202+
203+ let create n =
204+ Client. create ~name: (Printf. sprintf " test-lv-%d" n) ~size: mib ~creation_host ~creation_time: (Unix. gettimeofday () |> Int64. of_float) ~tags: [] in
205+ let destroy n =
206+ Client. remove ~name: (Printf. sprintf " test-lv-%d" n) in
207+
208+ let rec mkints = function
209+ | 0 -> []
210+ | n -> n :: (mkints (n - 1 )) in
211+ let creators = List. map (fun _ -> worker create) (mkints threads) in
212+ Lwt. join creators
213+ >> = fun () ->
214+
163215 let oc = open_out " benchmark.dat" in
164- List. iter (fun (n , t ) -> Printf. fprintf oc " %d %f\n " n t) (List. rev creates);
165- Printf. fprintf oc " # %d creates in %.1f s\n " number time;
166- Printf. fprintf oc " # Average %.1f /sec\n " (float_of_int number /. time);
167- let start = Unix. gettimeofday () in
168- fori " Removing volumes" [] (fun i -> Client. remove ~name: (Printf. sprintf " test-lv-%d" i)) number
169- >> = fun destroys ->
170- let time = Unix. gettimeofday () -. start in
171- List. iter (fun (n , t ) -> Printf. fprintf oc " %d %f\n " (number + n) t) (List. rev destroys);
172- Printf. fprintf oc " # %d destroys in %.1f s\n " number time;
173- Printf. fprintf oc " # Average %.1f /sec\n " (float_of_int number /. time);
216+ let time = Unix. gettimeofday () -. ! start in
217+ List. iter (fun (n , t ) -> Printf. fprintf oc " %d %f\n " n t) (List. rev ! times);
218+ Printf. fprintf oc " # %d creates in %.1f s\n " volumes time;
219+ Printf. fprintf oc " # Average %.1f /sec\n " (float_of_int volumes /. time);
220+
221+ start := Unix. gettimeofday () ;
222+ n_pending := volumes;
223+ n_complete := 0 ;
224+ times := [] ;
225+
226+ let destroyers = List. map (fun _ -> worker destroy) (mkints threads) in
227+ Lwt. join destroyers
228+ >> = fun () ->
229+ let time = Unix. gettimeofday () -. ! start in
230+ List. iter (fun (n , t ) -> Printf. fprintf oc " %d %f\n " (volumes + n) t) (List. rev ! times);
231+ Printf. fprintf oc " # %d destroys in %.1f s\n " volumes time;
232+ Printf. fprintf oc " # Average %.1f /sec\n " (float_of_int volumes /. time);
233+ close_out oc;
234+ let oc = open_out " benchmark.gp" in
235+ Printf. fprintf oc " set xlabel \" LV number\"\n " ;
236+ Printf. fprintf oc " set ylabel \" Time/seconds\"\n " ;
237+ Printf. fprintf oc " set title \" Creating and then destroying %d LVs\"\n " volumes;
238+ Printf. fprintf oc " plot \" benchmark.dat\" with points\n " ;
239+ close_out oc;
174240 return () in
175241 Lwt_main. run t
176242
@@ -213,6 +279,15 @@ let size =
213279 let doc = " Size of the LV in megs" in
214280 Arg. (value & opt int64 4L & info [" size" ] ~docv: " SIZE" ~doc )
215281
282+ let dump_cmd =
283+ let doc = " Dump the metadata in LVM format to stdout" in
284+ let man = [
285+ `S " DESCRIPTION" ;
286+ `P " Prints the volume group metadata to stdout in LVM format. Note this will not include any updates which are still pending in the redo-log."
287+ ] in
288+ Term. (pure dump $ copts_t $ filenames),
289+ Term. info " dump" ~sdocs: copts_sect ~doc ~man
290+
216291let format_cmd =
217292 let doc = " Format the specified file as a VG" in
218293 let man = [
@@ -285,7 +360,13 @@ let benchmark_cmd =
285360 `S " DESCRIPTION" ;
286361 `P " Perform some microbenchmarks and print the results." ;
287362 ] in
288- Term. (pure benchmark $ copts_t $ name_arg),
363+ let volumes_arg =
364+ let doc = " The number of logical volumes which should be created then destroyed." in
365+ Arg. (value & opt int 10000 & info [ " volumes" ; " v" ] ~docv: " VOLUMES" ~doc ) in
366+ let threads_arg =
367+ let doc = " The number of concurrent worker threads which should create then destroy the volumes." in
368+ Arg. (value & opt int 1 & info [ " threads" ; " t" ] ~docv: " THREADS" ~doc ) in
369+ Term. (pure benchmark $ copts_t $ name_arg $ volumes_arg $ threads_arg),
289370 Term. info " benchmark" ~sdocs: copts_sect ~doc ~man
290371
291372let default_cmd =
@@ -295,6 +376,7 @@ let cmds = [
295376 Lvresize. lvresize_cmd;
296377 Lvresize. lvextend_cmd;
297378 format_cmd;
379+ dump_cmd;
298380 shutdown_cmd; host_create_cmd; host_destroy_cmd;
299381 host_list_cmd;
300382 host_connect_cmd; host_disconnect_cmd; benchmark_cmd;
0 commit comments