瀏覽代碼

HDFS-3840. JournalNodes log JournalNotFormattedException backtrace error before being formatted. Contributed by Todd Lipcon.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-3077@1383252 13f79535-47bb-0310-9956-ffa450edef68
Todd Lipcon 12 年之前
父節點
當前提交
a93ba1648a

+ 2 - 0
hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-3077.txt

@@ -68,3 +68,5 @@ HDFS-3914. QJM: acceptRecovery should abort current segment (todd)
 HDFS-3915. QJM: Failover fails with auth error in secure cluster (todd)
 
 HDFS-3906. QJM: quorum timeout on failover with large log segment (todd)
+
+HDFS-3840. JournalNodes log JournalNotFormattedException backtrace error before being formatted (todd)

+ 5 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/client/AsyncLogger.java

@@ -90,6 +90,11 @@ interface AsyncLogger {
    */
   public ListenableFuture<Void> format(NamespaceInfo nsInfo);
 
+  /**
+   * @return whether or not the remote node has any valid data.
+   */
+  public ListenableFuture<Boolean> isFormatted();
+  
   /**
    * @return the state of the last epoch on the target node.
    */

+ 1 - 23
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/client/AsyncLoggerSet.java

@@ -216,29 +216,7 @@ class AsyncLoggerSet {
   public QuorumCall<AsyncLogger, Boolean> isFormatted() {
     Map<AsyncLogger, ListenableFuture<Boolean>> calls = Maps.newHashMap();
     for (AsyncLogger logger : loggers) {
-      final SettableFuture<Boolean> ret = SettableFuture.create();
-      ListenableFuture<GetJournalStateResponseProto> jstate =
-          logger.getJournalState();
-      Futures.addCallback(jstate, new FutureCallback<GetJournalStateResponseProto>() {
-        @Override
-        public void onFailure(Throwable t) {
-          if (t instanceof RemoteException) {
-            t = ((RemoteException)t).unwrapRemoteException();
-          }
-          if (t instanceof JournalNotFormattedException) {
-            ret.set(false);
-          } else {
-            ret.setException(t);
-          }
-        }
-
-        @Override
-        public void onSuccess(GetJournalStateResponseProto jstate) {
-          ret.set(true);
-        }
-      });
-      
-      calls.put(logger, ret);
+      calls.put(logger, logger.isFormatted());
     }
     return QuorumCall.create(calls);
   }

+ 10 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/client/IPCLoggerChannel.java

@@ -293,6 +293,16 @@ public class IPCLoggerChannel implements AsyncLogger {
     }
   }
 
+  @Override
+  public ListenableFuture<Boolean> isFormatted() {
+    return executor.submit(new Callable<Boolean>() {
+      @Override
+      public Boolean call() throws IOException {
+        return getProxy().isFormatted(journalId);
+      }
+    });
+  }
+
   @Override
   public ListenableFuture<GetJournalStateResponseProto> getJournalState() {
     return executor.submit(new Callable<GetJournalStateResponseProto>() {

+ 6 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/protocol/QJournalProtocol.java

@@ -47,6 +47,12 @@ import org.apache.hadoop.security.KerberosInfo;
 public interface QJournalProtocol {
   public static final long versionID = 1L;
 
+  /**
+   * @return true if the given journal has been formatted and
+   * contains valid data.
+   */
+  public boolean isFormatted(String journalId) throws IOException;
+
   /**
    * Get the current state of the journal, including the most recent
    * epoch number and the HTTP port.

+ 18 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/protocolPB/QJournalProtocolServerSideTranslatorPB.java

@@ -32,6 +32,8 @@ import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.GetJourna
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.GetJournalStateResponseProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.HeartbeatRequestProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.HeartbeatResponseProto;
+import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.IsFormattedRequestProto;
+import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.IsFormattedResponseProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.JournalIdProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.JournalRequestProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.JournalResponseProto;
@@ -67,6 +69,22 @@ public class QJournalProtocolServerSideTranslatorPB implements QJournalProtocolP
     this.impl = impl;
   }
 
+  
+  @Override
+  public IsFormattedResponseProto isFormatted(RpcController controller,
+      IsFormattedRequestProto request) throws ServiceException {
+    try {
+      boolean ret = impl.isFormatted(
+          convert(request.getJid()));
+      return IsFormattedResponseProto.newBuilder()
+          .setIsFormatted(ret)
+          .build();
+    } catch (IOException ioe) {
+      throw new ServiceException(ioe);
+    }
+  }
+
+
   @Override
   public GetJournalStateResponseProto getJournalState(RpcController controller,
       GetJournalStateRequestProto request) throws ServiceException {

+ 16 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/protocolPB/QJournalProtocolTranslatorPB.java

@@ -33,6 +33,8 @@ import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.GetEditLo
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.GetJournalStateRequestProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.GetJournalStateResponseProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.HeartbeatRequestProto;
+import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.IsFormattedRequestProto;
+import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.IsFormattedResponseProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.JournalIdProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.JournalRequestProto;
 import org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos.NewEpochRequestProto;
@@ -78,6 +80,20 @@ public class QJournalProtocolTranslatorPB implements ProtocolMetaInterface,
   }
 
 
+  @Override
+  public boolean isFormatted(String journalId) throws IOException {
+    try {
+      IsFormattedRequestProto req = IsFormattedRequestProto.newBuilder()
+          .setJid(convertJournalId(journalId))
+          .build();
+      IsFormattedResponseProto resp = rpcProxy.isFormatted(
+          NULL_CONTROLLER, req);
+      return resp.getIsFormatted();
+    } catch (ServiceException e) {
+      throw ProtobufHelper.getRemoteException(e);
+    }
+  }
+
   @Override
   public GetJournalStateResponseProto getJournalState(String jid)
       throws IOException {

+ 7 - 3
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/server/Journal.java

@@ -402,10 +402,14 @@ class Journal implements Closeable {
     }
   }
   
+  public synchronized boolean isFormatted() {
+    return storage.isFormatted();
+  }
+
   private void checkFormatted() throws JournalNotFormattedException {
-    if (!storage.isFormatted()) {
-      throw new JournalNotFormattedException("Journal " + storage +
-          " not formatted");
+    if (!isFormatted()) {
+      throw new JournalNotFormattedException("Journal " +
+          storage.getSingularStorageDir() + " not formatted");
     }
   }
 

+ 5 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/server/JournalNodeRpcServer.java

@@ -107,6 +107,11 @@ class JournalNodeRpcServer implements QJournalProtocol {
         DFSConfigKeys.DFS_JOURNALNODE_RPC_ADDRESS_KEY);
   }
 
+  @Override
+  public boolean isFormatted(String journalId) throws IOException {
+    return jn.getOrCreateJournal(journalId).isFormatted();
+  }
+
   @Override
   public GetJournalStateResponseProto getJournalState(String journalId)
         throws IOException {

+ 13 - 0
hadoop-hdfs-project/hadoop-hdfs/src/main/proto/QJournalProtocol.proto

@@ -116,6 +116,17 @@ message PurgeLogsRequestProto {
 message PurgeLogsResponseProto {
 }
 
+/**
+ * isFormatted()
+ */
+message IsFormattedRequestProto {
+  required JournalIdProto jid = 1;
+}
+
+message IsFormattedResponseProto {
+  required bool isFormatted = 1;
+}
+
 /**
  * getJournalState()
  */
@@ -210,6 +221,8 @@ message AcceptRecoveryResponseProto {
  * See the request and response for details of rpc call.
  */
 service QJournalProtocolService {
+  rpc isFormatted(IsFormattedRequestProto) returns (IsFormattedResponseProto);
+
   rpc getJournalState(GetJournalStateRequestProto) returns (GetJournalStateResponseProto);
 
   rpc newEpoch(NewEpochRequestProto) returns (NewEpochResponseProto);

+ 4 - 1
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/server/TestJournal.java

@@ -156,10 +156,13 @@ public class TestJournal {
 
     assertEquals(12345L, journal.getLastPromisedEpoch());
     assertEquals(12345L, journal.getLastWriterEpoch());
-
+    assertTrue(journal.isFormatted());
+    
     journal.format(FAKE_NSINFO_2);
+    
     assertEquals(0, journal.getLastPromisedEpoch());
     assertEquals(0, journal.getLastWriterEpoch());
+    assertTrue(journal.isFormatted());
   }
   
   /**