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.regionserver.wal;
019
020import java.io.IOException;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.fs.FileSystem;
023import org.apache.hadoop.fs.Path;
024import org.apache.hadoop.hbase.ServerName;
025import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder;
026import org.apache.hadoop.hbase.namequeues.WALEventTrackerPayload;
027import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
028import org.apache.yetus.audience.InterfaceAudience;
029
030@InterfaceAudience.Private
031public class WALEventTrackerListener implements WALActionsListener {
032  private final Configuration conf;
033  private final NamedQueueRecorder namedQueueRecorder;
034  private final String serverName;
035
036  public enum WalState {
037    ROLLING,
038    ROLLED,
039    ACTIVE
040  }
041
042  public WALEventTrackerListener(Configuration conf, NamedQueueRecorder namedQueueRecorder,
043    ServerName serverName) {
044    this.conf = conf;
045    this.namedQueueRecorder = namedQueueRecorder;
046    this.serverName = serverName.getHostname();
047  }
048
049  @Override
050  public void preLogRoll(Path oldPath, Path newPath) {
051    if (oldPath != null) {
052      // oldPath can be null for first wal
053      // Just persist the last component of path not the whole walName which includes filesystem
054      // scheme, walDir.
055      WALEventTrackerPayload payloadForOldPath =
056        getPayload(oldPath.getName(), WalState.ROLLING.name(), 0L);
057      this.namedQueueRecorder.addRecord(payloadForOldPath);
058    }
059  }
060
061  @Override
062  public void postLogRoll(Path oldPath, Path newPath) {
063    // Create 2 entries entry in RingBuffer.
064    // 1. Change state to Rolled for oldPath
065    // 2. Change state to Active for newPath.
066    if (oldPath != null) {
067      // oldPath can be null for first wal
068      // Just persist the last component of path not the whole walName which includes filesystem
069      // scheme, walDir.
070
071      long fileLength = 0L;
072      try {
073        FileSystem fs = oldPath.getFileSystem(this.conf);
074        fileLength = fs.getFileStatus(oldPath).getLen();
075      } catch (IOException ioe) {
076        // Saving wal length is best effort. In case of any exception just ignore.
077      }
078      WALEventTrackerPayload payloadForOldPath =
079        getPayload(oldPath.getName(), WalState.ROLLED.name(), fileLength);
080      this.namedQueueRecorder.addRecord(payloadForOldPath);
081    }
082
083    WALEventTrackerPayload payloadForNewPath =
084      getPayload(newPath.getName(), WalState.ACTIVE.name(), 0L);
085    this.namedQueueRecorder.addRecord(payloadForNewPath);
086  }
087
088  private WALEventTrackerPayload getPayload(String path, String state, long walLength) {
089    long timestamp = EnvironmentEdgeManager.currentTime();
090    WALEventTrackerPayload payload =
091      new WALEventTrackerPayload(serverName, path, timestamp, state, walLength);
092    return payload;
093  }
094}