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

oracle.kv.impl.admin.plan.ChangeSNParamsPlan Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

The newest version!
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.admin.plan;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import oracle.kv.KVVersion;
import oracle.kv.impl.admin.Admin;
import oracle.kv.impl.admin.IllegalCommandException;
import oracle.kv.impl.admin.param.Parameters;
import oracle.kv.impl.admin.param.RepNodeParams;
import oracle.kv.impl.admin.param.StorageNodeParams;
import oracle.kv.impl.admin.param.StorageNodeParams.RNHeapAndCacheSize;
import oracle.kv.impl.admin.plan.task.NewRepNodeParameters;
import oracle.kv.impl.admin.plan.task.StartNode;
import oracle.kv.impl.admin.plan.task.StopNode;
import oracle.kv.impl.admin.plan.task.WaitForNodeState;
import oracle.kv.impl.admin.plan.task.WriteNewParams;
import oracle.kv.impl.admin.plan.task.WriteNewSNParams;
import oracle.kv.impl.mgmt.MgmtUtil;
import oracle.kv.impl.param.Parameter;
import oracle.kv.impl.param.ParameterMap;
import oracle.kv.impl.param.ParameterState;
import oracle.kv.impl.param.SizeParameter;
import oracle.kv.impl.security.KVStorePrivilege;
import oracle.kv.impl.security.SystemPrivilege;
import oracle.kv.impl.topo.RepNodeId;
import oracle.kv.impl.topo.StorageNodeId;
import oracle.kv.impl.util.ConfigurableService.ServiceStatus;

import com.sleepycat.persist.model.Persistent;

@Persistent
public class ChangeSNParamsPlan extends AbstractPlan {

    private static final long serialVersionUID = 1L;

    public static final KVVersion STORAGE_DIR_SIZE_SUPPORT = KVVersion.R4_2;

    protected ParameterMap newParams;

    public ChangeSNParamsPlan(String name,
                              Planner planner,
                              StorageNodeId snId,
                              ParameterMap newParams) {

        super(name, planner);

        this.newParams = newParams;

        /**
         * Set correct storage node id because this is going to be stored.
         */
        newParams.setParameter(ParameterState.COMMON_SN_ID,
                               Integer.toString(snId.getStorageNodeId()));

        validateParams(planner, snId);
        addTask(new WriteNewSNParams(this, snId, newParams, true));

        /*
         * If we have changed the capacity, file system percentage, memory
         * setting or numCPUS of this SN, we may have to change the params
         * for any RNs on this SN.  Also check for storage directory size
         * changes.
         */
        if (newParams.exists(ParameterState.COMMON_MEMORY_MB) ||
            newParams.exists(ParameterState.SN_RN_HEAP_PERCENT) ||
            newParams.exists(ParameterState.JVM_OVERHEAD_PERCENT) ||
            newParams.exists(ParameterState.COMMON_CAPACITY) ||
            newParams.exists(ParameterState.COMMON_NUMCPUS) ||
            newParams.exists(ParameterState.SN_ROOT_DIR_SIZE)) {
            updateRNParams(snId, newParams);
        } else if (newParams.getName().
                      equals(ParameterState.BOOTSTRAP_MOUNT_POINTS)) {
            updateRNStorageDirs(snId, newParams);
            /*
             * TODO : Yet to add support for changing
             * BOOTSTRAP_ADMIN_MOUNT POINTS and BOOTSTRAP_RNLOG_MOUNT_POINTS
             */
        }

        /*
         * This is a no-restart plan at this time, we are done.
         */
    }

    /* DPL */
    protected ChangeSNParamsPlan() {
    }

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

    @Override
    void preExecutionSave() {
       /* Nothing to save before execution. */
    }

    @Override
    public String getDefaultName() {
        return "Change Storage Node Params";
    }

    private void validateParams(Planner p, StorageNodeId snId) {
        if (newParams.getName().
            equals(ParameterState.BOOTSTRAP_MOUNT_POINTS)) {
            Admin admin = p.getAdmin();
            Parameters parameters = admin.getCurrentParameters();
            /*
             * Will throw an IllegalCommandException if a storage directory
             * is in use.
             */
            StorageNodeParams.validateStorageDirMap(newParams, parameters,snId);
        }
        if (newParams.getName().equals(ParameterState.SNA_TYPE)) {
            String error = validateMgmtParams(newParams);
            if (error != null) {
                throw new IllegalCommandException(error);
            }
            /* Let the StorageNodeParams class validate */
            new StorageNodeParams(newParams).validate();
        }
    }

    /**
     * Return a non-null error message if incorrect mgmt param values are
     * present.
     */
    public static String validateMgmtParams(ParameterMap aParams) {
        if (!aParams.exists(ParameterState.COMMON_MGMT_CLASS)) {
            return null;
        }
        Parameter mgmtClass
            = aParams.get(ParameterState.COMMON_MGMT_CLASS);
        if (! MgmtUtil.verifyImplClassName(mgmtClass.asString())) {
            return
                ("The given value " + mgmtClass.asString() +
                 " is not allowed for the parameter " +
                 mgmtClass.getName());
        }
        return null;
    }

