#!/usr/bin/python

# Copyright C 2002-2004 by Isilon Systems, Inc. All rights not expressly
# granted herein are reserved.
# Created in the United States of America.
# 
# This digital media is protected by U.S. and international copyright and
# intellectual property laws. Unless otherwise specified, all information
# and screens appearing as part of this digital medium, including
# software, services, documents, text, images, icons, and logos design;
# the selection, assembly, arrangement, and design thereof; and the code
# that enables its presentation, are the sole property of Isilon Systems,
# Inc.
# 
# Except as otherwise required by applicable law, no part of any
# copyrighted material may be reproduced, modified, translated,
# distributed, published, or transmitted by any means, electronic or
# mechanical, for any purpose, without the prior written consent of Isilon
# Systems. 
#  
# Isilon and Isilon Systems are registered trademarks of Isilon Systems,
# Inc.  Legion is a trademark of Isilon Systems, Inc.  All other
# trademarks and registered trademarks are the property of their
# respective holders.


import commands
import getopt
import os
import re
import string
import sys

import isi.fs.collect
import isi.fs.lin
import isi.fs.pctl2 as pctl2
import isi.ui.lib.format as format

def error(message, exit=1):
    print >>sys.stderr, '%s:' % os.path.basename(sys.argv[0]), message
    if exit:
        sys.exit(1);

def usage(exitCode):
    print >>sys.stderr, \
r'''usage: %s <iaddr>...

  Each <iaddr> must be specified as {i}devid,drive,ldnum

  Flags:
      -d: turn on debugging
      -h: show this help message
      -q: quiet (no progress)
      -n: display addresses then quit
''' % os.path.basename(sys.argv[0])
    sys.exit(exitCode)

def fmtEccIaddr(ecc):
    return "i%d,%d,%d" % (ecc.iaddr[0], ecc.iaddr[1], ecc.iaddr[2])

def main():
    debug = False
    quiet = False
    noScan = False


    # Parse arguments.
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'dhqn')
    except getopt.GetoptError, e:
        error(str(e), 0)
        usage(1)

    for opt, arg in opts:

        if opt == '-d':
            debug = True

        if opt == '-h':
            usage(0)

        if opt == '-q':
            quiet = True

        if opt == '-n':
            noScan = True

    if not len(args):
        error("Must specifiy iaddrs.", 0)
        usage(1)

    # Parse list of ECC addrs
    eccAddrList = []
    for arg in args:
        try:
            tokens = arg.split(',')
            nodeId = int(tokens[0].replace('i', ''))
            drive  = int(tokens[1])
            offset  = long(tokens[2])
            size = int(tokens[3])
            eccAddrList.append(pctl2.EccAddr(nodeId, drive, offset, size,
                                             pctl2.AT_ALLOCED_INODES, 0, 0))
        except Exception, e:
            error("Invalid ecc addr %s (%s)" % (arg, str(e)), 0)
            usage(1)

    if noScan:
        print "%s" % map(fmtEccIaddr, eccAddrList)
        sys.exit(0)

    try:
        prevLin = long(1)
	prevSnapid = long(0)
        maxLin = isi.fs.lin.getMaxLin()
        while prevLin != 0 and prevLin < maxLin:
            (prevLin, prevSnapid, unprotectedLins, unprotectedSnapids, zombies, pct) = \
                isi.fs.lin.findUnprotectedLins(prevLin, prevSnapid, maxLin, 1, eccAddrList)
            if not quiet:
                sys.stdout.write("\r%.2f" % pct)
                sys.stdout.flush()

    except EnvironmentError, (errcode, strerror):
        error(strerror, 1)

    if not quiet:
        sys.stdout.write('\n')

    for ecc in eccAddrList:
        if ecc.lin == 0:
            result = "(unknown)"
        else:
            result = "LIN %s" % format.fmtLin(ecc.lin)
        print "%s -> %s" % (fmtEccIaddr(ecc), result)

if __name__ == '__main__':
    try:
        main()
    except EnvironmentError, (errno, strerror):
        error(strerror)

