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

Commit 2d0dece

Browse files
author
Dave Cassel
committed
#424 distribute replica forests evenly
1 parent fd5f4f8 commit 2d0dece

File tree

5 files changed

+259
-103
lines changed

5 files changed

+259
-103
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.mgmt.api.forest.Forest;
5+
import com.marklogic.mgmt.api.forest.ForestReplica;
6+
7+
import java.util.ArrayList;
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
public class DistributedReplicaBuilderStrategy extends ReplicaBuilderStrategy {
13+
14+
/**
15+
* Distributes the replicas throughout the cluster.
16+
*/
17+
public void buildReplicas(List<Forest> forests, ForestPlan forestPlan, AppConfig appConfig,
18+
List<String> dataDirectories, ForestNamingStrategy fns)
19+
{
20+
final String databaseName = forestPlan.getDatabaseName();
21+
final List<String> hostNames = forestPlan.getHostNames();
22+
final int replicaCount = forestPlan.getReplicaCount();
23+
24+
if (appConfig.getReplicaForestDataDirectory() != null) {
25+
dataDirectories = new ArrayList<>();
26+
dataDirectories.add(appConfig.getReplicaForestDataDirectory());
27+
}
28+
Map<String, String> replicaDataDirectoryMap = appConfig.getDatabaseReplicaDataDirectories();
29+
if (replicaDataDirectoryMap != null && replicaDataDirectoryMap.containsKey(databaseName)) {
30+
dataDirectories = new ArrayList<>();
31+
dataDirectories.add(replicaDataDirectoryMap.get(databaseName));
32+
}
33+
34+
HashMap<String, List<Forest>> hostToForests = new HashMap<String, List<Forest>>();
35+
36+
for (Forest f : forests) {
37+
String host = f.getHost();
38+
if (hostToForests.containsKey(host)) {
39+
hostToForests.get(host).add(f);
40+
}
41+
else {
42+
ArrayList<Forest> hostForests = new ArrayList<Forest>();
43+
hostForests.add(f);
44+
hostToForests.put(host, hostForests);
45+
}
46+
}
47+
48+
for (String host : hostToForests.keySet()) {
49+
50+
// availableHosts will be the hosts that we can put a forest's replicas on, which excludes the host where
51+
// the forest lives. We also want to have the hosts in different order as we assign replicas to hosts, so
52+
// that we don't overload any of them. So if we have five hosts, and we're looking to build replicas for
53+
// the forests on host 2, this list will be [host3, host4, host5, host1].
54+
List<String> availableHosts = new ArrayList<String>();
55+
int hostIndex = hostNames.indexOf(host);
56+
if (hostIndex != -1 && hostIndex < hostNames.size()) {
57+
availableHosts.addAll(hostNames.subList(hostIndex + 1, hostNames.size()));
58+
}
59+
availableHosts.addAll(hostNames.subList(0, hostIndex));
60+
61+
int hostPointer = 0;
62+
63+
for (Forest currForest : hostToForests.get(host)) {
64+
List<ForestReplica> replicas = new ArrayList<>();
65+
int dataDirectoryPointer = dataDirectories.indexOf(currForest.getDataDirectory());
66+
67+
for (int i = 1; i <= replicaCount; i++) {
68+
ForestReplica replica = new ForestReplica();
69+
replica.setReplicaName(fns.getReplicaName(databaseName, currForest.getForestName(), i, appConfig));
70+
replicas.add(replica);
71+
72+
int replicaHostPointer = hostPointer + i - 1;
73+
if (replicaHostPointer == availableHosts.size()) {
74+
replicaHostPointer = 0;
75+
}
76+
77+
replica.setHost(availableHosts.get(replicaHostPointer));
78+
79+
dataDirectoryPointer++;
80+
if (dataDirectoryPointer == dataDirectories.size()) {
81+
dataDirectoryPointer = 0;
82+
}
83+
84+
final String dataDir = dataDirectories.get(dataDirectoryPointer);
85+
if (dataDir != null && dataDir.trim().length() > 0) {
86+
replica.setDataDirectory(dataDir);
87+
}
88+
89+
configureReplica(replica, databaseName, appConfig);
90+
}
91+
92+
currForest.setForestReplica(replicas);
93+
94+
++hostPointer;
95+
96+
if (hostPointer == availableHosts.size()) {
97+
hostPointer = 0;
98+
}
99+
100+
}
101+
}
102+
103+
}
104+
}

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

