HDFS-10251. Ozone: Shutdown cleanly. Contributed by Anu Engineer
This commit is contained in:
parent
e11e824c9b
commit
7bb2ab7d7c
|
@ -19,8 +19,11 @@ package org.apache.hadoop.ozone.container.common.helpers;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import org.apache.hadoop.hdfs.ozone.protocol.proto.ContainerProtos;
|
import org.apache.hadoop.hdfs.ozone.protocol.proto.ContainerProtos;
|
||||||
|
import org.apache.hadoop.ozone.container.common.impl.KeyManagerImpl;
|
||||||
import org.apache.hadoop.ozone.container.common.utils.ContainerCache;
|
import org.apache.hadoop.ozone.container.common.utils.ContainerCache;
|
||||||
import org.apache.hadoop.ozone.container.common.utils.LevelDBStore;
|
import org.apache.hadoop.ozone.container.common.utils.LevelDBStore;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -71,6 +74,27 @@ public final class KeyUtils {
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown all DB Handles.
|
||||||
|
*
|
||||||
|
* @param cache - Cache for DB Handles.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static void shutdownCache(ContainerCache cache) {
|
||||||
|
Logger log = LoggerFactory.getLogger(KeyManagerImpl.class);
|
||||||
|
LevelDBStore[] handles = new LevelDBStore[cache.values().size()];
|
||||||
|
cache.values().toArray(handles);
|
||||||
|
Preconditions.checkState(handles.length == cache.values().size());
|
||||||
|
for (LevelDBStore db : handles) {
|
||||||
|
try {
|
||||||
|
db.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("error closing db. error {}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns successful keyResponse.
|
* Returns successful keyResponse.
|
||||||
* @param msg - Request.
|
* @param msg - Request.
|
||||||
|
|
|
@ -146,4 +146,15 @@ public class ChunkManagerImpl implements ChunkManager {
|
||||||
containerManager.readUnlock();
|
containerManager.readUnlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the chunkManager.
|
||||||
|
*
|
||||||
|
* In the chunkManager we haven't acquired any resources, so nothing to do
|
||||||
|
* here. This call is made with containerManager Writelock held.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
Preconditions.checkState(this.containerManager.hasWriteLock());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,8 +385,9 @@ public class ContainerManagerImpl implements ContainerManager {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() throws IOException {
|
public void shutdown() {
|
||||||
|
Preconditions.checkState(this.hasWriteLock());
|
||||||
|
this.containerMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -142,4 +142,13 @@ public class KeyManagerImpl implements KeyManager {
|
||||||
// TODO :
|
// TODO :
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown keyManager.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
Preconditions.checkState(this.containerManager.hasWriteLock());
|
||||||
|
KeyUtils.shutdownCache(containerCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,9 @@ public interface ChunkManager {
|
||||||
|
|
||||||
// TODO : Support list operations.
|
// TODO : Support list operations.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the chunkManager.
|
||||||
|
*/
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ public interface ContainerManager extends RwLock {
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
void shutdown() throws IOException;
|
void shutdown();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Chunk Manager.
|
* Sets the Chunk Manager.
|
||||||
|
|
|
@ -29,13 +29,15 @@ import java.util.List;
|
||||||
public interface KeyManager {
|
public interface KeyManager {
|
||||||
/**
|
/**
|
||||||
* Puts or overwrites a key.
|
* Puts or overwrites a key.
|
||||||
|
*
|
||||||
* @param pipeline - Pipeline.
|
* @param pipeline - Pipeline.
|
||||||
* @param data - Key Data.
|
* @param data - Key Data.
|
||||||
*/
|
*/
|
||||||
void putKey(Pipeline pipeline, KeyData data) throws IOException;
|
void putKey(Pipeline pipeline, KeyData data) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an existing key.
|
* Gets an existing key.
|
||||||
|
*
|
||||||
* @param data - Key Data.
|
* @param data - Key Data.
|
||||||
* @return Key Data.
|
* @return Key Data.
|
||||||
*/
|
*/
|
||||||
|
@ -43,21 +45,26 @@ public interface KeyManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an existing Key.
|
* Deletes an existing Key.
|
||||||
* @param pipeline - Pipeline.
|
*
|
||||||
* @param keyName Key Data.
|
* @param pipeline - Pipeline.
|
||||||
|
* @param keyName Key Data.
|
||||||
*/
|
*/
|
||||||
void deleteKey(Pipeline pipeline, String keyName) throws IOException;
|
void deleteKey(Pipeline pipeline, String keyName) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List keys in a container.
|
* List keys in a container.
|
||||||
|
*
|
||||||
* @param pipeline - pipeline.
|
* @param pipeline - pipeline.
|
||||||
* @param prefix - Prefix in needed.
|
* @param prefix - Prefix in needed.
|
||||||
* @param prevKey - Key to Start from, EMPTY_STRING to begin.
|
* @param prevKey - Key to Start from, EMPTY_STRING to begin.
|
||||||
* @param count - Number of keys to return.
|
* @param count - Number of keys to return.
|
||||||
* @return List of Keys that match the criteria.
|
* @return List of Keys that match the criteria.
|
||||||
*/
|
*/
|
||||||
List<KeyData> listKey(Pipeline pipeline, String prefix, String prevKey, int
|
List<KeyData> listKey(Pipeline pipeline, String prefix, String prevKey, int
|
||||||
count);
|
count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown keyManager.
|
||||||
|
*/
|
||||||
|
void shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public final class XceiverServer {
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void stop() throws Exception {
|
public void stop() {
|
||||||
if (bossGroup != null) {
|
if (bossGroup != null) {
|
||||||
bossGroup.shutdownGracefully();
|
bossGroup.shutdownGracefully();
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,20 +92,4 @@ public class ContainerCache extends LRUMap {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an entry from the cache.
|
|
||||||
*
|
|
||||||
* @param containerName - Name of the container.
|
|
||||||
*/
|
|
||||||
public void removeDB(String containerName) {
|
|
||||||
Preconditions.checkNotNull(containerName);
|
|
||||||
Preconditions.checkState(!containerName.isEmpty());
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
this.remove(containerName);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,10 +100,48 @@ public class OzoneContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the ozone container.
|
* Stops the ozone container.
|
||||||
* @throws Exception
|
*
|
||||||
|
* Shutdown logic is not very obvious from the following code.
|
||||||
|
* if you need to modify the logic, please keep these comments in mind.
|
||||||
|
* Here is the shutdown sequence.
|
||||||
|
*
|
||||||
|
* 1. We shutdown the network ports.
|
||||||
|
*
|
||||||
|
* 2. Now we need to wait for all requests in-flight to finish.
|
||||||
|
*
|
||||||
|
* 3. The container manager lock is a read-write lock with "Fairness" enabled.
|
||||||
|
*
|
||||||
|
* 4. This means that the waiting threads are served in a "first-come-first
|
||||||
|
* -served" manner. Please note that this applies to waiting threads only.
|
||||||
|
*
|
||||||
|
* 5. Since write locks are exclusive, if we are waiting to get a lock it
|
||||||
|
* implies that we are waiting for in-flight operations to complete.
|
||||||
|
*
|
||||||
|
* 6. if there are other write operations waiting on the reader-writer lock,
|
||||||
|
* fairness guarantees that they will proceed before the shutdown lock
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* 7. Since all operations either take a reader or writer lock of container
|
||||||
|
* manager, we are guaranteed that we are the last operation since we have
|
||||||
|
* closed the network port, and we wait until close is successful.
|
||||||
|
*
|
||||||
|
* 8. We take the writer lock and call shutdown on each of the managers in
|
||||||
|
* reverse order. That is chunkManager, keyManager and containerManager is
|
||||||
|
* shutdown.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public void stop() throws Exception {
|
public void stop() {
|
||||||
|
LOG.info("Attempting to stop container services.");
|
||||||
server.stop();
|
server.stop();
|
||||||
|
try {
|
||||||
|
this.manager.writeLock();
|
||||||
|
this.chunkManager.shutdown();
|
||||||
|
this.keyManager.shutdown();
|
||||||
|
this.manager.shutdown();
|
||||||
|
LOG.info("container services shutdown complete.");
|
||||||
|
} finally {
|
||||||
|
this.manager.writeUnlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue