private boolean calculateIsStaleConfigs(ServiceComponentHost sch, Map<String, DesiredConfig> desiredConfigs,
                                          HostComponentDesiredStateEntity hostComponentDesiredStateEntity) throws AmbariException {

    if (sch.isRestartRequired(hostComponentDesiredStateEntity)) {
      return true;
    }

    Map<String, HostConfig> actual = sch.getActualConfigs();
    if (null == actual || actual.isEmpty()) {
      return false;
    }

    Cluster cluster = clusters.getClusterById(sch.getClusterId());

    Map<String, Map<String, String>> desired = getEffectiveDesiredTags(cluster, sch.getHostName(),
            desiredConfigs);

    Boolean stale = null;
    int staleHash = 0;
    if (STALE_CONFIGS_CACHE_ENABLED){
      staleHash = Objects.hashCode(actual.hashCode(),
              desired.hashCode(),
              sch.getHostName(),
              sch.getServiceComponentName(),
              sch.getServiceName());
      stale = staleConfigsCache.getIfPresent(staleHash);
      if(stale != null) {
        return stale;
      }
    }

    stale = false;

    StackId stackId = sch.getServiceComponent().getDesiredStackId();

    StackInfo stackInfo = ambariMetaInfo.getStack(stackId);

    ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
            stackId.getStackVersion(), sch.getServiceName());

    ComponentInfo componentInfo = serviceInfo.getComponentByName(sch.getServiceComponentName());
    // Configs are considered stale when:
    // - desired type DOES NOT exist in actual
    // --- desired type DOES NOT exist in stack: not_stale
    // --- desired type DOES exist in stack: check stack for any key: stale
    // - desired type DOES exist in actual
    // --- desired tags DO match actual tags: not_stale
    // --- desired tags DO NOT match actual tags
    // ---- merge values, determine changed keys, check stack: stale

    Iterator<Entry<String, Map<String, String>>> it = desired.entrySet().iterator();
    List<String> changedProperties = new LinkedList<>();

    while (it.hasNext()) {
      boolean staleEntry = false;
      Entry<String, Map<String, String>> desiredEntry = it.next();

      String type = desiredEntry.getKey();
      Map<String, String> tags = desiredEntry.getValue();

      if (!actual.containsKey(type)) {
        // desired is set, but actual is not
        staleEntry = (serviceInfo.hasConfigDependency(type) || componentInfo.hasConfigType(type));
      } else {
        // desired and actual both define the type
        HostConfig hc = actual.get(type);
        Map<String, String> actualTags = buildTags(hc);

        if (!isTagChanged(tags, actualTags, hasGroupSpecificConfigsForType(cluster, sch.getHostName(), type))) {
          staleEntry = false;
        } else {
          staleEntry = (serviceInfo.hasConfigDependency(type) || componentInfo.hasConfigType(type));
          if (staleEntry) {
            Collection<String> changedKeys = findChangedKeys(cluster, type, tags.values(), actualTags.values());
            changedProperties.addAll(changedKeys);
          }
        }
      }
      stale = stale | staleEntry;
    }

    String refreshCommand = calculateRefreshCommand(stackInfo.getRefreshCommandConfiguration(), sch, changedProperties);

    if (STALE_CONFIGS_CACHE_ENABLED) {
      staleConfigsCache.put(staleHash, stale);
      if (refreshCommand != null) {
        refreshConfigCommandCache.put(staleHash, refreshCommand);
      }
    }

    // gather all changed properties and see if we can find a common refreshConfigs command for this component
    if (LOG.isDebugEnabled()) {
      LOG.debug("Changed properties {} ({}) {} :  COMMAND: {}", stale, sch.getServiceComponentName(), sch.getHostName(), refreshCommand);
      for (String p : changedProperties) {
        LOG.debug(p);
      }
    }

    return stale;
  }
@param stack
         the stack to pull stack-values from (not {@code null})
@param serviceName
         the service name {@code null}).
@return a mapping of configuration type to map of key/value pairs for the
        default configurations.
@throws AmbariException
ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java