Package org.elasticsearch.rest.action.bench

Source Code of org.elasticsearch.rest.action.bench.RestBenchAction

/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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.
*/

package org.elasticsearch.rest.action.bench;

import com.google.common.primitives.Doubles;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.bench.*;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.admin.indices.cache.clear.RestClearIndicesCacheAction;
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
import org.elasticsearch.rest.action.support.RestBuilderListener;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.elasticsearch.common.xcontent.json.JsonXContent.contentBuilder;
import static org.elasticsearch.rest.RestRequest.Method.*;
import static org.elasticsearch.rest.RestStatus.*;

/**
* REST handler for benchmark actions.
*/
public class RestBenchAction extends BaseRestHandler {

    @Inject
    public RestBenchAction(Settings settings, RestController controller, Client client) {
        super(settings, controller, client);

        // List active benchmarks
        controller.registerHandler(GET, "/_bench", this);
        controller.registerHandler(GET, "/{index}/_bench", this);
        controller.registerHandler(GET, "/{index}/{type}/_bench", this);

        // Submit benchmark
        controller.registerHandler(PUT, "/_bench", this);
        controller.registerHandler(PUT, "/{index}/_bench", this);
        controller.registerHandler(PUT, "/{index}/{type}/_bench", this);

        // Abort benchmark
        controller.registerHandler(POST, "/_bench/abort/{name}", this);
    }

