Reconfig Command:
hdfs dfsadmin [-reconfig <datanode|...> <host:ipc_port> <start|status>
Code Analysis
DFSAdmin.run
if ("-reconfig".equals(cmd)) {
exitCode = reconfig(argv, i);
DFSAdmin.reconfig
If op equals start, then calls startReconfiguration.
public int reconfig(String[] argv, int i) throws IOException {
String nodeType = argv[i];
String address = argv[i + 1];
String op = argv[i + 2];
if ("start".equals(op)) {
return startReconfiguration(nodeType, address);
} else if ("status".equals(op)) {
return getReconfigurationStatus(nodeType, address, System.out, System.err);
}
System.err.println("Unknown operation: " + op);
return -1;
}
DFSAdmin. startReconfiguration
startReconfiguration only allows datanode reconfig. It calls datanode.startReconfiguration();
int startReconfiguration(String nodeType, String address) throws IOException {
if ("datanode".equals(nodeType)) {
ClientDatanodeProtocol dnProxy = getDataNodeProxy(address);
dnProxy.startReconfiguration();
System.out.println("Started reconfiguration task on DataNode " + address);
return 0;
} else {
System.err.println("Node type " + nodeType +
" does not support reconfiguration.");
return 1;
}
}
Datanode.startReconfiguration
Datanode is a subclass of ReconfigurableBase. In startReconfiguration calls startReconfigurationTask();
@Override // ClientDatanodeProtocol
public void startReconfiguration() throws IOException {
checkSuperuserPrivilege();
startReconfigurationTask();
}
ReconfigurableBase.startReconfigurationTask
public void startReconfigurationTask() throws IOException {
synchronized (reconfigLock) {
if (!shouldRun) {
String errorMessage = "The server is stopped.";
LOG.warn(errorMessage);
throw new IOException(errorMessage);
}
if (reconfigThread != null) {
String errorMessage = "Another reconfiguration task is running.";
LOG.warn(errorMessage);
throw new IOException(errorMessage);
}
reconfigThread = new ReconfigurationThread(this);
reconfigThread.setDaemon(true);
reconfigThread.setName("Reconfiguration Task");
reconfigThread.start();
startTime = Time.now();
}
}
ReconfigurableBase.ReconfigurationThread
/**
* A background thread to apply configuration changes.
*/
private static class ReconfigurationThread extends Thread {
private ReconfigurableBase parent;
ReconfigurationThread(ReconfigurableBase base) {
this.parent = base;
}
// See {@link ReconfigurationServlet#applyChanges}
public void run() {
LOG.info("Starting reconfiguration task.");
Configuration oldConf = this.parent.getConf();
Configuration newConf = new Configuration();
Collection<PropertyChange> changes =
this.parent.getChangedProperties(newConf, oldConf);
Map<PropertyChange, Optional<String>> results = Maps.newHashMap();
for (PropertyChange change : changes) {
String errorMessage = null;
if (!this.parent.isPropertyReconfigurable(change.prop)) {
errorMessage = "Property " + change.prop +
" is not reconfigurable";
LOG.info(errorMessage);
results.put(change, Optional.of(errorMessage));
continue;
}
LOG.info("Change property: " + change.prop + " from \""
+ ((change.oldVal == null) ? "<default>" : change.oldVal)
+ "\" to \"" + ((change.newVal == null) ? "<default>" : change.newVal)
+ "\".");
try {
this.parent.reconfigurePropertyImpl(change.prop, change.newVal);
} catch (ReconfigurationException e) {
errorMessage = e.getCause().getMessage();
}
results.put(change, Optional.fromNullable(errorMessage));
}
synchronized (this.parent.reconfigLock) {
this.parent.endTime = Time.now();
this.parent.status = Collections.unmodifiableMap(results);
this.parent.reconfigThread = null;
}
}
}
ReconfigurableBase.isPropertyReconfigurable
/**
* {@inheritDoc}
*
* Subclasses may wish to override this with a more efficient implementation.
*/
@Override
public boolean isPropertyReconfigurable(String property) {
return getReconfigurableProperties().contains(property);
}
DataNode.getReconfigurableProperties
It indicates that only DFS_DATANODE_DATA_DIR_KEY=dfs.datanode.data.dir is reconfigurable.
/**
* Get a list of the keys of the re-configurable properties in configuration.
*/
@Override
public Collection<String> getReconfigurableProperties() {
List<String> reconfigurable =
Collections.unmodifiableList(Arrays.asList(DFS_DATANODE_DATA_DIR_KEY));
return reconfigurable;
}