88import com .marklogic .mgmt .mapper .ResourceMapper ;
99
1010import java .util .ArrayList ;
11+ import java .util .LinkedHashMap ;
1112import java .util .List ;
1213import java .util .Map ;
1314
@@ -19,6 +20,7 @@ public class ForestBuilder extends LoggingObject {
1920
2021 private ForestNamingStrategy forestNamingStrategy ;
2122 private ReplicaBuilderStrategy replicaBuilderStrategy ;
23+ private ResourceMapper resourceMapper ;
2224
2325 public ForestBuilder () {
2426 this (new DefaultForestNamingStrategy ());
@@ -27,6 +29,7 @@ public ForestBuilder() {
2729 public ForestBuilder (ForestNamingStrategy forestNamingStrategy ) {
2830 this .forestNamingStrategy = forestNamingStrategy ;
2931 this .replicaBuilderStrategy = new DistributedReplicaBuilderStrategy ();
32+ this .resourceMapper = new DefaultResourceMapper (new API (null ));
3033 }
3134
3235 /**
@@ -42,66 +45,100 @@ public ForestBuilder(ForestNamingStrategy forestNamingStrategy) {
4245 */
4346 public List <Forest > buildForests (ForestPlan forestPlan , AppConfig appConfig ) {
4447 final String databaseName = forestPlan .getDatabaseName ();
45- final List <String > hostNames = forestPlan .getHostNames ();
4648
47- List <String > dataDirectories = determineDataDirectories (databaseName , appConfig );
49+ // Find out what forests we have already, keyed on host and then data directory
50+ Map <String , Map <String , List <Forest >>> existingForestsMap = existingForestsMap (forestPlan );
4851
49- int forestsPerDataDirectory = determineForestsPerDataDirectory (forestPlan , appConfig );
52+ final int forestsPerDataDirectory = determineForestsPerDataDirectory (forestPlan , appConfig );
53+ final List <String > dataDirectories = determineDataDirectories (databaseName , appConfig );
5054
51- // Number of hosts * number of data directories * number of forests per data directory
52- int numberToBuild = hostNames .size () * dataDirectories .size () * forestsPerDataDirectory ;
55+ List <Forest > forestsToBuild = new ArrayList <>();
5356
54- // So now we have numberToBuild - we want to iterate over each host, and over each data directory
55- int forestCounter = ( hostNames . size () * dataDirectories .size () * forestPlan . getExistingForestsPerDataDirectory ()) + 1 ;
57+ // For naming any new forests we build, start with the current count and bump up as we build each forest
58+ int forestCounter = forestPlan . getExistingForests () .size ();
5659
57- forestsPerDataDirectory -= forestPlan .getExistingForestsPerDataDirectory ();
60+ /**
61+ * Now loop over each host, and for each host, loop over each data directory. See how many forests exist already
62+ * in that data directory. Build new forests as needed so each data directory has the correct amount.
63+ */
64+ for (String hostName : forestPlan .getHostNames ()) {
65+ Map <String , List <Forest >> hostMap = existingForestsMap .get (hostName );
66+ for (String dataDirectory : dataDirectories ) {
67+ int forestsToCreate = forestsPerDataDirectory ;
68+ if (hostMap != null && hostMap .containsKey (dataDirectory )) {
69+ forestsToCreate -= hostMap .get (dataDirectory ).size ();
70+ }
71+ for (int i = 0 ; i < forestsToCreate ; i ++) {
72+ forestCounter ++;
73+ Forest forest = newForest (forestPlan );
74+ forest .setForestName (getForestName (databaseName , forestCounter , appConfig ));
75+ forest .setHost (hostName );
76+ forest .setDatabase (databaseName );
77+
78+ if (dataDirectory != null && dataDirectory .trim ().length () > 0 ) {
79+ forest .setDataDirectory (dataDirectory );
80+ }
5881
59- List <Forest > forests = new ArrayList <>();
82+ // First see if we have any database-agnostic forest directories
83+ if (appConfig .getForestFastDataDirectory () != null ) {
84+ forest .setFastDataDirectory (appConfig .getForestFastDataDirectory ());
85+ }
86+ if (appConfig .getForestLargeDataDirectory () != null ) {
87+ forest .setLargeDataDirectory (appConfig .getForestLargeDataDirectory ());
88+ }
6089
61- for (String hostName : hostNames ) {
62- for (String dataDirectory : dataDirectories ) {
63- for (int i = 0 ; i < forestsPerDataDirectory ; i ++) {
64- if (forestCounter <= numberToBuild ) {
65- Forest forest = newForest (forestPlan );
66- forest .setForestName (getForestName (databaseName , forestCounter , appConfig ));
67- forest .setHost (hostName );
68- forest .setDatabase (databaseName );
69-
70- if (dataDirectory != null && dataDirectory .trim ().length () > 0 ) {
71- forest .setDataDirectory (dataDirectory );
72- }
73-
74- // First see if we have any database-agnostic forest directories
75- if (appConfig .getForestFastDataDirectory () != null ) {
76- forest .setFastDataDirectory (appConfig .getForestFastDataDirectory ());
77- }
78- if (appConfig .getForestLargeDataDirectory () != null ) {
79- forest .setLargeDataDirectory (appConfig .getForestLargeDataDirectory ());
80- }
81-
82- // Now check for database-specific forest directories
83- Map <String , String > map = appConfig .getDatabaseFastDataDirectories ();
84- if (map != null && map .containsKey (databaseName )) {
85- forest .setFastDataDirectory (map .get (databaseName ));
86- }
87- map = appConfig .getDatabaseLargeDataDirectories ();
88- if (map != null && map .containsKey (databaseName )) {
89- forest .setLargeDataDirectory (map .get (databaseName ));
90- }
91-
92- forests .add (forest );
93-
94- forestCounter ++;
90+ // Now check for database-specific forest directories
91+ Map <String , String > map = appConfig .getDatabaseFastDataDirectories ();
92+ if (map != null && map .containsKey (databaseName )) {
93+ forest .setFastDataDirectory (map .get (databaseName ));
94+ }
95+ map = appConfig .getDatabaseLargeDataDirectories ();
96+ if (map != null && map .containsKey (databaseName )) {
97+ forest .setLargeDataDirectory (map .get (databaseName ));
9598 }
99+
100+ forestsToBuild .add (forest );
96101 }
97102 }
98103 }
99104
100105 if (forestPlan .getReplicaCount () > 0 ) {
101- addReplicasToForests (forests , forestPlan , appConfig , dataDirectories );
106+ addReplicasToForests (forestsToBuild , forestPlan , appConfig , dataDirectories );
102107 }
103108
104- return forests ;
109+ return forestsToBuild ;
110+ }
111+
112+ /**
113+ * Returns a map with keys of host names, where each value is a map whose keys are data directory paths bound to
114+ * a list of forests that already exist at each data directory path.
115+ *
116+ * @param forestPlan
117+ * @return
118+ */
119+ protected Map <String , Map <String , List <Forest >>> existingForestsMap (ForestPlan forestPlan ) {
120+ Map <String , Map <String , List <Forest >>> existingForestsMap = new LinkedHashMap <>();
121+ for (Forest f : forestPlan .getExistingForests ()) {
122+ String host = f .getHost ();
123+ String dataDirectory = f .getDataDirectory ();
124+ if (dataDirectory == null ) {
125+ dataDirectory = "" ;
126+ }
127+
128+ Map <String , List <Forest >> dataDirectoryMap = existingForestsMap .get (host );
129+ if (dataDirectoryMap == null ) {
130+ dataDirectoryMap = new LinkedHashMap <>();
131+ existingForestsMap .put (host , dataDirectoryMap );
132+ }
133+
134+ List <Forest > list = dataDirectoryMap .get (dataDirectory );
135+ if (list == null ) {
136+ list = new ArrayList <>();
137+ dataDirectoryMap .put (dataDirectory , list );
138+ }
139+ list .add (f );
140+ }
141+ return existingForestsMap ;
105142 }
106143
107144 /**
@@ -146,7 +183,6 @@ protected Forest newForest(ForestPlan forestPlan) {
146183 return new Forest ();
147184 }
148185 try {
149- ResourceMapper resourceMapper = new DefaultResourceMapper (new API (null ));
150186 return resourceMapper .readResource (template , Forest .class );
151187 } catch (Exception ex ) {
152188 logger .warn ("Unable to construct a new Forest using template: " + template , ex );
@@ -229,7 +265,6 @@ protected int determineForestsPerDataDirectory(ForestPlan forestPlan, AppConfig
229265 }
230266
231267 /**
232- *
233268 * @param databaseName
234269 * @param forestNumber
235270 * @param appConfig
@@ -240,7 +275,6 @@ protected String getForestName(String databaseName, int forestNumber, AppConfig
240275 }
241276
242277 /**
243- *
244278 * @param databaseName
245279 * @param appConfig
246280 * @return
0 commit comments