Index: /trunk/jobmond/jobmond.py
===================================================================
--- /trunk/jobmond/jobmond.py	(revision 659)
+++ /trunk/jobmond/jobmond.py	(revision 660)
@@ -27,4 +27,5 @@
 from xml.sax.handler import feature_namespaces
 from collections import deque
+from types import *
 
 VERSION='0.3.1'
@@ -181,35 +182,35 @@
 def loadConfig( filename ):
 
-        def getlist( cfg_string ):
-
-                my_list = [ ]
-
-                for item_txt in cfg_string.split( ',' ):
-
-                        sep_char = None
-
-                        item_txt = item_txt.strip()
-
-                        for s_char in [ "'", '"' ]:
-
-                                if item_txt.find( s_char ) != -1:
-
-                                        if item_txt.count( s_char ) != 2:
-
-                                                print 'Missing quote: %s' %item_txt
-                                                sys.exit( 1 )
-
-                                        else:
-
-                                                sep_char = s_char
-                                                break
-
-                        if sep_char:
-
-                                item_txt = item_txt.split( sep_char )[1]
-
-                        my_list.append( item_txt )
-
-                return my_list
+    def getlist( cfg_string ):
+
+        my_list = [ ]
+
+        for item_txt in cfg_string.split( ',' ):
+
+                sep_char = None
+
+                item_txt = item_txt.strip()
+
+                for s_char in [ "'", '"' ]:
+
+                        if item_txt.find( s_char ) != -1:
+
+                                if item_txt.count( s_char ) != 2:
+
+                                        print 'Missing quote: %s' %item_txt
+                                        sys.exit( 1 )
+
+                                else:
+
+                                        sep_char = s_char
+                                        break
+
+                if sep_char:
+
+                        item_txt = item_txt.split( sep_char )[1]
+
+                my_list.append( item_txt )
+
+        return my_list
 
     cfg     = ConfigParser.ConfigParser()
@@ -304,5 +305,5 @@
         gmetric_dest_ip     = ganglia_cfg.getStr( 'udp_send_channel', 'host' )
 
-    gmetric_dest_port   = ganglia_cfg.getStr( 'udp_send_channel', 'port' )
+        gmetric_dest_port   = ganglia_cfg.getStr( 'udp_send_channel', 'port' )
 
     if gmetric_dest_ip and gmetric_dest_port:
@@ -534,13 +535,17 @@
             print '\t%s = %s' %( name, val )
 
-    def getAttr( self, attrs, name ):
+    def getAttr( self, d, name ):
 
         """Return certain attribute from dictionary, if exists"""
 
-        if attrs.has_key( name ):
-
-            return attrs[ name ]
-        else:
-            return ''
+        if d.has_key( name ):
+
+            if type( d[ name ] ) == ListType:
+
+                return string.join( d[ name ], ' ' )
+
+            return d[ name ]
+        
+        return ''
 
     def jobDataChanged( self, jobs, job_id, attrs ):
@@ -608,9 +613,9 @@
             for name, node in self.pq.getnodes().items():
 
-                if ( node[ 'state' ].find( "down" ) != -1 ):
+                if 'down' in node[ 'state' ]:
 
                     downed_nodes.append( name )
 
-                if ( node[ 'state' ].find( "offline" ) != -1 ):
+                if 'offline' in node[ 'state' ]:
 
                     offline_nodes.append( name )
@@ -629,157 +634,84 @@
 
             # Make gmetric values for each job: respect max gmetric value length
-                        #
-            gmetric_val     = self.compileGmetricVal( jobid, jobattrs )
-            metric_increment    = 0
-
-            # If we have more job info than max gmetric value length allows, split it up
-                        # amongst multiple metrics
             #
-            for val in gmetric_val:
-
-                self.dp.multicastGmetric( 'MONARCH-JOB-' + jobid + '-' + str(metric_increment), val )
-
-                # Increase follow number if this jobinfo is split up amongst more than 1 gmetric
-                                #
-                metric_increment    = metric_increment + 1
+            gmetrics     = self.compileGmetricVal( jobid, jobattrs )
+
+            for g_name, g_val in gmetrics.items():
+
+                self.dp.multicastGmetric( g_name, g_val )
 
     def compileGmetricVal( self, jobid, jobattrs ):
 
-        """Create a val string for gmetric of jobinfo"""
-
-        gval_lists  = [ ]
-        val_list    = { }
+        """Create gmetric name/value pairs of jobinfo"""
+
+        gmetrics = { }
 
         for val_name, val_value in jobattrs.items():
 
