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

com.hazelcast.client.cache.impl.ClientCacheHelper Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.hazelcast.client.cache.impl;

import com.hazelcast.cache.impl.CacheProxyUtil;
import com.hazelcast.client.HazelcastClientNotActiveException;
import com.hazelcast.client.connection.nio.ClientConnection;
import com.hazelcast.client.impl.clientside.HazelcastClientInstanceImpl;
import com.hazelcast.client.impl.protocol.ClientMessage;
import com.hazelcast.client.impl.protocol.codec.CacheCreateConfigCodec;
import com.hazelcast.client.impl.protocol.codec.CacheGetConfigCodec;
import com.hazelcast.client.impl.protocol.codec.CacheManagementConfigCodec;
import com.hazelcast.client.spi.impl.AbstractClientInvocationService;
import com.hazelcast.client.spi.impl.ClientInvocation;
import com.hazelcast.client.spi.properties.ClientProperty;
import com.hazelcast.config.CacheConfig;
import com.hazelcast.config.LegacyCacheConfig;
import com.hazelcast.core.Member;
import com.hazelcast.core.OperationTimeoutException;
import com.hazelcast.instance.BuildInfo;
import com.hazelcast.nio.Address;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.spi.serialization.SerializationService;
import com.hazelcast.util.ExceptionUtil;
import com.hazelcast.util.FutureUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static com.hazelcast.util.ExceptionUtil.rethrow;
import static com.hazelcast.util.ExceptionUtil.sneakyThrow;
import static com.hazelcast.util.StringUtil.timeToString;

/**
 * Helper class for some client cache related stuff.
 */
final class ClientCacheHelper {
    private ClientCacheHelper() {
    }

    /**
     * Gets the cache configuration from the server.
     *
     * @param client          the client instance which will send the operation to server
     * @param cacheName       full cache name with prefixes
     * @param simpleCacheName pure cache name without any prefix
     * @param              type of the key of the cache
     * @param              type of the value of the cache
     * @return the cache configuration if it can be found
     */
    static  CacheConfig getCacheConfig(HazelcastClientInstanceImpl client,
                                                   String cacheName, String simpleCacheName) {
        ClientMessage request = CacheGetConfigCodec.encodeRequest(cacheName, simpleCacheName);
        try {
            int partitionId = client.getClientPartitionService().getPartitionId(cacheName);
            ClientInvocation clientInvocation = new ClientInvocation(client, request, cacheName, partitionId);
            Future future = clientInvocation.invoke();
            ClientMessage responseMessage = future.get();
            SerializationService serializationService = client.getSerializationService();

            return deserializeCacheConfig(client, responseMessage, serializationService, clientInvocation);
        } catch (Exception e) {
            throw rethrow(e);
        }
    }

    private static  CacheConfig deserializeCacheConfig(HazelcastClientInstanceImpl client,
                                                                   ClientMessage responseMessage,
                                                                   SerializationService serializationService,
                                                                   ClientInvocation clientInvocation) {
        Data responseData = CacheGetConfigCodec.decodeResponse(responseMessage).response;
        ClientConnection sendConnection = clientInvocation.getSendConnection();
        if (null != sendConnection && BuildInfo.UNKNOWN_HAZELCAST_VERSION == sendConnection.getConnectedServerVersion()) {
            boolean compatibilityEnabled = client.getProperties().getBoolean(ClientProperty.COMPATIBILITY_3_6_SERVER_ENABLED);
            if (compatibilityEnabled) {
                LegacyCacheConfig legacyConfig = serializationService.toObject(responseData, LegacyCacheConfig.class);
                if (null == legacyConfig) {
                    return null;
                }
                return legacyConfig.getConfigAndReset();
            }
        }

        return serializationService.toObject(responseData);
    }

    /**
     * Creates a new cache configuration on Hazelcast members.
     *
     * @param client             the client instance which will send the operation to server
     * @param newCacheConfig     the cache configuration to be sent to server
     * @param                 type of the key of the cache
     * @param                 type of the value of the cache
     * @return the created cache configuration
     * @see com.hazelcast.cache.impl.operation.CacheCreateConfigOperation
     */
    static  CacheConfig createCacheConfig(HazelcastClientInstanceImpl client,
                                                      CacheConfig newCacheConfig, boolean urgent) {
        try {
            String nameWithPrefix = newCacheConfig.getNameWithPrefix();
            int partitionId = client.getClientPartitionService().getPartitionId(nameWithPrefix);

            Object resolvedConfig = resolveCacheConfigWithRetry(client, newCacheConfig, partitionId);

            Data configData = client.getSerializationService().toData(resolvedConfig);
            ClientMessage request = CacheCreateConfigCodec.encodeRequest(configData, true);
            ClientInvocation clientInvocation = new ClientInvocation(client, request, nameWithPrefix, partitionId);
            Future future = urgent ? clientInvocation.invokeUrgent() : clientInvocation.invoke();
            final ClientMessage response = future.get();
            final Data data = CacheCreateConfigCodec.decodeResponse(response).response;
            return resolveCacheConfig(client, clientInvocation, data);
        } catch (Exception e) {
            throw rethrow(e);
        }
    }

    private static  CacheConfig resolveCacheConfig(HazelcastClientInstanceImpl client,
                                                               ClientInvocation clientInvocation, Data configData) {
        ClientConnection sendConnection = clientInvocation.getSendConnection();
        if (null != sendConnection && BuildInfo.UNKNOWN_HAZELCAST_VERSION == sendConnection.getConnectedServerVersion()) {
            boolean compatibilityEnabled = client.getProperties().getBoolean(ClientProperty.COMPATIBILITY_3_6_SERVER_ENABLED);
            if (compatibilityEnabled) {
                LegacyCacheConfig legacyConfig = client.getSerializationService().toObject(configData, LegacyCacheConfig.class);
                if (null == legacyConfig) {
                    return null;
                }
                return legacyConfig.getConfigAndReset();
            }
        }
        return client.getSerializationService().toObject(configData);
    }

    private static  Object resolveCacheConfig(HazelcastClientInstanceImpl client, CacheConfig newCacheConfig,
                                                    int partitionId)
            throws IOException {

        Address address = getSendAddress(client, partitionId);
        ClientConnection sendConnection = (ClientConnection) client.getConnectionManager().getOrConnect(address);
        if (BuildInfo.UNKNOWN_HAZELCAST_VERSION == sendConnection.getConnectedServerVersion()) {
            boolean compatibilityEnabled = client.getProperties().getBoolean(ClientProperty.COMPATIBILITY_3_6_SERVER_ENABLED);
            if (compatibilityEnabled) {
                return new LegacyCacheConfig(newCacheConfig);
            }
        }
        return newCacheConfig;
    }

    private static Address getSendAddress(HazelcastClientInstanceImpl client, int partitionId) throws IOException {
        Address address;
        if (client.getClientConfig().getNetworkConfig().isSmartRouting()) {
            address = client.getClientPartitionService().getPartitionOwner(partitionId);
            if (address == null) {
                throw new IOException("Partition does not have an owner. partitionId: " + partitionId);
            }
        } else {
            address = client.getConnectionManager().getOwnerConnectionAddress();
            if (address == null) {
                throw new IOException("NonSmartClientInvocationService: Owner connection is not available.");
            }
        }
        return address;
    }

    private static  Object resolveCacheConfigWithRetry(HazelcastClientInstanceImpl client,
                                                             CacheConfig newCacheConfig, int partitionId) {
        AbstractClientInvocationService invocationService = (AbstractClientInvocationService) client.getInvocationService();
        long invocationRetryPauseMillis = invocationService.getInvocationRetryPauseMillis();
        long invocationTimeoutMillis = invocationService.getInvocationTimeoutMillis();
        long startMillis = System.currentTimeMillis();
        Exception lastException;
        do {
            try {
                return resolveCacheConfig(client, newCacheConfig, partitionId);
            } catch (Exception e) {
                lastException = e;
            }

            timeOutOrSleepBeforeNextTry(startMillis, invocationRetryPauseMillis, invocationTimeoutMillis, lastException);

        } while (client.getLifecycleService().isRunning());
        throw new HazelcastClientNotActiveException("Client is shut down");
    }

    private static void sleepBeforeNextTry(long invocationRetryPauseMillis) {
        try {
            Thread.sleep(invocationRetryPauseMillis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw ExceptionUtil.rethrow(e);
        }
    }

    private static void timeOutOrSleepBeforeNextTry(long startMillis, long invocationRetryPauseMillis,
                                                    long invocationTimeoutMillis, Exception lastException) {
        long nowInMillis = System.currentTimeMillis();
        long elapsedMillis = nowInMillis - startMillis;
        boolean timedOut = elapsedMillis > invocationTimeoutMillis;

        if (timedOut) {
            throwOperationTimeoutException(startMillis, nowInMillis, elapsedMillis, invocationTimeoutMillis, lastException);
        } else {
            sleepBeforeNextTry(invocationRetryPauseMillis);
        }
    }

    private static void throwOperationTimeoutException(long startMillis, long nowInMillis,
                                                       long elapsedMillis, long invocationTimeoutMillis,
                                                       Exception lastException) {
        throw new OperationTimeoutException("Creating cache config is timed out."
                + " Current time: " + timeToString(nowInMillis) + ", "
                + " Start time : " + timeToString(startMillis) + ", "
                + " Client invocation timeout : " + invocationTimeoutMillis + " ms, "
                + " Elapsed time : " + elapsedMillis + " ms. ", lastException);
    }


    /**
     * Enables/disables statistics or management support of cache on the all servers in the cluster.
     *
     * @param client    the client instance which will send the operation to server
     * @param cacheName full cache name with prefixes
     * @param statOrMan flag that represents which one of the statistics or management will be enabled
     * @param enabled   flag which represents whether it is enable or disable
     */
    static void enableStatisticManagementOnNodes(HazelcastClientInstanceImpl client, String cacheName,
                                                 boolean statOrMan, boolean enabled) {
        Collection members = client.getClientClusterService().getMemberList();
        Collection futures = new ArrayList();
        for (Member member : members) {
            try {
                Address address = member.getAddress();
                ClientMessage request = CacheManagementConfigCodec.encodeRequest(cacheName, statOrMan, enabled, address);
                ClientInvocation clientInvocation = new ClientInvocation(client, request, cacheName, address);
                Future future = clientInvocation.invoke();
                futures.add(future);
            } catch (Exception e) {
                sneakyThrow(e);
            }
        }
        // make sure all configs are created
        FutureUtil.waitWithDeadline(futures, CacheProxyUtil.AWAIT_COMPLETION_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy