Author: arp
Date: Mon Feb 24 20:46:35 2014
New Revision: 1571431

URL: http://svn.apache.org/r1571431
Log:
HDFS-6005. Simplify Datanode rollback and downgrade. (Contributed by Suresh 
Srinivas)

Modified:
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/CHANGES_HDFS-5535.txt
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BlockPoolSliceStorage.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataStorage.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/FsDatasetSpi.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeRollingUpgrade.java
    
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDatanodeStartupOptions.java

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/CHANGES_HDFS-5535.txt
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/CHANGES_HDFS-5535.txt?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/CHANGES_HDFS-5535.txt
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/CHANGES_HDFS-5535.txt
 Mon Feb 24 20:46:35 2014
@@ -75,3 +75,7 @@ HDFS-5535 subtasks:
     HDFS-5994. Fix TestDataNodeRollingUpgrade.  (Arpit Agarwal via szetszwo)
 
     HDFS-5999. Do not create rollback fsimage when it already exists. (jing9)
+
+    HDFS-6005. Simplify Datanode rollback and downgrade. (Suresh Srinivas via
+    Arpit Agarwal)
+

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPOfferService.java
 Mon Feb 24 20:46:35 2014
@@ -17,13 +17,10 @@
  */
 package org.apache.hadoop.hdfs.server.datanode;
 
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.apache.commons.logging.Log;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
@@ -32,24 +29,15 @@ import org.apache.hadoop.hdfs.protocol.B
 import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
 import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
 import 
org.apache.hadoop.hdfs.protocolPB.DatanodeProtocolClientSideTranslatorPB;
-import org.apache.hadoop.hdfs.server.protocol.BalancerBandwidthCommand;
-import org.apache.hadoop.hdfs.server.protocol.BlockCommand;
-import org.apache.hadoop.hdfs.server.protocol.BlockIdCommand;
-import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand;
-import org.apache.hadoop.hdfs.server.protocol.DatanodeCommand;
-import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
-import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
-import org.apache.hadoop.hdfs.server.protocol.FinalizeCommand;
-import org.apache.hadoop.hdfs.server.protocol.KeyUpdateCommand;
-import org.apache.hadoop.hdfs.server.protocol.NNHAStatusHeartbeat;
-import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
-import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo;
+import org.apache.hadoop.hdfs.server.protocol.*;
 import 
org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo.BlockStatus;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * One instance per block-pool/namespace on the DN, which handles the
@@ -419,9 +407,9 @@ class BPOfferService {
    */
   void signalRollingUpgrade(boolean inProgress) {
     if (inProgress) {
-      dn.getFSDataset().enableDeleteToTrash(getBlockPoolId());
+      dn.getFSDataset().enableTrash(getBlockPoolId());
     } else {
-      dn.getFSDataset().disableAndPurgeTrashStorage(getBlockPoolId());
+      dn.getFSDataset().restoreTrash(getBlockPoolId());
     }
   }
 

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BlockPoolSliceStorage.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BlockPoolSliceStorage.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BlockPoolSliceStorage.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BlockPoolSliceStorage.java
 Mon Feb 24 20:46:35 2014
@@ -18,15 +18,7 @@
 
 package org.apache.hadoop.hdfs.server.datanode;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.fs.FileUtil;
 import org.apache.hadoop.fs.HardLink;
@@ -40,7 +32,14 @@ import org.apache.hadoop.hdfs.server.com
 import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
 import org.apache.hadoop.util.Daemon;
 
-import com.google.common.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Manages storage for the set of BlockPoolSlices which share a particular 
@@ -174,7 +173,7 @@ public class BlockPoolSliceStorage exten
 
   /**
    * Format a block pool slice storage. 
-   * @param sd the block pool storage
+   * @param bpSdir the block pool storage
    * @param nsInfo the name space info
    * @throws IOException Signals that an I/O exception has occurred.
    */
@@ -212,7 +211,7 @@ public class BlockPoolSliceStorage exten
     
     if (!blockpoolID.equals("") && !blockpoolID.equals(bpid)) {
       throw new InconsistentFSStateException(storage,
-          "Unexepcted blockpoolID " + bpid + " . Expected " + blockpoolID);
+          "Unexpected blockpoolID " + bpid + ". Expected " + blockpoolID);
     }
     blockpoolID = bpid;
   }
@@ -236,7 +235,6 @@ public class BlockPoolSliceStorage exten
    * Upgrade if this.LV > LAYOUT_VERSION || this.cTime < namenode.cTime Regular
    * startup if this.LV = LAYOUT_VERSION && this.cTime = namenode.cTime
    * 
-   * @param dn DataNode to which this storage belongs to
    * @param sd storage directory <SD>/current/<bpid>
    * @param nsInfo namespace info
    * @param startOpt startup option