Lines changed: 9 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,20 @@
1919
public class ForestBuilder extends LoggingObject {
2020

2121
private ForestNamingStrategy forestNamingStrategy;
22+
private ReplicaBuilderStrategy replicaBuilderStrategy;
2223

2324
public ForestBuilder() {
2425
this(new DefaultForestNamingStrategy());
2526
}
2627

2728
public ForestBuilder(ForestNamingStrategy forestNamingStrategy) {
2829
this.forestNamingStrategy = forestNamingStrategy;
30+
this.replicaBuilderStrategy = new DistributedReplicaBuilderStrategy();
31+
}
32+
33+
public ForestBuilder(ForestNamingStrategy forestNamingStrategy, ReplicaBuilderStrategy replicaBuilderStrategy) {
34+
this.forestNamingStrategy = forestNamingStrategy;
35+
this.replicaBuilderStrategy = replicaBuilderStrategy;
2936
}
3037

3138
/**
@@ -122,98 +129,12 @@ public void addReplicasToForests(List<Forest> forests, ForestPlan forestPlan, Ap
122129
replicaCount, databaseName, hostNames));
123130
}
124131

125-
List<String> dataDirectories = determineDataDirectories(forestPlan.getDatabaseName(), appConfig);
126-
127-
if (appConfig.getReplicaForestDataDirectory() != null) {
128-
dataDirectories = new ArrayList<>();
129-
dataDirectories.add(appConfig.getReplicaForestDataDirectory());
130-
}
131-
Map<String, String> replicaDataDirectoryMap = appConfig.getDatabaseReplicaDataDirectories();
132-
if (replicaDataDirectoryMap != null && replicaDataDirectoryMap.containsKey(databaseName)) {
133-
dataDirectories = new ArrayList<>();
134-
dataDirectories.add(replicaDataDirectoryMap.get(databaseName));
135-
}
136-
137-
for (Forest f : forests) {
138-
List<ForestReplica> replicas = new ArrayList<>();
139-
int hostPointer = hostNames.indexOf(f.getHost());
140-
int dataDirectoryPointer = dataDirectories.indexOf(f.getDataDirectory());
141-
for (int i = 1; i <= replicaCount; i++) {
142-
ForestReplica replica = new ForestReplica();
143-
replica.setReplicaName(getForestReplicaName(databaseName, f.getForestName(), i, appConfig));
144-
replicas.add(replica);
145-
146-
hostPointer++;
147-
if (hostPointer == hostNames.size()) {
148-
hostPointer = 0;
149-
}
150-
151-
dataDirectoryPointer++;
152-
if (dataDirectoryPointer == dataDirectories.size()) {
153-
dataDirectoryPointer = 0;
154-
}
155-
156-
replica.setHost(hostNames.get(hostPointer));
157-
158-
final String dataDir = dataDirectories.get(dataDirectoryPointer);
159-
if (dataDir != null && dataDir.trim().length() > 0) {
160-
replica.setDataDirectory(dataDir);
161-
}
162-
163-
configureReplica(replica, databaseName, appConfig);
164-
}
165-
166-
f.setForestReplica(replicas);
167-
}
168-
}
169-
170-
/**
171-
* Configures the fast and large data directories for a replica based on what's in AppConfig for the given
172-
* database.
173-
*
174-
* @param replica
175-
* @param databaseName
176-
* @param appConfig
177-
*/
178-
protected void configureReplica(ForestReplica replica, String databaseName, AppConfig appConfig) {
179-
// First set to the database-agnostic forest directories
180-
replica.setFastDataDirectory(appConfig.getForestFastDataDirectory());
181-
replica.setLargeDataDirectory(appConfig.getForestLargeDataDirectory());
182-
183-
// Now set to the database-specific forest directories if set
184-
if (databaseName != null) {
185-
Map<String, String> map = appConfig.getDatabaseFastDataDirectories();
186-
if (map != null && map.containsKey(databaseName)) {
187-
replica.setFastDataDirectory(map.get(databaseName));
188-
}
189-
map = appConfig.getDatabaseLargeDataDirectories();
190-
if (map != null && map.containsKey(databaseName)) {
191-
replica.setLargeDataDirectory(map.get(databaseName));
192-
}
193-
}
132+
List<String> dataDirectories = determineDataDirectories(databaseName, appConfig);
194133

195-
// Now set to the replica forest directories if set
196-
if (appConfig.getReplicaForestFastDataDirectory() != null) {
197-
replica.setFastDataDirectory(appConfig.getReplicaForestFastDataDirectory());
198-
}
199-
if (appConfig.getReplicaForestLargeDataDirectory() != null) {
200-
replica.setLargeDataDirectory(appConfig.getReplicaForestLargeDataDirectory());
201-
}
134+
replicaBuilderStrategy.buildReplicas(forests, forestPlan, appConfig, dataDirectories, determineForestNamingStrategy(databaseName, appConfig));
202135

203-
// And now set to the database-specific replica forest directories if set
204-
if (databaseName != null) {
205-
Map<String, String> map = appConfig.getDatabaseReplicaFastDataDirectories();
206-
if (map != null && map.containsKey(databaseName)) {
207-
replica.setFastDataDirectory(map.get(databaseName));
208-
}
209-
map = appConfig.getDatabaseReplicaLargeDataDirectories();
210-
if (map != null && map.containsKey(databaseName)) {
211-
replica.setLargeDataDirectory(map.get(databaseName));
212-
}
213-
}
214136
}
215137

216-
217138
protected Forest newForest(ForestPlan forestPlan) {
218139
String template = forestPlan.getTemplate();
219140
if (template == null) {
@@ -288,18 +209,6 @@ protected String getForestName(String databaseName, int forestNumber, AppConfig
288209
return determineForestNamingStrategy(databaseName, appConfig).getForestName(databaseName, forestNumber, appConfig);
289210
}
290211

291-
/**
292-
*
293-
* @param databaseName
294-
* @param forestName
295-
* @param forestReplicaNumber
296-
* @param appConfig
297-
* @return
298-
*/
299-
protected String getForestReplicaName(String databaseName, String forestName, int forestReplicaNumber, AppConfig appConfig) {
300-
return determineForestNamingStrategy(databaseName, appConfig).getReplicaName(databaseName, forestName, forestReplicaNumber, appConfig);
301-
}
302-
303212
/**
304213
*
305214
* @param databaseName
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.mgmt.api.forest.Forest;
5+
import com.marklogic.mgmt.api.forest.ForestReplica;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Map;
10+
11+
public class GroupedReplicaBuilderStrategy extends ReplicaBuilderStrategy {
12+
13+
/**
14+
* This is the original ReplicaBuilderStrategy. The first replica for forest n on host h will be on host
15+
* (h+1)%hostCount.
16+
*/
17+
public void buildReplicas(List<Forest> forests, ForestPlan forestPlan, AppConfig appConfig,
18+
List<String> dataDirectories, ForestNamingStrategy fns)
19+
{
20+
final String databaseName = forestPlan.getDatabaseName();
21+
final List<String> hostNames = forestPlan.getHostNames();
22+
final int replicaCount = forestPlan.getReplicaCount();
23+
24+
if (appConfig.getReplicaForestDataDirectory() != null) {
25+
dataDirectories = new ArrayList<>();
26+
dataDirectories.add(appConfig.getReplicaForestDataDirectory());
27+
}
28+
Map<String, String> replicaDataDirectoryMap = appConfig.getDatabaseReplicaDataDirectories();
29+
if (replicaDataDirectoryMap != null && replicaDataDirectoryMap.containsKey(databaseName)) {
30+
dataDirectories = new ArrayList<>();
31+
dataDirectories.add(replicaDataDirectoryMap.get(databaseName));
32+
}
33+
34+
for (Forest f : forests) {
35+
List<ForestReplica> replicas = new ArrayList<>();
36+
int hostPointer = hostNames.indexOf(f.getHost());
37+
int dataDirectoryPointer = dataDirectories.indexOf(f.getDataDirectory());
38+
for (int i = 1; i <= replicaCount; i++) {
39+
ForestReplica replica = new ForestReplica();
40+
replica.setReplicaName(fns.getReplicaName(databaseName, f.getForestName(), i, appConfig));
41+
replicas.add(replica);
42+
43+
hostPointer++;
44+
if (hostPointer == hostNames.size()) {
45+
hostPointer = 0;
46+
}
47+
48+
dataDirectoryPointer++;
49+
if (dataDirectoryPointer == dataDirectories.size()) {
50+
dataDirectoryPointer = 0;
51+
}
52+
53+
replica.setHost(hostNames.get(hostPointer));
54+
55+
final String dataDir = dataDirectories.get(dataDirectoryPointer);
56+
if (dataDir != null && dataDir.trim().length() > 0) {
57+
replica.setDataDirectory(dataDir);
58+
}
59+
60+
configureReplica(replica, databaseName, appConfig);
61+
}
62+
63+
f.setForestReplica(replicas);
64+
}
65+
66+
}
67+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.mgmt.api.forest.Forest;
5+
import com.marklogic.mgmt.api.forest.ForestReplica;
6+
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
public abstract class ReplicaBuilderStrategy {
11+
12+
public abstract void buildReplicas(List<Forest> forests, ForestPlan forestPlan, AppConfig appConfig,
13+
List<String> dataDirectories, ForestNamingStrategy fns);
14+
15+
/**
16+
* Configures the fast and large data directories for a replica based on what's in AppConfig for the given
17+
* database.
18+
*
19+
* @param replica
20+
* @param databaseName
21+
* @param appConfig
22+
*/
23+
protected void configureReplica(ForestReplica replica, String databaseName, AppConfig appConfig) {
24+
// First set to the database-agnostic forest directories
25+
replica.setFastDataDirectory(appConfig.getForestFastDataDirectory());
26+
replica.setLargeDataDirectory(appConfig.getForestLargeDataDirectory());
27+
28+
// Now set to the database-specific forest directories if set
29+
if (databaseName != null) {
30+
Map<String, String> map = appConfig.getDatabaseFastDataDirectories();
31+
if (map != null && map.containsKey(databaseName)) {
32+
replica.setFastDataDirectory(map.get(databaseName));
33+
}
34+
map = appConfig.getDatabaseLargeDataDirectories();
35+
if (map != null && map.containsKey(databaseName)) {
36+
replica.setLargeDataDirectory(map.get(databaseName));
37+
}
38+
}
39+
40+
// Now set to the replica forest directories if set
41+
if (appConfig.getReplicaForestFastDataDirectory() != null) {
42+
replica.setFastDataDirectory(appConfig.getReplicaForestFastDataDirectory());
43+
}
44+
if (appConfig.getReplicaForestLargeDataDirectory() != null) {
45+
replica.setLargeDataDirectory(appConfig.getReplicaForestLargeDataDirectory());
46+
}
47+
48+
// And now set to the database-specific replica forest directories if set
49+
if (databaseName != null) {
50+
Map<String, String> map = appConfig.getDatabaseReplicaFastDataDirectories();
51+
if (map != null && map.containsKey(databaseName)) {
52+
replica.setFastDataDirectory(map.get(databaseName));
53+
}
54+
map = appConfig.getDatabaseReplicaLargeDataDirectories();
55+
if (map != null && map.containsKey(databaseName)) {
56+
replica.setLargeDataDirectory(map.get(databaseName));
57+
}
58+
}
59+
}
60+
61+
62+
}

0 commit comments

Comments
 (0)