-            # These are our own metric names, i.e.: status, start_timestamp, etc
-                        #
-            val_list_names_len  = len( string.join( val_list.keys() ) ) + len(val_list.keys())
-
-            # These are their corresponding values
-                        #
-            val_list_vals_len   = len( string.join( val_list.values() ) ) + len(val_list.values())
-
-            if val_name == 'nodes' and jobattrs['status'] == 'R':
-
-                node_str = None
-
-                for node in val_value:
-
-                    if node_str:
-
-                        node_str = node_str + ';' + node
-                    else:
-                        node_str = node
-
-                    # Make sure if we add this new info, that the total metric's value length does not exceed METRIC_MAX_VAL_LEN
-                                        #
-                    if (val_list_names_len + len(val_name) ) + (val_list_vals_len + len(node_str) ) > METRIC_MAX_VAL_LEN:
-
-                        # It's too big, we need to make a new gmetric for the additional info
-                                                #
-                        val_list[ val_name ]    = node_str
-
-                        gval_lists.append( val_list )
-
-                        val_list        = { }
-                        node_str        = None
-
-                val_list[ val_name ]    = node_str
-
-                gval_lists.append( val_list )
-
-                val_list        = { }
-
-            elif val_value != '':
-
-                # Make sure if we add this new info, that the total metric's value length does not exceed METRIC_MAX_VAL_LEN
-                                #
-                if (val_list_names_len + len(val_name) ) + (val_list_vals_len + len(str(val_value)) ) > METRIC_MAX_VAL_LEN:
-
-                    # It's too big, we need to make a new gmetric for the additional info
-                                        #
-                    gval_lists.append( val_list )
-
-                    val_list        = { }
-
-                val_list[ val_name ]    = val_value
-
-        if len( val_list ) > 0:
-
-            gval_lists.append( val_list )
-
-        str_list    = [ ]
-
-        # Now append the value names and values together, i.e.: stop_timestamp=value, etc
-                #
-        for val_list in gval_lists:
-
-            my_val_str  = None
-
-            for val_name, val_value in val_list.items():
-
-                if type(val_value) == list:
-
-                    val_value   = val_value.join( ',' )
-
-                if my_val_str:
-
-                    try:
-                        # fixme: It's getting
-                        # ('nodes', None) items
-                        my_val_str = my_val_str + ' ' + val_name + '=' + val_value
-                    except:
-                        pass
-
-                else:
-                    my_val_str = val_name + '=' + val_value
-
-            str_list.append( my_val_str )
-
-        return str_list
-
-        def daemon( self ):
-
-                """Run as daemon forever"""
-
-                # Fork the first child
-                #
-                pid = os.fork()
-                if pid > 0:
-                        sys.exit(0)  # end parent
-
-                # creates a session and sets the process group ID
-                #
-                os.setsid()
-
-                # Fork the second child
-                #
-                pid = os.fork()
-                if pid > 0:
-                        sys.exit(0)  # end parent
+            gmetric_sequence = 0
+
+            if len( val_value ) > METRIC_MAX_VAL_LEN:
+
+                while len( val_value ) > METRIC_MAX_VAL_LEN:
+
+                    gmetric_value   = val_value[:METRIC_MAX_VAL_LEN]
+                    val_value       = val_value[METRIC_MAX_VAL_LEN:]
+
+                    gmetric_name    = 'MONARCHJOB$%s$%s$%s' %( jobid, string.upper(val_name), gmetric_sequence )
+
+                    gmetrics[ gmetric_name ] = gmetric_value
+
+                    gmetric_sequence = gmetric_sequence + 1
+            else:
+                gmetric_value   = val_value
+
+                gmetric_name    = 'MONARCH$%s$%s$%s' %( jobid, string.upper(val_name), gmetric_sequence )
+
+                gmetrics[ gmetric_name ] = gmetric_value
+
+        return gmetrics
+
+    def daemon( self ):
+
+        """Run as daemon forever"""
+
+        # Fork the first child
+        #
+        pid = os.fork()
+        if pid > 0:
+                sys.exit(0)  # end parent
+
+        # creates a session and sets the process group ID
+        #
+        os.setsid()
+
+        # Fork the second child
+        #
+        pid = os.fork()
+        if pid > 0:
+                sys.exit(0)  # end parent
 
         write_pidfile()
 