    @Override
    public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
        switch (request.method()) {
            case POST:
                handleAbortRequest(request, channel, client);
                break;
            case PUT:
                handleSubmitRequest(request, channel, client);
                break;
            case GET:
                handleStatusRequest(request, channel, client);
                break;
            default:
                // Politely ignore methods we don't support
                channel.sendResponse(new BytesRestResponse(METHOD_NOT_ALLOWED));
        }
    }

    /**
     * Reports on the status of all actively running benchmarks
     */
    private void handleStatusRequest(final RestRequest request, final RestChannel channel, final Client client) {

        BenchmarkStatusRequest benchmarkStatusRequest = new BenchmarkStatusRequest();

        client.benchStatus(benchmarkStatusRequest, new RestBuilderListener<BenchmarkStatusResponse>(channel) {

            @Override
            public RestResponse buildResponse(BenchmarkStatusResponse response, XContentBuilder builder) throws Exception {
                builder.startObject();
                response.toXContent(builder, request);
                builder.endObject();
                return new BytesRestResponse(OK, builder);
            }
        });
    }

    /**
     * Aborts an actively running benchmark
     */
    private void handleAbortRequest(final RestRequest request, final RestChannel channel, final Client client) {
        final String[] benchmarkNames = Strings.splitStringByCommaToArray(request.param("name"));
        AbortBenchmarkRequest abortBenchmarkRequest = new AbortBenchmarkRequest(benchmarkNames);

        client.abortBench(abortBenchmarkRequest, new AcknowledgedRestListener<AbortBenchmarkResponse>(channel));
    }

    /**
     * Submits a benchmark for execution
     */
    private void handleSubmitRequest(final RestRequest request, final RestChannel channel, final Client client) {

        String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
        String[] types = Strings.splitStringByCommaToArray(request.param("type"));

        final BenchmarkRequest benchmarkRequest;
        try {
            BenchmarkRequestBuilder builder = new BenchmarkRequestBuilder(client);
            builder.setVerbose(request.paramAsBoolean("verbose", false));
            benchmarkRequest = parse(builder, request.content(), request.contentUnsafe());
            benchmarkRequest.cascadeGlobalSettings();                   // Make sure competitors inherit global settings
            benchmarkRequest.applyLateBoundSettings(indices, types);    // Some settings cannot be applied until after parsing
            Exception ex = benchmarkRequest.validate();
            if (ex != null) {
                throw ex;
            }
            benchmarkRequest.listenerThreaded(false);
        } catch (Exception e) {
                logger.debug("failed to parse search request parameters", e);
            try {
                channel.sendResponse(new BytesRestResponse(BAD_REQUEST, contentBuilder().startObject().field("error", e.getMessage()).endObject()));
            } catch (IOException e1) {
                logger.error("Failed to send failure response", e1);
            }
            return;
        }
        client.bench(benchmarkRequest, new RestBuilderListener<BenchmarkResponse>(channel) {

            @Override
            public RestResponse buildResponse(BenchmarkResponse response, XContentBuilder builder) throws Exception {
                builder.startObject();
                response.toXContent(builder, request);
                builder.endObject();
                return new BytesRestResponse(OK, builder);
            }
        });
    }

    public static BenchmarkRequest parse(BenchmarkRequestBuilder builder, BytesReference data, boolean contentUnsafe) throws Exception {
        XContent xContent = XContentFactory.xContent(data);
        XContentParser p = xContent.createParser(data);
        XContentParser.Token token = p.nextToken();
        assert token == XContentParser.Token.START_OBJECT;
        String fieldName = null;
        while ((token = p.nextToken()) != XContentParser.Token.END_OBJECT) {
            switch (token) {
                case START_ARRAY:
                    if ("requests".equals(fieldName)) {
                        while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) {
                            assert token == XContentParser.Token.START_OBJECT;
                            XContentBuilder payloadBuilder = XContentFactory.contentBuilder(p.contentType()).copyCurrentStructure(p);
                            SearchRequest req = new SearchRequest();
                            req.source(payloadBuilder.bytes(), contentUnsafe);
                            builder.addSearchRequest(req);
                        }
                    } else if ("competitors".equals(fieldName)) {
                        while (p.nextToken() != XContentParser.Token.END_ARRAY) {
                            builder.addCompetitor(parse(p, contentUnsafe));
                        }
                    } else if ("percentiles".equals(fieldName)) {
                        List<Double> percentiles = new ArrayList<>();
                        while (p.nextToken() != XContentParser.Token.END_ARRAY) {
                            percentiles.add(p.doubleValue());
                        }
                        builder.setPercentiles(Doubles.toArray(percentiles));
                    } else {
                        throw new ElasticsearchParseException("Failed parsing array field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case START_OBJECT:
                    if ("clear_caches".equals(fieldName)) {
                        BenchmarkSettings.ClearCachesSettings clearCachesSettings = new BenchmarkSettings.ClearCachesSettings();
                        builder.setClearCachesSettings(clearCachesSettings);
                        parseClearCaches(p, clearCachesSettings);
                    } else {
                        throw new ElasticsearchParseException("Failed parsing object field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case FIELD_NAME:
                    fieldName = p.text();
                    break;
                case VALUE_NUMBER:
                    if ("num_executor_nodes".equals(fieldName)) {
                        builder.setNumExecutorNodes(p.intValue());
                    } else if ("iterations".equals(fieldName)) {
                        builder.setIterations(p.intValue());
                    } else if ("concurrency".equals(fieldName)) {
                        builder.setConcurrency(p.intValue());
                    } else if ("multiplier".equals(fieldName)) {
                        builder.setMultiplier(p.intValue());
                    } else if ("num_slowest".equals(fieldName)) {
                        builder.setNumSlowest(p.intValue());
                    } else {
                        throw new ElasticsearchParseException("Failed parsing numeric field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case VALUE_BOOLEAN:
                    if ("warmup".equals(fieldName)) {
                        builder.setWarmup(p.booleanValue());
                    } else if ("clear_caches".equals(fieldName)) {
                        if (p.booleanValue()) {
                            throw new ElasticsearchParseException("Failed parsing field [" + fieldName + "] must specify which caches to clear");
                        } else {
                            builder.setAllowCacheClearing(false);
                        }
                    } else {
                        throw new ElasticsearchParseException("Failed parsing boolean field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case VALUE_STRING:
                    if ("name".equals(fieldName)) {
                        builder.setBenchmarkId(p.text());
                    } else {
                        throw new ElasticsearchParseException("Failed parsing string field [" + fieldName + "] field is not recognized");
                    }
                    break;
                default:
                    throw new ElasticsearchParseException("Failed parsing " + token.name() + " field [" + fieldName + "] field is not recognized");
            }
        }

        return builder.request();
    }

    private static BenchmarkCompetitorBuilder parse(XContentParser p, boolean contentUnsafe) throws Exception {
        XContentParser.Token token = p.currentToken();
        BenchmarkCompetitorBuilder builder = new BenchmarkCompetitorBuilder();
        assert token == XContentParser.Token.START_OBJECT;
        String fieldName = null;
        while ((token = p.nextToken()) != XContentParser.Token.END_OBJECT) {
            switch (token) {
                case START_ARRAY:
                    if ("requests".equals(fieldName)) {
                        while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) {
                            assert token == XContentParser.Token.START_OBJECT;
                            XContentBuilder payloadBuilder = XContentFactory.contentBuilder(p.contentType()).copyCurrentStructure(p);
                            SearchRequest req = new SearchRequest();
                            req.source(payloadBuilder.bytes(), contentUnsafe);
                            builder.addSearchRequest(req);
                        }
                    } else if ("indices".equals(fieldName)) {
                        List<String> perCompetitorIndices = new ArrayList<>();
                        while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) {
                            if (token == XContentParser.Token.VALUE_STRING) {
                                perCompetitorIndices.add(p.text());
                            } else {
                                throw new ElasticsearchParseException("Failed parsing array field [" + fieldName + "] expected string values but got: " + token);
                            }
                        }
                        builder.setIndices(perCompetitorIndices.toArray(new String[perCompetitorIndices.size()]));
                    } else if ("types".equals(fieldName)) {
                        List<String> perCompetitorTypes = new ArrayList<>();
                        while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) {
                            if (token == XContentParser.Token.VALUE_STRING) {
                                perCompetitorTypes.add(p.text());
                            } else {
                                throw new ElasticsearchParseException("Failed parsing array field [" + fieldName + "] expected string values but got: " + token);
                            }
                        }
                        builder.setTypes(perCompetitorTypes.toArray(new String[perCompetitorTypes.size()]));
                    } else {
                        throw new ElasticsearchParseException("Failed parsing array field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case START_OBJECT:
                    if ("clear_caches".equals(fieldName)) {
                        BenchmarkSettings.ClearCachesSettings clearCachesSettings = new BenchmarkSettings.ClearCachesSettings();
                        builder.setClearCachesSettings(clearCachesSettings);
                        parseClearCaches(p, clearCachesSettings);
                    } else {
                        throw new ElasticsearchParseException("Failed parsing object field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case FIELD_NAME:
                    fieldName = p.text();
                    break;
                case VALUE_NUMBER:
                    if ("multiplier".equals(fieldName)) {
                        builder.setMultiplier(p.intValue());
                    } else if ("num_slowest".equals(fieldName)) {
                        builder.setNumSlowest(p.intValue());
                    } else if ("iterations".equals(fieldName)) {
                        builder.setIterations(p.intValue());
                    } else if ("concurrency".equals(fieldName)) {
                        builder.setConcurrency(p.intValue());
                    } else {
                        throw new ElasticsearchParseException("Failed parsing numeric field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case VALUE_BOOLEAN:
                    if ("warmup".equals(fieldName)) {
                        builder.setWarmup(p.booleanValue());
                    } else if ("clear_caches".equals(fieldName)) {
                        if (p.booleanValue()) {
                            throw new ElasticsearchParseException("Failed parsing field [" + fieldName + "] must specify which caches to clear");
                        } else {
                            builder.setAllowCacheClearing(false);
                        }
                    } else {
                        throw new ElasticsearchParseException("Failed parsing boolean field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case VALUE_STRING:
                    if ("name".equals(fieldName)) {
                        builder.setName(p.text());
                    } else if ("search_type".equals(fieldName) || "searchType".equals(fieldName)) {
                        builder.setSearchType(SearchType.fromString(p.text()));
                    } else {
                        throw new ElasticsearchParseException("Failed parsing string field [" + fieldName + "] field is not recognized");
                    }
                    break;
                default:
                    throw new ElasticsearchParseException("Failed parsing " + token.name() + " field [" + fieldName + "] field is not recognized");
            }
        }
        return builder;
    }

    private static void parseClearCaches(XContentParser p, BenchmarkSettings.ClearCachesSettings clearCachesSettings) throws Exception {
        XContentParser.Token token;
        String fieldName = null;
        while ((token = p.nextToken()) != XContentParser.Token.END_OBJECT) {
            switch (token) {
                case START_OBJECT:
                    break;
                case VALUE_BOOLEAN:
                    if (RestClearIndicesCacheAction.Fields.FILTER.match(fieldName)) {
                        clearCachesSettings.filterCache(p.booleanValue());
                    } else if (RestClearIndicesCacheAction.Fields.FIELD_DATA.match(fieldName)) {
                        clearCachesSettings.fieldDataCache(p.booleanValue());
                    } else if (RestClearIndicesCacheAction.Fields.ID.match(fieldName)) {
                        clearCachesSettings.idCache(p.booleanValue());
                    } else if (RestClearIndicesCacheAction.Fields.RECYCLER.match(fieldName)) {
                        clearCachesSettings.recycler(p.booleanValue());
                    } else {
                        throw new ElasticsearchParseException("Failed parsing " + token.name() + " field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case START_ARRAY:
                    List<String> fields = new ArrayList<>();
                    while ((token = p.nextToken()) != XContentParser.Token.END_ARRAY) {
                        fields.add(p.text());
                    }
                    if (RestClearIndicesCacheAction.Fields.FIELDS.match(fieldName)) {
                        clearCachesSettings.fields(fields.toArray(new String[fields.size()]));
                    } else if (RestClearIndicesCacheAction.Fields.FILTER_KEYS.match(fieldName)) {
                        clearCachesSettings.filterKeys(fields.toArray(new String[fields.size()]));
                    } else {
                        throw new ElasticsearchParseException("Failed parsing " + token.name() + " field [" + fieldName + "] field is not recognized");
                    }
                    break;
                case FIELD_NAME:
                    fieldName = p.text();
                    break;
                default:
                    throw new ElasticsearchParseException("Failed parsing " + token.name() + " field [" + fieldName + "] field is not recognized");
            }
        }
    }
}
TOP

Related Classes of org.elasticsearch.rest.action.bench.RestBenchAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.