/* * 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.admin.internal; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.logging.log4j.Logger; import org.apache.geode.admin.GemFireHealth; import org.apache.geode.admin.GemFireHealthConfig; import org.apache.geode.distributed.internal.DistributionManager; import org.apache.geode.internal.Assert; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; /** * Evaluates the health of various GemFire components in the VM according to a * {@link GemFireHealthConfig}. * * <P> * * Note that evaluators never reside in the administration VM, they only in member VMs. They are not * <code>Serializable</code> and aren't meant to be. * * @see MemberHealthEvaluator * @see CacheHealthEvaluator * * * @since GemFire 3.5 */ public class GemFireHealthEvaluator { private static final Logger logger = LogService.getLogger(); /** Determines how the health of GemFire is determined */ private GemFireHealthConfig config; /** Evaluates the health of this member of the distributed system */ private MemberHealthEvaluator memberHealth; /** Evaluates the health of the Cache hosted in this VM */ private CacheHealthEvaluator cacheHealth; /** * The most recent <code>OKAY_HEALTH</code> diagnoses of the GemFire system */ private List okayDiagnoses; /** * The most recent <code>POOR_HEALTH</code> diagnoses of the GemFire system */ private List poorDiagnoses; /////////////////////// Constructors /////////////////////// /** * Creates a new <code>GemFireHealthEvaluator</code> * * @param config The configuration that determines whether or GemFire is healthy * @param dm The distribution manager */ public GemFireHealthEvaluator(GemFireHealthConfig config, DistributionManager dm) { if (config == null) { throw new NullPointerException( LocalizedStrings.GemFireHealthEvaluator_NULL_GEMFIREHEALTHCONFIG.toLocalizedString()); } this.config = config; this.memberHealth = new MemberHealthEvaluator(config, dm); this.cacheHealth = new CacheHealthEvaluator(config, dm); this.okayDiagnoses = new ArrayList(); this.poorDiagnoses = new ArrayList(); } ////////////////////// Instance Methods ////////////////////// /** * Evaluates the health of the GemFire components in this VM. * * @return The aggregate health code (such as {@link GemFireHealth#OKAY_HEALTH}) of the GemFire * components. */ public GemFireHealth.Health evaluate() { List status = new ArrayList(); this.memberHealth.evaluate(status); this.cacheHealth.evaluate(status); GemFireHealth.Health overallHealth = GemFireHealth.GOOD_HEALTH; this.okayDiagnoses.clear(); this.poorDiagnoses.clear(); for (Iterator iter = status.iterator(); iter.hasNext();) { AbstractHealthEvaluator.HealthStatus health = (AbstractHealthEvaluator.HealthStatus) iter.next(); if (overallHealth == GemFireHealth.GOOD_HEALTH) { if ((health.getHealthCode() != GemFireHealth.GOOD_HEALTH)) { overallHealth = health.getHealthCode(); } } else if (overallHealth == GemFireHealth.OKAY_HEALTH) { if (health.getHealthCode() == GemFireHealth.POOR_HEALTH) { overallHealth = GemFireHealth.POOR_HEALTH; } } GemFireHealth.Health healthCode = health.getHealthCode(); if (healthCode == GemFireHealth.OKAY_HEALTH) { this.okayDiagnoses.add(health.getDiagnosis()); } else if (healthCode == GemFireHealth.POOR_HEALTH) { this.poorDiagnoses.add(health.getDiagnosis()); } } if (logger.isDebugEnabled()) { logger.debug("Evaluated health to be {}", overallHealth); } return overallHealth; } /** * Returns detailed information explaining the current health status. Each array element is a * different cause for the current status. An empty array will be returned if the current status * is {@link GemFireHealth#GOOD_HEALTH}. */ public String[] getDiagnosis(GemFireHealth.Health healthCode) { if (healthCode == GemFireHealth.GOOD_HEALTH) { return new String[0]; } else if (healthCode == GemFireHealth.OKAY_HEALTH) { String[] array = new String[this.okayDiagnoses.size()]; this.okayDiagnoses.toArray(array); return array; } else { Assert.assertTrue(healthCode == GemFireHealth.POOR_HEALTH); String[] array = new String[this.poorDiagnoses.size()]; this.poorDiagnoses.toArray(array); return array; } } /** * Resets the state of this evaluator */ public void reset() { this.okayDiagnoses.clear(); this.poorDiagnoses.clear(); } /** * Returns the heath evaluation interval, in seconds. * * @see GemFireHealthConfig#getHealthEvaluationInterval */ public int getEvaluationInterval() { return this.config.getHealthEvaluationInterval(); } /** * Closes this evaluator and releases all of its resources */ public void close() { this.memberHealth.close(); this.cacheHealth.close(); } }