-                # Go to the root directory and set the umask
-                #
-                os.chdir('/')
-                os.umask(0)
-
-                sys.stdin.close()
-                sys.stdout.close()
-                sys.stderr.close()
-
-                os.open('/dev/null', os.O_RDWR)
-                os.dup2(0, 1)
-                os.dup2(0, 2)
-
-                self.run()
-
-        def run( self ):
-
-                """Main thread"""
-
-                while ( 1 ):
+        # Go to the root directory and set the umask
+        #
+        os.chdir('/')
+        os.umask(0)
+
+        sys.stdin.close()
+        sys.stdout.close()
+        sys.stderr.close()
+
+        os.open('/dev/null', os.O_RDWR)
+        os.dup2(0, 1)
+        os.dup2(0, 2)
+
+        self.run()
+
+    def run( self ):
+
+        """Main thread"""
+
+        while ( 1 ):
         
             self.getJobData()
@@ -1022,11 +954,11 @@
             parse_err = 1
             if piping.wait():
-            debug_msg(10,
+                debug_msg(10,
                   "qstat error, skipping until next polling interval: "
                   + piping.childerr.readline())
-            return None
-        elif parse_err:
-            debug_msg(10, "Bad XML output from qstat"())
-            exit (1)
+                return None
+            elif parse_err:
+                debug_msg(10, "Bad XML output from qstat"())
+                exit (1)
         for f in piping.fromchild, piping.tochild, piping.childerr:
             f.close()
@@ -1104,21 +1036,21 @@
         def _countDuplicatesInList( self, dupedList ):
 
-        countDupes  = { }
-
-        for item in dupedList:
-
-            if not countDupes.has_key( item ):
-
-                countDupes[ item ]  = 1
-            else:
-                countDupes[ item ]  = countDupes[ item ] + 1
-
-        dupeCountList   = [ ]
-
-        for item, count in countDupes.items():
-
-            dupeCountList.append( ( item, count ) )
-
-                return dupeCountList
+            countDupes  = { }
+
+            for item in dupedList:
+
+                if not countDupes.has_key( item ):
+
+                    countDupes[ item ]  = 1
+                else:
+                    countDupes[ item ]  = countDupes[ item ] + 1
+
+            dupeCountList   = [ ]
+
+            for item, count in countDupes.items():
+
+                dupeCountList.append( ( item, count ) )
+
+            return dupeCountList
 #
 #lst = ['I1','I2','I1','I3','I4','I4','I7','I7','I7','I7','I7']
@@ -1180,14 +1112,14 @@
                                 requested_cpus = 1
 
-            if QUEUE:
-                for q in QUEUE:
-                    if q == queue:
-                        display_queue = 1
-                        break
-                    else:
-                        display_queue = 0
-                        continue
-            if display_queue == 0:
-                continue
+                        if QUEUE:
+                            for q in QUEUE:
+                                if q == queue:
+                                    display_queue = 1
+                                    break
+                                else:
+                                    display_queue = 0
+                                    continue
+                        if display_queue == 0:
+                            continue
 
                         runState = self.getAttr( attrs, 'status' )
@@ -1236,5 +1168,5 @@
                         myAttrs[ 'reported' ]       = str( int( int( self.cur_time ) + int( self.timeoffset ) ) )
                         myAttrs[ 'nodes' ]      = do_nodelist( nodelist )
-            myAttrs[ 'domain' ]     = fqdn_parts( socket.getfqdn() )[1]
+                        myAttrs[ 'domain' ]     = fqdn_parts( socket.getfqdn() )[1]
                         myAttrs[ 'poll_interval' ]  = str(BATCH_POLL_INTERVAL)
 
@@ -1249,6 +1181,6 @@
                                 #
                                 del jobs[ id ]
-                self.jobs=jobs
-
+
+                self.jobs = jobs
 
 class PbsDataGatherer( DataGatherer ):
@@ -1316,8 +1248,8 @@
 
             owner           = self.getAttr( attrs, 'Job_Owner' ).split( '@' )[0]
-            requested_time      = self.getAttr( attrs, 'Resource_List.walltime' )
-            requested_memory    = self.getAttr( attrs, 'Resource_List.mem' )
-
-            mynoderequest       = self.getAttr( attrs, 'Resource_List.nodes' )
+            requested_time      = self.getAttr( attrs['Resource_List'], 'walltime' )
+            requested_memory    = self.getAttr( attrs['Resource_List'], 'mem' )
+
+            mynoderequest       = self.getAttr( attrs['Resource_List'], 'nodes' )
 
             ppn         = ''
@@ -1566,5 +1498,5 @@
     global DAEMONIZE, DEBUG_LEVEL, SYSLOG_LEVEL
 
-        if (not DAEMONIZE and DEBUG_LEVEL >= level):
+    if (not DAEMONIZE and DEBUG_LEVEL >= level):
         sys.stderr.write( msg + '\n' )
 
