/** * 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.hadoop.hdfs.server.namenode; import org.apache.commons.logging.*; import org.apache.hadoop.conf.*; import java.io.*; import java.util.LinkedList; /*************************************************** * Manager FSNamesystem dynamic loadingof configurations. ***************************************************/ public class ConfigManager { public static final Log LOG = LogFactory.getLog(FSNamesystem.class); /** Time to wait between checks of the allocation file */ public static final long CONFIG_RELOAD_INTERVAL = 300 * 1000; /** * Time to wait after the allocation has been modified before reloading it * (this is done to prevent loading a file that hasn't been fully written). */ public static final long DEFAULT_CONFIG_RELOAD_WAIT = 10 * 1000; private FSNamesystem namesys; private String whitelistFile; // Path to file that contains whitelist directories private long configReloadWait = DEFAULT_CONFIG_RELOAD_WAIT; private long lastReloadAttempt; // Last time we tried to reload the pools file private long lastSuccessfulReload; // Last time we successfully reloaded pools private boolean lastReloadAttemptFailed = false; public ConfigManager(FSNamesystem namesys, Configuration conf) { this.namesys = namesys; // the name of the whitelist file this.whitelistFile = conf.get("dfs.namenode.whitelist.file"); if (whitelistFile == null) { LOG.warn("No whitelist file specified in dfs.namenode.whitelist.file." + " The namenode will allow deletion/renaming of any directory."); } // periodicity of reload of the config file long value = conf.getLong("dfs.namenode.config.reload.wait", 0); if (value != 0) { configReloadWait = value; } } /** * Checks to see if the namenode config file is updated on * disk, If so, then read all it contents. At present, only * the whitelist config is updated, but we will enahnce this to * update all possible namenode configs in future. */ public void reloadConfigIfNecessary() { if (whitelistFile == null) { return; } long time = System.currentTimeMillis(); if (time > lastReloadAttempt + CONFIG_RELOAD_INTERVAL) { lastReloadAttempt = time; try { File file = new File(whitelistFile); long lastModified = file.lastModified(); if (lastModified > lastSuccessfulReload && time > lastModified + configReloadWait) { reloadWhitelist(); lastSuccessfulReload = time; lastReloadAttemptFailed = false; } } catch (Exception e) { // Throwing the error further out here won't help - the RPC thread // will catch it and report it in a loop. Instead, just log it and // hope somebody will notice from the log. // We log the error only on the first failure so we don't fill up the // server's log with these messages. if (!lastReloadAttemptFailed) { LOG.error("Failed to reload whitelist file - " + "will use existing allocations.", e); } lastReloadAttemptFailed = true; } } } /** * Removes all the entries currently in neverDeletePaths * and add the new ones specified */ void reloadWhitelist() throws IOException { // read the entire whitelist into memory outside the // FSNamessytem lock. // LinkedList<String> paths = new LinkedList<String>(); FileInputStream fstream = new FileInputStream(whitelistFile); DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); int count = 0; while (true) { String str = br.readLine(); if (str == null) { break; // end of file } str = str.trim(); // remove all whitespace from start and end if (str.startsWith("#")) { continue; // ignore lines with starting with # } paths.add(str); LOG.info("Whitelisted directory [" + count + "] " + str); count++; } in.close(); // acquire the writelock and insert newly read entries into // the Namenode's configuration. namesys.writeLock(); try { namesys.neverDeletePaths.clear(); for (String s: paths) { namesys.neverDeletePaths.add(s); } } finally { namesys.writeUnlock(); } } }