All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dasasian.chok.client.ClientHelper Maven / Gradle / Ivy

/**
 * Copyright (C) 2014 Dasasian ([email protected])
 *
 * 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.
 */
package com.dasasian.chok.client;

import com.dasasian.chok.util.ChokException;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Client helper
 *
 * Created by damith.chandrasekara on 8/26/15.
 */
public class ClientHelper {

    private final static Logger LOG = LoggerFactory.getLogger(ClientHelper.class);

    private long queryCount = 0;
    private final long startupTime;
    private final int maxTryCount;
    private final SetMultimap indexToShards;
    private final INodeProxyManager proxyManager;
    private final INodeSelectionPolicy selectionPolicy;

    public ClientHelper(int maxTryCount, SetMultimap indexToShards,INodeProxyManager proxyManager, INodeSelectionPolicy selectionPolicy) {
        this.maxTryCount = maxTryCount;
        this.indexToShards = indexToShards;
        this.proxyManager = proxyManager;
        this.selectionPolicy = selectionPolicy;
        startupTime = System.currentTimeMillis();
    }


    public  void broadcastInternalReceiver(IResultPolicy resultPolicy, Method method, int shardArrayParamIndex, ImmutableSetMultimap nodeShardsMap, IResultReceiver resultReceiver, Object... args) throws ChokException {
        final ExecutorService executorService = Executors.newCachedThreadPool();

        try {
            try (ResultReceiverWrapper resultReceiverWrapper = new ResultReceiverWrapper<>(ImmutableSet.copyOf(nodeShardsMap.values()), resultReceiver)) {
                broadcastInternalReceiverWrapper(executorService, resultPolicy, method, shardArrayParamIndex, nodeShardsMap, resultReceiverWrapper, args);
            }
        }
        finally {
            if(!executorService.isShutdown()) {
                executorService.shutdownNow();
            }
        }
    }

    protected   void broadcastInternalReceiverWrapper(ExecutorService executor, IResultPolicy resultPolicy, Method method, int shardArrayParamIndex, ImmutableSetMultimap node2ShardsMap, IResultReceiverWrapper resultReceiverWrapper, Object... args) throws ChokException {
        queryCount++;

        // Validate inputs.
        if (method == null || args == null) {
            throw new IllegalArgumentException("Null method or args!");
        }
        Class[] types = method.getParameterTypes();

        validateArgs(types, args);
        validateShardArryaParamIndex(shardArrayParamIndex, types);

        if (LOG.isTraceEnabled()) {
            for (String indexName : indexToShards.keySet()) {
                LOG.trace("index2Shards " + indexName + " --> " + indexToShards.get(indexName).toString());
            }
            for (Map.Entry> e : node2ShardsMap.asMap().entrySet()) {
                LOG.trace("broadcast using " + e.getKey() + " --> " + e.getValue().toString());
            }
            LOG.trace("selection policy = " + selectionPolicy);
        }

        // Make RPC calls to all nodes in parallel.
        long start = 0;
        if (LOG.isDebugEnabled()) {
            start = System.currentTimeMillis();
        }

        try {
            WorkQueue workQueue = new WorkQueue<>(executor, proxyManager, method, shardArrayParamIndex, resultReceiverWrapper, args);
            node2ShardsMap.keySet().stream().forEach(node -> workQueue.execute(node, node2ShardsMap, 1, maxTryCount));
            workQueue.waitTillDone(resultPolicy);
        }
        catch (Exception e) {
            throw new ChokException("Got error", e);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug(String.format("broadcast(%s(%s), %s) took %d msec", method.getName(), Arrays.toString(args), node2ShardsMap, (System.currentTimeMillis() - start)));
        }
    }

    public  ClientResult broadcastInternal(IResultPolicy resultPolicy, Method method, int shardArrayParamIndex, ImmutableSetMultimap nodeShardsMap, Object... args) throws ChokException {
        final ExecutorService executorService = Executors.newCachedThreadPool();

        try (ClientResult clientResults = new ClientResult<>(ImmutableSet.copyOf(nodeShardsMap.values()))){
            broadcastInternalReceiverWrapper(executorService, resultPolicy, method, shardArrayParamIndex, nodeShardsMap, clientResults.getResultReceiverWrapper(), args);
            return clientResults;
        }
        finally {
            if(!executorService.isShutdown()) {
                executorService.shutdownNow();
            }
        }
    }

    private void validateShardArryaParamIndex(int shardArrayParamIndex, Class[] types) {
        if (shardArrayParamIndex > 0) {
            if (shardArrayParamIndex >= types.length) {
                throw new IllegalArgumentException("shardArrayParamIndex out of range!");
            }
            if (!(types[shardArrayParamIndex]).equals(String[].class)) {
                throw new IllegalArgumentException("shardArrayParamIndex parameter (" + shardArrayParamIndex + ") is not of type String[]!");
            }
        }
    }

    private void validateArgs(Class[] types, Object[] args) {
        if (args.length != types.length) {
            throw new IllegalArgumentException("Wrong number of args: found " + args.length + ", expected " + types.length + "!");
        }
        for (int i = 0; i < args.length; i++) {
            if (args[i] != null) {
                Class from = args[i].getClass();
                Class to = types[i];
                if (!to.isAssignableFrom(from) && !(from.isPrimitive() || to.isPrimitive())) {
                    // Assume autoboxing will work.
                    throw new IllegalArgumentException("Incorrect argument type for param " + i + ": expected " + types[i] + "!");
                }
            }
        }
    }

    public double getQueryPerMinute() {
        double minutes = (System.currentTimeMillis() - startupTime) / 60000.0;
        if (minutes > 0.0F) {
            return queryCount / minutes;
        }
        return 0.0F;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy