Skip to content

Commit 0ee50df

Browse files
Steve Lee (POWERSHELL HE/HIM) (from Dev Box)SteveL-MSFT
authored andcommitted
Add static memory cache for discovered resources
1 parent b1306bd commit 0ee50df

File tree

3 files changed

+109
-35
lines changed

3 files changed

+109
-35
lines changed

dsc_lib/src/discovery/command_discovery.rs

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
use crate::discovery::discovery_trait::{DiscoveryFilter, DiscoveryKind, ResourceDiscovery};
4+
use crate::discovery::{
5+
command_discovery_cache::{
6+
get_adapted_resource, get_adapted_resources, get_adapters, get_extensions, get_resource, get_resources, resources_is_empty,
7+
adapters_is_empty, extensions_is_empty, extend_adapted_resources, extend_adapters, extend_extensions, extend_resources
8+
},
9+
discovery_trait::{DiscoveryFilter, DiscoveryKind, ResourceDiscovery}
10+
};
511
use crate::dscresources::dscresource::{Capability, DscResource, ImplementedAs};
612
use crate::dscresources::resource_manifest::{import_manifest, validate_semver, Kind, ResourceManifest, SchemaKind};
713
use crate::dscresources::command_resource::invoke_command;
@@ -36,13 +42,9 @@ pub enum ImportedManifest {
3642
Extension(DscExtension),
3743
}
3844

45+
3946
#[derive(Clone)]
4047
pub struct CommandDiscovery {
41-
// use BTreeMap so that the results are sorted by the typename, the Vec is sorted by version
42-
adapters: BTreeMap<String, Vec<DscResource>>,
43-
resources: BTreeMap<String, Vec<DscResource>>,
44-
extensions: BTreeMap<String, DscExtension>,
45-
adapted_resources: BTreeMap<String, Vec<DscResource>>,
4648
progress_format: ProgressFormat,
4749
}
4850

