<commit_before>(*
 * Copyright (C) 2006-2009 Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program 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 Lesser General Public License for more details.
 *)
(* Allows xapi to drive the sparse_dd program *)

open Pervasiveext
open Client
open Printf
open Threadext

module D=Debug.Debugger(struct let name="xapi" end)
open D

let sparse_dd_path = Filename.concat Fhs.libexecdir "sparse_dd"

type progress =
		| Started of Forkhelpers.pidty
		| Continuing of float
		| Finished of exn option

exception Cancelled

(** Use the new external sparse_dd program *)
let dd_internal progress_cb base prezeroed infile outfile size =
	let pipe_read, pipe_write = Unix.pipe () in
	let to_close = ref [ pipe_read; pipe_write ] in
	let close x = if List.mem x !to_close then (Unix.close x; to_close := List.filter (fun y -> y <> x) !to_close) in
	finally
	(fun () ->
		try match Forkhelpers.with_logfile_fd "sparse_dd"
			(fun log_fd ->
				let args = [
					"-machine";
					"-src"; infile;
					"-dest"; outfile;
					"-size"; Int64.to_string size
				] @ (if prezeroed then [ "-prezeroed" ] else []
				) @ (Opt.default [] (Opt.map (fun x -> [ "-base"; x ]) base)) in
				debug "%s %s" sparse_dd_path (String.concat " " args);
				let pid = Forkhelpers.safe_close_and_exec None (Some pipe_write) (Some log_fd) []
					sparse_dd_path args in
				close pipe_write;
				progress_cb (Started pid);
				(* Read Progress: output from the binary *)
				let open Sparse_encoding in
				Chunk.fold
					(fun () chunk ->
						debug "sparse_dd: %s" chunk.Chunk.data;
						try 
							Scanf.sscanf chunk.Chunk.data "Progress: %d"
								(fun progress ->
									progress_cb (Continuing (float_of_int progress /. 100.))
								)
						with _ -> ()
					) () pipe_read;
				match Forkhelpers.waitpid pid with
				| (_, Unix.WEXITED 0) -> progress_cb (Finished None)
				| (_, Unix.WEXITED 5) -> error "sparse_dd received NBD error"; failwith "sparse_dd NBD error"
				| (_, Unix.WEXITED n) -> error "sparse_dd exit: %d" n; failwith "sparse_dd"
				| _ -> error "sparse_dd exit with WSTOPPED or WSIGNALED"; failwith "sparse_dd"
			) with
		| Forkhelpers.Success _ -> progress_cb (Finished None)
		| Forkhelpers.Failure (log, exn) ->
			error "Failure from sparse_dd: %s raising %s" log (Printexc.to_string exn);
		        raise (Api_errors.Server_error (("VDI_COPY_FAILED", [Printexc.to_string exn])));		
		with e -> 
			progress_cb (Finished (Some e));
			raise e
	)<commit_msg>Remove Whitespace<commit_after>(*
 * Copyright (C) 2006-2009 Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program 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 Lesser General Public License for more details.
 *)
(* Allows xapi to drive the sparse_dd program *)

open Pervasiveext
open Client
open Printf
open Threadext

module D=Debug.Debugger(struct let name="xapi" end)
open D

let sparse_dd_path = Filename.concat Fhs.libexecdir "sparse_dd"

type progress =
		| Started of Forkhelpers.pidty
		| Continuing of float
		| Finished of exn option

exception Cancelled

(** Use the new external sparse_dd program *)
let dd_internal progress_cb base prezeroed infile outfile size =
	let pipe_read, pipe_write = Unix.pipe () in
	let to_close = ref [ pipe_read; pipe_write ] in
	let close x = if List.mem x !to_close then (Unix.close x; to_close := List.filter (fun y -> y <> x) !to_close) in
	finally
	(fun () ->
		try match Forkhelpers.with_logfile_fd "sparse_dd"
			(fun log_fd ->
				let args = [
					"-machine";
					"-src"; infile;
					"-dest"; outfile;
					"-size"; Int64.to_string size
				] @ (if prezeroed then [ "-prezeroed" ] else []
				) @ (Opt.default [] (Opt.map (fun x -> [ "-base"; x ]) base)) in
				debug "%s %s" sparse_dd_path (String.concat " " args);
				let pid = Forkhelpers.safe_close_and_exec None (Some pipe_write) (Some log_fd) []
					sparse_dd_path args in
				close pipe_write;
				progress_cb (Started pid);
				(* Read Progress: output from the binary *)
				let open Sparse_encoding in
				Chunk.fold
					(fun () chunk ->
						debug "sparse_dd: %s" chunk.Chunk.data;
						try 
							Scanf.sscanf chunk.Chunk.data "Progress: %d"
								(fun progress ->
									progress_cb (Continuing (float_of_int progress /. 100.))
								)
						with _ -> ()
					) () pipe_read;
				match Forkhelpers.waitpid pid with
				| (_, Unix.WEXITED 0) -> progress_cb (Finished None)
				| (_, Unix.WEXITED 5) -> error "sparse_dd received NBD error"; failwith "sparse_dd NBD error"
				| (_, Unix.WEXITED n) -> error "sparse_dd exit: %d" n; failwith "sparse_dd"
				| _ -> error "sparse_dd exit with WSTOPPED or WSIGNALED"; failwith "sparse_dd"
			) with
		| Forkhelpers.Success _ -> progress_cb (Finished None)
		| Forkhelpers.Failure (log, exn) ->
			error "Failure from sparse_dd: %s raising %s" log (Printexc.to_string exn);
			raise (Api_errors.Server_error (("VDI_COPY_FAILED", [Printexc.to_string exn])));		
		with e -> 
			progress_cb (Finished (Some e));
			raise e
	)
{'fraction_non_alphanumeric': 0.10422778257118205, 'fraction_numerical': 0.005867126833477136, 'mean_word_length': 3.277490774907749, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4489126', 'n_tokens_mistral': 2222, 'n_tokens_neox': 1896, 'n_words': 651}