@@ -246,13 +244,13 @@ public class BlockPoolSliceStorage exten
       NamespaceInfo nsInfo, StartupOption startOpt) throws IOException {
     if (startOpt == StartupOption.ROLLBACK) {
       doRollback(sd, nsInfo); // rollback if applicable
-    } else if (StartupOption.isRollingUpgradeRollback(startOpt)) {
-      File trashRoot = getTrashRootDir(sd);
-      int filesRestored =
-          trashRoot.exists() ? restoreBlockFilesFromTrash(trashRoot) : 0;
-      LOG.info("Restored " + filesRestored + " block files from trash.");
+    } else {
+      // Restore all the files in the trash. The restored files are retained
+      // during rolling upgrade rollback. They are deleted during rolling
+      // upgrade downgrade.
+      int restored = restoreBlockFilesFromTrash(getTrashRootDir(sd));
+      LOG.info("Restored " + restored + " block files from trash.");
     }
-    
     readProperties(sd);
     checkVersionUpgradable(this.layoutVersion);
     assert this.layoutVersion >= HdfsConstants.DATANODE_LAYOUT_VERSION 
@@ -335,7 +333,8 @@ public class BlockPoolSliceStorage exten
     File bpTmpDir = bpSd.getPreviousTmp();
     assert !bpTmpDir.exists() : "previous.tmp directory must not exist.";
     
-    // 2. Rename <SD>/curernt/<bpid>/current to 
<SD>/curernt/<bpid>/previous.tmp
+    // 2. Rename <SD>/current/<bpid>/current to
+    //    <SD>/current/<bpid>/previous.tmp
     rename(bpCurDir, bpTmpDir);
     
     // 3. Create new <SD>/current with block files hardlinks and VERSION
@@ -346,7 +345,8 @@ public class BlockPoolSliceStorage exten
     this.cTime = nsInfo.getCTime();
     writeProperties(bpSd);
     
-    // 4.rename <SD>/curernt/<bpid>/previous.tmp to 
<SD>/curernt/<bpid>/previous
+    // 4.rename <SD>/current/<bpid>/previous.tmp to
+    // <SD>/current/<bpid>/previous
     rename(bpTmpDir, bpPrevDir);
     LOG.info("Upgrade of block pool " + blockpoolID + " at " + bpSd.getRoot()
         + " is complete");
@@ -380,15 +380,17 @@ public class BlockPoolSliceStorage exten
   /**
    * Restore all files from the trash directory to their corresponding
    * locations under current/
-   *
-   * @param trashRoot
-   * @throws IOException 
    */
-  private int restoreBlockFilesFromTrash(File trashRoot) throws IOException {
+  private int restoreBlockFilesFromTrash(File trashRoot)
+      throws  IOException {
     int filesRestored = 0;
-    File restoreDirectory = null;
+    File[] children = trashRoot.exists() ? trashRoot.listFiles() : null;
+    if (children == null) {
+      return 0;
+    }
 
-    for (File child : trashRoot.listFiles()) {
+    File restoreDirectory = null;
+    for (File child : children) {
       if (child.isDirectory()) {
         // Recurse to process subdirectories.
         filesRestored += restoreBlockFilesFromTrash(child);
@@ -408,7 +410,7 @@ public class BlockPoolSliceStorage exten
       }
       ++filesRestored;
     }
-
+    FileUtil.fullyDelete(trashRoot);
     return filesRestored;
   }
 
@@ -527,9 +529,6 @@ public class BlockPoolSliceStorage exten
 
   /**
    * gets the data node storage directory based on block pool storage
-   * 
-   * @param bpRoot
-   * @return
    */
   private static String getDataNodeStorageRoot(String bpRoot) {
     Matcher matcher = BLOCK_POOL_PATH_PATTERN.matcher(bpRoot);
@@ -571,7 +570,6 @@ public class BlockPoolSliceStorage exten
    * The subdirectory structure under trash/ mirrors that under current/ to 
keep
    * implicit memory of where the files are to be restored (if necessary).
    *
-   * @param blockFile
    * @return the trash directory for a given block file that is being deleted.
    */
   public String getTrashDirectory(File blockFile) {
@@ -587,7 +585,6 @@ public class BlockPoolSliceStorage exten
    * The subdirectory structure under trash/ mirrors that under current/ to 
keep
    * implicit memory of where the files are to be restored.
    *
-   * @param blockFile
    * @return the target directory to restore a previously deleted block file.
    */
   @VisibleForTesting
@@ -601,9 +598,26 @@ public class BlockPoolSliceStorage exten
   /**
    * Delete all files and directories in the trash directories.
    */
-  public void emptyTrash() {
+  public void restoreTrash() {
     for (StorageDirectory sd : storageDirs) {
-      FileUtil.fullyDelete(getTrashRootDir(sd));
+      File trashRoot = getTrashRootDir(sd);
+      try {
+        restoreBlockFilesFromTrash(trashRoot);
+        FileUtil.fullyDelete(getTrashRootDir(sd));
+      } catch (IOException ioe) {
+        LOG.warn("Restoring trash failed for storage directory " + sd);
+      }
     }
   }
+
+  /** trash is enabled if at least one storage directory contains trash root */
+  @VisibleForTesting
+  public boolean trashEnabled() {
+    for (StorageDirectory sd : storageDirs) {
+      if (getTrashRootDir(sd).exists()) {
+        return true;
+      }
+    }
+    return false;
+  }
 }

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java
 Mon Feb 24 20:46:35 2014
@@ -17,42 +17,10 @@
  */
 package org.apache.hadoop.hdfs.server.datanode;
 
-import static org.apache.hadoop.hdfs.DFSConfigKeys.*;
-import static org.apache.hadoop.util.ExitUtil.terminate;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.nio.channels.ClosedByInterruptException;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.SocketChannel;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.management.ObjectName;
-
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.protobuf.BlockingService;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
@@ -69,41 +37,17 @@ import org.apache.hadoop.hdfs.HDFSPolicy
 import org.apache.hadoop.hdfs.HdfsConfiguration;
 import org.apache.hadoop.hdfs.net.DomainPeerServer;
 import org.apache.hadoop.hdfs.net.TcpPeerServer;
-import org.apache.hadoop.hdfs.protocol.Block;
-import org.apache.hadoop.hdfs.protocol.BlockLocalPathInfo;
-import org.apache.hadoop.hdfs.protocol.ClientDatanodeProtocol;
-import org.apache.hadoop.hdfs.protocol.DatanodeID;
-import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
-import org.apache.hadoop.hdfs.protocol.DatanodeLocalInfo;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.HdfsBlocksMetadata;
-import org.apache.hadoop.hdfs.protocol.HdfsConstants;
-import org.apache.hadoop.hdfs.protocol.RecoveryInProgressException;
-import org.apache.hadoop.hdfs.protocol.datatransfer.BlockConstructionStage;
-import org.apache.hadoop.hdfs.protocol.datatransfer.DataTransferEncryptor;
-import org.apache.hadoop.hdfs.protocol.datatransfer.DataTransferProtocol;
-import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair;
-import org.apache.hadoop.hdfs.protocol.datatransfer.Sender;
+import org.apache.hadoop.hdfs.protocol.*;
+import org.apache.hadoop.hdfs.protocol.datatransfer.*;
 import 
org.apache.hadoop.hdfs.protocol.proto.ClientDatanodeProtocolProtos.ClientDatanodeProtocolService;
 import 
org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.DNTransferAckProto;
 import org.apache.hadoop.hdfs.protocol.proto.DataTransferProtos.Status;
 import 
org.apache.hadoop.hdfs.protocol.proto.InterDatanodeProtocolProtos.InterDatanodeProtocolService;
-import org.apache.hadoop.hdfs.protocolPB.ClientDatanodeProtocolPB;
-import 
org.apache.hadoop.hdfs.protocolPB.ClientDatanodeProtocolServerSideTranslatorPB;
-import 
org.apache.hadoop.hdfs.protocolPB.DatanodeProtocolClientSideTranslatorPB;
-import org.apache.hadoop.hdfs.protocolPB.InterDatanodeProtocolPB;
-import 
org.apache.hadoop.hdfs.protocolPB.InterDatanodeProtocolServerSideTranslatorPB;
-import org.apache.hadoop.hdfs.protocolPB.InterDatanodeProtocolTranslatorPB;
-import org.apache.hadoop.hdfs.protocolPB.PBHelper;
-import org.apache.hadoop.hdfs.security.token.block.BlockPoolTokenSecretManager;
-import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
-import org.apache.hadoop.hdfs.security.token.block.BlockTokenSecretManager;
+import org.apache.hadoop.hdfs.protocolPB.*;
+import org.apache.hadoop.hdfs.security.token.block.*;
 import 
org.apache.hadoop.hdfs.security.token.block.BlockTokenSecretManager.AccessMode;
-import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
-import org.apache.hadoop.hdfs.security.token.block.InvalidBlockTokenException;
 import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
 import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
-import 
org.apache.hadoop.hdfs.server.common.HdfsServerConstants.RollingUpgradeStartupOption;
 import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption;
 import org.apache.hadoop.hdfs.server.common.JspHelper;
 import org.apache.hadoop.hdfs.server.common.StorageInfo;
@@ -115,11 +59,7 @@ import org.apache.hadoop.hdfs.server.dat
 import org.apache.hadoop.hdfs.server.namenode.FileChecksumServlets;
 import org.apache.hadoop.hdfs.server.namenode.StreamFile;
 import 
org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
-import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol;
-import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration;
-import org.apache.hadoop.hdfs.server.protocol.InterDatanodeProtocol;
-import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
-import org.apache.hadoop.hdfs.server.protocol.ReplicaRecoveryInfo;
+import org.apache.hadoop.hdfs.server.protocol.*;
 import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
 import org.apache.hadoop.hdfs.web.resources.Param;
 import org.apache.hadoop.http.HttpConfig;
@@ -142,21 +82,24 @@ import org.apache.hadoop.security.UserGr
 import org.apache.hadoop.security.authorize.AccessControlList;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.TokenIdentifier;
-import org.apache.hadoop.util.Daemon;
-import org.apache.hadoop.util.DiskChecker;
+import org.apache.hadoop.util.*;
 import org.apache.hadoop.util.DiskChecker.DiskErrorException;
 import org.apache.hadoop.util.DiskChecker.DiskOutOfSpaceException;
-import org.apache.hadoop.util.GenericOptionsParser;
-import org.apache.hadoop.util.JvmPauseMonitor;
-import org.apache.hadoop.util.ServicePlugin;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.VersionInfo;
 import org.mortbay.util.ajax.JSON;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.protobuf.BlockingService;
+import javax.management.ObjectName;
+import java.io.*;
+import java.lang.management.ManagementFactory;
+import java.net.*;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SocketChannel;
+import java.security.PrivilegedExceptionAction;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.apache.hadoop.hdfs.DFSConfigKeys.*;
+import static org.apache.hadoop.util.ExitUtil.terminate;
 
 /**********************************************************
  * DataNode is a class (and program) that stores a set of
@@ -1770,7 +1713,6 @@ public class DataNode extends Configured
     }
     
     if (!parseArguments(args, conf)) {
-      LOG.error("Bad command line arguments");
       printUsage(System.err);
       return null;
     }
@@ -1940,18 +1882,6 @@ public class DataNode extends Configured
         startOpt = StartupOption.ROLLBACK;
       } else if (StartupOption.REGULAR.getName().equalsIgnoreCase(cmd)) {
         startOpt = StartupOption.REGULAR;
-      } else if (StartupOption.ROLLINGUPGRADE.getName().equalsIgnoreCase(cmd)) 
{
-        startOpt = StartupOption.ROLLINGUPGRADE;
-
-        if ((i < args.length ) &&
-            
(args[i].equalsIgnoreCase(RollingUpgradeStartupOption.ROLLBACK.toString()))) {
-          startOpt.setRollingUpgradeStartupOption(args[i++]);
-        } else {
-          LOG.error("Missing or unrecognized option to " + 
StartupOption.ROLLINGUPGRADE);
-          return false;
-        }
-
-        LOG.info("Rolling upgrade rollback requested via startup option");
       } else {
         return false;
       }
@@ -2579,4 +2509,9 @@ public class DataNode extends Configured
   boolean shouldRun() {
     return shouldRun;
   }
+
+  @VisibleForTesting
+  DataStorage getStorage() {
+    return storage;
+  }
 }

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataStorage.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataStorage.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataStorage.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataStorage.java
 Mon Feb 24 20:46:35 2014
@@ -18,22 +18,10 @@
 
 package org.apache.hadoop.hdfs.server.datanode;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileLock;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FileUtil;
-import org.apache.hadoop.fs.HardLink;
-import org.apache.hadoop.fs.LocalFileSystem;
-import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.*;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hdfs.DFSConfigKeys;
 import org.apache.hadoop.hdfs.HdfsConfiguration;
@@ -50,6 +38,11 @@ import org.apache.hadoop.io.IOUtils;
 import org.apache.hadoop.util.Daemon;
 import org.apache.hadoop.util.DiskChecker;
 
+import java.io.*;
+import java.nio.channels.FileLock;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
 /** 
  * Data storage information file.
  * <p>
@@ -95,7 +88,7 @@ public class DataStorage extends Storage
         new ConcurrentHashMap<String, Boolean>());
   }
   
-  public StorageInfo getBPStorage(String bpid) {
+  public BlockPoolSliceStorage getBPStorage(String bpid) {
     return bpStorageMap.get(bpid);
   }
   
@@ -120,9 +113,6 @@ public class DataStorage extends Storage
 
   /**
    * Enable trash for the specified block pool storage.
-   *
-   * @param bpid
-   * @param  inProgress
    */
   public void enableTrash(String bpid) {
     if (trashEnabledBpids.add(bpid)) {
@@ -130,18 +120,16 @@ public class DataStorage extends Storage
     }
   }
 
-  /**
-   * Disable trash for the specified block pool storage.
-   * Existing files in trash are purged i.e. permanently deleted.
-   *
-   * @param bpid
-   * @param  inProgress
-   */
-  public void disableAndPurgeTrash(String bpid) {
-    if (trashEnabledBpids.remove(bpid)) {
-      LOG.info("Disabled trash for bpid " + bpid);
+  public void restoreTrash(String bpid) {
+    if (trashEnabledBpids.contains(bpid)) {
+      getBPStorage(bpid).restoreTrash();
+      trashEnabledBpids.remove(bpid);
+      LOG.info("Restored trash for bpid " + bpid);
     }
-    ((BlockPoolSliceStorage) getBPStorage(bpid)).emptyTrash();
+  }
+
+  public boolean trashEnabled(String bpid) {
+    return trashEnabledBpids.contains(bpid);
   }
 
   /**
@@ -150,7 +138,6 @@ public class DataStorage extends Storage
    * 'trash' directory. If there is a subsequent rollback, then the block
    * files will be restored from trash.
    *
-   * @param blockFile
    * @return trash directory if rolling upgrade is in progress, null
    *         otherwise.
    */
@@ -242,7 +229,7 @@ public class DataStorage extends Storage
     // 3. Update all storages. Some of them might have just been formatted.
     this.writeAll();
     
-    // 4. mark DN storage is initilized
+    // 4. mark DN storage is initialized
     this.initialized = true;
   }
 
@@ -724,9 +711,11 @@ public class DataStorage extends Storage
   
   /*
    * Finalize the upgrade for a block pool
+   * This also empties trash created during rolling upgrade and disables
+   * trash functionality.
    */
   void finalizeUpgrade(String bpID) throws IOException {
-    // To handle finalizing a snapshot taken at datanode level while 
+    // To handle finalizing a snapshot taken at datanode level while
     // upgrading to federation, if datanode level snapshot previous exists, 
     // then finalize it. Else finalize the corresponding BP.
     for (StorageDirectory sd : storageDirs) {

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/FsDatasetSpi.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/FsDatasetSpi.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/FsDatasetSpi.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/FsDatasetSpi.java
 Mon Feb 24 20:46:35 2014
@@ -417,11 +417,16 @@ public interface FsDatasetSpi<V extends 
    * moved to a separate trash directory instead of being deleted immediately.
    * This can be useful for example during rolling upgrades.
    */
-  public void enableDeleteToTrash(String bpid);
+  public void enableTrash(String bpid);
 
   /**
-   * Disable 'trash' for the given dataset and purge existing files in 'trash'.
+   * Restore trash
    */
-  public void disableAndPurgeTrashStorage(String bpid);
+  public void restoreTrash(String bpid);
+
+  /**
+   * @return true when trash is enabled
+   */
+  public boolean trashEnabled(String bpid);
 }
 

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImpl.java
 Mon Feb 24 20:46:35 2014
@@ -17,27 +17,6 @@
  */
 package org.apache.hadoop.hdfs.server.datanode.fsdataset.impl;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.StandardMBean;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.classification.InterfaceAudience;
@@ -45,37 +24,12 @@ import org.apache.hadoop.conf.Configurat
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hdfs.DFSConfigKeys;
 import org.apache.hadoop.hdfs.StorageType;
-import org.apache.hadoop.hdfs.protocol.Block;
-import org.apache.hadoop.hdfs.protocol.BlockListAsLongs;
-import org.apache.hadoop.hdfs.protocol.BlockLocalPathInfo;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.HdfsBlocksMetadata;
-import org.apache.hadoop.hdfs.protocol.RecoveryInProgressException;
+import org.apache.hadoop.hdfs.protocol.*;
 import org.apache.hadoop.hdfs.server.common.GenerationStamp;
 import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.ReplicaState;
 import org.apache.hadoop.hdfs.server.common.Storage;
-import org.apache.hadoop.hdfs.server.datanode.BlockMetadataHeader;
-import org.apache.hadoop.hdfs.server.datanode.DataBlockScanner;
-import org.apache.hadoop.hdfs.server.datanode.DataNode;
-import org.apache.hadoop.hdfs.server.datanode.DataStorage;
-import org.apache.hadoop.hdfs.server.datanode.FinalizedReplica;
-import org.apache.hadoop.hdfs.server.datanode.Replica;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaAlreadyExistsException;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaBeingWritten;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaInPipeline;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaInfo;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaNotFoundException;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaUnderRecovery;
-import org.apache.hadoop.hdfs.server.datanode.ReplicaWaitingToBeRecovered;
-import org.apache.hadoop.hdfs.server.datanode.StorageLocation;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.ReplicaInputStreams;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.ReplicaOutputStreams;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.RollingLogs;
-import 
org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.VolumeChoosingPolicy;
+import org.apache.hadoop.hdfs.server.datanode.*;
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.*;
 import org.apache.hadoop.hdfs.server.datanode.metrics.FSDatasetMBean;
 import 
org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
 import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
@@ -89,6 +43,15 @@ import org.apache.hadoop.util.DiskChecke
 import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.hadoop.util.Time;
 
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.*;
+import java.util.concurrent.Executor;
+
 /**************************************************
  * FSDataset manages a set of data blocks.  Each block
  * has a unique name and an extent on disk.
@@ -1894,13 +1857,18 @@ class FsDatasetImpl implements FsDataset
   }
 
   @Override
-  public void enableDeleteToTrash(String bpid) {
+  public void enableTrash(String bpid) {
     dataStorage.enableTrash(bpid);
   }
 
   @Override
-  public void disableAndPurgeTrashStorage(String bpid) {
-    dataStorage.disableAndPurgeTrash(bpid);
+  public void restoreTrash(String bpid) {
+    dataStorage.restoreTrash(bpid);
+  }
+
+  @Override
+  public boolean trashEnabled(String bpid) {
+    return dataStorage.trashEnabled(bpid);
   }
 
   @Override

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java
 Mon Feb 24 20:46:35 2014
@@ -17,10 +17,6 @@
  */
 package org.apache.hadoop.hdfs;
 
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -39,6 +35,10 @@ import org.apache.hadoop.hdfs.tools.DFSA
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+
 
 /**
  * This class tests rolling upgrade.
@@ -46,8 +46,13 @@ import org.junit.Test;
 public class TestRollingUpgrade {
   private static final Log LOG = LogFactory.getLog(TestRollingUpgrade.class);
 
-  private void runCmd(DFSAdmin dfsadmin, String... args) throws Exception {
-    Assert.assertEquals(0, dfsadmin.run(args));
+  public static void runCmd(DFSAdmin dfsadmin, boolean success,
+      String... args) throws  Exception {
+    if (success) {
+      Assert.assertEquals(0, dfsadmin.run(args));
+    } else {
+      Assert.assertTrue(dfsadmin.run(args) != 0);
+    }
   }
 
   /**
@@ -71,30 +76,29 @@ public class TestRollingUpgrade {
         final DFSAdmin dfsadmin = new DFSAdmin(conf);
         dfs.mkdirs(foo);
 
-        {
-          //illegal argument
-          final String[] args = {"-rollingUpgrade", "abc"};
-          Assert.assertTrue(dfsadmin.run(args) != 0);
-        }
+        //illegal argument "abc" to rollingUpgrade option
+        runCmd(dfsadmin, false, "-rollingUpgrade", "abc");
 
         //query rolling upgrade
-        runCmd(dfsadmin, "-rollingUpgrade");
+        runCmd(dfsadmin, true, "-rollingUpgrade");
 
         //start rolling upgrade
-        runCmd(dfsadmin, "-rollingUpgrade", "start");
+        runCmd(dfsadmin, true, "-rollingUpgrade", "start");
 
         //query rolling upgrade
-        runCmd(dfsadmin, "-rollingUpgrade", "query");
+        runCmd(dfsadmin, true, "-rollingUpgrade", "query");
 
         dfs.mkdirs(bar);
         
         //finalize rolling upgrade
-        runCmd(dfsadmin, "-rollingUpgrade", "finalize");
+        runCmd(dfsadmin, true, "-rollingUpgrade", "finalize");
 
         dfs.mkdirs(baz);
 
-        runCmd(dfsadmin, "-rollingUpgrade");
+        runCmd(dfsadmin, true, "-rollingUpgrade");
 
+        // All directories created before upgrade, when upgrade in progress and
+        // after upgrade finalize exists
         Assert.assertTrue(dfs.exists(foo));
         Assert.assertTrue(dfs.exists(bar));
         Assert.assertTrue(dfs.exists(baz));
@@ -104,6 +108,7 @@ public class TestRollingUpgrade {
         dfs.setSafeMode(SafeModeAction.SAFEMODE_LEAVE);
       }
 
+      // Ensure directories exist after restart
       cluster.restartNameNode();
       {
         final DistributedFileSystem dfs = cluster.getFileSystem();

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java
 Mon Feb 24 20:46:35 2014
@@ -1055,13 +1055,17 @@ public class SimulatedFSDataset implemen
   }
 
   @Override
-  public void enableDeleteToTrash(String bpid) {
+  public void enableTrash(String bpid) {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  public void disableAndPurgeTrashStorage(String bpid) {
-    // do nothing
+  public void restoreTrash(String bpid) {
+  }
+
+  @Override
+  public boolean trashEnabled(String bpid) {
+    return false;
   }
 
   @Override

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeRollingUpgrade.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeRollingUpgrade.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeRollingUpgrade.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDataNodeRollingUpgrade.java
 Mon Feb 24 20:46:35 2014
@@ -20,23 +20,22 @@ package org.apache.hadoop.hdfs.server.da
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.commons.logging.impl.Log4JLogger;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.DFSTestUtil;
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-import org.apache.hadoop.hdfs.HdfsConfiguration;
-import org.apache.hadoop.hdfs.MiniDFSCluster;
-import org.apache.hadoop.hdfs.MiniDFSCluster.DataNodeProperties;
+import org.apache.hadoop.hdfs.*;
+import org.apache.hadoop.hdfs.protocol.BlockLocalPathInfo;
+import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
+import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
+import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.tools.DFSAdmin;
-import org.apache.log4j.Level;
 import org.junit.Test;
 
+import java.io.File;
 import java.io.IOException;
 
+import static org.apache.hadoop.hdfs.MiniDFSCluster.*;
 import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 /**
  * Ensure that the DataNode correctly handles rolling upgrade
@@ -47,132 +46,190 @@ public class TestDataNodeRollingUpgrade 
 
   private static final short REPL_FACTOR = 1;
   private static final int BLOCK_SIZE = 1024 * 1024;
-  private static final long FILE_SIZE = BLOCK_SIZE * 4;
+  private static final long FILE_SIZE = BLOCK_SIZE;
   private static final long SEED = 0x1BADF00DL;
 
   Configuration conf;
   MiniDFSCluster cluster = null;
-  DistributedFileSystem fs;
+  DistributedFileSystem fs = null;
+  DataNode dn = null;
+  NameNode nn = null;
+  String blockPoolId = null;
+
+  private void startCluster() throws IOException {
+    conf = new HdfsConfiguration();
+    cluster = new Builder(conf).numDataNodes(REPL_FACTOR).build();
+    cluster.waitActive();
+    fs = cluster.getFileSystem();
+    nn = cluster.getNameNode(0);
+    assertNotNull(nn);
+    dn = cluster.getDataNodes().get(0);
+    assertNotNull(dn);
+    blockPoolId = cluster.getNameNode(0).getNamesystem().getBlockPoolId();
+  }
 
-  private void runCmd(DFSAdmin dfsadmin, String... args) throws Exception {
-    assertThat(dfsadmin.run(args), is(0));
+  private void shutdownCluster() {
+    if (cluster != null) {
+      cluster.shutdown();
+      cluster = null;
+    }
+    fs = null;
+    nn = null;
+    dn = null;
+    blockPoolId = null;
+  }
+
+  private void triggerHeartBeats() throws Exception {
+    // Sleep briefly so that DN learns of the rolling upgrade
+    // state and other states from heartbeats.
+    cluster.triggerHeartbeats();
+    Thread.sleep(5000);
+  }
+
+  /** Test assumes that the file has a single block */
+  private File getBlockForFile(Path path, boolean exists) throws IOException {
+    LocatedBlocks blocks = nn.getRpcServer().getBlockLocations(path.toString(),
+        0, Long.MAX_VALUE);
+    assertEquals(1, blocks.getLocatedBlocks().size());
+    ExtendedBlock block = blocks.getLocatedBlocks().get(0).getBlock();
+    BlockLocalPathInfo bInfo = dn.getFSDataset().getBlockLocalPathInfo(block);
+    File blockFile = new File(bInfo.getBlockPath());
+    assertEquals(exists, blockFile.exists());
+    return blockFile;
+  }
+
+  private File getTrashFileForBlock(File blockFile, boolean exists) {
+    File trashFile = new File(
+        dn.getStorage().getTrashDirectoryForBlockFile(blockPoolId, blockFile));
+    assertEquals(exists, trashFile.exists());
+    return trashFile;
+  }
+
+  /**
+   * Ensures that the blocks belonging to the deleted file are in trash
+   */
+  private void deleteAndEnsureInTrash(Path pathToDelete,
+      File blockFile, File trashFile) throws Exception {
+    assertTrue(blockFile.exists());
+    assertFalse(trashFile.exists());
+
+    // Now delete the file and ensure the corresponding block in trash
+    LOG.info("Deleting file " + pathToDelete + " during rolling upgrade");
+    fs.delete(pathToDelete, false);
+    assert(!fs.exists(pathToDelete));
+    triggerHeartBeats();
+    assertTrue(trashFile.exists());
+    assertFalse(blockFile.exists());
+  }
+
+  private void ensureTrashDisabled() {
+    // Trash is disabled; trash root does not exist
+    assertFalse(dn.getFSDataset().trashEnabled(blockPoolId));
+    BlockPoolSliceStorage bps = dn.getStorage().getBPStorage(blockPoolId);
+    assertFalse(bps.trashEnabled());
+  }
+
+  /**
+   * Ensures that the blocks from trash are restored
+   */
+  private void ensureTrashRestored(File blockFile, File trashFile)
+      throws Exception {
+    assertTrue(blockFile.exists());
+    assertFalse(trashFile.exists());
+    ensureTrashDisabled();
   }
 
   private void startRollingUpgrade() throws Exception {
     LOG.info("Starting rolling upgrade");
     final DFSAdmin dfsadmin = new DFSAdmin(conf);
-    runCmd(dfsadmin, "-rollingUpgrade", "start");
+    TestRollingUpgrade.runCmd(dfsadmin, true, "-rollingUpgrade", "start");
+    triggerHeartBeats();
+
+    // Ensure datanode rolling upgrade is started
+    assertTrue(dn.getFSDataset().trashEnabled(blockPoolId));
   }
 
   private void finalizeRollingUpgrade() throws Exception {
     LOG.info("Finalizing rolling upgrade");
     final DFSAdmin dfsadmin = new DFSAdmin(conf);
-    runCmd(dfsadmin, "-rollingUpgrade", "finalize");
+    TestRollingUpgrade.runCmd(dfsadmin, true, "-rollingUpgrade", "finalize");
+    triggerHeartBeats();
+
+    // Ensure datanode rolling upgrade is started
+    assertFalse(dn.getFSDataset().trashEnabled(blockPoolId));
+    BlockPoolSliceStorage bps = dn.getStorage().getBPStorage(blockPoolId);
+    assertFalse(bps.trashEnabled());
   }
 
   private void rollbackRollingUpgrade() throws Exception {
+    // Shutdown datanodes and namenodes
+    // Restart the namenode with rolling upgrade rollback
     LOG.info("Starting rollback of the rolling upgrade");
-
-    // Shutdown the DN and the NN in preparation for rollback.
-    DataNodeProperties dnprop = cluster.stopDataNode(0);
+    MiniDFSCluster.DataNodeProperties dnprop = cluster.stopDataNode(0);
     cluster.shutdownNameNodes();
-
-    // Restart the daemons with rollback flags.
     cluster.restartNameNode("-rollingupgrade", "rollback");
-    dnprop.setDnArgs("-rollingupgrade", "rollback");
     cluster.restartDataNode(dnprop);
     cluster.waitActive();
+    nn = cluster.getNameNode(0);
+    dn = cluster.getDataNodes().get(0);
+    triggerHeartBeats();
   }
 
   @Test (timeout=600000)
   public void testDatanodeRollingUpgradeWithFinalize() throws Exception {
-    // start a cluster
     try {
-      // Start a cluster.
-      conf = new HdfsConfiguration();
-      cluster = new 
MiniDFSCluster.Builder(conf).numDataNodes(REPL_FACTOR).build();
-      cluster.waitActive();
-      fs = cluster.getFileSystem();
-      Path testFile1 = new Path("/TestDataNodeRollingUpgrade1.dat");
-      Path testFile2 = new Path("/TestDataNodeRollingUpgrade2.dat");
+      startCluster();
 
       // Create files in DFS.
+      Path testFile1 = new Path("/TestDataNodeRollingUpgrade1.dat");
+      Path testFile2 = new Path("/TestDataNodeRollingUpgrade2.dat");
       DFSTestUtil.createFile(fs, testFile1, FILE_SIZE, REPL_FACTOR, SEED);
       DFSTestUtil.createFile(fs, testFile2, FILE_SIZE, REPL_FACTOR, SEED);
 
       startRollingUpgrade();
-
-      // Sleep briefly so that DN learns of the rolling upgrade
-      // from heartbeats.
-      cluster.triggerHeartbeats();
-      Thread.sleep(5000);
-
-      fs.delete(testFile2, false);
-
-      // Sleep briefly so that block files can be moved to trash
-      // (this is scheduled for asynchronous execution).
-      cluster.triggerBlockReports();
-      Thread.sleep(5000);
-
+      File blockFile = getBlockForFile(testFile2, true);
+      File trashFile = getTrashFileForBlock(blockFile, false);
+      deleteAndEnsureInTrash(testFile2, blockFile, trashFile);
       finalizeRollingUpgrade();
 
-      // Ensure that testFile2 stays deleted.
+      // Ensure that delete file testFile2 stays deleted after finalize
+      ensureTrashDisabled();
       assert(!fs.exists(testFile2));
       assert(fs.exists(testFile1));
 
     } finally {
-      if (cluster != null) {
-        cluster.shutdown();
-        cluster = null;
-      }
+      shutdownCluster();
     }
   }
 
   @Test (timeout=600000)
   public void testDatanodeRollingUpgradeWithRollback() throws Exception {
-    // start a cluster
     try {
-      // Start a cluster.
-      conf = new HdfsConfiguration();
-      cluster = new 
MiniDFSCluster.Builder(conf).numDataNodes(REPL_FACTOR).build();
-      cluster.waitActive();
-      fs = cluster.getFileSystem();
-      Path testFile1 = new Path("/TestDataNodeRollingUpgrade1.dat");
+      startCluster();
 
       // Create files in DFS.
-      DFSTestUtil.createFile(fs, testFile1, BLOCK_SIZE, BLOCK_SIZE, FILE_SIZE, 
REPL_FACTOR, SEED);
+      Path testFile1 = new Path("/TestDataNodeRollingUpgrade1.dat");
+      DFSTestUtil.createFile(fs, testFile1, FILE_SIZE, REPL_FACTOR, SEED);
       String fileContents1 = DFSTestUtil.readFile(fs, testFile1);
 
       startRollingUpgrade();
 
-      // Sleep briefly so that DN learns of the rolling upgrade
-      // from heartbeats.
-      cluster.triggerHeartbeats();
-      Thread.sleep(5000);
-
-      LOG.info("Deleting file during rolling upgrade");
-      fs.delete(testFile1, false);
-
-      // Sleep briefly so that block files can be moved to trash
-      // (this is scheduled for asynchronous execution).
-      cluster.triggerBlockReports();
-      Thread.sleep(5000);
-      assert(!fs.exists(testFile1));
+      File blockFile = getBlockForFile(testFile1, true);
+      File trashFile = getTrashFileForBlock(blockFile, false);
+      deleteAndEnsureInTrash(testFile1, blockFile, trashFile);
 
       // Now perform a rollback to restore DFS to the pre-rollback state.
       rollbackRollingUpgrade();
 
-      // Ensure that testFile1 was restored after the rollback.
+      // Ensure that block was restored from trash
+      ensureTrashRestored(blockFile, trashFile);
+
+      // Ensure that files exist and restored file contents are the same.
       assert(fs.exists(testFile1));
       String fileContents2 = DFSTestUtil.readFile(fs, testFile1);
-
-      // Ensure that file contents are the same.
       assertThat(fileContents1, is(fileContents2));
     } finally {
-      if (cluster != null) {
-        cluster.shutdown();
-        cluster = null;
-      }
+      shutdownCluster();
     }
   }
 }

Modified: 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDatanodeStartupOptions.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDatanodeStartupOptions.java?rev=1571431&r1=1571430&r2=1571431&view=diff
==============================================================================
--- 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDatanodeStartupOptions.java
 (original)
+++ 
hadoop/common/branches/HDFS-5535/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestDatanodeStartupOptions.java
 Mon Feb 24 20:46:35 2014
@@ -83,8 +83,6 @@ public class TestDatanodeStartupOptions 
     checkExpected(true, StartupOption.REGULAR, conf, "-regular");
     checkExpected(true, StartupOption.REGULAR, conf, "-REGULAR");
     checkExpected(true, StartupOption.ROLLBACK, conf, "-rollback");
-    checkExpected(true, StartupOption.ROLLINGUPGRADE, conf, "-rollingupgrade", 
"rollback");
-    checkExpected(true, StartupOption.ROLLINGUPGRADE, conf, "-rollingupgraDE", 
"ROLLBack");
   }
 
   /**
@@ -94,7 +92,5 @@ public class TestDatanodeStartupOptions 
   public void testStartupFailure() {
     checkExpected(false, StartupOption.REGULAR, conf, "unknownoption");
     checkExpected(false, StartupOption.REGULAR, conf, "-regular -rollback");
-    checkExpected(false, StartupOption.REGULAR, conf, "-rollingupgrade", 
"downgrade");
-    checkExpected(false, StartupOption.REGULAR, conf, "-rollingupgrade", 
"unknownoption");
   }
 }


Reply via email to