Package org.apache.hadoop.hdfs.notifier.server

Source Code of org.apache.hadoop.hdfs.notifier.server.ServerLogReaderAvatar

/**
* 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.notifier.server;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.AvatarZooKeeperClient;
import org.apache.hadoop.hdfs.CachingAvatarZooKeeperClient;
import org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager;
import org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory;
import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.apache.hadoop.hdfs.server.common.Util;
import org.apache.hadoop.hdfs.server.namenode.AvatarNode;
import org.apache.hadoop.hdfs.server.namenode.FileJournalManagerReadOnly;
import org.apache.hadoop.hdfs.server.namenode.JournalManager;
import org.apache.hadoop.hdfs.server.namenode.NNStorage;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;

/**
* This class supports reading the edit logs from HDFS Avatar nodes, so it is
* failover-aware, and the HDFS namenode failover would be transparent for
* this log reader.
*
*/
public class ServerLogReaderAvatar extends ServerLogReaderTransactional {

  public static final Log LOG = LogFactory
      .getLog(ServerLogReaderAvatar.class);

  // remote journal from which the reader is consuming transactions
  private final JournalManager remoteJournalManagerZero;
  private final JournalManager remoteJournalManagerOne;
 
  /**
   * The location of the edits logs for Avatar zero and one node.
   */
  private final URI editsUriZero;
  private final URI editsUriOne;
 
  /* We will look up the rpc address in zookeeper entity to determine
   *  which node is the current primary node
   */
  // rpc address of the avatar zero node
  private URI avatarZeroURI;
  // rpc address of the avatar one node
  private URI avatarOneURI;
 
  // the rpc address we read from zookeeper entity.
  private URI primaryURI = null;

  // the name of the zookeeper entity.
  private URI logicalName;
 
  private CachingAvatarZooKeeperClient zk;
 
  private static final int FAILOVER_RETRY_SLEEP = 1000;
 
  static {
    Configuration.addDefaultResource("avatar-default.xml");
    Configuration.addDefaultResource("avatar-site.xml");
  }

  static void throwIOException(String msg, Throwable e)
      throws IOException {
    LOG.error(msg, e);
    throw new IOException(msg, e);
  }
 
  public ServerLogReaderAvatar(IServerCore core)
      throws IOException {
   
    super(core, null);
   
    // append the service name to each avatar meta directory name
    String serviceName = core.getServiceName();
    if (serviceName != null && !serviceName.equals("")) {
      AvatarNode.adjustMetaDirectoryNames(conf, serviceName);
    } else {
      serviceName = "";
    }
   
    // edits directory uri
    String editsStringZero = core.getConfiguration().get(
        AvatarNode.DFS_SHARED_EDITS_DIR0_KEY);
    String editsStringOne = core.getConfiguration().get(
        AvatarNode.DFS_SHARED_EDITS_DIR1_KEY);
   
    editsUriZero = Util.stringAsURI(editsStringZero);
    editsUriOne = Util.stringAsURI(editsStringOne);

    remoteJournalManagerZero = constructJournalManager(editsUriZero);
    remoteJournalManagerOne = constructJournalManager(editsUriOne);
   
    try {
      this.logicalName = new URI("hdfs://" +
          conf.get(NameNode.DFS_NAMENODE_RPC_ADDRESS_KEY +
          (serviceName.isEmpty() ? "" : "." + serviceName), ""));
     
      this.avatarZeroURI = addrToURI(conf.get(
                          AvatarNode.DFS_NAMENODE_RPC_ADDRESS0_KEY +
                          (serviceName.isEmpty() ? "" : "." + serviceName), ""));
      this.avatarOneURI = addrToURI(conf.get(
                          AvatarNode.DFS_NAMENODE_RPC_ADDRESS1_KEY +
                          (serviceName.isEmpty() ? "" : "." + serviceName), ""));
     
      zk = new CachingAvatarZooKeeperClient(conf, null);

      LOG.info("Initializing input stream");
      initialize();
      LOG.info("Initialization completed");
    } catch (URISyntaxException e) {
      throwIOException(e.getMessage(), e);
    }
  }
 
  private JournalManager constructJournalManager(URI editsUri)
      throws IOException {
    if (editsUri.getScheme().equals(NNStorage.LOCAL_URI_SCHEME)) {
      StorageDirectory sd = new NNStorage(new StorageInfo()).new StorageDirectory(
          new File(editsUri.getPath()));
      return new FileJournalManagerReadOnly(sd);
    } else if (editsUri.getScheme().equals(QuorumJournalManager.QJM_URI_SCHEME)) {
      return new QuorumJournalManager(conf, editsUri,
              new NamespaceInfo(new StorageInfo()), null, false);
    } else {
      throwIOException("Other journals not supported yet.", null);
    }
    return null;
  }
 
  /**
   * Construct URI from address string.
   */
  private URI addrToURI(String addrString) throws URISyntaxException {
    if (addrString.startsWith(logicalName.getScheme())) {
      // if the scheme is correct, we just return the new URI(...)
      return new URI(addrString);
    } else {
      // otherwise, we will extract the host and port from the address
      // string, and construct the URI using logicalName's scheme (hdfs://).
      if (addrString.indexOf(":") == -1) {
        // This is not a valid addr string
        return null;
      }
      String fsHost = addrString.substring(0, addrString.indexOf(":"));
      int port = Integer.parseInt(addrString
                                  .substring(addrString.indexOf(":") + 1));
      return new URI(logicalName.getScheme(),
                     logicalName.getUserInfo(),
                     fsHost, port, logicalName.getPath(),
                     logicalName.getQuery(), logicalName.getFragment());
    }
  }

  /**
   * Detect the primary node and the current Journal Manager;
   * @throws IOException
   */
  protected void detectJournalManager() throws IOException {
    int failures = 0;
    do {
      try {
        Stat stat = new Stat();
        String primaryAddr = zk.getPrimaryAvatarAddress(logicalName,
                                                     stat, true, true);
        if (primaryAddr == null || primaryAddr.trim().isEmpty()) {
          primaryURI = null;
          remoteJournalManager = null;
          LOG.warn("Failover detected, wait for it to finish...");
          failures = 0;
          sleep(FAILOVER_RETRY_SLEEP);
          continue;
        }
       
        primaryURI = addrToURI(primaryAddr);
       
        LOG.info("Read primary URI from zk: " + primaryURI);
        if (primaryURI.equals(avatarZeroURI)) {
          remoteJournalManager = remoteJournalManagerZero;
        } else if (primaryURI.equals(avatarOneURI)) {
          remoteJournalManager = remoteJournalManagerOne;
        } else {
          LOG.warn("Invalid primaryURI: " + primaryURI);
          primaryURI = null;
          remoteJournalManager = null;
          failures = 0;
          sleep(FAILOVER_RETRY_SLEEP);
        }
     
      } catch (KeeperException kex) {
        if (KeeperException.Code.CONNECTIONLOSS == kex.code()
            && failures < AvatarZooKeeperClient.ZK_CONNECTION_RETRIES) {
          failures++;
          // This means there was a failure connecting to zookeeper
          // we should retry since some nodes might be down.
          sleep(FAILOVER_RETRY_SLEEP);
          continue;
        }
        throwIOException(kex.getMessage(), kex);
      } catch (InterruptedException e) {
        throwIOException(e.getMessage(), e);
      } catch (URISyntaxException e) {
        throwIOException(e.getMessage(), e);
      }
    } while (remoteJournalManager == null);
  }
}
TOP

Related Classes of org.apache.hadoop.hdfs.notifier.server.ServerLogReaderAvatar

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.