#!/usr/bin/env python
# -----------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------

#
# This scirpt stops the ducc system-test simulator
#
import os
import sys
import time

DUCC_HOME = os.path.abspath(__file__ + '/../../..')
sys.path.append(DUCC_HOME + '/admin')

import getopt

from ducc_util  import DuccUtil
from properties import Properties
from ducc       import Ducc
from ducc_util  import ThreadPool

class StopSim(DuccUtil):

    def signal_process(self, args):
        inst, data_prop, signal = args
        data = data_prop
        (node, pid, pname) = data.split(' ')

        msgs = []
        msgs.append(('Stopping process', inst, 'on', node, pid, pname, 'with signal', signal))
        if ( not (inst in self.default_components )):
            cmp = 'agent'
        else:
            cmp = inst
        self.ssh(node, True, 'kill', signal, pid)

        return msgs

    def usage(self, msg):

        if ( msg != None ):
            print ' '.join(msg)

              
        print "Usage:"
        print "   stop_sim [options]"   
        print "        If no options are given, all ducc processes from sim.pids are stopped using SIGINT"
        print ""
        print "Options:"
        print "   -c --component compenent name"
        print "        The name is one of", self.default_components, "or an ID from sim.pids"
        print ""
        print "   -k --kill"
        print "        Sends SIGKILL to the indicated process"
        print ""
        print "   -p --pause"
        print "        Sends SIGSTOP to the indicated process"
        print ""
        print "   -r --resume"
        print "        Sends SIGCONT to the indicated process"
        print ""
        print "    --nothreading"
        print "        Disable multithreaded operation if it would otherwise be used"
        print ""
        print "   -v, --version"
        print "        Print the current DUCC version"
        print ""
        print "   -?,  -h, --help,"
        print "        Print this"
        print ""
        sys.exit(1) 
            

    def invalid(self, *msg):
        if ( msg[0] != None ):
            print ' '.join(msg)
            
            print "For usage run"
            print "    stop_sim -h"
            print 'or'
            print '    stop_sim --help'
            sys.exit(1)

    def main(self, argv):

        components = []
        instances = []
        signal = '-INT'
        stopbroker = False
        stopdatabase = False

        try:
            opts, args = getopt.getopt(argv, 'c:kprvh?', ['component=', 'kill' 'pause', 'resume', 'nothreading', 'version', 'help'])
        except:
            self.invalid('Invalid arguments', ' '.join(argv))
                  
        for ( o, a ) in opts:
            if o in ( '-c', '--component' ):
                instances.append(a)
            elif o in ( '-k', '--kill' ):
                signal = '-KILL'
            elif o in ( '-p', '--pause' ):
                signal = '-STOP'
            elif o in ( '-r', '--resume' ):
                signal = '-CONT'
            elif o in ( '--nothreading' ):
                self.disable_threading()
            elif o in ( '-v', '--version' ):
                print self.version()
                sys.exit(0)
            elif o in ( '-h', '--help' ):
                self.usage(None)
            elif ( o == '-?'):
                self.usage(None)
            else:
                self.invalid('bad args: ', ' '.join(argv))

        pids = Properties()
        pids.load('sim.pids')

        self.threadpool = ThreadPool(50)

        try:
            if ( (len(components) + len(instances)) == 0 ):
                for (inst, data) in pids.items():                    
                    self.threadpool.invoke(self.signal_process, inst, pids.get(inst), signal)
                    time.sleep(.1)
                    if ( signal in ('-KILL', '-INT') ):
                        pids.delete(inst)
                        stopbroker = True
                        stopdatabase = True
    
            else:
                for inst in instances:
                    print 'Instance', inst
                    data = pids.get(inst)
                    if ( data == None ):
                        if ( inst == 'broker' and signal in ('-KILL', '-INT') ):
                            stopbroker = True
                        else:
                            print "WARNING - No PID found for instance", inst
                    elif ( inst == 'db' ):
                        stopdatabase = True
                    else:
                        self.threadpool.invoke(self.signal_process, inst, pids.get(inst), signal)
                        time.sleep(.1)
                        if ( signal in ('-KILL', '-INT') ):
                            pids.delete(inst)
        except:
            self.threadpool.quit()
            print sys.exc_info()[0], "Exiting, simulator may not be properly stopped."
            sys.exit(1)
            
        self.threadpool.quit();

        pids.write('sim.pids')

        sleeptime = 5
        print "Waiting " + str(sleeptime) + " seconds to broadcast agent shutdown."
        time.sleep(sleeptime)

        if ( stopdatabase ) :
            print 'Stopping database'
            self.db_stop()

        if ( stopbroker and self.automanage ):
            print "Stopping broker"
            self.stop_broker()                

if __name__ == "__main__":
    stopper = StopSim()
    stopper.main(sys.argv[1:])
