Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 58b96c3

Browse files
committed
#214 Can now specify the hosts for database forests
1 parent ad64288 commit 58b96c3

File tree

9 files changed

+186
-76
lines changed

9 files changed

+186
-76
lines changed

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ public class AppConfig {
151151
private String databaseNamesAndReplicaCounts;
152152

153153
// Comma-delimited string of database names that should only have forests (most likely just one) created on one host
154-
private Set<String> databaseNamesWithForestsOnOneHost;
154+
private Set<String> databasesWithForestsOnOneHost;
155+
156+
private Map<String, Set<String>> databaseHosts;
155157

156158
// Data/fast/large directories for default forests
157159
private String forestDataDirectory;
@@ -1056,11 +1058,19 @@ public void setCatchUndeployExceptions(boolean catchUndeployExceptions) {
10561058
this.catchUndeployExceptions = catchUndeployExceptions;
10571059
}
10581060

1059-
public Set<String> getDatabaseNamesWithForestsOnOneHost() {
1060-
return databaseNamesWithForestsOnOneHost;
1061+
public Set<String> getDatabasesWithForestsOnOneHost() {
1062+
return databasesWithForestsOnOneHost;
1063+
}
1064+
1065+
public void setDatabasesWithForestsOnOneHost(Set<String> databasesWithForestsOnOneHost) {
1066+
this.databasesWithForestsOnOneHost = databasesWithForestsOnOneHost;
1067+
}
1068+
1069+
public Map<String, Set<String>> getDatabaseHosts() {
1070+
return databaseHosts;
10611071
}
10621072

1063-
public void setDatabaseNamesWithForestsOnOneHost(Set<String> databaseNamesWithForestsOnOneHost) {
1064-
this.databaseNamesWithForestsOnOneHost = databaseNamesWithForestsOnOneHost;
1073+
public void setDatabaseHosts(Map<String, Set<String>> databaseHosts) {
1074+
this.databaseHosts = databaseHosts;
10651075
}
10661076
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,15 +276,32 @@ public AppConfig newAppConfig() {
276276
c.setDatabaseNamesAndReplicaCounts(prop);
277277
}
278278

279-
prop = getProperty("mlDatabaseNamesWithForestsOnOneHost");
279+
prop = getProperty("mlDatabasesWithForestsOnOneHost");
280280
if (prop != null) {
281281
logger.info("Databases that will have their forest(s) created on a single host: " + prop);
282282
String[] names = prop.split(",");
283283
Set<String> set = new HashSet<>();
284284
for (String name : names) {
285285
set.add(name);
286286
}
287-
c.setDatabaseNamesWithForestsOnOneHost(set);
287+
c.setDatabasesWithForestsOnOneHost(set);
288+
}
289+
290+
prop = getProperty("mlDatabaseHosts");
291+
if (prop != null) {
292+
logger.info("Databases and the hosts that their forests will be created on: " + prop);
293+
String[] tokens = prop.split(",");
294+
Map<String, Set<String>> map = new HashMap<>();
295+
for (int i = 0; i < tokens.length; i += 2) {
296+
String dbName = tokens[i];
297+
String[] hostNames = tokens[i + 1].split("\\|");
298+
Set<String> names = new HashSet<>();
299+
for (String name : hostNames) {
300+
names.add(name);
301+
}
302+
map.put(dbName, names);
303+
}
304+
c.setDatabaseHosts(map);
288305
}
289306

290307
prop = getProperty("mlForestDataDirectory");

src/main/java/com/marklogic/appdeployer/command/databases/DeployDatabaseCommand.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.util.ArrayList;
1717
import java.util.List;
1818
import java.util.Map;
19-
import java.util.Set;
2019

2120
/**
2221
* Can be used for creating any kind of database with any sorts of forests. Specifying a config file for the database or
@@ -284,9 +283,6 @@ protected boolean customForestsExist(CommandContext context, String dbName) {
284283
/**
285284
* Allows for how an instance of DeployForestsCommand is built to be overridden by a subclass.
286285
*
287-
* Starting in 3.2.0, the "createForestsOnEachHost" property is overridden if the database name is in the
288-
* databaseNamesWithForestsOnOneHost property in AppConfig.
289-
*
290286
* @param dbPayload
291287
* Needed so we can look up forest counts based on the database name
292288
* @param receipt
@@ -298,17 +294,7 @@ protected DeployForestsCommand buildDeployForestsCommand(String dbPayload, SaveR
298294
final String databaseName = receipt.getResourceId();
299295

300296
DeployForestsCommand c = new DeployForestsCommand();
301-
302-
Set<String> names = context.getAppConfig().getDatabaseNamesWithForestsOnOneHost();
303-
if (names != null && names.contains(databaseName)) {
304-
if (logger.isInfoEnabled()) {
305-
logger.info("Will only create forest(s) on one host for database: " + databaseName);
306-
}
307-
c.setCreateForestsOnEachHost(false);
308-
} else {
309-
c.setCreateForestsOnEachHost(createForestsOnEachHost);
310-
}
311-
297+
c.setCreateForestsOnEachHost(createForestsOnEachHost);
312298
c.setForestsPerHost(determineForestCountPerHost(dbPayload, context));
313299
c.setForestFilename(forestFilename);
314300
c.setDatabaseName(databaseName);

src/main/java/com/marklogic/appdeployer/command/forests/DeployForestsCommand.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import java.io.File;
1313
import java.util.ArrayList;
1414
import java.util.List;
15+
import java.util.Map;
16+
import java.util.Set;
1517

1618
/**
1719
* This command is for a simple use case where all the forests created for a database have the same structure,
@@ -76,12 +78,7 @@ protected void createForests(String originalPayload, CommandContext context) {
7678

7779
// Find out which hosts to create forests on
7880
List<String> hostNames = new HostManager(context.getManageClient()).getHostNames();
79-
if (!createForestsOnEachHost) {
80-
String first = hostNames.get(0);
81-
logger.info(format("Only creating forests on the first host: " + first));
82-
hostNames = new ArrayList<>();
83-
hostNames.add(first);
84-
}
81+
hostNames = determineHostNamesForForest(context, hostNames);
8582

8683
// Find out how many forests exist already
8784
int countOfExistingForests = new DatabaseManager(context.getManageClient()).getPrimaryForestIds(getForestDatabaseName(appConfig)).size();
@@ -104,6 +101,42 @@ protected void createForests(String originalPayload, CommandContext context) {
104101
}
105102
}
106103

104+
/**
105+
* @param context
106+
* @param hostNames
107+
* @return
108+
*/
109+
protected List<String> determineHostNamesForForest(CommandContext context, List<String> hostNames) {
110+
Set<String> databaseNames = context.getAppConfig().getDatabasesWithForestsOnOneHost();
111+
boolean onlyOnOneHost = databaseNames != null && databaseNames.contains(this.databaseName);
112+
113+
if (!createForestsOnEachHost || onlyOnOneHost) {
114+
String first = hostNames.get(0);
115+
logger.info(format("Only creating forests on the first host: " + first));
116+
hostNames = new ArrayList<>();
117+
hostNames.add(first);
118+
return hostNames;
119+
}
120+
121+
Map<String, Set<String>> databaseHosts = context.getAppConfig().getDatabaseHosts();
122+
if (databaseHosts != null) {
123+
Set<String> selectedHostNames = databaseHosts.get(this.databaseName);
124+
if (selectedHostNames != null) {
125+
List<String> newHostNames = new ArrayList<>();
126+
for (String name : selectedHostNames) {
127+
if (hostNames.contains(name)) {
128+
newHostNames.add(name);
129+
} else {
130+
logger.warn(format("Host '%s' for database '%s' is not recognized, ignoring", name, this.databaseName));
131+
}
132+
}
133+
return newHostNames;
134+
}
135+
}
136+
137+
return hostNames;
138+
}
139+
107140
protected String getForestName(AppConfig appConfig, int forestNumber) {
108141
return databaseName + "-" + forestNumber;
109142
}

src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ public void allProperties() {
140140
p.setProperty("mlResourceFilenamesToIncludeRegex", "qa-.*");
141141

142142
p.setProperty("mlDatabaseNamesAndReplicaCounts", "Documents,1,Security,2");
143-
p.setProperty("mlDatabaseNamesWithForestsOnOneHost", "Documents,Security");
143+
p.setProperty("mlDatabasesWithForestsOnOneHost", "Documents,Security");
144+
p.setProperty("mlDatabaseHosts", "Documents,host1|host2|host3,Security,host1|host2");
144145

145146
p.setProperty("mlForestDataDirectory", "/data/path");
146147
p.setProperty("mlForestFastDataDirectory", "/fast/path");
@@ -241,11 +242,21 @@ public void allProperties() {
241242

242243
assertEquals("Documents,1,Security,2", config.getDatabaseNamesAndReplicaCounts());
243244

244-
Set<String> set = config.getDatabaseNamesWithForestsOnOneHost();
245+
Set<String> set = config.getDatabasesWithForestsOnOneHost();
245246
assertEquals(2, set.size());
246247
assertTrue(set.contains("Documents"));
247248
assertTrue(set.contains("Security"));
248249

250+
Map<String, Set<String>> databaseHosts = config.getDatabaseHosts();
251+
assertEquals(2, databaseHosts.size());
252+
assertEquals(3, databaseHosts.get("Documents").size());
253+
assertTrue(databaseHosts.get("Documents").contains("host1"));
254+
assertTrue(databaseHosts.get("Documents").contains("host2"));
255+
assertTrue(databaseHosts.get("Documents").contains("host3"));
256+
assertEquals(2, databaseHosts.get("Security").size());
257+
assertTrue(databaseHosts.get("Security").contains("host1"));
258+
assertTrue(databaseHosts.get("Security").contains("host2"));
259+
249260
assertEquals("/data/path", config.getForestDataDirectory());
250261
assertEquals("/fast/path", config.getForestFastDataDirectory());
251262
assertEquals("/large/path", config.getForestLargeDataDirectory());

src/test/java/com/marklogic/appdeployer/command/databases/CreateForestsOnOneHostTest.java

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/test/java/com/marklogic/appdeployer/command/forests/CreateForestsOnOneHostDebug.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static void main(String[] args) {
2525
AppConfig appConfig = new AppConfig();
2626
Set<String> names = new HashSet<>();
2727
names.add("testdb");
28-
appConfig.setDatabaseNamesWithForestsOnOneHost(names);
28+
appConfig.setDatabasesWithForestsOnOneHost(names);
2929
CommandContext context = new CommandContext(appConfig, manageClient, null);
3030

3131
DeployDatabaseCommand ddc = new DeployDatabaseCommand();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.appdeployer.command.CommandContext;
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import java.util.ArrayList;
9+
import java.util.HashSet;
10+
import java.util.List;
11+
import java.util.Set;
12+
13+
public class CreateForestsOnOneHostTest extends Assert {
14+
15+
@Test
16+
public void test() {
17+
AppConfig appConfig = new AppConfig();
18+
CommandContext context = new CommandContext(appConfig, null, null);
19+
20+
DeployForestsCommand command = new DeployForestsCommand();
21+
command.setDatabaseName("test-db");
22+
23+
List<String> fakeHostNames = new ArrayList<>();
24+
fakeHostNames.add("host1");
25+
fakeHostNames.add("host2");
26+
fakeHostNames.add("host3");
27+
28+
List<String> hostNames = command.determineHostNamesForForest(context, fakeHostNames);
29+
assertEquals(3, hostNames.size());
30+
31+
command.setCreateForestsOnEachHost(false);
32+
hostNames = command.determineHostNamesForForest(context, fakeHostNames);
33+
assertEquals(1, hostNames.size());
34+
assertEquals("host1", hostNames.get(0));
35+
36+
command.setCreateForestsOnEachHost(true);
37+
hostNames = command.determineHostNamesForForest(context, fakeHostNames);
38+
assertEquals(3, hostNames.size());
39+
40+
Set<String> names = new HashSet<>();
41+
names.add("test-db");
42+
appConfig.setDatabasesWithForestsOnOneHost(names);
43+
hostNames = command.determineHostNamesForForest(context, fakeHostNames);
44+
assertEquals(1, hostNames.size());
45+
}
46+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.appdeployer.DefaultAppConfigFactory;
5+
import com.marklogic.appdeployer.command.CommandContext;
6+
import com.marklogic.mgmt.util.SimplePropertySource;
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
import org.springframework.core.env.PropertiesPropertySource;
10+
11+
import java.util.*;
12+
13+
public class CreateForestsOnSpecificHostsTest extends Assert {
14+
15+
@Test
16+
public void test() {
17+
AppConfig appConfig = new AppConfig();
18+
CommandContext context = new CommandContext(appConfig, null, null);
19+
20+
DeployForestsCommand command = new DeployForestsCommand();
21+
command.setDatabaseName("test-db");
22+
23+
List<String> fakeHostNames = new ArrayList<>();
24+
fakeHostNames.add("host1");
25+
fakeHostNames.add("host2");
26+
fakeHostNames.add("host3");
27+
28+
// Verify we get all 3 hosts back when nothing special is configured
29+
List<String> hostNames = command.determineHostNamesForForest(context, fakeHostNames);
30+
assertEquals(3, hostNames.size());
31+
32+
// Select 2 of the 3 hosts for test-db
33+
Properties props = new Properties();
34+
props.setProperty("mlDatabaseHosts", "test-db,host1|host2");
35+
DefaultAppConfigFactory factory = new DefaultAppConfigFactory(new SimplePropertySource(props));
36+
appConfig = factory.newAppConfig();
37+
context = new CommandContext(appConfig, null, null);
38+
39+
hostNames = command.determineHostNamesForForest(context, fakeHostNames);
40+
assertEquals(2, hostNames.size());
41+
assertTrue(hostNames.contains("host1"));
42+
assertTrue(hostNames.contains("host2"));
43+
44+
// Select 1 of the 3 hosts, and include a bad host; the bad one should be ignored
45+
props.setProperty("mlDatabaseHosts", "some-other-db,host2,test-db,bad-host|host2");
46+
appConfig = factory.newAppConfig();
47+
context = new CommandContext(appConfig, null, null);
48+
hostNames = command.determineHostNamesForForest(context, fakeHostNames);
49+
assertEquals(1, hostNames.size());
50+
assertTrue(hostNames.contains("host2"));
51+
}
52+
}

0 commit comments

Comments
 (0)