# Script looks at hbase .META. table verifying its content is coherent.
#
# To see usage for this script, run:
#
#  ${HBASE_HOME}/bin/hbase org.jruby.Main check_meta.rb --help
#

# Copyright 2010 The Apache Software Foundation
#
# 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.
#
include Java
import org.apache.commons.logging.LogFactory
import org.apache.hadoop.hbase.util.VersionInfo
import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import org.apache.hadoop.hbase.HConstants
import org.apache.hadoop.hbase.util.FSUtils
import org.apache.hadoop.hbase.client.HTable
import org.apache.hadoop.hbase.client.Scan
import org.apache.hadoop.hbase.util.Writables
import org.apache.hadoop.hbase.HRegionInfo
import org.apache.hadoop.hbase.util.Bytes
import org.apache.hadoop.hbase.HTableDescriptor
import org.apache.hadoop.hbase.client.Put

# Name of this script
NAME = 'check_meta'

# Print usage for this script
def usage
  puts 'Usage: %s.rb [--fix]' % NAME
  puts ' fix   Try to fixup meta issues'
  puts 'Script checks consistency of the .META. table.  It reports if .META. has missing entries.'
  puts 'If you pass "--fix", it will try looking in the filesystem for the dropped region and if it'
  puts 'finds a likely candidate, it will try pluggin the .META. hole.'
  exit!
end

def isFixup
  # Are we to do fixup during this run
  usage if ARGV.size > 1
  fixup = nil
  if ARGV.size == 1
    usage unless ARGV[0].downcase.match('--fix.*')
    fixup = 1
  end
  return fixup
end

def getConfiguration
  hbase_twenty = VersionInfo.getVersion().match('0\.20\..*')
  # Get configuration to use.
  if hbase_twenty
    c = HBaseConfiguration.new()
  else
    c = HBaseConfiguration.create()
  end
  # Set hadoop filesystem configuration using the hbase.rootdir.
  # Otherwise, we'll always use localhost though the hbase.rootdir
  # might be pointing at hdfs location. Do old and new key for fs.
  c.set("fs.default.name", c.get(HConstants::HBASE_DIR))
  c.set("fs.defaultFS", c.get(HConstants::HBASE_DIR))
  return c
end

def fixup(leftEdge, rightEdge, metatable, fs, rootdir)
  plugged = nil
  # Try and fix the passed holes in meta.
  tabledir = HTableDescriptor::getTableDir(rootdir, leftEdge.getTableDesc().getName())
  statuses = fs.listStatus(tabledir)
  for status in statuses
    next unless status.isDir()
    next if status.getPath().getName() == "compaction.dir"
    regioninfofile =  Path.new(status.getPath(), ".regioninfo")
    unless fs.exists(regioninfofile)
      LOG.warn("Missing .regioninfo: " + regioninfofile.toString())
      next
    end
    is = fs.open(regioninfofile)
    hri = HRegionInfo.new()
    hri.readFields(is)
    is.close()
    next unless Bytes.equals(leftEdge.getEndKey(), hri.getStartKey())
    # TODO: Check against right edge to make sure this addition does not overflow right edge.
    # TODO: Check that the schema matches both left and right edges schemas.
    p = Put.new(hri.getRegionName())
    p.add(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER, Writables.getBytes(hri))
    metatable.put(p)
    LOG.info("Plugged hole in .META. at: " + hri.toString())
    plugged = true
  end
  return plugged
end

fixup = isFixup()

# Get configuration
conf = getConfiguration()

# Filesystem
fs = FileSystem.get(conf)

# Rootdir
rootdir = FSUtils.getRootDir(conf)

# Get a logger and a metautils instance.
LOG = LogFactory.getLog(NAME)

# Scan the .META. looking for holes
metatable = HTable.new(conf, HConstants::META_TABLE_NAME)
scan = Scan.new()
scanner = metatable.getScanner(scan)
oldHRI = nil
bad = nil
while (result = scanner.next())
  rowid = Bytes.toString(result.getRow())
  rowidStr = java.lang.String.new(rowid)
  bytes = result.getValue(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER)
  hri = Writables.getHRegionInfo(bytes)
  if oldHRI
    if oldHRI.isOffline() && Bytes.equals(oldHRI.getStartKey(), hri.getStartKey())
      # Presume offlined parent
    elsif Bytes.equals(oldHRI.getEndKey(), hri.getStartKey())
      # Start key of next matches end key of previous
    else
      LOG.warn("hole after " + oldHRI.toString())
      if fixup
        bad = 1 unless fixup(oldHRI, hri, metatable, fs, rootdir)
      else
        bad = 1
      end
    end
  end
  oldHRI = hri
end
scanner.close()
if bad
  LOG.info(".META. has holes")
else
  LOG.info(".META. is healthy")
end

# Return 0 if meta is good, else non-zero.
exit bad
