alluxio.master.meta.checkconf.ConfigurationChecker Maven / Gradle / Ivy
The newest version!
/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package alluxio.master.meta.checkconf;
import alluxio.conf.PropertyKey;
import alluxio.conf.PropertyKey.ConsistencyCheckLevel;
import alluxio.grpc.ConfigStatus;
import alluxio.grpc.Scope;
import alluxio.wire.Address;
import alluxio.wire.ConfigCheckReport;
import alluxio.wire.InconsistentProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* This class is responsible for checking server-side configuration.
*/
public class ConfigurationChecker {
private static final Logger LOG = LoggerFactory.getLogger(ConfigurationChecker.class);
private static final int LOG_CONF_SIZE = 5;
private static final String CONSISTENT_CONFIGURATION_INFO
= "All server-side configurations are consistent.";
private static final String INCONSISTENT_CONFIGURATION_INFO
= "Inconsistent configuration detected. "
+ "Only a limited set of inconsistent configuration will be shown here. "
+ "For details, please visit Alluxio web UI or "
+ "run fsadmin doctor CLI.";
/** Contain all the master configuration information. */
private final ConfigurationStore mMasterStore;
/** Contain all the worker configuration information. */
private final ConfigurationStore mWorkerStore;
/** Contain the checker results. */
private ConfigCheckReport mConfigCheckReport;
/** Whether the configuration has been changed since the last time the report was generated. */
private volatile boolean mConfigDirty = true;
/**
* Constructs a new {@link ConfigurationChecker}.
*
* @param masterStore master configuration store
* @param workerStore worker configuration store
*/
public ConfigurationChecker(ConfigurationStore masterStore,
ConfigurationStore workerStore) {
mMasterStore = masterStore;
mWorkerStore = workerStore;
mConfigCheckReport = new ConfigCheckReport();
mMasterStore.registerChangeListener(() -> mConfigDirty = true);
mWorkerStore.registerChangeListener(() -> mConfigDirty = true);
}
/**
* Checks the server-side configurations and records the check results.
*/
public synchronized void regenerateReport() {
// Generate the configuration map from master and worker configuration records
Map, List>> confMap = generateConfMap();
// Update the errors and warnings configuration
Map> confErrors = new HashMap<>();
Map> confWarns = new HashMap<>();
for (Map.Entry, List>> entry : confMap.entrySet()) {
if (entry.getValue().size() >= 2) {
PropertyKey key = entry.getKey();
InconsistentProperty inconsistentProperty = new InconsistentProperty()
.setName(key.getName()).setValues(entry.getValue());
Scope scope = key.getScope().equals(Scope.ALL) ? Scope.SERVER : key.getScope();
if (entry.getKey().getConsistencyLevel().equals(ConsistencyCheckLevel.ENFORCE)) {
confErrors.putIfAbsent(scope, new ArrayList<>());
confErrors.get(scope).add(inconsistentProperty);
} else {
confWarns.putIfAbsent(scope, new ArrayList<>());
confWarns.get(scope).add(inconsistentProperty);
}
}
}
// Update configuration status
ConfigStatus status = confErrors.values().stream().anyMatch(a -> a.size() > 0)
? ConfigStatus.FAILED : confWarns.values().stream().anyMatch(a -> a.size() > 0)
? ConfigStatus.WARN : ConfigStatus.PASSED;
if (!status.equals(mConfigCheckReport.getConfigStatus())) {
logConfigReport();
}
mConfigCheckReport = new ConfigCheckReport(confErrors, confWarns, status);
}
/**
* @return the configuration checker report
*/
public synchronized ConfigCheckReport getConfigCheckReport() {
if (mConfigDirty) {
// Reset mConfigDirty *before* calling regenerateReport so that if the configuration changes
// during report regeneration, the change will be reflected in the next call to
// getConfigCheckReport.
mConfigDirty = false;
LOG.debug("Regenerating config check report");
regenerateReport();
} else {
LOG.debug("Skipping regenerating config check report");
}
return mConfigCheckReport;
}
/**
* Logs the configuration check report information.
*/
public synchronized void logConfigReport() {
ConfigStatus reportStatus = mConfigCheckReport.getConfigStatus();
if (reportStatus.equals(ConfigStatus.PASSED)) {
LOG.debug(CONSISTENT_CONFIGURATION_INFO);
} else if (reportStatus.equals(ConfigStatus.WARN)) {
LOG.warn("{}\nWarnings: {}", INCONSISTENT_CONFIGURATION_INFO,
mConfigCheckReport.getConfigWarns().values().stream()
.map(Object::toString).limit(LOG_CONF_SIZE).collect(Collectors.joining(", ")));
} else {
LOG.error("{}\nErrors: {}\nWarnings: {}", INCONSISTENT_CONFIGURATION_INFO,
mConfigCheckReport.getConfigErrors().values().stream()
.map(Object::toString).limit(LOG_CONF_SIZE).collect(Collectors.joining(", ")),
mConfigCheckReport.getConfigWarns().values().stream()
.map(Object::toString).limit(LOG_CONF_SIZE).collect(Collectors.joining(", ")));
}
}
/**
* Generates the configuration map to find wrong configuration.
* The map is of format Map<PropertyKey, Map<Value, List<Host:Port>>>.
*
* @return the generated configuration map
*/
private Map, List>> generateConfMap() {
Map, List>> confMap = new HashMap<>();
fillConfMap(confMap, mMasterStore.getConfMap());
fillConfMap(confMap, mWorkerStore.getConfMap());
return confMap;
}
/**
* Fills the configuration map.
*
* @param targetMap the map to fill
* @param recordMap the map to get data from
*/
private void fillConfMap(Map, List>> targetMap,
Map> recordMap) {
for (Map.Entry> record : recordMap.entrySet()) {
Address address = record.getKey();
String addressStr = String.format("%s:%s", address.getHost(), address.getRpcPort());
for (ConfigRecord conf : record.getValue()) {
PropertyKey key = conf.getKey();
if (key.getConsistencyLevel() == ConsistencyCheckLevel.IGNORE) {
continue;
}
Optional value = conf.getValue();
targetMap.putIfAbsent(key, new HashMap<>());
Map, List> values = targetMap.get(key);
values.putIfAbsent(value, new ArrayList<>());
values.get(value).add(addressStr);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy