/* * Copyright (c) 2008-2017, 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.internal.config; import com.hazelcast.config.EvictionConfig; import com.hazelcast.config.EvictionPolicy; import com.hazelcast.config.InMemoryFormat; import com.hazelcast.config.MapConfig; import com.hazelcast.config.NearCacheConfig; import com.hazelcast.config.NearCachePreloaderConfig; import com.hazelcast.instance.BuildInfoProvider; import com.hazelcast.internal.eviction.EvictionPolicyComparator; import com.hazelcast.logging.ILogger; import com.hazelcast.logging.Logger; import static com.hazelcast.config.EvictionPolicy.NONE; import static com.hazelcast.config.EvictionPolicy.RANDOM; import static com.hazelcast.config.InMemoryFormat.NATIVE; import static com.hazelcast.config.MapConfig.DEFAULT_EVICTION_PERCENTAGE; import static com.hazelcast.config.MapConfig.DEFAULT_MIN_EVICTION_CHECK_MILLIS; import static com.hazelcast.config.NearCacheConfig.LocalUpdatePolicy.INVALIDATE; import static com.hazelcast.util.StringUtil.isNullOrEmpty; import static java.lang.String.format; /** * Validates a Hazelcast configuration in a specific context like OS vs. EE or client vs. member nodes. */ public final class ConfigValidator { private static final ILogger LOGGER = Logger.getLogger(ConfigValidator.class); private ConfigValidator() { } /** * Checks preconditions to create a map proxy. * * @param mapConfig the {@link MapConfig} */ public static void checkMapConfig(MapConfig mapConfig) { checkNotNative(mapConfig.getInMemoryFormat()); logIgnoredConfig(mapConfig); } /** * Checks preconditions to create a map proxy with Near Cache. * * @param mapName name of the map that Near Cache will be created for * @param nearCacheConfig the {@link NearCacheConfig} to be checked * @param isClient {@code true} if the config is for a Hazelcast client, {@code false} otherwise */ public static void checkNearCacheConfig(String mapName, NearCacheConfig nearCacheConfig, boolean isClient) { checkLocalUpdatePolicy(mapName, nearCacheConfig); checkNotNative(nearCacheConfig.getInMemoryFormat()); checkEvictionConfig(nearCacheConfig.getEvictionConfig(), true); if (isClient && nearCacheConfig.isCacheLocalEntries()) { throw new IllegalArgumentException("The Near Cache option `cache-local-entries` is not supported in " + "client configurations."); } checkPreloaderConfig(nearCacheConfig, isClient); } /** * Checks IMaps' supported Near Cache local update policy configuration. * * @param mapName name of the map that Near Cache will be created for * @param nearCacheConfig the {@link NearCacheConfig} to be checked */ public static void checkLocalUpdatePolicy(String mapName, NearCacheConfig nearCacheConfig) { NearCacheConfig.LocalUpdatePolicy localUpdatePolicy = nearCacheConfig.getLocalUpdatePolicy(); if (localUpdatePolicy != INVALIDATE) { throw new IllegalArgumentException(format("Wrong `local-update-policy` option is selected for `%s` map Near Cache." + " Only `%s` option is supported but found `%s`", mapName, INVALIDATE, localUpdatePolicy)); } } /** * Checks if a {@link EvictionConfig} is valid in its context. * * @param evictionConfig the {@link EvictionConfig} * @param isNearCache {@code true} if the config is for a Near Cache, {@code false} otherwise */ @SuppressWarnings("ConstantConditions") public static void checkEvictionConfig(EvictionConfig evictionConfig, boolean isNearCache) { if (evictionConfig == null) { throw new IllegalArgumentException("Eviction config cannot be null!"); } EvictionPolicy evictionPolicy = evictionConfig.getEvictionPolicy(); String comparatorClassName = evictionConfig.getComparatorClassName(); EvictionPolicyComparator comparator = evictionConfig.getComparator(); checkEvictionConfig(evictionPolicy, comparatorClassName, comparator, isNearCache); } /** * Checks if parameters for an {@link EvictionConfig} are valid in their context. * * @param evictionPolicy the {@link EvictionPolicy} for the {@link EvictionConfig} * @param comparatorClassName the comparator class name for the {@link EvictionConfig} * @param comparator the comparator implementation for the {@link EvictionConfig} * @param isNearCache {@code true} if the config is for a Near Cache, {@code false} otherwise */ public static void checkEvictionConfig(EvictionPolicy evictionPolicy, String comparatorClassName, Object comparator, boolean isNearCache) { if (comparatorClassName != null && comparator != null) { throw new IllegalArgumentException("Only one of the `comparator class name` and `comparator`" + " can be configured in the eviction configuration!"); } if (!isNearCache && (evictionPolicy == null || evictionPolicy == NONE || evictionPolicy == RANDOM)) { if (isNullOrEmpty(comparatorClassName) && comparator == null) { throw new IllegalArgumentException( "Eviction policy must be set to an eviction policy type rather than `null`, `NONE`, `RANDOM`" + " or custom eviction policy comparator must be specified!"); } } else { if (evictionPolicy != EvictionConfig.DEFAULT_EVICTION_POLICY) { if (!isNullOrEmpty(comparatorClassName)) { throw new IllegalArgumentException( "Only one of the `eviction policy` and `comparator class name` can be configured!"); } if (comparator != null) { throw new IllegalArgumentException( "Only one of the `eviction policy` and `comparator` can be configured!"); } } } } /** * Throws {@link IllegalArgumentException} if the supplied {@link InMemoryFormat} is {@link InMemoryFormat#NATIVE}. * * @param inMemoryFormat supplied inMemoryFormat */ private static void checkNotNative(InMemoryFormat inMemoryFormat) { if (inMemoryFormat == NATIVE && !BuildInfoProvider.BUILD_INFO.isEnterprise()) { throw new IllegalArgumentException("NATIVE storage format is supported in Hazelcast Enterprise only." + " Make sure you have Hazelcast Enterprise JARs on your classpath!"); } } /** * Throws {@link IllegalArgumentException} if the supplied {@link NearCacheConfig} * has an invalid {@link NearCachePreloaderConfig}. * * @param nearCacheConfig supplied NearCacheConfig * @param isClient {@code true} if the config is for a Hazelcast client, {@code false} otherwise */ private static void checkPreloaderConfig(NearCacheConfig nearCacheConfig, boolean isClient) { if (!isClient && nearCacheConfig.getPreloaderConfig().isEnabled()) { throw new IllegalArgumentException("The Near Cache pre-loader is just available on Hazelcast clients!"); } } @SuppressWarnings("deprecation") private static void logIgnoredConfig(MapConfig mapConfig) { if (mapConfig.getMinEvictionCheckMillis() != DEFAULT_MIN_EVICTION_CHECK_MILLIS || mapConfig.getEvictionPercentage() != DEFAULT_EVICTION_PERCENTAGE) { LOGGER.warning("As of version 3.7 `minEvictionCheckMillis` and `evictionPercentage`" + " are deprecated due to a change of the eviction mechanism." + " The new eviction mechanism uses a probabilistic algorithm based on sampling." + " Please see documentation for further details."); } } }