001/*
002  * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.zookeeper;
019
020import java.io.IOException;
021import java.io.UnsupportedEncodingException;
022import java.net.URLDecoder;
023import java.net.URLEncoder;
024
025import org.apache.hadoop.fs.FileSystem;
026import org.apache.hadoop.fs.Path;
027import org.apache.hadoop.hbase.HConstants;
028import org.apache.yetus.audience.InterfaceAudience;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032/**
033 * Common methods and attributes used by SplitLogManager and SplitLogWorker running distributed
034 * splitting of WAL logs.
035 */
036@InterfaceAudience.Private
037public final class ZKSplitLog {
038  private static final Logger LOG = LoggerFactory.getLogger(ZKSplitLog.class);
039
040  private ZKSplitLog() {
041  }
042
043  /**
044   * Gets the full path node name for the log file being split.
045   * This method will url encode the filename.
046   * @param zkw zk reference
047   * @param filename log file name (only the basename)
048   */
049  public static String getEncodedNodeName(ZKWatcher zkw, String filename) {
050    return ZNodePaths.joinZNode(zkw.getZNodePaths().splitLogZNode, encode(filename));
051  }
052
053  public static String getFileName(String node) {
054    String basename = node.substring(node.lastIndexOf('/') + 1);
055    return decode(basename);
056  }
057
058  static String encode(String s) {
059    try {
060      return URLEncoder.encode(s, "UTF-8");
061    } catch (UnsupportedEncodingException e) {
062      throw new RuntimeException("URLENCODER doesn't support UTF-8");
063    }
064  }
065
066  static String decode(String s) {
067    try {
068      return URLDecoder.decode(s, "UTF-8");
069    } catch (UnsupportedEncodingException e) {
070      throw new RuntimeException("URLDecoder doesn't support UTF-8");
071    }
072  }
073
074  public static String getRescanNode(ZKWatcher zkw) {
075    return ZNodePaths.joinZNode(zkw.getZNodePaths().splitLogZNode, "RESCAN");
076  }
077
078  /**
079   * @param name the last part in path
080   * @return whether the node name represents a rescan node
081   */
082  public static boolean isRescanNode(String name) {
083    return name.startsWith("RESCAN");
084  }
085
086  /**
087   * Checks if the given path represents a rescan node.
088   *
089   * @param zkw reference to the {@link ZKWatcher} which also contains configuration and constants
090   * @param path the absolute path, starts with '/'
091   * @return whether the path represents a rescan node
092   */
093  public static boolean isRescanNode(ZKWatcher zkw, String path) {
094    String prefix = getRescanNode(zkw);
095    if (path.length() <= prefix.length()) {
096      return false;
097    }
098    for (int i = 0; i < prefix.length(); i++) {
099      if (prefix.charAt(i) != path.charAt(i)) {
100        return false;
101      }
102    }
103    return true;
104  }
105
106  public static Path getSplitLogDir(Path rootdir, String tmpname) {
107    return new Path(new Path(rootdir, HConstants.SPLIT_LOGDIR_NAME), tmpname);
108  }
109
110  public static void markCorrupted(Path rootdir, String logFileName,
111      FileSystem fs) {
112    Path file = new Path(getSplitLogDir(rootdir, logFileName), "corrupt");
113    try {
114      fs.createNewFile(file);
115    } catch (IOException e) {
116      LOG.warn("Could not flag a log file as corrupted. Failed to create " +
117          file, e);
118    }
119  }
120
121  public static boolean isCorrupted(Path rootdir, String logFileName,
122      FileSystem fs) throws IOException {
123    Path file = new Path(getSplitLogDir(rootdir, logFileName), "corrupt");
124    boolean isCorrupt;
125    isCorrupt = fs.exists(file);
126    return isCorrupt;
127  }
128}