private ElasticSearchManager(String sIndexName, String sIndexType, boolean bRemote, String hostAndPort,
Builder settings, String sMapping) {
// (0. cluster management)
PropertiesManager properties = new PropertiesManager();
if (null == _clusterName) {
try {
_clusterName = properties.getElasticCluster();
if (null == _clusterName) {
_clusterName = _defaultClusterName;
}
}
catch (Exception e) {
_clusterName = _defaultClusterName;
}
}
// 1. Link to client (or cluster)
if (_bLocalMode) {
NodeBuilder nBuilder = NodeBuilder.nodeBuilder().local(true);
if (null == _elasticClient) {
_elasticClient = new CrossVersionClient(nBuilder.node().client());
}
}
else if (bRemote) {
if (null == _elasticClient) {
String sHostname = null;
String sPort = null;
if (null == hostAndPort) {
hostAndPort = new PropertiesManager().getElasticUrl();
}
String[] hostPort = hostAndPort.split("[:/]");
sHostname = hostPort[0];
sPort = hostPort[1];
Builder globalSettings = ImmutableSettings.settingsBuilder();
Settings snode = globalSettings.put("cluster.name", _clusterName).build();
TransportClient tmp = new TransportClient(snode);
_elasticClient = new CrossVersionClient(tmp.addTransportAddress(new InetSocketTransportAddress(sHostname, Integer.parseInt(sPort))));
}
} //TESTED
else { // Create a "no data" cluster
if (null == _elasticClient) {
Builder globalSettings = ImmutableSettings.settingsBuilder();
Settings snode = globalSettings.put("cluster.name", _clusterName).build();
NodeBuilder nBuilder = NodeBuilder.nodeBuilder().settings(snode);
nBuilder.data(false); // Don't store your own data
_elasticClient = new CrossVersionClient(nBuilder.build().start().client());
}
}//TOTEST
_sIndexName = sIndexName;
_sIndexType = sIndexType;
// 2. Create the index if necessary
if (null != settings) { // Need to create the index
for (int i = 0; i < 10; i++) { // retry up to 10 times if NoNodeAvailableException found
try {
CreateIndexRequest cir = new CreateIndexRequest(_sIndexName);
String sCachePolicy = properties.getElasticCachePolicy();
if (null != sCachePolicy) {
settings.put("index.cache.field.type", sCachePolicy);
}
if (null != sMapping) {
cir.mapping(_sIndexType, sMapping);
}
cir.settings(settings.build());
_elasticClient.admin().indices().create(cir).actionGet();
//(Wait for above operation to be completed)
_elasticClient.admin().cluster().health(new ClusterHealthRequest(_sIndexName).waitForYellowStatus()).actionGet();
break;
}
catch (NoNodeAvailableException e) {
// Strange NoNodeAvailableException error I see intermittently on t1.micro
// Sleep and try again I guess?
if (9 == i) {
throw new RuntimeException("elasticsearch.NoNodeAvailableException1: " + _sIndexName + "/" + _clusterName + "/" + hostAndPort);
}
try {
Thread.sleep(1500);
}
catch (Exception e2) {} // (ignore)
}
catch (IndexCreationException e) {
if (e.getRootCause() instanceof IllegalArgumentException) {
// (probably the mapping is invalid)
throw new RuntimeException(e.getMessage());
}
// (probably just exists)
break;
}
catch (Exception e) {
// Fine, index probably just exists
break;
}
} // (end retry loop)
} //TESTED - normal NOT clustered
// Either check index exists or wait for above operation to be completed
for (int i = 0; i < 10; i++) { // retry up to 10 times if NoNodeAvailableException found
try {
_elasticClient.admin().cluster().health(new ClusterHealthRequest(_sIndexName).waitForYellowStatus()).actionGet();
break;
}
catch (NoNodeAvailableException e) {
// Strange NoNodeAvailableException error I see intermittently on t1.micro
// Sleep and try again I guess?
if (9 == i) {
throw new RuntimeException("elasticsearch.NoNodeAvailableException2: " + _sIndexName + "/" + _clusterName + "/" + hostAndPort);
}
try {
Thread.sleep(1500);
}
catch (Exception e2) {} // (ignore)
}
} // (end retry loop)
//TESTED - throws a horrible slow exception, but does fail
// 3. Sort out replication, if necessary
// First time through, check the replication factor is correct...
ClusterHealthResponse health =
_elasticClient.admin().cluster().health(new ClusterHealthRequest(sIndexName)).actionGet();
ClusterIndexHealth indexStatus = health.getIndices().get(sIndexName);
if ((null != indexStatus) && (1 == indexStatus.getShards().size())) { // 1 shard => this is a "data local" index
int nNumNodes = health.getNumberOfDataNodes();
Builder localSettings = ImmutableSettings.settingsBuilder();
if (nNumNodes > 1) {
localSettings.put("number_of_replicas", nNumNodes - 1); // (ie shard=1 + replicas==num_nodes)
}
else {
localSettings.put("number_of_replicas", 1); // (System doesn't work very well if has no replicas?)
}
UpdateSettingsUtils.updateSettings(_elasticClient.admin().indices(), sIndexName, localSettings.build());
//(Wait for above operation to be completed)
_elasticClient.admin().cluster().health(new ClusterHealthRequest(sIndexName).waitForYellowStatus()).actionGet();
}
else if ((null != indexStatus) && (indexStatus.getNumberOfReplicas() > 1)) { // Multi shard index, just need to check there aren't too many replicas for nodes
int nNumNodes = health.getNumberOfDataNodes();
int nReplicas = indexStatus.getNumberOfReplicas();
int nNodesPerReplica = properties.getElasticNodesPerReplica();
if ((nNumNodes > 0) && (nNodesPerReplica > 0)) {
int nNewReplicas = (nNumNodes + nNodesPerReplica-1)/nNodesPerReplica;
// (ie round up)
int nMaxReplicas = properties.getElasticMaxReplicas();
if (nNewReplicas > nMaxReplicas) {
nNewReplicas = nMaxReplicas;
}
if (nNewReplicas != nReplicas) { // Change the number of replicas