/**
* 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 java.io.IOException;
import java.net.URI;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.protocol.AvatarConstants.InstanceId;
import org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager;
import org.apache.hadoop.hdfs.server.namenode.AvatarNode.StartupInfo;
import org.apache.hadoop.hdfs.server.namenode.JournalStream.JournalType;
import org.apache.hadoop.util.FlushableLogger;
public class AvatarStorageSetup {
public static final Log LOG = LogFactory.getLog(AvatarStorageSetup.class.getName());
// immediate flush logger
private static final Log FLOG = FlushableLogger.getLogger(LOG);
static void validate(Configuration conf,
Collection<URI> namedirs, Collection<URI> editsdir,
URI img0, URI img1, URI edit0, URI edit1) throws IOException {
FLOG.info("Avatar conf validation - namedirs: " + namedirs);
FLOG.info("Avatar conf validation - editdirs: " + editsdir);
FLOG.info("Avatar conf validation - shared namedirs: " + img0 + ", " + img1);
FLOG.info("Avatar conf validation - shared editdirs: " + edit0 + ", " + edit1);
String msg = "";
if (conf == null) {
msg += "Configuration should not be null. ";
}
if (img0 == null || img1 == null || edit0 == null || edit1 == null) {
msg += "Configuration does not contain shared locations for image and edits. ";
// at this point there we fail
checkMessage(msg);
}
if (img0.equals(img1)) {
msg += "Configuration contains the same image location for dfs.name.dir.shared0 "
+ "and dfs.name.dir.shared1";
// at this point there we fail
checkMessage(msg);
}
if (edit0.equals(edit1)) {
msg += "Configuration contains the same edits location for dfs.name.edits.dir.shared0 "
+ "and dfs.name.edits.dir.shared1";
// at this point there we fail
checkMessage(msg);
}
// non-shared storage is file based
msg += checkFileURIScheme(namedirs);
msg += checkFileURIScheme(editsdir);
// verify that the shared image dirctories are not specified as dfs.name.dir
msg += checkContainment(namedirs, img0, "dfs.name.dir",
"dfs.name.dir.shared0");
msg += checkContainment(namedirs, img1, "dfs.name.dir",
"dfs.name.dir.shared1");
// verify that the shared edits directories are not specified as
// dfs.name.edits.dir
msg += checkContainment(editsdir, edit0, "dfs.name.edits.dir",
"dfs.name.edits.dir.shared0");
msg += checkContainment(editsdir, edit1, "dfs.name.edits.dir",
"dfs.name.edits.dir.shared1");
if (conf.get("dfs.name.dir.shared") != null
|| conf.get("dfs.name.edits.dir.shared") != null) {
msg += " dfs.name.dir.shared and dfs.name.edits.dir.shared should not be set manually";
}
// check shared image location
msg += checkImageStorage(img0, edit0);
msg += checkImageStorage(img1, edit1);
checkMessage(msg);
}
private static String checkContainment(Collection<URI> set, URI key,
String setName, String keyName) {
if (set.contains(key)) {
return " The name specified in " + keyName + " is already part of "
+ setName + ". ";
}
return "";
}
private static void checkMessage(String msg) throws IOException {
if (msg.length() != 0) {
FLOG.fatal(msg);
throw new IOException(msg);
}
}
/**
* Shared image needs to be in file storage, or QJM providing that QJM also
* stores edits.
*/
private static String checkImageStorage(URI sharedImage, URI sharedEdits) {
if (sharedImage.getScheme().equals(NNStorage.LOCAL_URI_SCHEME)) {
// shared image is stored in file storage
return "";
} else if (sharedImage.getScheme().equals(
QuorumJournalManager.QJM_URI_SCHEME)
&& sharedImage.equals(sharedEdits)) {
// image is stored in qjm together with edits
return "";
}
return "Shared image uri: " + sharedImage + " must be either file storage"
+ " or be equal to shared edits storage " + sharedEdits + ". ";
}
/**
* For non-shared storage, we enforce file uris
*/
private static String checkFileURIScheme(Collection<URI> uris) {
for (URI uri : uris)
if (uri.getScheme().compareTo(JournalType.FILE.name().toLowerCase()) != 0)
return "The specified path is not a file."
+ "Avatar supports file non-shared storage only... ";
return "";
}
static void updateConf(StartupInfo startInfo, Configuration newconf,
Collection<URI> dirs, URI dir0, URI dir1, String keyName) {
StringBuffer buf = new StringBuffer();
if (startInfo.instance == InstanceId.NODEONE) {
buf.append(dir1);
newconf.set(keyName + ".shared", dir1.toString());
} else if (startInfo.instance == InstanceId.NODEZERO) {
buf.append(dir0);
newconf.set(keyName + ".shared", dir0.toString());
}
for (URI str : dirs) {
buf.append(",");
buf.append(str);
}
newconf.set(keyName, buf.toString());
buf = null;
}
}