org.apache.geode.management.internal.cli.functions.RegionCreateFunction.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.geode.management.internal.cli.functions.RegionCreateFunction.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF 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.apache.geode.management.internal.cli.functions;

import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Logger;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.PartitionResolver;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionExistsException;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.execute.ResultSender;
import org.apache.geode.compression.Compressor;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.internal.InternalEntity;
import org.apache.geode.internal.cache.xmlcache.CacheXml;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.commands.RegionCommandsUtils;
import org.apache.geode.management.internal.cli.exceptions.CreateSubregionException;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.util.RegionPath;
import org.apache.geode.management.internal.configuration.domain.XmlEntity;

/**
 *
 * @since GemFire 7.0
 */
public class RegionCreateFunction implements Function, InternalEntity {

    private static final Logger logger = LogService.getLogger();

    private static final long serialVersionUID = 8746830191680509335L;

    private static final String ID = RegionCreateFunction.class.getName();

    public static RegionCreateFunction INSTANCE = new RegionCreateFunction();

    @Override
    public boolean isHA() {
        return false;
    }

    @Override
    public void execute(FunctionContext context) {
        ResultSender<Object> resultSender = context.getResultSender();

        Cache cache = context.getCache();
        String memberNameOrId = CliUtil.getMemberNameOrId(cache.getDistributedSystem().getDistributedMember());

        RegionFunctionArgs regionCreateArgs = (RegionFunctionArgs) context.getArguments();

        if (regionCreateArgs.isSkipIfExists()) {
            Region<Object, Object> region = cache.getRegion(regionCreateArgs.getRegionPath());
            if (region != null) {
                resultSender.lastResult(new CliFunctionResult(memberNameOrId, true,
                        CliStrings.format(CliStrings.CREATE_REGION__MSG__SKIPPING_0_REGION_PATH_1_ALREADY_EXISTS,
                                memberNameOrId, regionCreateArgs.getRegionPath())));
                return;
            }
        }

        try {
            Region<?, ?> createdRegion = createRegion(cache, regionCreateArgs);
            XmlEntity xmlEntity = new XmlEntity(CacheXml.REGION, "name", createdRegion.getName());
            resultSender.lastResult(new CliFunctionResult(memberNameOrId, xmlEntity,
                    CliStrings.format(CliStrings.CREATE_REGION__MSG__REGION_0_CREATED_ON_1,
                            createdRegion.getFullPath(), memberNameOrId)));
        } catch (IllegalStateException e) {
            String exceptionMsg = e.getMessage();
            String localizedString = LocalizedStrings.DiskStore_IS_USED_IN_NONPERSISTENT_REGION.toLocalizedString();
            if (localizedString.equals(e.getMessage())) {
                exceptionMsg = exceptionMsg + " "
                        + CliStrings.format(CliStrings.CREATE_REGION__MSG__USE_ONE_OF_THESE_SHORTCUTS_0,
                                new Object[] { String.valueOf(RegionCommandsUtils.PERSISTENT_OVERFLOW_SHORTCUTS) });
            }
            resultSender.lastResult(handleException(memberNameOrId, exceptionMsg, null/* do not log */));
        } catch (IllegalArgumentException | CreateSubregionException e) {
            resultSender.lastResult(handleException(memberNameOrId, e.getMessage(), e));
        } catch (RegionExistsException e) {
            String exceptionMsg = CliStrings.format(
                    CliStrings.CREATE_REGION__MSG__REGION_PATH_0_ALREADY_EXISTS_ON_1,
                    regionCreateArgs.getRegionPath(), memberNameOrId);
            resultSender.lastResult(handleException(memberNameOrId, exceptionMsg, e));
        } catch (Exception e) {
            String exceptionMsg = e.getMessage();
            if (exceptionMsg == null) {
                exceptionMsg = CliUtil.stackTraceAsString(e);
            }
            resultSender.lastResult(handleException(memberNameOrId, exceptionMsg, e));
        }
    }