    public StorageNodeParams getNewParams() {
        return new StorageNodeParams(newParams);
    }

    /**
     * Generate tasks to update the JE cache size or JVM args for any RNS on
     * this SN.
     */
    private void updateRNParams(StorageNodeId snId,
                                ParameterMap newMap) {

        Admin admin = planner.getAdmin();
        StorageNodeParams snp = admin.getStorageNodeParams(snId);
        ParameterMap policyMap = admin.getCurrentParameters().copyPolicies();

        /* Find the capacity value to use */
        int capacity = snp.getCapacity();
        if (newMap.exists(ParameterState.COMMON_CAPACITY)) {
            capacity = newMap.get(ParameterState.COMMON_CAPACITY).asInt();
        }

        /*
         * Find the number of RNs hosted on this SN; that affects whether we
         * modify the heap value.
         */
        final int numHostedRNs =
            admin.getCurrentTopology().getHostedRepNodeIds(snId).size();

        final int numHostedANs =
                admin.getCurrentTopology().getHostedArbNodeIds(snId).size();

        /* Find the RN heap memory percent to use */
        int rnHeapPercent = snp.getRNHeapPercent();
        if (newMap.exists(ParameterState.SN_RN_HEAP_PERCENT)) {
            rnHeapPercent =
                newMap.get(ParameterState.SN_RN_HEAP_PERCENT).asInt();
        }

        /* Find the memory mb value to use */
        int memoryMB = snp.getMemoryMB();
        if (newMap.exists(ParameterState.COMMON_MEMORY_MB)) {
            memoryMB = newMap.get(ParameterState.COMMON_MEMORY_MB).asInt();
        }

        /* Find the numCPUs value to use */
        int numCPUs = snp.getNumCPUs();
        if (newMap.exists(ParameterState.COMMON_NUMCPUS)) {
            numCPUs = newMap.get(ParameterState.COMMON_NUMCPUS).asInt();
        }

        Parameter newRootSize = snp.getMap().
                                    get(ParameterState.SN_ROOT_DIR_SIZE);
        if (newParams.exists(ParameterState.SN_ROOT_DIR_SIZE)) {
            newRootSize = newMap.get(ParameterState.SN_ROOT_DIR_SIZE);
        }

        /* Find the -XX:ParallelGCThread flag to use */
        int gcThreads = StorageNodeParams.calcGCThreads
            (numCPUs, capacity, snp.getGCThreadFloor(),
             snp.getGCThreadThreshold(), snp.getGCThreadPercent());

        HashMap pmap = 
            new HashMap();
        for (RepNodeParams rnp :
                 admin.getCurrentParameters().getRepNodeParams()) {
            if (!rnp.getStorageNodeId().equals(snId)) {
                continue;
            }

            RNHeapAndCacheSize heapAndCache =
                StorageNodeParams.calculateRNHeapAndCache
                (policyMap, capacity, numHostedRNs, memoryMB, rnHeapPercent,
                 rnp.getRNCachePercent(), numHostedANs);
            ParameterMap rnMap = new ParameterMap(ParameterState.REPNODE_TYPE,
                                                  ParameterState.REPNODE_TYPE);

            /*
             * Hang onto the current JVM params in a local variable. We may
             * be making multiple changes to them, if we change both heap and
             * parallel gc threads.
             */
            String currentJavaMisc = rnp.getJavaMiscParams();
            if (rnp.getMaxHeapMB() != heapAndCache.getHeapMB()) {
                /* Set both the -Xms and -Xmx flags */
                currentJavaMisc = rnp.replaceOrRemoveJVMArg
                    (currentJavaMisc, RepNodeParams.XMS_FLAG,
                     heapAndCache.getHeapValAndUnit());
                currentJavaMisc = rnp.replaceOrRemoveJVMArg
                    (currentJavaMisc, RepNodeParams.XMX_FLAG,
                     heapAndCache.getHeapValAndUnit());
                rnMap.setParameter(ParameterState.JVM_MISC, currentJavaMisc);
            }

            if (rnp.getRNCachePercent() != heapAndCache.getCachePercent()) {
                rnMap.setParameter(ParameterState.RN_CACHE_PERCENT,
                                Long.toString (heapAndCache.getCachePercent()));
            }

            if (rnp.getJECacheSize() != heapAndCache.getCacheBytes()) {
                rnMap.setParameter(ParameterState.JE_CACHE_SIZE,
                                   Long.toString(heapAndCache.getCacheBytes()));
            }

            if (gcThreads != 0) {
                /* change only if old and new values don't match */
                String oldGc = RepNodeParams.parseJVMArgsForPrefix
                    (RepNodeParams.PARALLEL_GC_FLAG, currentJavaMisc);
                if (oldGc != null) {
                    if (Integer.parseInt(oldGc) != gcThreads) {
                        currentJavaMisc =
                            rnp.replaceOrRemoveJVMArg(currentJavaMisc,
                                              RepNodeParams.PARALLEL_GC_FLAG,
                                              Integer.toString(gcThreads));
                        rnMap.setParameter
                            (ParameterState.JVM_MISC, currentJavaMisc);
                    }
                }
            }

            /* If the RN mount point is null, it is on the root */
            if ((rnp.getStorageDirectoryPath() == null) && (newRootSize != null)) {
                rnMap.setParameter(ParameterState.RN_MOUNT_POINT_SIZE,
                                   newRootSize.asString());
            }
            if (!rnMap.isEmpty()) {
                pmap.put(rnp.getRepNodeId(), rnMap);
            }
        }

        if (admin.checkAdminGroupVersion(WriteNewParams.WITH_NOTIFY)) {
            generateRNUpdateTasksV2(pmap, snId);
        } else {
            generateRNUpdateTasksV1(pmap, snId);   
        }
    }

