/* Copyright 1995-2015 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. For additional information, contact: Environmental Systems Research Institute, Inc. Attn: Contracts Dept 380 New York Street Redlands, California, USA 92373 email: contracts@esri.com */ package com.esri.geoevent.test.performance.db.elasticsearch; import java.io.IOException; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import com.esri.geoevent.test.performance.db.DBClient; import com.esri.geoevent.test.performance.db.DBResult; public class ElasticSearchClient implements DBClient { // member vars private String indexName; private String indexType; private String fieldName = "_timestamp"; private int numOfNodes = 1; // setup the cluster private Client client; @SuppressWarnings("resource") public ElasticSearchClient(String hostName, String clusterName, String indexName, String indexType, int numOfNodes) { this.indexName = indexName; this.indexType = indexType; this.numOfNodes = numOfNodes; // TODO: Fixed the hard coding of the port number Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", clusterName).build(); this.client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress(hostName, 9300)); } @Override public void close() throws IOException { client.close(); } @Override public void createSchema() { if (numOfNodes > 1) { for (int i = 1; i <= numOfNodes; i++) { addSchema(i); } } else { addSchema(0); } } private void addSchema(int iter) { String indexIter = ""; if (iter > 0) { indexIter += iter; } String mappingJSON = "{\"" + indexType + "\":{\"_timestamp\":{\"enabled\":true,\"store\":true,\"index\":\"not_analyzed\"},\"_all\":{\"enabled\":false},\"properties\":{\"trackId\":{\"type\":\"string\"},\"timestamp\":{\"type\":\"date\"},\"speed\":{\"type\":\"float\",\"index\":\"no\"}}}}"; CreateIndexRequestBuilder builder = client.admin().indices().prepareCreate(indexName + indexIter); builder.addMapping(indexType, mappingJSON); //builder.setSettings("index.number_of_shards", 1); //builder.setSettings("index.number_of_replicas", 0); //builder.setSettings("refresh_interval", "120s"); builder.setSettings("index.store.type", "memory"); CreateIndexResponse createResponse = builder.execute().actionGet(); if (!createResponse.isAcknowledged()) { System.err.println("Index was not created!"); } } @Override public void truncate() { IndicesExistsResponse indicesExistsResponse = client.admin().indices().prepareExists(indexName + "*").execute().actionGet(); if (indicesExistsResponse.isExists()) { DeleteIndexResponse response = client.admin().indices().prepareDelete(indexName + "*").execute().actionGet(); if (!response.isAcknowledged()) { System.err.println("Index wasn't deleted"); } } } @Override public DBResult queryForLastWriteTimes() { SearchResponse response = client.prepareSearch(indexName + "*") .setTypes(indexType) .setQuery(QueryBuilders.matchAllQuery()) .addFields(fieldName) .setFrom(0) .setSize(Integer.MAX_VALUE) .execute().actionGet(); List<SearchHit> hits = Arrays.asList(response.getHits().getHits()); // sort all of the rows accordingly hits.sort(new RowComparator()); // gather the information we need int totalCount = hits.size(); long startTime = Long.MAX_VALUE; long endTime = Long.MIN_VALUE; if (hits.size() > 0) { startTime = (long) (hits.get(0).field(fieldName).getValue()); endTime = (long) (hits.get(hits.size() - 1).field(fieldName).getValue()); } return new DBResult(startTime, endTime, totalCount); } /** * Inner class used to sort the incoming Cassandra rows by last updated * (long) */ class RowComparator implements Comparator<SearchHit> { @Override public int compare(SearchHit row1, SearchHit row2) { if (row1 == null || row2 == null) { return 0; } return Long.compare(row1.field(fieldName).getValue(), row2.field(fieldName).getValue()); } } }