    private CliFunctionResult handleException(final String memberNameOrId, final String exceptionMsg,
            final Exception e) {
        if (e != null && logger.isDebugEnabled()) {
            logger.debug(e.getMessage(), e);
        }
        if (exceptionMsg != null) {
            return new CliFunctionResult(memberNameOrId, false, exceptionMsg);
        }

        return new CliFunctionResult(memberNameOrId);
    }

    public static <K, V> Region<?, ?> createRegion(Cache cache, RegionFunctionArgs regionCreateArgs) {
        Region<K, V> createdRegion = null;

        final String regionPath = regionCreateArgs.getRegionPath();
        final RegionShortcut regionShortcut = regionCreateArgs.getRegionShortcut();
        final String useAttributesFrom = regionCreateArgs.getUseAttributesFrom();

        // If a region path indicates a sub-region, check whether the parent region exists
        RegionPath regionPathData = new RegionPath(regionPath);
        String parentRegionPath = regionPathData.getParent();
        Region<?, ?> parentRegion = null;
        if (parentRegionPath != null && !Region.SEPARATOR.equals(parentRegionPath)) {
            parentRegion = cache.getRegion(parentRegionPath);
            if (parentRegion == null) {
                throw new IllegalArgumentException(
                        CliStrings.format(CliStrings.CREATE_REGION__MSG__PARENT_REGION_FOR_0_DOES_NOT_EXIST,
                                new Object[] { regionPath }));
            }

            if (parentRegion.getAttributes().getPartitionAttributes() != null) {
                // For a PR, sub-regions are not supported.
                throw new CreateSubregionException(
                        CliStrings.format(CliStrings.CREATE_REGION__MSG__0_IS_A_PR_CANNOT_HAVE_SUBREGIONS,
                                parentRegion.getFullPath()));
            }
        }

        // One of Region Shortcut OR Use Attributes From has to be given
        if (regionShortcut == null && useAttributesFrom == null) {
            throw new IllegalArgumentException(
                    CliStrings.CREATE_REGION__MSG__ONE_OF_REGIONSHORTCUT_AND_USEATTRIBUTESFROM_IS_REQUIRED);
        }

        boolean isPartitioned = false;
        RegionFactory<K, V> factory = null;
        RegionAttributes<K, V> regionAttributes = null;
        if (regionShortcut != null) {
            regionAttributes = cache.getRegionAttributes(regionShortcut.toString());
            if (logger.isDebugEnabled()) {
                logger.debug("Using shortcut {} for {} region attributes : {}", regionShortcut, regionPath,
                        regionAttributes);
            }

            if (regionAttributes == null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Shortcut {} doesn't have attributes in {}", regionShortcut,
                            cache.listRegionAttributes());
                }
                throw new IllegalStateException(CliStrings.format(
                        CliStrings.CREATE_REGION__MSG__COULD_NOT_LOAD_REGION_ATTRIBUTES_FOR_SHORTCUT_0,
                        regionShortcut));
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Using Manager's region attributes for {}", regionPath);
            }
            regionAttributes = regionCreateArgs.getRegionAttributes();
            if (logger.isDebugEnabled()) {
                logger.debug("Using Attributes : {}", regionAttributes);
            }
        }
        isPartitioned = regionAttributes.getPartitionAttributes() != null;

        factory = cache.createRegionFactory(regionAttributes);

        if (!isPartitioned && regionCreateArgs.hasPartitionAttributes()) {
            throw new IllegalArgumentException(CliStrings.format(
                    CliStrings.CREATE_REGION__MSG__OPTION_0_CAN_BE_USED_ONLY_FOR_PARTITIONEDREGION,
                    regionCreateArgs.getPartitionArgs().getUserSpecifiedPartitionAttributes()));
        }

        if (isPartitioned) {
            PartitionAttributes<K, V> partitionAttributes = extractPartitionAttributes(cache, regionAttributes,
                    regionCreateArgs);

            DataPolicy originalDataPolicy = regionAttributes.getDataPolicy();
            factory.setPartitionAttributes(partitionAttributes);
            // We have to do this because AttributesFactory.setPartitionAttributes()
            // checks RegionAttributes.hasDataPolicy() which is set only when the data
            // policy is set explicitly
            factory.setDataPolicy(originalDataPolicy);
        }

        // Set Constraints
        final String keyConstraint = regionCreateArgs.getKeyConstraint();
        final String valueConstraint = regionCreateArgs.getValueConstraint();
        if (keyConstraint != null && !keyConstraint.isEmpty()) {
            Class<K> keyConstraintClass = CliUtil.forName(keyConstraint, CliStrings.CREATE_REGION__KEYCONSTRAINT);
            factory.setKeyConstraint(keyConstraintClass);
        }

        if (valueConstraint != null && !valueConstraint.isEmpty()) {
            Class<V> valueConstraintClass = CliUtil.forName(valueConstraint,
                    CliStrings.CREATE_REGION__VALUECONSTRAINT);
            factory.setValueConstraint(valueConstraintClass);
        }

        // Expiration attributes
        final RegionFunctionArgs.ExpirationAttrs entryExpirationIdleTime = regionCreateArgs
                .getEntryExpirationIdleTime();
        if (entryExpirationIdleTime != null) {
            factory.setEntryIdleTimeout(entryExpirationIdleTime.convertToExpirationAttributes());
        }
        final RegionFunctionArgs.ExpirationAttrs entryExpirationTTL = regionCreateArgs.getEntryExpirationTTL();
        if (entryExpirationTTL != null) {
            factory.setEntryTimeToLive(entryExpirationTTL.convertToExpirationAttributes());
        }
        final RegionFunctionArgs.ExpirationAttrs regionExpirationIdleTime = regionCreateArgs
                .getRegionExpirationIdleTime();
        if (regionExpirationIdleTime != null) {
            factory.setEntryIdleTimeout(regionExpirationIdleTime.convertToExpirationAttributes());
        }
        final RegionFunctionArgs.ExpirationAttrs regionExpirationTTL = regionCreateArgs.getRegionExpirationTTL();
        if (regionExpirationTTL != null) {
            factory.setEntryTimeToLive(regionExpirationTTL.convertToExpirationAttributes());
        }

        // Associate a Disk Store
        final String diskStore = regionCreateArgs.getDiskStore();
        if (diskStore != null && !diskStore.isEmpty()) {
            factory.setDiskStoreName(diskStore);
        }
        if (regionCreateArgs.isSetDiskSynchronous()) {
            factory.setDiskSynchronous(regionCreateArgs.isDiskSynchronous());
        }

        if (regionCreateArgs.isSetOffHeap()) {
            factory.setOffHeap(regionCreateArgs.isOffHeap());
        }

        // Set stats enabled
        if (regionCreateArgs.isSetStatisticsEnabled()) {
            factory.setStatisticsEnabled(regionCreateArgs.isStatisticsEnabled());
        }

        // Set conflation
        if (regionCreateArgs.isSetEnableAsyncConflation()) {
            factory.setEnableAsyncConflation(regionCreateArgs.isEnableAsyncConflation());
        }
        if (regionCreateArgs.isSetEnableSubscriptionConflation()) {
            factory.setEnableSubscriptionConflation(regionCreateArgs.isEnableSubscriptionConflation());
        }

        // Gateway Sender Ids
        final Set<String> gatewaySenderIds = regionCreateArgs.getGatewaySenderIds();
        if (gatewaySenderIds != null && !gatewaySenderIds.isEmpty()) {
            for (String gatewaySenderId : gatewaySenderIds) {
                factory.addGatewaySenderId(gatewaySenderId);
            }
        }

        // Async Queue Ids
        final Set<String> asyncEventQueueIds = regionCreateArgs.getAsyncEventQueueIds();
        if (asyncEventQueueIds != null && !asyncEventQueueIds.isEmpty()) {
            for (String asyncEventQueueId : asyncEventQueueIds) {
                factory.addAsyncEventQueueId(asyncEventQueueId);
            }
        }

        // concurrency check enabled & concurrency level
        if (regionCreateArgs.isSetConcurrencyChecksEnabled()) {
            factory.setConcurrencyChecksEnabled(regionCreateArgs.isConcurrencyChecksEnabled());
        }
        if (regionCreateArgs.isSetConcurrencyLevel()) {
            factory.setConcurrencyLevel(regionCreateArgs.getConcurrencyLevel());
        }

        // cloning enabled for delta
        if (regionCreateArgs.isSetCloningEnabled()) {
            factory.setCloningEnabled(regionCreateArgs.isCloningEnabled());
        }

        // multicast enabled for replication
        if (regionCreateArgs.isSetMcastEnabled()) {
            factory.setMulticastEnabled(regionCreateArgs.isMcastEnabled());
        }

        // Set plugins
        final Set<String> cacheListeners = regionCreateArgs.getCacheListeners();
        if (cacheListeners != null && !cacheListeners.isEmpty()) {
            for (String cacheListener : cacheListeners) {
                Class<CacheListener<K, V>> cacheListenerKlass = CliUtil.forName(cacheListener,
                        CliStrings.CREATE_REGION__CACHELISTENER);
                factory.addCacheListener(
                        CliUtil.newInstance(cacheListenerKlass, CliStrings.CREATE_REGION__CACHELISTENER));
            }
        }

        // Compression provider
        if (regionCreateArgs.isSetCompressor()) {
            Class<Compressor> compressorKlass = CliUtil.forName(regionCreateArgs.getCompressor(),
                    CliStrings.CREATE_REGION__COMPRESSOR);
            factory.setCompressor(CliUtil.newInstance(compressorKlass, CliStrings.CREATE_REGION__COMPRESSOR));
        }

        final String cacheLoader = regionCreateArgs.getCacheLoader();
        if (cacheLoader != null) {
            Class<CacheLoader<K, V>> cacheLoaderKlass = CliUtil.forName(cacheLoader,
                    CliStrings.CREATE_REGION__CACHELOADER);
            factory.setCacheLoader(CliUtil.newInstance(cacheLoaderKlass, CliStrings.CREATE_REGION__CACHELOADER));
        }

        final String cacheWriter = regionCreateArgs.getCacheWriter();
        if (cacheWriter != null) {
            Class<CacheWriter<K, V>> cacheWriterKlass = CliUtil.forName(cacheWriter,
                    CliStrings.CREATE_REGION__CACHEWRITER);
            factory.setCacheWriter(CliUtil.newInstance(cacheWriterKlass, CliStrings.CREATE_REGION__CACHEWRITER));
        }

        String regionName = regionPathData.getName();

        if (parentRegion != null) {
            createdRegion = factory.createSubregion(parentRegion, regionName);
        } else {
            createdRegion = factory.create(regionName);
        }

        return createdRegion;
    }

    @SuppressWarnings("unchecked")
    private static <K, V> PartitionAttributes<K, V> extractPartitionAttributes(Cache cache,
            RegionAttributes<K, V> regionAttributes, RegionFunctionArgs regionCreateArgs) {
        RegionFunctionArgs.PartitionArgs partitionArgs = regionCreateArgs.getPartitionArgs();

        PartitionAttributesFactory<K, V> prAttrFactory = null;

        PartitionAttributes<K, V> partitionAttributes = regionAttributes.getPartitionAttributes();
        if (partitionAttributes != null) {
            prAttrFactory = new PartitionAttributesFactory<>(partitionAttributes);
        } else {
            prAttrFactory = new PartitionAttributesFactory<>();
        }

        String colocatedWith = partitionArgs.getPrColocatedWith();
        if (colocatedWith != null) {
            Region<Object, Object> colocatedWithRegion = cache.getRegion(colocatedWith);
            if (colocatedWithRegion == null) {
                throw new IllegalArgumentException(CliStrings.format(
                        CliStrings.CREATE_REGION__MSG__COLOCATEDWITH_REGION_0_DOES_NOT_EXIST, colocatedWith));
            }
            if (!colocatedWithRegion.getAttributes().getDataPolicy().withPartitioning()) {
                throw new IllegalArgumentException(CliStrings.format(
                        CliStrings.CREATE_REGION__MSG__COLOCATEDWITH_REGION_0_IS_NOT_PARTITIONEDREGION,
                        colocatedWith));
            }
            prAttrFactory.setColocatedWith(colocatedWith);
        }
        if (partitionArgs.isSetPRLocalMaxMemory()) {
            prAttrFactory.setLocalMaxMemory(partitionArgs.getPrLocalMaxMemory());
        }
        if (partitionArgs.isSetPRTotalMaxMemory()) {
            prAttrFactory.setTotalMaxMemory(partitionArgs.getPrTotalMaxMemory());
        }
        if (partitionArgs.isSetPRTotalNumBuckets()) {
            prAttrFactory.setTotalNumBuckets(partitionArgs.getPrTotalNumBuckets());
        }
        if (partitionArgs.isSetPRRedundantCopies()) {
            prAttrFactory.setRedundantCopies(partitionArgs.getPrRedundantCopies());
        }
        if (partitionArgs.isSetPRRecoveryDelay()) {
            prAttrFactory.setRecoveryDelay(partitionArgs.getPrRecoveryDelay());
        }
        if (partitionArgs.isSetPRStartupRecoveryDelay()) {
            prAttrFactory.setStartupRecoveryDelay(partitionArgs.getPrStartupRecoveryDelay());
        }

        if (regionCreateArgs.isPartitionResolverSet()) {
            Class<PartitionResolver> partitionResolverClass = forName(regionCreateArgs.getPartitionResolver(),
                    CliStrings.CREATE_REGION__PARTITION_RESOLVER);
            prAttrFactory.setPartitionResolver((PartitionResolver<K, V>) newInstance(partitionResolverClass,
                    CliStrings.CREATE_REGION__PARTITION_RESOLVER));
        }
        return prAttrFactory.create();
    }

    private static Class<PartitionResolver> forName(String className, String neededFor) {
        if (StringUtils.isBlank(className)) {
            throw new IllegalArgumentException(CliStrings
                    .format(CliStrings.CREATE_REGION__MSG__INVALID_PARTITION_RESOLVER, className, neededFor));
        }
        try {
            return (Class<PartitionResolver>) ClassPathLoader.getLatest().forName(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(CliStrings.format(
                    CliStrings.CREATE_REGION_PARTITION_RESOLVER__MSG__COULD_NOT_FIND_CLASS_0_SPECIFIED_FOR_1,
                    className, neededFor), e);
        } catch (ClassCastException e) {
            throw new RuntimeException(CliStrings.format(
                    CliStrings.CREATE_REGION__MSG__PARTITION_RESOLVER__CLASS_0_SPECIFIED_FOR_1_IS_NOT_OF_EXPECTED_TYPE,
                    className, neededFor), e);
        }
    }

    private static PartitionResolver newInstance(Class<PartitionResolver> klass, String neededFor) {
        try {
            return klass.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(CliStrings.format(
                    CliStrings.CREATE_REGION__MSG__PARTITION_RESOLVER__COULD_NOT_INSTANTIATE_CLASS_0_SPECIFIED_FOR_1,
                    klass, neededFor), e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(CliStrings.format(
                    CliStrings.CREATE_REGION__MSG__PARTITION_RESOLVER__COULD_NOT_ACCESS_CLASS_0_SPECIFIED_FOR_1,
                    klass, neededFor), e);
        }
    }

    @Override
    public String getId() {
        return ID;
    }
}