source: trunk/src/testing/ui/sageData.py @ 4

Revision 4, 33.4 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1############################################################################
2#
3# SAGE UI - A Graphical User Interface for SAGE
4# Copyright (C) 2005 Electronic Visualization Laboratory,
5# University of Illinois at Chicago
6#
7# All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions are met:
11#
12#  * Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14#  * Redistributions in binary form must reproduce the above
15#    copyright notice, this list of conditions and the following disclaimer
16#    in the documentation and/or other materials provided with the distribution.
17#  * Neither the name of the University of Illinois at Chicago nor
18#    the names of its contributors may be used to endorse or promote
19#    products derived from this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32#
33# Direct questions, comments etc about SAGE UI to www.evl.uic.edu/cavern/forum
34#
35# Author: Ratko Jagodic
36#       
37############################################################################
38
39
40
41# python stuff
42import sys, string, pickle, time, os.path, os, xmlrpclib, shutil
43import traceback as tb
44
45# my imports
46from sageApp import SageApp, SageAppInitial
47from sageAppPerfInfo import sageAppPerfInfo
48from sageDisplayInfo import SageDisplayInfo
49import Graph
50from globals import *
51from sagePath import getUserPath
52
53
54## Main class to store all the messages returned by SAGE
55class SageData:
56
57
58    #### constructor initializes member values       
59    def __init__(self, sageGate, autosave, displayName):
60        self.noOfApps = 0
61        self.hashCallback = {}       # functions to call in sageui.py for updating the UI
62        self.hashApps = {}           # all the apps available for running??
63        self.hashAppStatusInfo = {}  # apps currently running
64        self.hashAppPerfInfo = {}
65        self.hashFileInfo = {}
66        self.displayInfo = SageDisplayInfo()
67        self.sageGate = sageGate
68        self.autosave = autosave
69        self.timeStarted = time.strftime("%Y%m%d-%H%M%S", time.localtime())
70        self.displayName = displayName.strip()
71        self.__firstAutosave = True
72       
73        self._sageColor = (0,0,0)
74        self.__bPerformanceLogging = True
75
76        # (AKS 2005-02-15) The hash below is used for determining when to
77        # calculate the total values for all active applications.  This
78        # hash originally belonged in GraphManager of Graph.py.  However,
79        # the implementation was not clean and lent itself to infinite
80        # recursion.  So, having the total calculation at the source of
81        # where the data is kept seemed to make the most sense.
82        #self.__hashAppGraphUpdateFlag = {}
83
84
85        # Constants used for keys in __hashAppPerfTotals (public scope)
86        self.I_RENDER_TOTAL_BANDWIDTH = 10
87        self.I_RENDER_AVG_FRAME_RATE = 20
88        self.I_RENDER_TOTAL_NODES = 30
89        self.I_DISPLAY_TOTAL_BANDWIDTH = 40
90        self.I_DISPLAY_AVG_FRAME_RATE = 50
91        self.I_DISPLAY_TOTAL_NODES = 60
92
93        self.__hashAppPerfTotals = {}
94        self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_BANDWIDTH ] = 0.0
95        self.__hashAppPerfTotals[ self.I_RENDER_AVG_FRAME_RATE ] = 0.0
96        self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_NODES ] = 0
97        self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_BANDWIDTH ] = 0.0
98        self.__hashAppPerfTotals[ self.I_DISPLAY_AVG_FRAME_RATE ] = 0.0
99        self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_NODES ] = 0
100       
101        # for knowing when to zero out the totals since
102        # sage doesnt send perf data when it's 0
103        self.__lastTotalsUpdate = time.time() 
104
105        # (AKS 2005-05-07) Create two PerformanceGraphs (one for total render bandwidth
106        # and one for total display bandwidth).  This is a hack...2 is specified in
107        # the GraphManager class not for updating purposes but so that the x-axis values
108        # are computed correctly.  The created numarray object takes the place of what
109        # sageAppPerfInfo does (well, it's adjusted manually later)
110        self.__iMaxArraySize = 30
111        self.__iUpdateInterval = 2
112
113        self.__pgTotalRenderBandwidth = Graph.PerformanceGraph( "Totals", "Render Bandwidth (Mbps)",
114            self.__iMaxArraySize, self.__iUpdateInterval )
115
116        self.__pgTotalDisplayBandwidth = Graph.PerformanceGraph( "Totals", "Display Bandwidth (Mbps)",
117            self.__iMaxArraySize, self.__iUpdateInterval )
118        self.__sapiPerfTotals = sageAppPerfInfo()
119
120       
121    #### Set the sage status
122    def setSageStatus(self, appHash) : 
123        self.noOfApps = len(appHash)
124
125        #for line in listTokens:
126        for appName, configs in appHash.iteritems():
127            hashSingleAppInfo = {}
128            self.hashApps[appName] = SageAppInitial(appName, configs)
129           
130        # when done processing the incoming data, call a function in the UI to update the screen
131        if ( 40000 in self.hashCallback ):
132            self.hashCallback[ 40000 ]()
133
134
135
136    #----------------------------------------------------------------------
137
138
139    ### Set the possible execution configurations for each app
140    def setSageAppExecConfig(self, data):
141        tokens = string.split( data, '\n', 1 )
142        appName = tokens[0]
143        data = tokens[1] #the rest
144        configList = string.split( data, "config ")
145
146        del configList[0]  #remove the first item in the list
147
148        for config in configList:
149            if appName in self.hashApps.keys():
150                (name, stringConfig) = string.split(config, ":", 1)
151                self.hashApps[appName].AddConfig(name, stringConfig)
152
153        if ( 40006 in self.hashCallback ):
154            self.hashCallback[ 40006 ](self.hashApps[appName])
155       
156
157    #----------------------------------------------------------------------
158   
159     
160    #### Set the SAGE display information
161    ####
162    def setDisplayInfo(self, data):
163        listTokens = string.split(data, '\n')
164
165        for i in range(0, len(listTokens), 3):
166            tileNumTokens = string.split(listTokens[i], ' ')
167            desktopTokens = string.split(listTokens[i+1], ' ')
168            tileConfTokens = string.split(listTokens[i+2], ' ')           
169           
170            # so that we can support the old sage as well
171            displayId = 0
172            if len(tileConfTokens) > 2:
173                displayId = int(tileConfTokens[2])
174
175            self.displayInfo.addDisplay(int(tileNumTokens[0]), int(tileNumTokens[1]), int(tileNumTokens[2]),
176                                   int(desktopTokens[0]), int(desktopTokens[1]),
177                                   int(tileConfTokens[0]), int(tileConfTokens[1]), displayId)
178
179        # (AKS 2004-10-23) Provide the app-id to the callback
180        if ( 40004 in self.hashCallback ):
181            self.hashCallback[ 40004 ]()
182
183
184    #----------------------------------------------------------------------
185
186
187    # returns the SageDisplayInfo object
188    def getDisplayInfo(self, displayId=0):
189        return self.displayInfo
190
191
192    #----------------------------------------------------------------------
193
194
195    def setDisplayConnections(self, data):
196        for connection in data.split('\n'):
197            tokens = connection.split()
198            displayId = int(tokens[2])
199            self.displayInfo.getDisplay(displayId).placement = int(tokens[1])
200
201        if ( 40007 in self.hashCallback ):
202            self.hashCallback[ 40007 ]()   
203
204
205    #----------------------------------------------------------------------
206   
207
208    #### Get the new list of z values from SAGE
209    #### and update local hashes, then call the function to update the UI visually
210    def setSageZValue(self, message):
211        tokens = string.split(message)
212        numZChanges = int(tokens[0])  #the first item that comes in is the number of z changes
213       
214        # loop through all the tokens and update the z values of the apps
215        for i in range(numZChanges):
216            self.setZvalue( int(tokens[i*2+1]), int(tokens[i*2+2]) )
217
218        # now call the appropriate function to update the UI visually
219        if ( 40005 in self.hashCallback ):
220            self.hashCallback[ 40005 ]( )
221         
222       
223    #----------------------------------------------------------------------
224
225   
226    #### Set the SAGE app status
227    #### prints Invalid app ID if does not exists
228    def setSageAppInfo(self, data):
229        listTokens = string.split(data)
230        listApps = self.hashApps.keys()
231
232        # to support old sage as well
233        displayId = 0
234        orientation = 0
235        appId = 0
236        launcherId = "none"
237        if len(listTokens) > 8:
238            orientation = int(listTokens[8])
239            displayId = int(listTokens[9])
240            if len(listTokens) > 11:
241                appId = int(listTokens[10])
242                launcherId = listTokens[11]
243                   
244        # now update the app properties... or create a new one
245        windowId = int( listTokens[ 1 ] )
246        if windowId in self.hashAppStatusInfo:   # app exists
247            self.hashAppStatusInfo[ windowId ].setAll( listTokens[0], int(listTokens[1]),
248                   int(listTokens[2]), int(listTokens[3]), int(listTokens[4]), int(listTokens[5]),
249                   int(listTokens[6]), int(listTokens[7]), orientation, displayId, appId, launcherId)
250        else:
251            # when new app is started it is assigned a z=0 but since previous app on top had z=0,
252            # we set this one even higher temporarily (z=-1) so that it gets drawn on top
253            # the new z order message comes right after the app is started so this -1 is temporary
254            zValue = int(listTokens[7])
255            for app in self.hashAppStatusInfo.itervalues():
256                if app.getZvalue() == zValue:
257                    zValue = -1
258            self.hashAppStatusInfo[ windowId ] = SageApp( listTokens[0], int(listTokens[1]),
259                   int(listTokens[2]), int(listTokens[3]), int(listTokens[4]), int(listTokens[5]),
260                   int(listTokens[6]), zValue, orientation, displayId, appId, launcherId)
261
262
263        # (AKS 2004-10-23) Provide the app-id to the callback
264        if ( 40001 in self.hashCallback ):
265            self.hashCallback[ 40001 ]( self.hashAppStatusInfo[windowId] )
266
267        if self.autosave:
268            if self.__firstAutosave:
269                self.__deleteOldAutosaves()
270                self.__firstAutosave = False
271            self.saveState("_autosave_LATEST", "")
272
273        return
274
275    #----------------------------------------------------------------------
276   
277   
278    ##### ShutDown the sage application
279    ##### prints invalid app ID if doesn't exist
280    def sageAppShutDown(self, data):
281        listTokens = string.split(data)
282        windowId = int(listTokens[0])
283        listApps = self.hashApps.keys()
284
285
286        # do this first and then remove the app from the hash!!
287        if ( 40003 in self.hashCallback ):
288            self.hashCallback[ 40003 ]( self.hashAppStatusInfo[windowId]  )
289           
290        if windowId in self.hashAppStatusInfo :
291            del self.hashAppStatusInfo[windowId]
292        if windowId in self.hashAppPerfInfo :
293            del self.hashAppPerfInfo[windowId]
294
295        if windowId in self.hashFileInfo :
296            fileObject = self.hashFileInfo.get(windowId)
297            fileObject.close()
298            del self.hashFileInfo[windowId]
299           
300
301    #----------------------------------------------------------------------
302
303    def getLogFileHash(self):
304        return self.hashFileInfo
305
306
307    #----------------------------------------------------------------------
308
309       
310    #### Set the SAGE app performance status
311    #### prints Invalid app ID if does not exists
312    def setSagePerfInfo(self, data):
313        #print ">>> SET SAGE PERF INFO <<<"
314        listTokens = string.split(data, '\n', 1)
315        windowId = int(listTokens[0])
316        data = listTokens[1]
317
318       
319        if not windowId in self.hashAppPerfInfo:
320            self.hashAppPerfInfo[windowId] = sageAppPerfInfo()
321
322        appPerfInfo = self.hashAppPerfInfo.get(windowId)
323       
324        if (appPerfInfo):
325            lineTokens = string.split(data, '\n')
326
327            displayItemTokens = string.split(lineTokens[0])
328            appPerfInfo.setDisplayPerfInfo(float(displayItemTokens[1]), float(displayItemTokens[2]),\
329                                           float(displayItemTokens[3]), int(displayItemTokens[4]))
330
331            renderItemTokens = string.split(lineTokens[1])
332            # FIX: this is just a hack for now.. there actually is no data coming in for the last
333            # two entries in the array but we fill it with 0s so that we dont have to change everything
334            # (it might be used later as well)
335            # in Graph.py we jsut decide not to print the last two values
336            #renderItemTokens.append(0.0)
337            #print "renderItemTokens = ", renderItemTokens
338            renderItemTokens.append(0)
339            appPerfInfo.setRenderPerfInfo(float(renderItemTokens[1]), float(renderItemTokens[2]),\
340                                           float(renderItemTokens[3]), int(renderItemTokens[4]))
341
342
343        # Now open a file and log the data on it
344            try:   #in case the file and directory permissions are not right
345
346                if not windowId in self.hashFileInfo:
347                    sageApp = self.hashAppStatusInfo[ windowId ]
348                    stAppName = sageApp.getName()
349                    stDateTime = time.strftime("%Y%m%d-%H%M%S", time.localtime())
350                    stFilename = stAppName + '-' + str(windowId) + '-' + stDateTime
351                   
352                    stPath = opj(DATA_DIR, stFilename + ".txt")
353                    stFilename = os.path.normpath( stPath )
354                    fileObject = open(stFilename, "w")
355
356                    fileObject.write( stAppName + ":" + str(windowId) + " >> " + time.asctime() + "\n" )
357                    fileObject.write( '-' * 120 + "\n\n" )
358                    tempString = (' Disp BW    Disp FR    Packet Loss    Num Receivers        Rend BW    Rend FR    Packet Loss    Num Receivers\n')
359                    fileObject.write(tempString)
360                    fileObject.write( '-' * len(tempString) + "\n" )
361                    self.hashFileInfo[windowId] = fileObject
362                    fileObject.flush()
363                # end of initialization
364
365                if ( self.__bPerformanceLogging == True ):
366
367                    fileObject = self.hashFileInfo.get(windowId)
368                    tempString = "%8.3f    %7.3f    %3.2f    %8d       " % (float(displayItemTokens[1]), float(displayItemTokens[2]),
369                                                                            float(displayItemTokens[3]), int(displayItemTokens[4]))
370
371                    fileObject.write(tempString)
372
373                    tempString = "%8.3f    %7.3f    %3.2f    %8d\n" % (float(renderItemTokens[1]), float(renderItemTokens[2]),
374                                                                       float(renderItemTokens[3]), int(renderItemTokens[4]))
375                    fileObject.write(tempString)
376                    fileObject.flush()
377            # >>> end file writing...else, nothing
378            except:
379                pass  #do nothing if something fails (such as permissions)
380
381               
382            # calculate totals
383        self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_BANDWIDTH ] = 0.0
384        self.__hashAppPerfTotals[ self.I_RENDER_AVG_FRAME_RATE ] = 0.0
385        self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_NODES ] = 0
386        self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_BANDWIDTH ] = 0.0
387        self.__hashAppPerfTotals[ self.I_DISPLAY_AVG_FRAME_RATE ] = 0.0
388        self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_NODES ] = 0
389       
390        fSumRenderFrameRate = 0.0
391        fSumDisplayFrameRate = 0.0
392       
393        #print "zeroing..."
394
395        # (AKS 2005-04-05) This comment is de
396        # For each application, I am taking each of its metrics and adding them to the
397        # totals which are stored in the hash.  The hash is just a dictionary of totals
398        # for metrics for *ALL* application instances.
399       
400        for iKey in self.hashAppPerfInfo:
401            #print "hash perf: ", self.hashAppPerfInfo
402            sapiAppStats = self.hashAppPerfInfo[ iKey ]
403           
404            self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_BANDWIDTH ] = self.__hashAppPerfTotals[
405                self.I_RENDER_TOTAL_BANDWIDTH ] + sapiAppStats.getRenderInformation(
406                'bandWidth', 1 )[0]
407           
408            fSumRenderFrameRate = fSumRenderFrameRate + sapiAppStats.getRenderInformation(
409                'frameRate', 1 )[0]
410           
411            self.__hashAppPerfTotals[ self.I_RENDER_TOTAL_NODES ] = self.__hashAppPerfTotals[
412                self.I_RENDER_TOTAL_NODES ] + sapiAppStats.getRenderInformation(
413                'nodes', 1 )[0]
414           
415            self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_BANDWIDTH ] = self.__hashAppPerfTotals[
416                self.I_DISPLAY_TOTAL_BANDWIDTH ] + sapiAppStats.getDisplayInformation(
417                'bandWidth', 1 )[0]
418           
419            fSumDisplayFrameRate = fSumRenderFrameRate + sapiAppStats.getDisplayInformation(
420                'frameRate', 1 )[0]             
421           
422            self.__hashAppPerfTotals[ self.I_DISPLAY_TOTAL_NODES ] = self.__hashAppPerfTotals[
423                self.I_DISPLAY_TOTAL_NODES ] + sapiAppStats.getDisplayInformation(
424                'nodes', 1 )[0]
425
426           
427            # Make sure to clear update flag since data has been processed
428            #self.__hashAppGraphUpdateFlag[ iKey ] = False
429           
430        # end of loop
431
432        iAppCount = len( self.hashAppStatusInfo )
433
434        # Calculate averages for frame rates
435        if ( iAppCount == 0 ):
436            self.__hashAppPerfTotals[ self.I_RENDER_AVG_FRAME_RATE ] = 0.0
437            self.__hashAppPerfTotals[ self.I_DISPLAY_AVG_FRAME_RATE ] = 0.0
438               
439        else:
440            self.__hashAppPerfTotals[ self.I_DISPLAY_AVG_FRAME_RATE ] = fSumDisplayFrameRate / iAppCount
441            self.__hashAppPerfTotals[ self.I_RENDER_AVG_FRAME_RATE ] = fSumRenderFrameRate / iAppCount
442                   
443       
444        # (AKS 2005-01-24) Performance data information is not posted at this time
445        #tempString = "%8.3f \t %4d \t %7.3f \n" % (float(dataItemTokens[1]), int(dataItemTokens[2]), float(dataItemTokens[3]))
446        #fileObject.write(tempString)
447
448
449        # (AKS 2005-05-07) Now that the total bandwidth metrics have been calculated,
450        # update their respective PerformanceGraphs
451        self.__sapiPerfTotals.setDisplayPerfInfo( float( self.__hashAppPerfTotals[
452            self.I_DISPLAY_TOTAL_BANDWIDTH ] ), 0.0, 0.0, 0 )
453       
454        self.__sapiPerfTotals.setRenderPerfInfo( float( self.__hashAppPerfTotals[
455            self.I_RENDER_TOTAL_BANDWIDTH ] ), 0.0, 0.0, 0 )
456
457        self.__pgTotalRenderBandwidth.update( self.__sapiPerfTotals.getRenderInformation( 'bandWidth', 30 ) )
458        self.__pgTotalDisplayBandwidth.update( self.__sapiPerfTotals.getDisplayInformation( 'bandWidth', 30 ) )
459
460
461        self.__lastTotalsUpdate = time.time()
462       
463        # (AKS 2004-10-23): Changed to send ID back
464        if ( 40002 in self.hashCallback ):
465            self.hashCallback[ 40002 ]( windowId )
466
467
468    #----------------------------------------------------------------------
469
470    # saves the performance data totals into a file from this SAGE site only
471    def saveSiteTotals(self, siteName):
472        totalsID = -10 # save the totals as appId = -10
473        try:
474            if not totalsID in self.hashFileInfo and self.__bPerformanceLogging: 
475                stDateTime = time.strftime("%Y%m%d-%H%M%S", time.localtime())
476                stFilename = "SITE_TOTAL-" + siteName + '-' + stDateTime
477                #stPath = "./data/" + stFilename + ".txt"
478                stPath = opj(DATA_DIR, stFilename + ".txt")
479                stFilename = os.path.normpath( stPath )
480                fileObject = open(stFilename, "w")
481
482                fileObject.write( siteName + "\n" + time.asctime() + "\n" )
483                fileObject.write( '-' * 65 + "\n" )
484                tempString = (' Timestamp(s)    Disp BW(Gbps)    Rend BW(Gbps)\n')
485                fileObject.write(tempString)
486                fileObject.write( '-' * len(tempString) + "\n" )
487                self.hashFileInfo[totalsID] = fileObject
488                fileObject.flush()
489            # end of initialization
490           
491            if ( self.__bPerformanceLogging ):
492               
493                fileObject = self.hashFileInfo[totalsID]
494                tempString = "%12d    %12.4f    %12.4f\n" % (getTimeStamp(),
495                                                            self.getDisplayBWTotal(),
496                                                            self.getRenderBWTotal())
497                fileObject.write(tempString)
498                fileObject.flush()
499
500        except:
501            print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
502       
503
504    #----------------------------------------------------------------------
505
506
507    def getRenderBWTotal(self):
508        # zero out the totals if it hasn't been update in a while
509        if time.time() - self.__lastTotalsUpdate > 2.0:
510            self.__hashAppPerfTotals[self.I_RENDER_TOTAL_BANDWIDTH] = 0.0
511        return float(self.__hashAppPerfTotals[self.I_RENDER_TOTAL_BANDWIDTH])/1000.0
512
513
514    def getDisplayBWTotal(self):
515        # zero out the totals if it hasn't been update in a while
516        if time.time() - self.__lastTotalsUpdate > 2.0:
517            self.__hashAppPerfTotals[self.I_DISPLAY_TOTAL_BANDWIDTH] = 0.0
518        return float(self.__hashAppPerfTotals[self.I_DISPLAY_TOTAL_BANDWIDTH])/1000.0
519   
520
521    #----------------------------------------------------------------------
522   
523    #   Get the z value of the app
524    #   @arg windowId App instance ID of the app
525    #   @return Returns Z value if windowId exists else returns -1
526    def getZvalue(self, windowId):
527        if windowId in self.hashAppStatusInfo:
528            return self.hashAppStatusInfo[windowId].getZvalue()
529        else:
530            print("getZvalue: Invalid app instance ID")
531            return
532
533           
534    #----------------------------------------------------------------------
535
536
537    #   Set the Z value of the app
538    #   @arg windowId App instance ID of the app
539    #   @arg value New Z value to be set
540    def setZvalue(self, windowId, value):
541        if (windowId in self.hashAppStatusInfo):
542            self.hashAppStatusInfo[windowId].setZvalue(value)
543        else:
544            print ('setZvalue: Invalid app instance ID: %d'% (windowId))
545        return
546
547
548    #----------------------------------------------------------------------
549
550   
551    ### Get the sage app Info
552    ### @arg windowId Instance id of the application
553    ### @returns A list of format [<left>, <right>, <top>, <bottom>]
554    def getAppInfo(self, windowId):
555        if windowId in self.hashAppStatusInfo:
556            return self.hashAppStatusInfo[windowId].getBounds()
557        else:
558            print("getAppInfo: Invalid app instance ID")
559            return []
560
561
562    #----------------------------------------------------------------------
563
564
565    # returns the SageApp associated with the given windowId
566    def getApp(self, windowId):
567        return self.hashAppStatusInfo[windowId]
568   
569
570    #----------------------------------------------------------------------
571
572
573    ### Get the sage app display information
574    ### @arg windowId Instance id of the application
575    ### @arg interval Total no of values required (max = 30)
576    ### @returns A array   
577    def getDisplayItem(self, stItemName, windowId, interval):
578        if windowId in self.hashAppPerfInfo:
579            appInfo = self.hashAppPerfInfo.get(windowId)
580            return appInfo.getDisplayInformation( stItemName, interval )
581        else:
582            print("getDisplayItem: Invalid app instance ID")
583
584
585    ### Get the sage app render information
586    ### @arg windowId Instance id of the application
587    ### @arg interval Total no of values required (max = 30)
588    ### @returns A array
589    def getRenderItem(self, stItemName, windowId, interval):
590        if windowId in self.hashAppPerfInfo:
591            appInfo = self.hashAppPerfInfo.get(windowId)
592            return appInfo.getRenderInformation( stItemName, interval )
593        else:
594            print("Invalid app instance ID")
595
596
597    #----------------------------------------------------------------------
598
599   
600    ### Get the sage app data service bandwidth
601    ### @arg windowId Instance id of the application
602    ### @arg interval Total no of values required (max = 30)
603    ### @returns A array
604    def getDataBandWidth(self, windowId, interval):
605        if windowId in self.hashAppPerfInfo:
606            appInfo = self.hashAppPerfInfo.get(windowId)
607            return appInfo.getDataBandWidth(interval)
608        else:
609            print("Invalid app instance ID")
610
611
612    #----------------------------------------------------------------------
613   
614
615    ### So that SageData knows what to call when a message arrives
616    def registerCallbackFunction( self, iSageID, function ):
617        self.hashCallback[ iSageID ] = function
618
619
620    #----------------------------------------------------------------------
621
622   
623    ### (RJ 2005-01-15)
624    ### Returns a list of all the available apps
625    def getAvailableApps( self ):
626        return self.hashApps
627
628    #----------------------------------------------------------------------
629
630    ### sage background color
631    def setSAGEColor(self, (r,g,b)):
632        self._sageColor = (r,g,b)
633
634    #----------------------------------------------------------------------
635
636    ### sage background color
637    def getSAGEColor(self):
638        return self._sageColor
639   
640    #----------------------------------------------------------------------
641
642    # checks all the apps and reports whether any one of them was
643    # hit with a click and which region was hit (corners or shape in general)
644    # if more than one shape was hit it returns the one on the top
645    def checkHits(self, x, y):
646        zHash = {}  #key=z value, value=SageApp
647
648        for windowId, sageApp in self.hashAppStatusInfo.iteritems():
649            zHash[sageApp.getZvalue()] = sageApp
650
651        zKeys = zHash.keys()
652        zKeys.sort()
653
654        for z in zKeys:
655            hitResult = zHash[z].hitTest(x,y)
656            if hitResult >= 0:
657                return (zHash[z], hitResult)
658
659        return (None, -1)
660
661
662    #----------------------------------------------------------------------
663
664    # returns (windowId, zValue) or (-1,sys.maxint) if no apps
665    def getTopApp(self):
666        minZ = (-1, sys.maxint)
667        for windowId, app in self.hashAppStatusInfo.iteritems():
668            if app.getZvalue() < minZ[1]:
669                minZ = (windowId, app.getZvalue())
670        return minZ
671
672    #----------------------------------------------------------------------
673
674    ### (AKS 2005-02-16)
675    ### Return totals/averages for performance metrics for applications
676    def getTotals( self ):
677        return self.__hashAppPerfTotals
678   
679    #----------------------------------------------------------------------
680
681    ### (AKS 2005-02-16)
682    ### Set the logging flag and close all the logging files
683    def setLoggingFlag( self, bFlag ):
684        self.__bPerformanceLogging = bFlag
685
686    def isLoggingEnabled(self):
687        return self.__bPerformanceLogging
688
689    #----------------------------------------------------------------------
690   
691    ### (RJ 2005-5-18)
692    ### Stops the logging and closes all the logging files
693    def stopLogging(self):
694        for windowId, fileObject in self.getLogFileHash().iteritems():
695            fileObject.close()
696
697    #----------------------------------------------------------------------
698
699    ### (AKS 2005-05-07)
700    ### Get render bandwidth graph
701    def getRenderBandwidthGraph( self ):
702        return self.__pgTotalRenderBandwidth
703
704
705    #----------------------------------------------------------------------
706
707    ### (AKS 2005-05-07)
708    ### Get display bandwidth graph
709    def getDisplayBandwidthGraph( self ):
710        return self.__pgTotalDisplayBandwidth
711
712
713    #----------------------------------------------------------------------
714
715
716    def saveState(self, stateName, description):
717        appLaunchers = self.sageGate.getLaunchers()
718        appList = []
719
720        # gather all the data that needs to be saved for each app
721        for app in self.hashAppStatusInfo.values():
722
723            # get the config info from the right appLauncher
724            if app.getLauncherId() != "none":
725                appLauncher = xmlrpclib.ServerProxy("http://" + app.getLauncherId())
726                try:
727                    res = appLauncher.getAppConfigInfo( app.getAppId() )
728                except:
729                    print "\nUnable to connect to appLauncher on", app.getLauncherId(), \
730                          "so not saving this app: ", app.getName()
731                    continue
732               
733                if res == -1:
734                    continue   # skip this app... something went wrong
735                configName, optionalArgs = res
736
737                # get the other app parameters from sageApp object
738                pos = (app.getLeft(), app.getBottom())
739                size = (app.getWidth(), app.getHeight())
740               
741                # append the tuple of app's data to the list that will be saved
742                appList.append( (app.getLauncherId(), app.getName(), configName,
743                                 pos, size, optionalArgs) )
744
745     
746        # open the file and write to it
747        try:   #in case the file and directory permissions are not right
748            f = open( opj(SAVED_STATES_DIR, stateName+".state"), "w")
749            pickle.Pickler(f, 0).dump( (description, appList) )
750            f.close()
751        except IOError:
752            print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
753            return False
754
755        return True
756
757
758    def __deleteOldAutosaves(self):
759        # remove old autosave files...
760        try:
761            sd = SAVED_STATES_DIR
762            saves = os.listdir(sd)
763            if "_autosave_PREV.state" in saves:
764                os.remove(opj(sd, "_autosave_PREV.state"))
765            if "_autosave_LATEST.state" in saves:
766                shutil.move(opj(sd, "_autosave_LATEST.state"), opj(sd, "_autosave_PREV.state"))
767        except:
768            print "ERROR while deleting old states:"
769            print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
770
771
772    def loadState(self, stateName):
773        """ tries to reload the apps from the saved state """
774        appList = []
775        description = ""
776
777        # load the state from a file
778        try:
779            f = open( opj(SAVED_STATES_DIR, stateName+".state"), "r")
780            (description, appList) = pickle.Unpickler(f).load()
781            f.close()
782        except:
783            print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
784            print "\nUnable to read saved state file: "+"saved-states/"+stateName+".state"
785            return False
786
787        # try re-running all the apps
788        count = 0
789        for appInfo in appList:
790            launcherId, appName, configName, pos, size, optionalArgs = appInfo
791            self.sageGate.executeRemoteApp(launcherId, appName, configName, pos, size, optionalArgs)
792            count+=1
793           
794        return True
795
796
797
798    def deleteState(self, stateName):
799        """ tries to delete an existing state """
800        try:
801            filePath = opj(SAVED_STATES_DIR, stateName+".state")
802            os.remove(filePath)
803        except:
804            print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
805            print "\nUnable to delete the saved state: ", filePath
806            return False
807
808        return True
809
810           
811
812    def getStateList(self):
813        """ returns a hash of key=stateName, value=description """
814        stateHash = {}
815        appList = []
816        description = ""
817
818        sd = SAVED_STATES_DIR
819       
820        # load all the states and read descriptions from them
821        for fileName in os.listdir( sd ):
822            filePath = opj(sd, fileName)
823            if os.path.isfile(filePath) and os.path.splitext(filePath)[1] == ".state":
824                try:
825                    stateName = os.path.splitext( os.path.split(filePath)[1] )[0]
826                    f = open(filePath, "rb")
827                    (description, appList) = pickle.Unpickler(f).load()
828                    f.close()
829                    stateHash[stateName] = description
830                except:
831                    print "\nUnable to read saved state file: "+filePath
832                    continue
833
834        return stateHash
835
836
837
838    def closeAllApps(self):
839        for app in self.hashAppStatusInfo.itervalues():
840            if app.getId() == -5:
841                continue
842            self.sageGate.shutdownApp(app.getId())
843            time.sleep(0.5)
844
845
846
Note: See TracBrowser for help on using the repository browser.