#!/usr/bin/env python
#
#  Copyright (C) 2015 Intel Corporation.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  1. Redistributions of source code must retain the above copyright notice(s),
#     this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright notice(s),
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
#  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
NAME
    memkind-hbw-nodes - Print comma separated list of high bandwidth nodes.

SYNOPSIS
    memkind-hbw-nodes -h | --help
        Print this help message.

DESCRIPTION
    Parse the /etc/memkind/node-bandwidth file and prints a comma
    separated list of high bandwidth nodes that can be used with the
    numactl --membind option.

EXIT STATUS
    Returns code is 1 on failure.

COPYRIGHT
    Copyright 2015 Intel Corporation All Rights Reserved.

AUTHORS
    Christopher M. Cantalupo

SEE ALSO
    hbwmalloc(3), memkind(3)

"""

import sys
import struct

def hbw_nodes(node_bandwidth_file='/etc/memkind/node-bandwidth'):
    with open(node_bandwidth_file, 'rb') as fid:
        data = fid.read()
    num_node = len(data)/4
    fmt = '{0}i'.format(num_node)
    node_bw = struct.unpack(fmt, data)
    max_bw = max(node_bw)
    hbw_nodes = ','.join([str(ii) for ii in range(len(node_bw))
                          if node_bw[ii] == max_bw])
    return hbw_nodes

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] in ('-h', '--help'):
        print __doc__
        sys.exit(0)

    if len(sys.argv) > 1:
        sys.stderr.write("ERROR: Unknown option {0}\n".format(' '.join(sys.argv[1:])))
        sys.exit(1)

    try:
        print hbw_nodes()
    except IOError as err:
        sys.stderr.write('{0}\n'.format(err))
        sys.exit(1)
