<commit_before>(*
 * Copyright (C) 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.
 *)

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

open Xstringext

exception Parse_error of exn

let nvidia_conf_dir = "/usr/share/nvidia/vgx"
let nvidia_vendor_id = 0x10deL

type vgpu_conf = {
	pdev_id : int64;
	vdev_id : int64;
	vsubdev_id : int64;
	framebufferlength : int64;
	num_heads : int64;
	max_instance : int64;
	max_x : int64;
	max_y : int64;
	file_path : string;
}

type vgpu_type = {
	vendor_name : string;
	model_name : string;
	framebuffer_size : int64;
	max_heads : int64;
	max_resolution_x : int64;
	max_resolution_y : int64;
	size : int64;
	internal_config : (string * string) list;
}

let entire_gpu = {
	vendor_name = "";
	model_name = "passthrough";
	framebuffer_size = 0L;
	max_heads = 0L;
	max_resolution_x = 0L;
	max_resolution_y = 0L;
	size = 0L;
	internal_config = [];
}

let create ~__context ~vendor_name ~model_name ~framebuffer_size ~max_heads
		~max_resolution_x ~max_resolution_y ~size ~internal_config =
	let ref = Ref.make () in
	let uuid = Uuid.to_string (Uuid.make_uuid ()) in
	Db.VGPU_type.create ~__context ~ref ~uuid ~vendor_name ~model_name
		~framebuffer_size ~max_heads ~max_resolution_x ~max_resolution_y
		~size ~internal_config;
	debug "VGPU_type ref='%s' created (vendor_name = '%s'; model_name = '%s')"
		(Ref.string_of ref) vendor_name model_name;
	ref

let find_or_create ~__context vgpu_type =
	let open Db_filter_types in
	let existing_types =
		Db.VGPU_type.get_internal_records_where ~__context
			~expr:(And
				(Eq (Field "vendor_name", Literal vgpu_type.vendor_name),
				(Eq (Field "model_name", Literal vgpu_type.model_name))))
	in
	match existing_types with
	| [vgpu_type_ref, rc] ->
		(* Update anything about the VGPU type which might have changed since we
		 * last read the config file. *)
		if vgpu_type.framebuffer_size <> rc.Db_actions.vGPU_type_framebuffer_size then
			Db.VGPU_type.set_framebuffer_size ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.framebuffer_size;
		if vgpu_type.max_heads <> rc.Db_actions.vGPU_type_max_heads then
			Db.VGPU_type.set_max_heads ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_heads;
		if vgpu_type.max_resolution_x <> rc.Db_actions.vGPU_type_max_resolution_x then
			Db.VGPU_type.set_max_resolution_x ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_resolution_x;
		if vgpu_type.max_resolution_y <> rc.Db_actions.vGPU_type_max_resolution_x then
			Db.VGPU_type.set_max_resolution_y ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_resolution_y;
		if vgpu_type.size <> rc.Db_actions.vGPU_type_size then
			Db.VGPU_type.set_size ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.size;
		if vgpu_type.internal_config <> rc.Db_actions.vGPU_type_internal_config then
			Db.VGPU_type.set_internal_config ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.internal_config;
		vgpu_type_ref
	| [] ->
		create ~__context ~vendor_name:vgpu_type.vendor_name
			~model_name:vgpu_type.model_name
			~framebuffer_size:vgpu_type.framebuffer_size
			~max_heads:vgpu_type.max_heads
			~max_resolution_x:vgpu_type.max_resolution_x
			~max_resolution_y:vgpu_type.max_resolution_y
			~size:vgpu_type.size
			~internal_config:vgpu_type.internal_config
	| _ ->
		failwith "Error: Multiple vGPU types exist with the same configuration."

let of_conf_file file_path =
	try
		let conf = Unixext.read_lines file_path in
		let args = List.filter
			(fun s -> not (String.startswith "#" s || s = "")) conf in
		let args = List.map (String.strip String.isspace) args in
		(* Expecting space separated key value entries *)
		let args = List.map
			(fun s ->
				match (String.split ' ' s ~limit:2) with
				| k :: [v] -> (k, v)
				| _ -> ("", "")
			) args in
		Scanf.sscanf (List.assoc "plugin0.pdev_id" args) "\"0x%Lx\"" (fun pdev_id ->
			(* NVIDIA key is "device_id:subdevice_id", N.B. not subvendor id *)
			Scanf.sscanf (List.assoc "plugin0.vdev_id" args) "\"0x%Lx:0x%Lx\"" (fun vdev_id vsubdev_id ->
				Scanf.sscanf (List.assoc "plugin0.max_resolution" args) "%Ldx%Ld" (fun max_x max_y ->
					let framebufferlength = Int64.of_string
						(List.assoc "plugin0.framebufferlength" args) in
					let num_heads = Int64.of_string
						(List.assoc "plugin0.num_heads" args) in
					let max_instance = Int64.of_string
						(List.assoc "plugin0.max_instance" args) in
							{pdev_id; vdev_id; vsubdev_id; framebufferlength;
							 num_heads; max_instance; max_x; max_y; file_path}
				)
			)
		)
	with e ->
		raise (Parse_error e)

let read_config_dir conf_dir =
	let rec read_configs ac = function<commit_msg>CP-8358: Read physical subsystem device from vgpu config files<commit_after>(*
 * Copyright (C) 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.
 *)

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

open Xstringext

exception Parse_error of exn

let nvidia_conf_dir = "/usr/share/nvidia/vgx"
let nvidia_vendor_id = 0x10deL

type vgpu_conf = {
	pdev_id : int64;
	psubdev_id : int64 option;
	vdev_id : int64;
	vsubdev_id : int64;
	framebufferlength : int64;
	num_heads : int64;
	max_instance : int64;
	max_x : int64;
	max_y : int64;
	file_path : string;
}

