95
95
import org .exist .xquery .update .Modification ;
96
96
import org .exist .xquery .util .SerializerUtils ;
97
97
import org .exist .xquery .value .*;
98
+ import org .jgrapht .Graph ;
98
99
import org .jgrapht .alg .interfaces .ShortestPathAlgorithm ;
99
100
import org .jgrapht .alg .shortestpath .TransitNodeRoutingShortestPath ;
100
101
import org .jgrapht .graph .DefaultEdge ;
@@ -235,7 +236,8 @@ public class XQueryContext implements BinaryValueManager, Context {
235
236
/**
236
237
* Describes a graph of all the modules and how they import each other.
237
238
*/
238
- private @ Nullable final FastutilMapGraph <ModuleVertex , DefaultEdge > modulesDependencyGraph ;
239
+ private @ Nullable Graph <ModuleVertex , DefaultEdge > modulesDependencyGraph ;
240
+ private @ Nullable ThreadPoolExecutor modulesDependencyGraphSPExecutor ;
239
241
240
242
/**
241
243
* Used to save current state when modules are imported dynamically
@@ -467,10 +469,6 @@ public XQueryContext(@Nullable final Database db, @Nullable final Configuration
467
469
}
468
470
469
471
protected XQueryContext (@ Nullable final Database db , @ Nullable final Configuration configuration , @ Nullable final Profiler profiler , final boolean loadDefaults ) {
470
- this (db , configuration , profiler , loadDefaults , new FastutilMapGraph <>(null , SupplierUtil .createDefaultEdgeSupplier (), DefaultGraphType .directedPseudograph ().asUnweighted ()));
471
- }
472
-
473
- protected XQueryContext (@ Nullable final Database db , @ Nullable final Configuration configuration , @ Nullable final Profiler profiler , final boolean loadDefaults , final @ Nullable FastutilMapGraph <ModuleVertex , DefaultEdge > modulesDependencyGraph ) {
474
472
this .db = db ;
475
473
476
474
// if needed, fallback to db.getConfiguration
@@ -491,8 +489,6 @@ protected XQueryContext(@Nullable final Database db, @Nullable final Configurati
491
489
this .profiler = new Profiler (null );
492
490
}
493
491
494
- this .modulesDependencyGraph = modulesDependencyGraph ;
495
-
496
492
this .watchdog = new XQueryWatchDog (this );
497
493
498
494
// load configuration defaults
@@ -1459,6 +1455,15 @@ public void reset(final boolean keepGlobals) {
1459
1455
httpContext = null ;
1460
1456
}
1461
1457
1458
+ if (modulesDependencyGraphSPExecutor != null ) {
1459
+ try {
1460
+ ConcurrencyUtil .shutdownExecutionService (modulesDependencyGraphSPExecutor );
1461
+ } catch (final InterruptedException e ) {
1462
+ Thread .currentThread ().interrupt ();
1463
+ }
1464
+ modulesDependencyGraphSPExecutor = null ;
1465
+ }
1466
+
1462
1467
analyzed = false ;
1463
1468
}
1464
1469
@@ -1548,13 +1553,21 @@ public void addModule(final String namespaceURI, final Module module) {
1548
1553
addRootModule (namespaceURI , module );
1549
1554
}
1550
1555
1556
+ private Graph <ModuleVertex , DefaultEdge > getModulesDependencyGraph () {
1557
+ // NOTE(AR) intentionally lazily initialised!
1558
+ if (modulesDependencyGraph == null ) {
1559
+ this .modulesDependencyGraph = new FastutilMapGraph <>(null , SupplierUtil .createDefaultEdgeSupplier (), DefaultGraphType .directedPseudograph ().asUnweighted ());
1560
+ }
1561
+ return modulesDependencyGraph ;
1562
+ }
1563
+
1551
1564
/**
1552
1565
* Add a vertex to the Modules Dependency Graph.
1553
1566
*
1554
1567
* @param moduleVertex the module vertex
1555
1568
*/
1556
1569
protected void addModuleVertex (final ModuleVertex moduleVertex ) {
1557
- modulesDependencyGraph .addVertex (moduleVertex );
1570
+ getModulesDependencyGraph () .addVertex (moduleVertex );
1558
1571
}
1559
1572
1560
1573
/**
@@ -1565,7 +1578,7 @@ protected void addModuleVertex(final ModuleVertex moduleVertex) {
1565
1578
* @return true if the module vertex exists, false otherwise
1566
1579
*/
1567
1580
protected boolean hasModuleVertex (final ModuleVertex moduleVertex ) {
1568
- return modulesDependencyGraph .containsVertex (moduleVertex );
1581
+ return getModulesDependencyGraph () .containsVertex (moduleVertex );
1569
1582
}
1570
1583
1571
1584
/**
@@ -1575,7 +1588,7 @@ protected boolean hasModuleVertex(final ModuleVertex moduleVertex) {
1575
1588
* @param sink the imported module
1576
1589
*/
1577
1590
protected void addModuleEdge (final ModuleVertex source , final ModuleVertex sink ) {
1578
- modulesDependencyGraph .addEdge (source , sink );
1591
+ getModulesDependencyGraph () .addEdge (source , sink );
1579
1592
}
1580
1593
1581
1594
/**
@@ -1591,20 +1604,13 @@ protected boolean hasModulePath(final ModuleVertex source, final ModuleVertex si
1591
1604
return false ;
1592
1605
}
1593
1606
1594
- ThreadPoolExecutor executor = null ;
1595
- try {
1596
- executor = ConcurrencyUtil .createThreadPoolExecutor (2 );
1597
- final ShortestPathAlgorithm <ModuleVertex , DefaultEdge > spa = new TransitNodeRoutingShortestPath <>(modulesDependencyGraph , executor );
1598
- return spa .getPath (source , sink ) != null ;
1599
- } finally {
1600
- if (executor != null ) {
1601
- try {
1602
- ConcurrencyUtil .shutdownExecutionService (executor );
1603
- } catch (final InterruptedException e ) {
1604
- Thread .currentThread ().interrupt ();
1605
- }
1606
- }
1607
+ // NOTE(AR) intentionally lazily initialised!
1608
+ if (modulesDependencyGraphSPExecutor == null ) {
1609
+ modulesDependencyGraphSPExecutor = ConcurrencyUtil .createThreadPoolExecutor (2 );
1607
1610
}
1611
+
1612
+ final ShortestPathAlgorithm <ModuleVertex , DefaultEdge > spa = new TransitNodeRoutingShortestPath <>(getModulesDependencyGraph (), modulesDependencyGraphSPExecutor );
1613
+ return spa .getPath (source , sink ) != null ;
1608
1614
}
1609
1615
1610
1616
protected void setRootModules (final String namespaceURI , @ Nullable final Module [] modules ) {
0 commit comments