Skip to content

Commit 8a3f4f9

Browse files
#744 - WriteBatcher hangs; #668 - White list and black list; #666 - Null host names; #579 - Job not stopped
1 parent c8266bd commit 8a3f4f9

File tree

8 files changed

+223
-33
lines changed

8 files changed

+223
-33
lines changed

src/main/java/com/marklogic/client/datamovement/FilteredForestConfiguration.java

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,18 @@
1515
*/
1616
package com.marklogic.client.datamovement;
1717

18+
import com.marklogic.client.datamovement.Forest.HostType;
19+
import com.marklogic.client.datamovement.impl.ForestConfigurationImpl;
1820
import com.marklogic.client.datamovement.impl.ForestImpl;
21+
22+
import java.util.ArrayList;
23+
import java.util.Arrays;
1924
import java.util.HashMap;
2025
import java.util.HashSet;
26+
import java.util.List;
2127
import java.util.Map;
2228
import java.util.Set;
29+
import java.util.stream.Collectors;
2330
import java.util.stream.Stream;
2431

2532
/**
@@ -71,6 +78,11 @@ public Forest[] listForests() {
7178
if ( renames.containsKey(openReplicaHost) ) {
7279
openReplicaHost = renames.get(openReplicaHost);
7380
}
81+
String requestHost = forest.getRequestHost();
82+
if ( requestHost != null ) requestHost = requestHost.toLowerCase();
83+
if ( renames.containsKey(requestHost) ) {
84+
requestHost = renames.get(requestHost);
85+
}
7486
String alternateHost = forest.getAlternateHost();
7587
if ( alternateHost != null ) alternateHost = alternateHost.toLowerCase();
7688
if ( renames.containsKey(alternateHost) ) {
@@ -81,12 +93,19 @@ public Forest[] listForests() {
8193
if ( renames.containsKey(host) ) {
8294
host = renames.get(host);
8395
}
84-
return new ForestImpl(host, openReplicaHost, alternateHost, forest.getDatabaseName(),
96+
return new ForestImpl(host, openReplicaHost, requestHost, alternateHost, forest.getDatabaseName(),
8597
forest.getForestName(), forest.getForestId(), forest.isUpdateable(), false);
8698
}).toArray(Forest[]::new);
8799

88-
String[] validHosts = Stream.of(renamedForests).flatMap( forest ->
89-
Stream.of(new String[] {forest.getHost(), forest.getOpenReplicaHost(), forest.getAlternateHost()})
100+
String[] validHosts = Stream.of(renamedForests).flatMap( forest -> {
101+
String[] hostArray;
102+
if((blackList.contains(forest.getPreferredHost()) || blackList.contains(forest.getHost()))
103+
&& forest.getPreferredHostType() == HostType.REQUEST_HOST) {
104+
hostArray = new String[] {forest.getOpenReplicaHost(), forest.getAlternateHost()};
105+
} else {
106+
hostArray = new String[] {forest.getHost(), forest.getOpenReplicaHost(), forest.getAlternateHost(), forest.getRequestHost()};
107+
}
108+
return Stream.of(hostArray)
90109
.filter( host -> host != null )
91110
.map ( host -> host.toLowerCase() )
92111
.filter( host -> {
@@ -100,13 +119,14 @@ public Forest[] listForests() {
100119
}
101120
// this host is valid, add it to the list
102121
return true;
103-
})
104-
).distinct().toArray(String[]::new);
122+
});
123+
}).distinct().toArray(String[]::new);
105124

106125
Stream<Forest> replaced = Stream.of(renamedForests);
107126
if ( blackList.size() > 0 ) {
108127
replaced = replaced.map( forest -> {
109-
if ( blackList.contains(forest.getPreferredHost()) ) {
128+
if ( blackList.contains(forest.getPreferredHost()) ||
129+
(forest.getPreferredHostType() == HostType.REQUEST_HOST && blackList.contains(forest.getHost()))) {
110130
if ( validHosts.length == 0 ) {
111131
throw new IllegalStateException("White list or black list rules are too restrictive:" +
112132
" no valid hosts are left");
@@ -117,15 +137,21 @@ public Forest[] listForests() {
117137
if ( blackList.contains(openReplicaHost) ) {
118138
openReplicaHost = replaceHost(openReplicaHost, validHosts);
119139
}
140+
String requestHost = forest.getRequestHost();
141+
String host = forest.getHost();
142+
if ( blackList.contains(requestHost) ) {
143+
requestHost = replaceHost(requestHost, validHosts);
144+
host = requestHost;
145+
}
120146
String alternateHost = forest.getAlternateHost();
121147
if ( blackList.contains(alternateHost) ) {
122148
alternateHost = replaceHost(alternateHost, validHosts);
123149
}
124-
String host = forest.getHost();
125150
if ( blackList.contains(host) ) {
126151
host = replaceHost(host, validHosts);
152+
if(requestHost != null) requestHost = host;
127153
}
128-
return new ForestImpl(host, openReplicaHost, alternateHost, forest.getDatabaseName(),
154+
return new ForestImpl(host, openReplicaHost, requestHost, alternateHost, forest.getDatabaseName(),
129155
forest.getForestName(), forest.getForestId(), forest.isUpdateable(), false);
130156
} else {
131157
return forest;
@@ -145,6 +171,10 @@ public Forest[] listForests() {
145171
if ( ! whiteList.contains(openReplicaHost) ) {
146172
openReplicaHost = replaceHost(openReplicaHost, validHosts);
147173
}
174+
String requestHost = forest.getRequestHost();
175+
if ( ! whiteList.contains(requestHost) ) {
176+
requestHost = replaceHost(requestHost, validHosts);
177+
}
148178
String alternateHost = forest.getAlternateHost();
149179
if ( ! whiteList.contains(alternateHost) ) {
150180
alternateHost = replaceHost(alternateHost, validHosts);
@@ -153,7 +183,7 @@ public Forest[] listForests() {
153183
if ( ! whiteList.contains(host) ) {
154184
host = replaceHost(host, validHosts);
155185
}
156-
return new ForestImpl(host, openReplicaHost, alternateHost, forest.getDatabaseName(),
186+
return new ForestImpl(host, openReplicaHost, requestHost, alternateHost, forest.getDatabaseName(),
157187
forest.getForestName(), forest.getForestId(), forest.isUpdateable(), false);
158188
} else {
159189
return forest;
@@ -182,6 +212,7 @@ private String replaceHost(String invalidHost, String[] validHosts) {
182212
*/
183213
public FilteredForestConfiguration withBlackList(String... hostNames) {
184214
if ( whiteList.size() > 0 ) throw new IllegalStateException("whiteList already initialized");
215+
if ( hostNames == null ) throw new IllegalArgumentException("hostNames must not be null");
185216
for ( String hostName : hostNames ) {
186217
if ( hostName != null ) blackList.add(hostName.toLowerCase());
187218
}
@@ -198,6 +229,7 @@ public FilteredForestConfiguration withBlackList(String... hostNames) {
198229
*/
199230
public FilteredForestConfiguration withWhiteList(String... hostNames) {
200231
if ( blackList.size() > 0 ) throw new IllegalStateException("blackList already initialized");
232+
if ( hostNames == null ) throw new IllegalArgumentException("hostNames must not be null");
201233
for ( String hostName : hostNames ) {
202234
if ( hostName != null ) whiteList.add(hostName.toLowerCase());
203235
}

src/main/java/com/marklogic/client/datamovement/Forest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public interface Forest {
6060
*/
6161
String getAlternateHost();
6262

63+
/** The request host name associated with the forest in the MarkLogic server.
64+
* The host name with which we have created the client - host name on the
65+
* request header.
66+
*
67+
* @return the host name of the request host in the MarkLogic server
68+
*/
69+
String getRequestHost();
70+
6371
/** Whether or not this forest is updateable.
6472
*
6573
* @return whether or not this forest is updateable
@@ -69,7 +77,8 @@ public interface Forest {
6977
/**
7078
* Returns the host your application should talk to for this forest. If
7179
* getAlternateHost() is not null, return it. Otherwise, if
72-
* getOpenReplicaHost() is not null, return it. Otherwise, return getHost().
80+
* getOpenReplicaHost() is not null, return it. Otherwise, if
81+
* getRequestHost() is not null, return it. Otherwise, return getHost().
7382
*
7483
* @return the preferred host for this forest
7584
*/
@@ -78,8 +87,48 @@ public default String getPreferredHost() {
7887
return getAlternateHost();
7988
} else if ( getOpenReplicaHost() != null ) {
8089
return getOpenReplicaHost();
90+
} else if ( getRequestHost() != null ) {
91+
return getRequestHost();
8192
} else {
8293
return getHost();
8394
}
8495
}
96+
97+
/**
98+
* Enum containing the list of host types a forest can have.
99+
*
100+
* FOREST_HOST - host type indicating the host associated with
101+
* the forest in the MarkLogic server
102+
*
103+
* REQUEST_HOST - host type indicating the request host with which
104+
* we have created the client - host on the request header.
105+
*
106+
* ALTERNATE_HOST - host type indicating the alternate host of the forest -
107+
* the host of the e - node when this forest belongs to an d - node.
108+
*
109+
* OPEN_REPLICA_HOST - host type indicating the replica host associated
110+
* with the forest in the MarkLogic server
111+
*/
112+
enum HostType { FOREST_HOST, REQUEST_HOST, ALTERNATE_HOST, OPEN_REPLICA_HOST };
113+
114+
/**
115+
* Returns the preferred host type for this forest. If
116+
* getAlternateHost() is not null, return ALTERNATE_HOST. Otherwise, if
117+
* getOpenReplicaHost() is not null, return OPEN_REPLICA_HOST. Otherwise,
118+
* if getRequestHost() is not null, return REQUEST_HOST.
119+
* Otherwise, return FOREST_HOST.
120+
*
121+
* @return the host type of the forest
122+
*/
123+
public default HostType getPreferredHostType() {
124+
if ( getAlternateHost() != null ) {
125+
return HostType.ALTERNATE_HOST;
126+
} else if ( getOpenReplicaHost() != null ) {
127+
return HostType.OPEN_REPLICA_HOST;
128+
} else if ( getRequestHost() != null ) {
129+
return HostType.REQUEST_HOST;
130+
} else {
131+
return HostType.FOREST_HOST;
132+
}
133+
}
85134
}

src/main/java/com/marklogic/client/datamovement/HostAvailabilityListener.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import org.slf4j.Logger;
1919
import org.slf4j.LoggerFactory;
2020

21+
import com.marklogic.client.datamovement.Forest.HostType;
22+
2123
import java.net.SocketException;
2224
import java.net.UnknownHostException;
2325
import javax.net.ssl.SSLException;
@@ -189,7 +191,19 @@ private synchronized boolean processException(Batcher batcher, Throwable throwab
189191
boolean shouldWeRetry = isHostUnavailableException;
190192
if ( isHostUnavailableException == true ) {
191193
ForestConfiguration existingForestConfig = batcher.getForestConfig();
192-
String[] preferredHosts = existingForestConfig.getPreferredHosts();
194+
Set<String> preferredHostsList = new HashSet<String>(Arrays.asList(existingForestConfig.getPreferredHosts()));
195+
if(existingForestConfig instanceof FilteredForestConfiguration) {
196+
FilteredForestConfiguration existingFilteredForestConfiguration = (FilteredForestConfiguration) existingForestConfig;
197+
for( Forest forest : existingFilteredForestConfiguration.listForests()) {
198+
if(forest.getPreferredHostType() == HostType.REQUEST_HOST
199+
&& !forest.getHost().toLowerCase().equals(forest.getRequestHost().toLowerCase())) {
200+
if(preferredHostsList.contains(forest.getHost())) {
201+
preferredHostsList.remove(forest.getHost());
202+
}
203+
}
204+
}
205+
}
206+
String[] preferredHosts = preferredHostsList.toArray(new String[preferredHostsList.size()]);
193207
if ( ! Arrays.asList(preferredHosts).contains(host) ) {
194208
// skip all the logic below because the host in question here is already
195209
// missing from the list of hosts for this batcher

src/main/java/com/marklogic/client/datamovement/impl/DataMovementManagerImpl.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,7 @@ public ForestConfiguration readForestConfig() {
169169

170170
public DatabaseClient getForestClient(Forest forest) {
171171
if ( forest == null ) throw new IllegalArgumentException("forest must not be null");
172-
String hostName = forest.getHost();
173-
if ( forest.getOpenReplicaHost() != null ) {
174-
hostName = forest.getOpenReplicaHost();
175-
} else if ( forest.getAlternateHost() != null ) {
176-
hostName = forest.getAlternateHost();
177-
}
172+
String hostName = forest.getPreferredHost();
178173
String key = hostName;
179174
DatabaseClient client = clientMap.get(key);
180175
if ( client != null ) return client;

src/main/java/com/marklogic/client/datamovement/impl/DataMovementServices.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,18 @@ public ForestConfigurationImpl readForestConfig() {
5757
String host = forestNode.get("host").asText();
5858
String openReplicaHost = null;
5959
if ( forestNode.get("openReplicaHost") != null ) openReplicaHost = forestNode.get("openReplicaHost").asText();
60+
String requestHost = null;
61+
if ( forestNode.get("requestHost") != null ) requestHost = forestNode.get("requestHost").asText();
6062
String alternateHost = null;
6163
if ( forestNode.get("alternateHost") != null ) alternateHost = forestNode.get("alternateHost").asText();
64+
// Since we added the forestinfo end point to populate both alternateHost and requestHost
65+
// in case we have a requestHost so that we don't break the existing API code, we will make the
66+
// alternateHost as null if both alternateHost and requestHost is set.
67+
if ( requestHost != null && alternateHost != null )
68+
alternateHost = null;
6269
boolean isUpdateable = "all".equals(forestNode.get("updatesAllowed").asText());
6370
boolean isDeleteOnly = false; // TODO: get this for real after we start using a REST endpoint
64-
forests.add(new ForestImpl(host, alternateHost, openReplicaHost, database, name, id, isUpdateable, isDeleteOnly));
71+
forests.add(new ForestImpl(host, openReplicaHost, requestHost, alternateHost, database, name, id, isUpdateable, isDeleteOnly));
6572
}
6673

6774
return new ForestConfigurationImpl(forests.toArray(new ForestImpl[forests.size()]));

src/main/java/com/marklogic/client/datamovement/impl/ForestImpl.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,20 @@ public class ForestImpl implements Forest {
2121
private String host;
2222
private String openReplicaHost;
2323
private String alternateHost;
24+
private String requestHost;
2425
private String databaseName;
2526
private String forestName;
2627
private String forestId;
2728
private boolean isUpdateable;
2829
private boolean isDeleteOnly;
2930

30-
public ForestImpl(String host, String openReplicaHost, String alternateHost, String databaseName,
31+
public ForestImpl(String host, String openReplicaHost, String requestHost, String alternateHost, String databaseName,
3132
String forestName, String forestId, boolean isUpdateable, boolean isDeleteOnly)
3233
{
3334
this.host = host;
3435
this.openReplicaHost = openReplicaHost;
3536
this.alternateHost = alternateHost;
37+
this.requestHost = requestHost;
3638
this.databaseName = databaseName;
3739
this.forestName = forestName;
3840
this.forestId = forestId;
@@ -67,6 +69,15 @@ public void setAlternateHost(String alternateHost) {
6769
this.alternateHost = alternateHost;
6870
}
6971

72+
@Override
73+
public String getRequestHost() {
74+
return requestHost;
75+
}
76+
77+
public void setRequestHost(String requestHost) {
78+
this.requestHost = requestHost;
79+
}
80+
7081
@Override
7182
public String getDatabaseName() {
7283
return databaseName;

0 commit comments

Comments
 (0)