#! /usr/bin/env python2
# $Id: dpns-usage-by-vouser,v 1.1 2009/01/23 15:20:41 gcowan Exp $

__author__ = 'Samuel C Skipsey'
__date__ = 'December 2008'
__version = 0.15

'''Per DN, per VO, du-like listing for DPM'''
import sys

try:
    import dpm
except:
    print 'Failed to import dpm API. Check your $PYTHONPATH. If this is correct, Please check the bitness of your system libraries - it may be that you have 64bit python and 32bit DPM.'
    sys.exit(1)

import stat
import string
from optparse import OptionParser

VO_user_hash = {};

def main():
    parser = OptionParser(
        usage = 'usage: %prog /dpm/path/to/directory')
    parser.add_option('-s','--si',dest='si',action='store_true',
                      help='Use powers of 1000, not 1024.')
    parser.add_option('-x','--exclude',dest='exclude',
                      help='Directory to ignore.')

    (options, args) = parser.parse_args()

    try:
        directory = args[0]
    except:
        parser.print_help()
	sys.exit(0)

    if len(args) > 1:
        parser.error("incorrect number of arguments")
    scan( directory, options.exclude)
    parse_hash(options.si)

def parse_hash(si):
    '''Parse hash of hashes - by VO then by DN - and print file usage info'''
    ss = 0
    s = 0
    for (gid, dn_hash) in VO_user_hash.items():
        groupname = "@" * 128
        dpm.dpns_getgrpbygid(gid,groupname)
        groupname = groupname.strip('@')
        print '\tVO: ', groupname
        s = 0
        for (uid, totalfiles) in dn_hash.items():
            username = "@" * 128
            dpm.dpns_getusrbyuid(uid,username)    
            username = username.strip('@')
#            print 'VO: ', groupname
            print '\t\tUser DN: ', username
            print '\t\tFilesize: ', parse_size(totalfiles,si)
            s += totalfiles
        print '\tTotal Filesize ', groupname,': ', parse_size(s,si)
        ss+=s
    print 'Total Filesize:', parse_size(ss,si)

def scan( directory, exclude):
    '''Scan through the directory tree, picking up + constructing our double hash of file consumption'''
    if directory == exclude:
        return 0
    if directory[-1] != '/':
        directory = directory + '/'
    dir_handle = dpm.dpns_opendirg( directory,'')
    if (dir_handle == None) or (dir_handle == 0):
        err_num = dpm.cvar.serrno
        err_string = dpm.sstrerror( err_num)
        print 'Error while looking for ' + name + ': Error ' \
              + str(err_num) + ' (' + err_string + ')'
        sys.exit(1)

    size = 0
    while 1:
        read_pt = dpm.dpns_readdirxr( dir_handle,'')
        if ( read_pt == None) or ( read_pt == 0):
            break
        entry, list = read_pt
        if stat.S_ISREG( entry.filemode):
            size += entry.filesize
            s = dpm.dpns_filestat()
            dpm.dpns_stat(directory+entry.d_name,s)
            try:
                VO_user_hash[s.gid][s.uid] += entry.filesize
            except:
                if ( not VO_user_hash.has_key(s.gid) ):
                    VO_user_hash[s.gid] = {};
                VO_user_hash[s.gid][s.uid] = entry.filesize
                 		       
        if stat.S_ISDIR( entry.filemode):
            dir = directory + entry.d_name
            size += scan( dir, exclude)
        
    dpm.dpns_closedir( dir_handle)
    return size


def parse_size(size,si):
    '''Utility function to correctly generate file size prefixes'''
    s = size
    if si:
        divisor = 1000.0
    else:
        divisor = 1024.0
    index = 0
    prefixes = ('B','K','M','G','T','P','E','Z','Y')
    while (s >= divisor):
        index+=1
        s = s/divisor
    
    return str(s) + prefixes[index]       

        
if __name__ == '__main__':
         main()
