22// Licensed under the MIT License.
33
44use crate :: discovery:: {
5- command_discovery_cache:: {
6- adapters_is_empty, extend_adapted_resources, extend_adapters, extend_extensions, extend_resources, extensions_is_empty,
7- get_adapted_resource, get_adapted_resources, get_adapters, get_extensions, get_resource, get_resources, resources_is_empty,
8- } ,
95 discovery_trait:: { DiscoveryFilter , DiscoveryKind , ResourceDiscovery }
106} ;
7+ use crate :: { locked_is_empty, locked_extend, locked_clone, locked_get} ;
118use crate :: dscresources:: dscresource:: { Capability , DscResource , ImplementedAs } ;
129use crate :: dscresources:: resource_manifest:: { import_manifest, validate_semver, Kind , ResourceManifest , SchemaKind } ;
1310use crate :: dscresources:: command_resource:: invoke_command;
@@ -21,7 +18,7 @@ use rust_i18n::t;
2118use semver:: { Version , VersionReq } ;
2219use schemars:: JsonSchema ;
2320use serde:: { Deserialize , Serialize } ;
24- use std:: collections:: { BTreeMap , HashSet , HashMap } ;
21+ use std:: { collections:: { BTreeMap , HashMap , HashSet } , sync :: { LazyLock , Mutex } } ;
2522use std:: env;
2623use std:: ffi:: OsStr ;
2724use std:: fs;
@@ -36,6 +33,12 @@ use crate::util::get_exe_path;
3633const DSC_RESOURCE_EXTENSIONS : [ & str ; 3 ] = [ ".dsc.resource.json" , ".dsc.resource.yaml" , ".dsc.resource.yml" ] ;
3734const DSC_EXTENSION_EXTENSIONS : [ & str ; 3 ] = [ ".dsc.extension.json" , ".dsc.extension.yaml" , ".dsc.extension.yml" ] ;
3835
36+ // use BTreeMap so that the results are sorted by the typename, the Vec is sorted by version
37+ static ADAPTERS : LazyLock < Mutex < BTreeMap < String , Vec < DscResource > > > > = LazyLock :: new ( || Mutex :: new ( BTreeMap :: new ( ) ) ) ;
38+ static RESOURCES : LazyLock < Mutex < BTreeMap < String , Vec < DscResource > > > > = LazyLock :: new ( || Mutex :: new ( BTreeMap :: new ( ) ) ) ;
39+ static EXTENSIONS : LazyLock < Mutex < BTreeMap < String , DscExtension > > > = LazyLock :: new ( || Mutex :: new ( BTreeMap :: new ( ) ) ) ;
40+ static ADAPTED_RESOURCES : LazyLock < Mutex < BTreeMap < String , Vec < DscResource > > > > = LazyLock :: new ( || Mutex :: new ( BTreeMap :: new ( ) ) ) ;
41+
3942#[ derive( Clone , Serialize , Deserialize , JsonSchema ) ]
4043pub enum ImportedManifest {
4144 Resource ( DscResource ) ,
@@ -79,9 +82,7 @@ impl CommandDiscovery {
7982 }
8083
8184 #[ must_use]
82- pub fn get_extensions ( & self ) -> BTreeMap < String , DscExtension > {
83- get_extensions ( )
84- }
85+ pub fn get_extensions ( & self ) -> BTreeMap < String , DscExtension > { locked_clone ! ( EXTENSIONS ) }
8586
8687 fn get_resource_path_setting ( ) -> Result < ResourcePathSetting , DscError >
8788 {
@@ -305,7 +306,7 @@ impl ResourceDiscovery for CommandDiscovery {
305306 match kind {
306307 DiscoveryKind :: Resource => {
307308 // Now we need to call discover extensions and add those resource to the list of resources
308- for extension in get_extensions ( ) . values ( ) {
309+ for extension in locked_clone ! ( EXTENSIONS ) . values ( ) {
309310 if extension. capabilities . contains ( & ExtensionCapability :: Discover ) {
310311 debug ! ( "{}" , t!( "discovery.commandDiscovery.callingExtension" , extension = extension. type_name) ) ;
311312 let discovered_resources = extension. discover ( ) ?;
@@ -318,27 +319,27 @@ impl ResourceDiscovery for CommandDiscovery {
318319 }
319320 }
320321 }
321- extend_adapters ( adapters) ;
322- extend_resources ( resources) ;
322+ locked_extend ! ( ADAPTERS , adapters) ;
323+ locked_extend ! ( RESOURCES , resources) ;
323324 } ,
324325 DiscoveryKind :: Extension => {
325- extend_extensions ( extensions) ;
326+ locked_extend ! ( EXTENSIONS , extensions) ;
326327 }
327328 }
328329
329330 Ok ( ( ) )
330331 }
331332
332333 fn discover_adapted_resources ( & mut self , name_filter : & str , adapter_filter : & str ) -> Result < ( ) , DscError > {
333- if resources_is_empty ( ) && adapters_is_empty ( ) {
334+ if locked_is_empty ! ( RESOURCES ) && locked_is_empty ! ( ADAPTERS ) {
334335 self . discover ( & DiscoveryKind :: Resource , "*" ) ?;
335336 }
336337
337- if adapters_is_empty ( ) {
338+ if locked_is_empty ! ( ADAPTERS ) {
338339 return Ok ( ( ) ) ;
339340 }
340341
341- let adapters = get_adapters ( ) ;
342+ let adapters = locked_clone ! ( ADAPTERS ) ;
342343 let regex_str = convert_wildcard_to_regex ( adapter_filter) ;
343344 debug ! ( "Using regex {regex_str} as filter for adapter name" ) ;
344345 let mut regex_builder = RegexBuilder :: new ( & regex_str) ;
@@ -430,7 +431,7 @@ impl ResourceDiscovery for CommandDiscovery {
430431 return Err ( DscError :: AdapterNotFound ( adapter_filter. to_string ( ) ) ) ;
431432 }
432433
433- extend_adapted_resources ( adapted_resources) ;
434+ locked_extend ! ( ADAPTED_RESOURCES , adapted_resources) ;
434435
435436 Ok ( ( ) )
436437 }
@@ -440,18 +441,18 @@ impl ResourceDiscovery for CommandDiscovery {
440441 if * kind == DiscoveryKind :: Resource {
441442 if adapter_name_filter. is_empty ( ) {
442443 self . discover ( kind, type_name_filter) ?;
443- for ( resource_name, resources_vec) in & get_resources ( ) {
444+ for ( resource_name, resources_vec) in & locked_clone ! ( RESOURCES ) {
444445 resources. insert ( resource_name. clone ( ) , resources_vec. iter ( ) . map ( |r| ImportedManifest :: Resource ( r. clone ( ) ) ) . collect ( ) ) ;
445446 }
446- for ( adapter_name, adapter_vec) in & get_adapters ( ) {
447+ for ( adapter_name, adapter_vec) in & locked_clone ! ( ADAPTERS ) {
447448 resources. insert ( adapter_name. clone ( ) , adapter_vec. iter ( ) . map ( |r| ImportedManifest :: Resource ( r. clone ( ) ) ) . collect ( ) ) ;
448449 }
449450 } else {
450451 self . discover ( kind, "*" ) ?;
451452 self . discover_adapted_resources ( type_name_filter, adapter_name_filter) ?;
452453
453454 // add/update found adapted resources to the lookup_table
454- let adapted_resources = get_adapted_resources ( ) ;
455+ let adapted_resources = locked_clone ! ( ADAPTED_RESOURCES ) ;
455456 add_resources_to_lookup_table ( & adapted_resources) ;
456457
457458 for ( adapted_name, adapted_vec) in & adapted_resources {
@@ -460,7 +461,7 @@ impl ResourceDiscovery for CommandDiscovery {
460461 }
461462 } else {
462463 self . discover ( kind, type_name_filter) ?;
463- for ( extension_name, extension) in & get_extensions ( ) {
464+ for ( extension_name, extension) in & locked_clone ! ( EXTENSIONS ) {
464465 resources. insert ( extension_name. clone ( ) , vec ! [ ImportedManifest :: Extension ( extension. clone( ) ) ] ) ;
465466 }
466467 }
@@ -470,7 +471,7 @@ impl ResourceDiscovery for CommandDiscovery {
470471
471472 fn find_resources ( & mut self , required_resource_types : & [ DiscoveryFilter ] ) -> Result < BTreeMap < String , Vec < DscResource > > , DscError > {
472473 debug ! ( "{}" , t!( "discovery.commandDiscovery.searchingForResources" , resources = required_resource_types : { : ?} ) ) ;
473- if resources_is_empty ( ) {
474+ if locked_is_empty ! ( RESOURCES ) {
474475 self . discover ( & DiscoveryKind :: Resource , "*" ) ?;
475476 }
476477 let mut found_resources = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
@@ -480,7 +481,7 @@ impl ResourceDiscovery for CommandDiscovery {
480481 }
481482
482483 for filter in required_resource_types {
483- if let Some ( resources) = get_resource ( filter. resource_type ( ) ) {
484+ if let Some ( resources) = locked_get ! ( RESOURCES , filter. resource_type( ) ) {
484485 filter_resources ( & mut found_resources, & mut required_resources, & resources, filter) ;
485486 }
486487 if required_resources. values ( ) . all ( |& v| v) {
@@ -494,11 +495,11 @@ impl ResourceDiscovery for CommandDiscovery {
494495 }
495496
496497 // now go through the adapters, this is for implicit adapters so version can't be specified so use latest version
497- for adapter_name in get_adapters ( ) . keys ( ) {
498+ for adapter_name in locked_clone ! ( ADAPTERS ) . keys ( ) {
498499 self . discover_adapted_resources ( "*" , adapter_name) ?;
499- add_resources_to_lookup_table ( & get_adapted_resources ( ) ) ;
500+ add_resources_to_lookup_table ( & locked_clone ! ( ADAPTED_RESOURCES ) ) ;
500501 for filter in required_resource_types {
501- if let Some ( adapted_resources) = get_adapted_resource ( filter. resource_type ( ) ) {
502+ if let Some ( adapted_resources) = locked_get ! ( ADAPTED_RESOURCES , filter. resource_type( ) ) {
502503 filter_resources ( & mut found_resources, & mut required_resources, & adapted_resources, filter) ;
503504 }
504505 if required_resources. values ( ) . all ( |& v| v) {
@@ -514,10 +515,10 @@ impl ResourceDiscovery for CommandDiscovery {
514515 }
515516
516517 fn get_extensions ( & mut self ) -> Result < BTreeMap < String , DscExtension > , DscError > {
517- if extensions_is_empty ( ) {
518+ if locked_is_empty ! ( EXTENSIONS ) {
518519 self . discover ( & DiscoveryKind :: Extension , "*" ) ?;
519520 }
520- Ok ( get_extensions ( ) )
521+ Ok ( locked_clone ! ( EXTENSIONS ) )
521522 }
522523}
523524
0 commit comments