1pub mod platform;
61pub mod providers;
62pub mod plugins;
63
64pub use platform::{
65 PlatformInfo,
66 PlatformType,
67 Architecture,
68 DiscoveryStrategy,
69 HardwareCategory,
70 PlatformCompatibility,
71};
72
73pub use providers::{
74 DMSCHardwareProvider,
75 ProviderRegistry,
76 DiscoveryResult,
77 CPUProvider,
78 MemoryProvider,
79 StorageProvider,
80 NetworkProvider,
81 GPUProvider,
82 USBProvider,
83};
84
85pub use plugins::{
86 DMSCHardwareDiscoveryPlugin,
87 PluginRegistry,
88 PluginMetadata,
89 PluginStatus,
90 PluginError,
91 PluginResult,
92 PluginLoader,
93 create_custom_plugin,
94};
95
96use std::sync::Arc;
97use tokio::sync::RwLock;
98use serde::{Serialize, Deserialize};
99
100use super::core::{DMSCDevice, DMSCDeviceType, DMSCDeviceCapabilities};
101use super::DMSCResult;
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
106pub struct DiscoveryConfig {
107 pub enable_cpu_discovery: bool,
109 pub enable_memory_discovery: bool,
111 pub enable_storage_discovery: bool,
113 pub enable_network_discovery: bool,
115 pub enable_gpu_discovery: bool,
117 pub enable_usb_discovery: bool,
119 pub enable_plugins: bool,
121 pub enable_mock_fallback: bool,
123 pub timeout_secs: u64,
125 pub max_retries: u32,
127 pub retry_delay_ms: u64,
129}
130
131impl Default for DiscoveryConfig {
132 fn default() -> Self {
133 Self {
134 enable_cpu_discovery: true,
135 enable_memory_discovery: true,
136 enable_storage_discovery: true,
137 enable_network_discovery: true,
138 enable_gpu_discovery: true,
139 enable_usb_discovery: true,
140 enable_plugins: true,
141 enable_mock_fallback: true,
142 timeout_secs: 30,
143 max_retries: 3,
144 retry_delay_ms: 1000,
145 }
146 }
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize, Default)]
151#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
152pub struct DiscoveryStats {
153 pub total_operations: u64,
155 pub successful_discoveries: u64,
157 pub failed_discoveries: u64,
159 pub total_devices_discovered: u64,
161 pub last_discovery_time_ms: u128,
163 pub avg_discovery_time_ms: f64,
165 pub providers_used: usize,
167 pub plugins_used: usize,
169}
170
171#[derive(Clone)]
173pub struct DMSCDeviceDiscovery {
174 config: Arc<DiscoveryConfig>,
175 platform: Arc<PlatformInfo>,
176 provider_registry: Arc<ProviderRegistry>,
177 plugin_registry: Arc<RwLock<PluginRegistry>>,
178 stats: Arc<RwLock<DiscoveryStats>>,
179 discovered_devices: Arc<RwLock<HashMap<String, DMSCDevice>>>,
180}
181
182impl DMSCDeviceDiscovery {
183 pub async fn new(config: DiscoveryConfig) -> DMSCResult<Self> {
185 let platform = Arc::new(PlatformInfo::new());
186 let provider_registry = Arc::new(ProviderRegistry::new());
187 let plugin_registry = PluginRegistry::new();
188
189 provider_registry.register_defaults().await;
191
192 if config.enable_plugins {
194 }
196
197 let stats = Arc::new(RwLock::new(DiscoveryStats::default()));
198 let discovered_devices = Arc::new(RwLock::new(HashMap::new()));
199
200 Ok(Self {
201 config: Arc::new(config),
202 platform,
203 provider_registry,
204 plugin_registry: Arc::new(RwLock::new(plugin_registry)),
205 stats,
206 discovered_devices,
207 })
208 }
209
210 pub async fn with_defaults() -> DMSCResult<Self> {
212 Self::new(DiscoveryConfig::default()).await
213 }
214
215 pub async fn discover_all(&self) -> DMSCResult<Vec<DMSCDevice>> {
217 let start_time = std::time::Instant::now();
218 let mut all_devices = Vec::new();
219 let mut providers_used = 0;
220 let mut plugins_used = 0;
221
222 if self.config.enable_cpu_discovery {
224 match self.discover_category(HardwareCategory::CPU).await {
225 Ok(devices) => {
226 all_devices.extend(devices);
227 providers_used += 1;
228 }
229 Err(e) => tracing::warn!("CPU discovery failed: {}", e),
230 }
231 }
232
233 if self.config.enable_memory_discovery {
234 match self.discover_category(HardwareCategory::Memory).await {
235 Ok(devices) => {
236 all_devices.extend(devices);
237 providers_used += 1;
238 }
239 Err(e) => tracing::warn!("Memory discovery failed: {}", e),
240 }
241 }
242
243 if self.config.enable_storage_discovery {
244 match self.discover_category(HardwareCategory::Storage).await {
245 Ok(devices) => {
246 all_devices.extend(devices);
247 providers_used += 1;
248 }
249 Err(e) => tracing::warn!("Storage discovery failed: {}", e),
250 }
251 }
252
253 if self.config.enable_network_discovery {
254 match self.discover_category(HardwareCategory::Network).await {
255 Ok(devices) => {
256 all_devices.extend(devices);
257 providers_used += 1;
258 }
259 Err(e) => tracing::warn!("Network discovery failed: {}", e),
260 }
261 }
262
263 if self.config.enable_gpu_discovery {
264 match self.discover_category(HardwareCategory::GPU).await {
265 Ok(devices) => {
266 all_devices.extend(devices);
267 providers_used += 1;
268 }
269 Err(e) => tracing::warn!("GPU discovery failed: {}", e),
270 }
271 }
272
273 if self.config.enable_usb_discovery {
274 match self.discover_category(HardwareCategory::USB).await {
275 Ok(devices) => {
276 all_devices.extend(devices);
277 providers_used += 1;
278 }
279 Err(e) => tracing::warn!("USB discovery failed: {}", e),
280 }
281 }
282
283 if self.config.enable_plugins {
285 let plugin_devices = self.discover_with_plugins().await?;
286 if !plugin_devices.is_empty() {
287 all_devices.extend(plugin_devices);
288 plugins_used += 1;
289 }
290 }
291
292 if self.config.enable_mock_fallback && all_devices.is_empty() {
294 tracing::info!("No devices discovered, using mock fallback");
295 let mock_devices = self.create_mock_devices().await?;
296 all_devices.extend(mock_devices);
297 }
298
299 let elapsed = start_time.elapsed();
301 self.update_stats(all_devices.len(), providers_used, plugins_used, elapsed).await;
302
303 let mut cache = self.discovered_devices.write().await;
305 for device in &all_devices {
306 cache.insert(device.id().to_string(), device.clone());
307 }
308
309 Ok(all_devices)
310 }
311
312 pub async fn discover_category(&self, category: HardwareCategory) -> DMSCResult<Vec<DMSCDevice>> {
314 let start_time = std::time::Instant::now();
315
316 let devices = self.provider_registry.discover_devices(&category, &self.platform).await
317 .map_err(|e| crate::core::DMSCError::Other(format!("Discovery failed: {}", e)))?;
318
319 let elapsed = start_time.elapsed().as_millis();
321 self.stats.write().await.last_discovery_time_ms = elapsed;
322 self.stats.write().await.total_devices_discovered += devices.len() as u64;
323
324 Ok(devices)
325 }
326
327 pub async fn discover_with_plugins(&self) -> DMSCResult<Vec<DMSCDevice>> {
329 let devices = self.plugin_registry.read().await.discover_all(&self.platform).await
330 .map_err(|e| crate::core::DMSCError::Other(format!("Plugin discovery failed: {}", e)))?;
331 Ok(devices)
332 }
333
334 pub async fn discover_cpus(&self) -> DMSCResult<Vec<DMSCDevice>> {
336 self.discover_category(HardwareCategory::CPU).await
337 }
338
339 pub async fn discover_memory(&self) -> DMSCResult<Vec<DMSCDevice>> {
341 self.discover_category(HardwareCategory::Memory).await
342 }
343
344 pub async fn discover_storage(&self) -> DMSCResult<Vec<DMSCDevice>> {
346 self.discover_category(HardwareCategory::Storage).await
347 }
348
349 pub async fn discover_network(&self) -> DMSCResult<Vec<DMSCDevice>> {
351 self.discover_category(HardwareCategory::Network).await
352 }
353
354 pub async fn discover_gpus(&self) -> DMSCResult<Vec<DMSCDevice>> {
356 self.discover_category(HardwareCategory::GPU).await
357 }
358
359 pub async fn discover_usb(&self) -> DMSCResult<Vec<DMSCDevice>> {
361 self.discover_category(HardwareCategory::USB).await
362 }
363
364 pub fn platform_info(&self) -> &PlatformInfo {
366 &self.platform
367 }
368
369 pub async fn stats(&self) -> DiscoveryStats {
371 self.stats.read().await.clone()
372 }
373
374 pub async fn get_discovered_devices(&self) -> Vec<DMSCDevice> {
376 self.discovered_devices.read().await.values().cloned().collect()
377 }
378
379 pub async fn get_device(&self, id: &str) -> Option<DMSCDevice> {
381 self.discovered_devices.read().await.get(id).cloned()
382 }
383
384 pub async fn clear_cache(&self) {
386 self.discovered_devices.write().await.clear();
387 }
388
389 pub async fn register_provider<P: DMSCHardwareProvider + 'static>(&self, provider: P) {
391 self.provider_registry.register(Box::new(provider)).await;
392 }
393
394 pub async fn register_plugin(&mut self, plugin: Box<dyn DMSCHardwareDiscoveryPlugin>) {
396 self.plugin_registry.write().await.register(plugin).await.ok();
397 }
398
399 pub async fn enable_plugin(&self, name: &str) {
401 self.plugin_registry.read().await.enable(name).await.ok();
402 }
403
404 pub async fn disable_plugin(&self, name: &str) {
406 self.plugin_registry.read().await.disable(name).await.ok();
407 }
408
409 pub async fn provider_count(&self) -> usize {
411 self.provider_registry.provider_count().await
412 }
413
414 pub async fn plugin_count(&self) -> usize {
416 self.plugin_registry.read().await.count().await
417 }
418
419 pub fn platform_compatibility(&self) -> PlatformCompatibility {
421 PlatformCompatibility::from_platform(&self.platform)
422 }
423
424 async fn update_stats(&self, device_count: usize, providers_used: usize, plugins_used: usize, elapsed: std::time::Duration) {
426 let mut stats = self.stats.write().await;
427 stats.total_operations += 1;
428 stats.successful_discoveries += 1;
429 stats.total_devices_discovered += device_count as u64;
430 stats.last_discovery_time_ms = elapsed.as_millis();
431
432 let total_time = stats.avg_discovery_time_ms * (stats.successful_discoveries as f64 - 1.0);
434 stats.avg_discovery_time_ms = (total_time + elapsed.as_millis() as f64) / stats.successful_discoveries as f64;
435
436 stats.providers_used = providers_used;
437 stats.plugins_used = plugins_used;
438 }
439
440 async fn create_mock_devices(&self) -> DMSCResult<Vec<DMSCDevice>> {
442 let mut devices = Vec::new();
443
444 if self.config.enable_cpu_discovery {
446 let cpu_capabilities = DMSCDeviceCapabilities::new()
447 .with_compute_units(self.platform.cpu_cores)
448 .with_memory_gb(self.platform.total_memory as f64 / (1024.0 * 1024.0 * 1024.0));
449
450 let cpu = DMSCDevice::new(
451 format!("Mock CPU ({} cores)", self.platform.cpu_cores),
452 DMSCDeviceType::CPU,
453 ).with_capabilities(cpu_capabilities);
454 devices.push(cpu);
455 }
456
457 if self.config.enable_memory_discovery {
459 let mem_capabilities = DMSCDeviceCapabilities::new()
460 .with_compute_units(0)
461 .with_memory_gb(self.platform.total_memory as f64 / (1024.0 * 1024.0 * 1024.0));
462
463 let memory = DMSCDevice::new(
464 format!("Mock Memory ({:.2} GB)", self.platform.total_memory as f64 / (1024.0 * 1024.0 * 1024.0)),
465 DMSCDeviceType::Memory,
466 ).with_capabilities(mem_capabilities);
467 devices.push(memory);
468 }
469
470 if self.config.enable_network_discovery {
472 let net_capabilities = DMSCDeviceCapabilities::new()
473 .with_bandwidth_gbps(1.0);
474
475 let network = DMSCDevice::new(
476 "Mock Loopback Interface".to_string(),
477 DMSCDeviceType::Network,
478 ).with_capabilities(net_capabilities);
479 devices.push(network);
480 }
481
482 Ok(devices)
483 }
484}
485
486pub struct AsyncDiscovery {
488 discovery: Arc<DMSCDeviceDiscovery>,
489 current_progress: Arc<RwLock<f32>>,
490 is_cancelled: Arc<RwLock<bool>>,
491}
492
493impl AsyncDiscovery {
494 pub fn new(discovery: Arc<DMSCDeviceDiscovery>) -> Self {
496 Self {
497 discovery,
498 current_progress: Arc::new(RwLock::new(0.0)),
499 is_cancelled: Arc::new(RwLock::new(false)),
500 }
501 }
502
503 pub async fn discover_all(&self) -> DMSCResult<Vec<DMSCDevice>> {
505 *self.current_progress.write().await = 0.0;
506
507 *self.current_progress.write().await = 0.1; if *self.is_cancelled.read().await {
509 return Err(crate::core::DMSCError::Other("Discovery cancelled".to_string()));
510 }
511
512 let result = self.discovery.discover_all().await;
513
514 *self.current_progress.write().await = 1.0; result
517 }
518
519 pub async fn progress(&self) -> f32 {
521 *self.current_progress.read().await
522 }
523
524 pub async fn cancel(&self) {
526 *self.is_cancelled.write().await = true;
527 }
528}
529
530#[async_trait::async_trait]
532pub trait DeviceDiscoveryExtension {
533 async fn perform_discovery(&mut self) -> DMSCResult<Vec<DMSCDevice>>;
535
536 fn discovery_engine(&self) -> Option<&DMSCDeviceDiscovery>;
538}
539
540use std::collections::HashMap;