    /**
     * Generate tasks to update storage directory sizes for RNs on the specified
     * SN. An update is done if the RN has a defined storage directory and the
     * size has changed.
     */
    private void updateRNStorageDirs(StorageNodeId snId, ParameterMap newMap) {
        final Admin admin = planner.getAdmin();
        final HashMap pmap = 
            new HashMap();
        for (RepNodeParams rnp :
                admin.getCurrentParameters().getRepNodeParams()) {
            if (!rnp.getStorageNodeId().equals(snId)) {
                continue;
            }

            /* If the current storage dir is null, this RN is in the root dir */
            final String rnPath = rnp.getStorageDirectoryPath();
            if (rnPath == null) {
                continue;
            }

            /*
             * If the RN's storage dir is not in the parameters, something is
             * wrong.
             */
            final Parameter updatedSD = newMap.get(rnPath);
            if (updatedSD == null) {
                throw new IllegalCommandException(
                             "The storage directory for " + rnp.getRepNodeId() +
                             " is not defined in the parameters for " + snId);
            }

            /* Update the RN only if the size has changed */
            final long updatedSize = SizeParameter.getSize(updatedSD);
            if (updatedSize == rnp.getStorageDirectorySize()) {
                continue;
            }

            /*
             * Don't allow non-zero storage directory sizes until all of the
             * Admins are upgraded. Otherwise, sizes may be lost if an older
             * Admin becomes the master and reads then writes storage directory
             * information.
             */
            if ((updatedSize > 0) &&
                !admin.checkAdminGroupVersion(STORAGE_DIR_SIZE_SUPPORT)) {
                throw new IllegalCommandException(
                           "Cannot set storage directory size until all Admin" +
                           " nodes are at or above software version " +
                           STORAGE_DIR_SIZE_SUPPORT.getNumericVersionString());
            }
            ParameterMap rnMap = new ParameterMap(ParameterState.REPNODE_TYPE,
                                                  ParameterState.REPNODE_TYPE);
            rnMap.setParameter(ParameterState.RN_MOUNT_POINT_SIZE,
                               updatedSD.asString());
            pmap.put(rnp.getRepNodeId(), rnMap);
        }
         
        if (admin.checkAdminGroupVersion(WriteNewParams.WITH_NOTIFY)) {
            generateRNUpdateTasksV2(pmap, snId);
        } else {
            generateRNUpdateTasksV1(pmap, snId);   
        }
    }
    
    /**
     * Generates tasks to update the RN parameters, and restart the RN
     * if needed.
     */
    private void generateRNUpdateTasksV2(Map pmap, 
                                         StorageNodeId snId) {
        
       for (Entry  pval : pmap.entrySet()) {
            addTask(new WriteNewParams(this,
                                       pval.getValue(),
                                       pval.getKey(),
                                       snId, 
                                       true));
        }
    }
    
    private void generateRNUpdateTasksV1(Map pmap, 
                                         StorageNodeId snId) {
        for (Entry  pval : pmap.entrySet()) {
            RepNodeId rnId = pval.getKey();
            addTask(new WriteNewParams(this,
                                       pval.getValue(),
                                       rnId,
                                       snId, 
                                       true));
            if (pval.getValue().hasRestartRequired()) {
                addTask(new StopNode(this, snId, rnId, false));
                addTask(new StartNode(this, snId, rnId, false));
                addTask(new WaitForNodeState(this,
                                             rnId,
                                             ServiceStatus.RUNNING));
            } else {
                addTask(new NewRepNodeParameters(this, rnId));
            }
        }
    }

    @Override
    public void stripForDisplay() {
        newParams = null;
    }

    @Override
    public List getRequiredPrivileges() {
        /* Requires SYSOPER */
        return SystemPrivilege.sysoperPrivList;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy