#!/bin/sh
#
# ------------------------------------------------------------------
#  show_blocked.sh
# 
#  October 2010, Michael C. Scott
# 
#  Copyright (c) 2010-2011, 2013 by Cisco Systems, Inc.
#  All rights reserved.
# ------------------------------------------------------------------


# Prints a header before iterating over the specified nodes (printing a node
# header if it iterates over more than one node). Within each node it iterates
# over the processes on the node and within each process it iterates over the
# threads of the process. For each thread it retrieves the thread name,
# thread state, the time in the state and if appopriate what process it is
# blocked against. Depending on the state of the thread this information may
# then be printed. If the "-v" (verbose) flag has been set then the list of
# states that trigger printing is increased. If a specific JID has been passed
# then the command is run recursively on any
# NOTE: Due to external requirements the printing on certain states and calling
# recursively functionality has not yet been implemented.


# SH_PROC_BLOCKED_FORMAT_STRING
#
# The format string used when printing information.
SH_PROC_BLOCKED_FORMAT_STRING="%-5.5s %-5.5s %-5.5s %15.15s %11.11s %15.15s %18.18s\n"


# Load the show_proc / pidin library.
source `dirname $0`/sh_proc_lib


function main
{
    local node_list=""
    local process_list=""
    local thread_list=""

    if [ $sh_proc_no_headers -eq 0 ]; then
        printf "$SH_PROC_BLOCKED_FORMAT_STRING" \
            "Jid" "Pid" "Tid" "Name" "State" "TimeInState" "Blocked-on"
    fi

    # Generate a list of nodes.
    sh_proc_node_iterator
    node_list=("${sh_proc_node_iterator_out[@]}")

    # Iterate over each node.
    for node in ${node_list[@]}; do
        # If there are multiple nodes we print a header for each node.
        if [ ${#node_list[@]} -gt 1 ]; then
            sh_proc_print_node_header $node
        fi
        # Set the path for the /proc filesystem of the current node.
        sh_proc_set_proc_path $node

        # Genereate a list of processes.
        sh_proc_process_iterator $node
        process_list=($sh_proc_process_iterator_out)

        # Generate a list of JIDs from the process list.
        sh_proc_pid_list_to_jid_list_in=("${process_list[@]}")
        sh_proc_pid_list_to_jid_list
        jid_list=($sh_proc_pid_list_to_jid_list_out)

        # Iterate over each process.
        local index=0
        while [ $index -lt ${#process_list[@]} ]; do
            local process=${process_list[$index]}
            # Generate a list of threads.
            sh_proc_thread_iterator $process
            thread_list=$sh_proc_thread_iterator_out

            # Iterate over each thread.           
            for thread in $thread_list; do

                # Retrieve the required information.
                sh_proc_get_item $thread "thread_state"
                thread_state_out=$sh_proc_get_item_out

                sh_proc_get_item $thread "time_in_state"
                time_in_state_out=$sh_proc_get_item_out

                sh_proc_get_item $thread "basename15"
                name_out=$sh_proc_get_item_out

                sh_proc_get_item $thread "blocked_on"
                blocked_on_out=$sh_proc_get_item_out

                #TODO - Only processes in certain states should be printed. This
                # will depend on what states are reported by the IPC
                #mechanism(s) and so has been left for later completion.
                # TODO - In addition when the extended argument has been passed
                # to "show proc blocked" (i.e the $sh_proc_verbose_flag is set)
                # then more states will trigger printing the information.

                # If the information was succesfully retrieved print it. If the
                # PID could not be converted to a JID print an apporpriate
                # error message.
                if [ $sh_proc_get_item_error -eq 0 ]; then
                    if [ ${jid_list[$index]} == "-1" ]; then
                        printf "Failed to get jobid from pid\n"
                    else
                        printf "$SH_PROC_BLOCKED_FORMAT_STRING" \
                               "${jid_list[$index]}" "$process" \
                               "$thread" "$name_out" \
                               "$thread_state_out" "$time_in_state_out" \
                               "$blocked_on_out"
                    fi
                else
                    sh_proc_get_item_error=0
                fi

                #TODO - Need to implement the specific JID option i.e recurse       
                # on to the blocking process. This has dependencies on the IPC
                # mechanism.
                #   
                # Pseudocode
                # if [ following -eq true ]; then
                #     print a message (i.e "following process x")
                #     call show_blocked with the -x option (and other options
                #     to target the right node/process)      
                #     print a message (i.e "returning to process x")
                # fi
            done       
            let index+=1
        done
        printf "\n"
    done
}


sh_proc_command_parser "$@"
main
