2
2
// Licensed under the MIT License.
3
3
4
4
use 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
- } ,
9
5
discovery_trait:: { DiscoveryFilter , DiscoveryKind , ResourceDiscovery }
10
6
} ;
7
+ use crate :: { locked_is_empty, locked_extend, locked_clone, locked_get} ;
11
8
use crate :: dscresources:: dscresource:: { Capability , DscResource , ImplementedAs } ;
12
9
use crate :: dscresources:: resource_manifest:: { import_manifest, validate_semver, Kind , ResourceManifest , SchemaKind } ;
13
10
use crate :: dscresources:: command_resource:: invoke_command;
@@ -21,7 +18,7 @@ use rust_i18n::t;
21
18
use semver:: { Version , VersionReq } ;
22
19
use schemars:: JsonSchema ;
23
20
use serde:: { Deserialize , Serialize } ;
24
- use std:: collections:: { BTreeMap , HashSet , HashMap } ;
21
+ use std:: { collections:: { BTreeMap , HashMap , HashSet } , sync :: { LazyLock , Mutex } } ;
25
22
use std:: env;
26
23
use std:: ffi:: OsStr ;
27
24
use std:: fs;
@@ -36,6 +33,12 @@ use crate::util::get_exe_path;
36
33
const DSC_RESOURCE_EXTENSIONS : [ & str ; 3 ] = [ ".dsc.resource.json" , ".dsc.resource.yaml" , ".dsc.resource.yml" ] ;
37
34
const DSC_EXTENSION_EXTENSIONS : [ & str ; 3 ] = [ ".dsc.extension.json" , ".dsc.extension.yaml" , ".dsc.extension.yml" ] ;
38
35
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
+
39
42
#[ derive( Clone , Serialize , Deserialize , JsonSchema ) ]
40
43
pub enum ImportedManifest {
41
44
Resource ( DscResource ) ,
@@ -79,9 +82,7 @@ impl CommandDiscovery {
79
82
}
80
83
81
84
#[ 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 ) }
85
86
86
87
fn get_resource_path_setting ( ) -> Result < ResourcePathSetting , DscError >
87
88
{
@@ -305,7 +306,7 @@ impl ResourceDiscovery for CommandDiscovery {
305
306
match kind {
306
307
DiscoveryKind :: Resource => {
307
308
// 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 ( ) {
309
310
if extension. capabilities . contains ( & ExtensionCapability :: Discover ) {
310
311
debug ! ( "{}" , t!( "discovery.commandDiscovery.callingExtension" , extension = extension. type_name) ) ;
311
312
let discovered_resources = extension. discover ( ) ?;
@@ -318,27 +319,27 @@ impl ResourceDiscovery for CommandDiscovery {
318
319
}
319
320
}
320
321
}
321
- extend_adapters ( adapters) ;
322
- extend_resources ( resources) ;
322
+ locked_extend ! ( ADAPTERS , adapters) ;
323
+ locked_extend ! ( RESOURCES , resources) ;
323
324
} ,
324
325
DiscoveryKind :: Extension => {
325
- extend_extensions ( extensions) ;
326
+ locked_extend ! ( EXTENSIONS , extensions) ;
326
327
}
327
328
}
328
329
329
330
Ok ( ( ) )
330
331
}
331
332
332
333
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 ) {
334
335
self . discover ( & DiscoveryKind :: Resource , "*" ) ?;
335
336
}
336
337
337
- if adapters_is_empty ( ) {
338
+ if locked_is_empty ! ( ADAPTERS ) {
338
339
return Ok ( ( ) ) ;
339
340
}
340
341
341
- let adapters = get_adapters ( ) ;
342
+ let adapters = locked_clone ! ( ADAPTERS ) ;
342
343
let regex_str = convert_wildcard_to_regex ( adapter_filter) ;
343
344
debug ! ( "Using regex {regex_str} as filter for adapter name" ) ;
344
345
let mut regex_builder = RegexBuilder :: new ( & regex_str) ;
@@ -430,7 +431,7 @@ impl ResourceDiscovery for CommandDiscovery {
430
431
return Err ( DscError :: AdapterNotFound ( adapter_filter. to_string ( ) ) ) ;
431
432
}
432
433
433
- extend_adapted_resources ( adapted_resources) ;
434
+ locked_extend ! ( ADAPTED_RESOURCES , adapted_resources) ;
434
435
435
436
Ok ( ( ) )
436
437
}
@@ -440,18 +441,18 @@ impl ResourceDiscovery for CommandDiscovery {
440
441
if * kind == DiscoveryKind :: Resource {
441
442
if adapter_name_filter. is_empty ( ) {
442
443
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 ) {
444
445
resources. insert ( resource_name. clone ( ) , resources_vec. iter ( ) . map ( |r| ImportedManifest :: Resource ( r. clone ( ) ) ) . collect ( ) ) ;
445
446
}
446
- for ( adapter_name, adapter_vec) in & get_adapters ( ) {
447
+ for ( adapter_name, adapter_vec) in & locked_clone ! ( ADAPTERS ) {
447
448
resources. insert ( adapter_name. clone ( ) , adapter_vec. iter ( ) . map ( |r| ImportedManifest :: Resource ( r. clone ( ) ) ) . collect ( ) ) ;
448
449
}
449
450
} else {
450
451
self . discover ( kind, "*" ) ?;
451
452
self . discover_adapted_resources ( type_name_filter, adapter_name_filter) ?;
452
453
453
454
// add/update found adapted resources to the lookup_table
454
- let adapted_resources = get_adapted_resources ( ) ;
455
+ let adapted_resources = locked_clone ! ( ADAPTED_RESOURCES ) ;
455
456
add_resources_to_lookup_table ( & adapted_resources) ;
456
457
457
458
for ( adapted_name, adapted_vec) in & adapted_resources {
@@ -460,7 +461,7 @@ impl ResourceDiscovery for CommandDiscovery {
460
461
}
461
462
} else {
462
463
self . discover ( kind, type_name_filter) ?;
463
- for ( extension_name, extension) in & get_extensions ( ) {
464
+ for ( extension_name, extension) in & locked_clone ! ( EXTENSIONS ) {
464
465
resources. insert ( extension_name. clone ( ) , vec ! [ ImportedManifest :: Extension ( extension. clone( ) ) ] ) ;
465
466
}
466
467
}
@@ -470,7 +471,7 @@ impl ResourceDiscovery for CommandDiscovery {
470
471
471
472
fn find_resources ( & mut self , required_resource_types : & [ DiscoveryFilter ] ) -> Result < BTreeMap < String , Vec < DscResource > > , DscError > {
472
473
debug ! ( "{}" , t!( "discovery.commandDiscovery.searchingForResources" , resources = required_resource_types : { : ?} ) ) ;
473
- if resources_is_empty ( ) {
474
+ if locked_is_empty ! ( RESOURCES ) {
474
475
self . discover ( & DiscoveryKind :: Resource , "*" ) ?;
475
476
}
476
477
let mut found_resources = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
@@ -480,7 +481,7 @@ impl ResourceDiscovery for CommandDiscovery {
480
481
}
481
482
482
483
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( ) ) {
484
485
filter_resources ( & mut found_resources, & mut required_resources, & resources, filter) ;
485
486
}
486
487
if required_resources. values ( ) . all ( |& v| v) {
@@ -494,11 +495,11 @@ impl ResourceDiscovery for CommandDiscovery {
494
495
}
495
496
496
497
// 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 ( ) {
498
499
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 ) ) ;
500
501
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( ) ) {
502
503
filter_resources ( & mut found_resources, & mut required_resources, & adapted_resources, filter) ;
503
504
}
504
505
if required_resources. values ( ) . all ( |& v| v) {
@@ -514,10 +515,10 @@ impl ResourceDiscovery for CommandDiscovery {
514
515
}
515
516
516
517
fn get_extensions ( & mut self ) -> Result < BTreeMap < String , DscExtension > , DscError > {
517
- if extensions_is_empty ( ) {
518
+ if locked_is_empty ! ( EXTENSIONS ) {
518
519
self . discover ( & DiscoveryKind :: Extension , "*" ) ?;
519
520
}
520
- Ok ( get_extensions ( ) )
521
+ Ok ( locked_clone ! ( EXTENSIONS ) )
521
522
}
522
523
}
523
524
0 commit comments