@@ -72,17 +74,13 @@ impl CommandDiscovery {
7274
#[must_use]
7375
pub fn new(progress_format: ProgressFormat) -> CommandDiscovery {
7476
CommandDiscovery {
75-
adapters: BTreeMap::new(),
76-
resources: BTreeMap::new(),
77-
extensions: BTreeMap::new(),
78-
adapted_resources: BTreeMap::new(),
7977
progress_format,
8078
}
8179
}
8280

8381
#[must_use]
84-
pub fn get_extensions(&self) -> &BTreeMap<String, DscExtension> {
85-
&self.extensions
82+
pub fn get_extensions(&self) -> BTreeMap<String, DscExtension> {
83+
get_extensions()
8684
}
8785

8886
fn get_resource_path_setting() -> Result<ResourcePathSetting, DscError>
@@ -307,7 +305,7 @@ impl ResourceDiscovery for CommandDiscovery {
307305
match kind {
308306
DiscoveryKind::Resource => {
309307
// Now we need to call discover extensions and add those resource to the list of resources
310-
for extension in self.extensions.values() {
308+
for extension in get_extensions().values() {
311309
if extension.capabilities.contains(&ExtensionCapability::Discover) {
312310
debug!("{}", t!("discovery.commandDiscovery.callingExtension", extension = extension.type_name));
313311
let discovered_resources = extension.discover()?;
@@ -320,26 +318,27 @@ impl ResourceDiscovery for CommandDiscovery {
320318
}
321319
}
322320
}
323-
self.adapters = adapters;
324-
self.resources = resources;
321+
extend_adapters(adapters);
322+
extend_resources(resources);
325323
},
326324
DiscoveryKind::Extension => {
327-
self.extensions = extensions;
325+
extend_extensions(extensions);
328326
}
329327
}
330328

331329
Ok(())
332330
}
333331

334332
fn discover_adapted_resources(&mut self, name_filter: &str, adapter_filter: &str) -> Result<(), DscError> {
335-
if self.resources.is_empty() && self.adapters.is_empty() {
333+
if resources_is_empty() && adapters_is_empty() {
336334
self.discover(&DiscoveryKind::Resource, "*")?;
337335
}
338336

339-
if self.adapters.is_empty() {
337+
if adapters_is_empty() {
340338
return Ok(());
341339
}
342340

341+
let adapters = get_adapters();
343342
let regex_str = convert_wildcard_to_regex(adapter_filter);
344343
debug!("Using regex {regex_str} as filter for adapter name");
345344
let mut regex_builder = RegexBuilder::new(&regex_str);
@@ -356,13 +355,13 @@ impl ResourceDiscovery for CommandDiscovery {
356355
return Err(DscError::Operation("Could not build Regex filter for resource name".to_string()));
357356
};
358357

359-
let mut progress = ProgressBar::new(self.adapters.len() as u64, self.progress_format)?;
358+
let mut progress = ProgressBar::new(adapters.len() as u64, self.progress_format)?;
360359
progress.write_activity("Searching for adapted resources");
361360

362361
let mut adapted_resources = BTreeMap::<String, Vec<DscResource>>::new();
363362

364363
let mut found_adapter: bool = false;
365-
for (adapter_name, adapters) in &self.adapters {
364+
for (adapter_name, adapters) in &adapters {
366365
for adapter in adapters {
367366
progress.write_increment(1);
368367

@@ -431,7 +430,7 @@ impl ResourceDiscovery for CommandDiscovery {
431430
return Err(DscError::AdapterNotFound(adapter_filter.to_string()));
432431
}
433432

434-
self.adapted_resources = adapted_resources;
433+
extend_adapted_resources(adapted_resources);
435434

436435
Ok(())
437436
}
@@ -441,26 +440,27 @@ impl ResourceDiscovery for CommandDiscovery {
441440
if *kind == DiscoveryKind::Resource {
442441
if adapter_name_filter.is_empty() {
443442
self.discover(kind, type_name_filter)?;
444-
for (resource_name, resources_vec) in &self.resources {
443+
for (resource_name, resources_vec) in &get_resources() {
445444
resources.insert(resource_name.clone(), resources_vec.iter().map(|r| ImportedManifest::Resource(r.clone())).collect());
446445
}
447-
for (adapter_name, adapter_vec) in &self.adapters {
446+
for (adapter_name, adapter_vec) in &get_adapters() {
448447
resources.insert(adapter_name.clone(), adapter_vec.iter().map(|r| ImportedManifest::Resource(r.clone())).collect());
449448
}
450449
} else {
451450
self.discover(kind, "*")?;
452451
self.discover_adapted_resources(type_name_filter, adapter_name_filter)?;
453452

454453
// add/update found adapted resources to the lookup_table
455-
add_resources_to_lookup_table(&self.adapted_resources);
454+
let adapted_resources = get_adapted_resources();
455+
add_resources_to_lookup_table(&adapted_resources);
456456

457-
for (adapted_name, adapted_vec) in &self.adapted_resources {
457+
for (adapted_name, adapted_vec) in &adapted_resources {
458458
resources.insert(adapted_name.clone(), adapted_vec.iter().map(|r| ImportedManifest::Resource(r.clone())).collect());
459459
}
460460
}
461461
} else {
462462
self.discover(kind, type_name_filter)?;
463-
for (extension_name, extension) in &self.extensions {
463+
for (extension_name, extension) in &get_extensions() {
464464
resources.insert(extension_name.clone(), vec![ImportedManifest::Extension(extension.clone())]);
465465
}
466466
}
@@ -470,16 +470,18 @@ impl ResourceDiscovery for CommandDiscovery {
470470

471471
fn find_resources(&mut self, required_resource_types: &[DiscoveryFilter]) -> Result<BTreeMap<String, Vec<DscResource>>, DscError> {
472472
debug!("{}", t!("discovery.commandDiscovery.searchingForResources", resources = required_resource_types : {:?}));
473-
self.discover( &DiscoveryKind::Resource, "*")?;
473+
if resources_is_empty() {
474+
self.discover( &DiscoveryKind::Resource, "*")?;
475+
}
474476
let mut found_resources = BTreeMap::<String, Vec<DscResource>>::new();
475477
let mut required_resources = HashMap::<DiscoveryFilter, bool>::new();
476478
for filter in required_resource_types {
477479
required_resources.insert(filter.clone(), false);
478480
}
479481

480482
for filter in required_resource_types {
481-
if let Some(resources) = self.resources.get(filter.resource_type()) {
482-
filter_resources(&mut found_resources, &mut required_resources, resources, filter);
483+
if let Some(resources) = get_resource(filter.resource_type()) {
484+
filter_resources(&mut found_resources, &mut required_resources, &resources, filter);
483485
}
484486
if required_resources.values().all(|&v| v) {
485487
break;
@@ -492,12 +494,12 @@ impl ResourceDiscovery for CommandDiscovery {
492494
}
493495

494496
// now go through the adapters, this is for implicit adapters so version can't be specified so use latest version
495-
for adapter_name in self.adapters.clone().keys() {
497+
for adapter_name in get_adapters().keys() {
496498
self.discover_adapted_resources("*", adapter_name)?;
497-
add_resources_to_lookup_table(&self.adapted_resources);
499+
add_resources_to_lookup_table(&get_adapted_resources());
498500
for filter in required_resource_types {
499-
if let Some(adapted_resources) = self.adapted_resources.get(filter.resource_type()) {
500-
filter_resources(&mut found_resources, &mut required_resources, adapted_resources, filter);
501+
if let Some(adapted_resources) = get_adapted_resource(filter.resource_type()) {
502+
filter_resources(&mut found_resources, &mut required_resources, &adapted_resources, filter);
501503
}
502504
if required_resources.values().all(|&v| v) {
503505
break;
@@ -512,10 +514,10 @@ impl ResourceDiscovery for CommandDiscovery {
512514
}
513515

514516
fn get_extensions(&mut self) -> Result<BTreeMap<String, DscExtension>, DscError> {
515-
if self.extensions.is_empty() {
517+
if extensions_is_empty() {
516518
self.discover(&DiscoveryKind::Extension, "*")?;
517519
}
518-
Ok(self.extensions.clone())
520+
Ok(get_extensions())
519521
}
520522
}
521523

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::dscresources::dscresource::DscResource;
5+
use crate::extensions::dscextension::DscExtension;
6+
use std::collections::BTreeMap;
7+
use std::sync::{LazyLock, Mutex};
8+
9+
// use BTreeMap so that the results are sorted by the typename, the Vec is sorted by version
10+
static ADAPTERS : LazyLock<Mutex<BTreeMap<String, Vec<DscResource>>>> = LazyLock::new(|| Mutex::new(BTreeMap::new()));
11+
static RESOURCES : LazyLock<Mutex<BTreeMap<String, Vec<DscResource>>>> = LazyLock::new(|| Mutex::new(BTreeMap::new()));
12+
static EXTENSIONS : LazyLock<Mutex<BTreeMap<String, DscExtension>>> = LazyLock::new(|| Mutex::new(BTreeMap::new()));
13+
static ADAPTED_RESOURCES : LazyLock<Mutex<BTreeMap<String, Vec<DscResource>>>> = LazyLock::new(|| Mutex::new(BTreeMap::new()));
14+
15+
pub fn get_adapters() -> BTreeMap<String, Vec<DscResource>> {
16+
ADAPTERS.lock().unwrap().clone()
17+
}
18+
19+
pub fn get_adapted_resources() -> BTreeMap<String, Vec<DscResource>> {
20+
ADAPTED_RESOURCES.lock().unwrap().clone()
21+
}
22+
23+
pub fn get_adapted_resource(type_name: &str) -> Option<Vec<DscResource>> {
24+
if let Some(resources) = ADAPTED_RESOURCES.lock().unwrap().get(type_name) {
25+
return Some(resources.clone());
26+
}
27+
None
28+
}
29+
30+
pub fn get_extensions() -> BTreeMap<String, DscExtension> {
31+
EXTENSIONS.lock().unwrap().clone()
32+
}
33+
34+
pub fn get_resources() -> BTreeMap<String, Vec<DscResource>> {
35+
RESOURCES.lock().unwrap().clone()
36+
}
37+
38+
pub fn get_resource(type_name: &str) -> Option<Vec<DscResource>> {
39+
if let Some(resources) = RESOURCES.lock().unwrap().get(type_name) {
40+
return Some(resources.clone());
41+
}
42+
None
43+
}
44+
45+
pub fn extend_adapters(new_adapters: BTreeMap<String, Vec<DscResource>>) {
46+
ADAPTERS.lock().unwrap().extend(new_adapters);
47+
}
48+
49+
pub fn extend_resources(new_resources: BTreeMap<String, Vec<DscResource>>) {
50+
RESOURCES.lock().unwrap().extend(new_resources);
51+
}
52+
53+
pub fn extend_extensions(new_extensions: BTreeMap<String, DscExtension>) {
54+
EXTENSIONS.lock().unwrap().extend(new_extensions);
55+
}
56+
57+
pub fn extend_adapted_resources(new_adapted_resources: BTreeMap<String, Vec<DscResource>>) {
58+
ADAPTED_RESOURCES.lock().unwrap().extend(new_adapted_resources);
59+
}
60+
61+
pub fn extensions_is_empty() -> bool {
62+
EXTENSIONS.lock().unwrap().is_empty()
63+
}
64+
65+
pub fn resources_is_empty() -> bool {
66+
RESOURCES.lock().unwrap().is_empty()
67+
}
68+
69+
pub fn adapters_is_empty() -> bool {
70+
ADAPTERS.lock().unwrap().is_empty()
71+
}

dsc_lib/src/discovery/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
pub mod command_discovery;
5+
mod command_discovery_cache;
56
pub mod discovery_trait;
67

78
use crate::discovery::discovery_trait::{DiscoveryKind, ResourceDiscovery, DiscoveryFilter};

0 commit comments

Comments
 (0)