type vgpu_type = {
	vendor_name : string;
	model_name : string;
	framebuffer_size : int64;
	max_heads : int64;
	max_resolution_x : int64;
	max_resolution_y : int64;
	size : int64;
	internal_config : (string * string) list;
}

let entire_gpu = {
	vendor_name = "";
	model_name = "passthrough";
	framebuffer_size = 0L;
	max_heads = 0L;
	max_resolution_x = 0L;
	max_resolution_y = 0L;
	size = 0L;
	internal_config = [];
}

let create ~__context ~vendor_name ~model_name ~framebuffer_size ~max_heads
		~max_resolution_x ~max_resolution_y ~size ~internal_config =
	let ref = Ref.make () in
	let uuid = Uuid.to_string (Uuid.make_uuid ()) in
	Db.VGPU_type.create ~__context ~ref ~uuid ~vendor_name ~model_name
		~framebuffer_size ~max_heads ~max_resolution_x ~max_resolution_y
		~size ~internal_config;
	debug "VGPU_type ref='%s' created (vendor_name = '%s'; model_name = '%s')"
		(Ref.string_of ref) vendor_name model_name;
	ref

let find_or_create ~__context vgpu_type =
	let open Db_filter_types in
	let existing_types =
		Db.VGPU_type.get_internal_records_where ~__context
			~expr:(And
				(Eq (Field "vendor_name", Literal vgpu_type.vendor_name),
				(Eq (Field "model_name", Literal vgpu_type.model_name))))
	in
	match existing_types with
	| [vgpu_type_ref, rc] ->
		(* Update anything about the VGPU type which might have changed since we
		 * last read the config file. *)
		if vgpu_type.framebuffer_size <> rc.Db_actions.vGPU_type_framebuffer_size then
			Db.VGPU_type.set_framebuffer_size ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.framebuffer_size;
		if vgpu_type.max_heads <> rc.Db_actions.vGPU_type_max_heads then
			Db.VGPU_type.set_max_heads ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_heads;
		if vgpu_type.max_resolution_x <> rc.Db_actions.vGPU_type_max_resolution_x then
			Db.VGPU_type.set_max_resolution_x ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_resolution_x;
		if vgpu_type.max_resolution_y <> rc.Db_actions.vGPU_type_max_resolution_x then
			Db.VGPU_type.set_max_resolution_y ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.max_resolution_y;
		if vgpu_type.size <> rc.Db_actions.vGPU_type_size then
			Db.VGPU_type.set_size ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.size;
		if vgpu_type.internal_config <> rc.Db_actions.vGPU_type_internal_config then
			Db.VGPU_type.set_internal_config ~__context
				~self:vgpu_type_ref
				~value:vgpu_type.internal_config;
		vgpu_type_ref
	| [] ->
		create ~__context ~vendor_name:vgpu_type.vendor_name
			~model_name:vgpu_type.model_name
			~framebuffer_size:vgpu_type.framebuffer_size
			~max_heads:vgpu_type.max_heads
			~max_resolution_x:vgpu_type.max_resolution_x
			~max_resolution_y:vgpu_type.max_resolution_y
			~size:vgpu_type.size
			~internal_config:vgpu_type.internal_config
	| _ ->
		failwith "Error: Multiple vGPU types exist with the same configuration."

let of_conf_file file_path =
	try
		let conf = Unixext.read_lines file_path in
		let args = List.filter
			(fun s -> not (String.startswith "#" s || s = "")) conf in
		let args = List.map (String.strip String.isspace) args in
		(* Expecting space separated key value entries *)
		let args = List.map
			(fun s ->
				match (String.split ' ' s ~limit:2) with
				| k :: [v] -> (k, v)
				| _ -> ("", "")
			) args in
		(* plugin0.pdev_id will either be just the physical device id, or of the
		 * form "device_id:subdevice_id" *)
		let pdev_id, psubdev_id =
			let pdev_id_data = (List.assoc "plugin0.pdev_id" args) in
			try
				Scanf.sscanf pdev_id_data "\"0x%Lx:0x%Lx\""
					(fun pdev_id psubdev_id -> pdev_id, Some psubdev_id)
			with Scanf.Scan_failure _ ->
				Scanf.sscanf pdev_id_data "\"0x%Lx\""
					(fun pdev_id -> pdev_id, None)
		in
		(* NVIDIA key is "device_id:subdevice_id", N.B. not subvendor id *)
		Scanf.sscanf (List.assoc "plugin0.vdev_id" args) "\"0x%Lx:0x%Lx\"" (fun vdev_id vsubdev_id ->
			Scanf.sscanf (List.assoc "plugin0.max_resolution" args) "%Ldx%Ld" (fun max_x max_y ->
				let framebufferlength = Int64.of_string
					(List.assoc "plugin0.framebufferlength" args) in
				let num_heads = Int64.of_string
					(List.assoc "plugin0.num_heads" args) in
				let max_instance = Int64.of_string
					(List.assoc "plugin0.max_instance" args) in
				{pdev_id; psubdev_id; vdev_id; vsubdev_id; framebufferlength;
						 num_heads; max_instance; max_x; max_y; file_path}
				)
			)
	with e ->
		raise (Parse_error e)

let read_config_dir conf_dir =
	let rec read_configs ac = function
{'fraction_non_alphanumeric': 0.09608740311887198, 'fraction_numerical': 0.01055187225698011, 'mean_word_length': 4.283670448939319, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 39, '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': '4864950', 'n_tokens_mistral': 4405, 'n_tokens_neox': 3943, 'n_words': 941}