package org.xbib.elasticsearch.util;
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequest;
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
import org.elasticsearch.client.support.AbstractClient;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.node.MockNode;
import org.elasticsearch.node.Node;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.TransportInfo;
import org.testng.Assert;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
public class NodeTestUtils extends Assert {
protected final static ESLogger logger = ESLoggerFactory.getLogger("test");
private Map<String, Node> nodes = new HashMap<>();
private Map<String, AbstractClient> clients = new HashMap<>();
// note, this must be same name as in json specs
protected final String index = "my_index";
protected final String type = "my_type";
private List<String> hosts;
public void startNodes() {
try {
startNode("1");
findNodeAddresses();
logger.info("ready");
} catch (Throwable t) {
logger.error("startNodes failed", t);
}
}
public void stopNodes() {
try {
closeNodes();
} catch (Exception e) {
logger.error("can not close nodes", e);
} finally {
try {
deleteFiles();
logger.info("data files wiped");
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
protected String[] getHosts() {
return hosts != null ? hosts.toArray(new String[hosts.size()]) : new String[]{};
}
protected Settings getNodeSettings() {
return settingsBuilder()
.put("cluster.name", "elasticsearch")
.put("http.enabled", false)
.put("index.number_of_replicas", 0)
.put("path.home", getHome())
.build();
}
protected String getHome() {
return System.getProperty("path.home");
}
public void startNode(String id) throws IOException {
buildNode(id).start();
}
public AbstractClient client(String id) {
return clients.get(id);
}
private void closeNodes() throws IOException {
logger.info("closing all clients");
for (AbstractClient client : clients.values()) {
client.close();
}
clients.clear();
logger.info("closing all nodes");
for (Node node : nodes.values()) {
if (node != null) {
node.close();
}
}
nodes.clear();
logger.info("all nodes closed");
}
protected void findNodeAddresses() {
NodesInfoRequest nodesInfoRequest = new NodesInfoRequest().transport(true);
NodesInfoResponse response = client("1").admin().cluster().nodesInfo(nodesInfoRequest).actionGet();
Iterator<NodeInfo> it = response.iterator();
hosts = new LinkedList<>();
hosts = new LinkedList<>();
while (it.hasNext()) {
NodeInfo nodeInfo = it.next();
TransportInfo transportInfo = nodeInfo.getTransport();
TransportAddress address = transportInfo.getAddress().publishAddress();
if (address instanceof InetSocketTransportAddress) {
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) address;
hosts.add(inetSocketTransportAddress.address().getHostName() + ":" + inetSocketTransportAddress.address().getPort());
}
}
}
private Node buildNode(String id) throws IOException {
Settings nodeSettings = settingsBuilder()
.put(getNodeSettings())
.put("name", id)
.build();
logger.info("settings={}", nodeSettings.getAsMap());
Node node = new MockNode(nodeSettings);
AbstractClient client = (AbstractClient)node.client();
nodes.put(id, node);
clients.put(id, client);
logger.info("clients={}", clients);
return node;
}
private static void deleteFiles() throws IOException {
Path directory = Paths.get(System.getProperty("path.home") + "/data");
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
protected void assertHits(String id, int expectedHits) {
client(id).admin().indices().prepareRefresh(index).execute().actionGet();
long hitsFound = client(id).prepareSearch(index).setTypes(type).execute().actionGet().getHits().getTotalHits();
logger.info("{}/{} = {} hits", index, type, hitsFound);
assertEquals(hitsFound, expectedHits);
}
protected void assertTimestampSort(String id, int expectedHits) {
client(id).admin().indices().prepareRefresh(index).execute().actionGet();
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
SortBuilder sortBuilder = SortBuilders.fieldSort("_timestamp").order(SortOrder.DESC);
SearchHits hits = client(id).prepareSearch(index).setTypes(type)
.setQuery(queryBuilder)
.addSort(sortBuilder)
.addFields("_source", "_timestamp")
.setSize(expectedHits)
.execute().actionGet().getHits();
Long prev = Long.MAX_VALUE;
for (SearchHit hit : hits) {
if (hit.getFields().get("_timestamp") == null) {
logger.warn("type mapping was not correctly applied for _timestamp field");
}
Long curr = hit.getFields().get("_timestamp").getValue();
logger.info("timestamp = {}", curr);
assertTrue(curr <= prev);
prev = curr;
}
logger.info("{}/{} = {} hits", index, type, hits.getTotalHits());
assertEquals(hits.getTotalHits(), expectedHits);
}
}