source: TI03-DataExtractor/branches/titania_install/pygss/ProcessList.py @ 1520

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/branches/titania_install/pygss/ProcessList.py@1610
Revision 1520, 7.3 KB checked in by astephen, 14 years ago (diff)

This is the live version on titania - changes have been made so safest to SVN it.

Line 
1#!/usr/bin/env python
2
3#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
4#   This software may be distributed under the terms of the
5#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
6
7"""
8ProcessList.py
9==============
10
11Module holding the ProcessList class which maps jobs run by users
12to a simple database of process IDs. You can access methods to
13check if the user has a process running and update the list.
14
15"""
16
17# Import standard library modules
18import os, sys, time, commands, shelve
19
20# Import local modules
21from serverConfig import PROCESS_LIST_DIR
22
23def convertETimeToSeconds(etime):
24    """
25    Takes a time string one of the formats "HH:MM:SS", "MM:SS", or "SS" and
26    converts to number of seconds.
27    """
28    print etime
29    mins=0
30    hours=0
31    items=etime.split(":")
32    secs=int(items[-1])
33    if len(items)>1:
34        mins=int(items[-2])
35        if len(items)>2:
36            if len(items[-3])>2:
37                # Sort out jobs that are very new with strange format
38                hours=0
39                mins=0
40            else:
41                hours=int(items[-3])
42    total=secs+(60*mins)+(60*60*hours)
43    return total           
44
45class ProcessList:
46    """
47    ProcessList class - used to manage a list of username:process_id
48    pairs to check if a user is running any jobs. The list is stored
49    in a simple python shelve database as a dictionary of username keys
50    and process ID values.
51    """
52
53    def __init__(self, process=os.path.split("LOCAL_CGI_NAME")[0]):
54        """
55        __init__ method - reads in the current list or creates one (and
56        the required directory) if needed.
57        """
58
59        # Set the name of the process being run
60        self.process_name=process
61
62        # Check directory first
63        self.plistdir=PROCESS_LIST_DIR       
64        if not os.path.isdir(PROCESS_LIST_DIR):
65            self._createListDir()
66
67        # Define the filename for the lock file
68        self.filelock=os.path.join(self.plistdir, ".locked")
69
70        # Open shelve object
71        self.plist=os.path.join(self.plistdir, "proclistdb")
72
73
74    def _createListDir(self):
75        """
76        _createListDir method - creates the directory to hold the list
77        and sets read/write/execute permissions for all.
78        """
79        os.mkdir(self.plistdir)
80        os.chmod(self.plistdir, 0777)
81
82
83    def _openListdb(self):
84        """
85        _openListdb method - opens (or creates) the shelve object in a file.
86        """
87        # Check if file is being read/written to and wait until free
88        count=0
89        while self._isLocked()==1:
90            count=count+1
91            if count>10: break      # override if waited 10 secs
92            time.sleep(1)
93
94        # Now open the file
95        self._lockFile()
96        self.listdb=shelve.open(self.plist)
97        self._syncProcessLists()
98
99
100    def _closeListdb(self):
101        """
102        _closeListdb method - closes the shelve object and sets read/write all permission.
103        """
104        # Check if file is being read/written to and wait until free
105        try:
106            self.listdb.close()
107        except:
108            pass
109        self._unlockFile()
110
111
112    def _isLocked(self):
113        """
114        _isLocked method - checks if shelve db is locked.
115        """
116        if os.path.exists(self.filelock):
117            return 1
118        else: 
119            return 0
120
121
122    def _lockFile(self):
123        """
124        _lockFile method - locks the shelve db by creating a temporary
125        file '.locked'.
126        """
127        try:
128            if not os.path.exists(self.filelock):
129                lock=open(self.filelock, 'w')
130                lock.close()
131            os.chmod(self.filelock, 0777)
132        except:
133            raise "Cannot create or set permissions on lock file: "+self.lock_file
134
135
136    def _unlockFile(self):
137        """
138        _unlockFile method - unlocks the shelve db by deleting a temporary
139        file '.locked'.
140        """
141        try:
142            if os.path.exists(self.filelock):
143                os.unlink(self.filelock) 
144                #print "Successfully unlocked!"
145        except:
146            raise "Cannot delete lock file: "+self.lock_file
147        delattr(self, "listdb")
148
149
150    def _getUserList(self):
151        """
152        _getUserList method - gets a current list of users running processes.
153        """
154        return self.listdb.keys()
155
156 
157    def _syncProcessLists(self):
158        """
159        _syncProcessLists method - gets a list of processes running (from the host)
160        and synchronises this with the process list db.
161        """
162        # Get command output - list of processes
163        ps_output=commands.getoutput("ps -Ao pid,etime,cmd | grep %s" % self.process_name).split("\n")
164
165        # Get current processes
166        processes=[]
167        for p in ps_output:   
168            items=p.strip().split()
169            (pid, etime)=items[0:2]
170            processes.append([int(pid), convertETimeToSeconds(etime)])
171           
172        print "Processes", processes   
173
174        # Update the process list to remove any processes that have finished
175        for user in self.listdb.keys():
176            matched=None
177            for proc in processes:
178                if self.listdb[user][0]==proc[0]:
179                    matched=1
180                    # Check if the start time of this process was within 30 seconds
181                    # of the process we know about. If so, assume it is the same one.
182                    startTime=self.listdb[user][1]
183                    if startTime<(proc[1]-30) or startTime>(proc[1]+30):
184                        matched=None   
185
186            if matched==None: # If process is not in the list delete it
187                del self.listdb[user]
188               
189               
190    def isUserRunningProcess(self, username):
191        """
192        isUserRunningProcess method - checks if the user is currently running a process.
193        """
194        self._openListdb()
195
196        if username in self.listdb.keys():
197            rtvalue=1
198        else:
199            rtvalue=0
200        self._closeListdb()
201        return rtvalue
202
203
204    def addProcessToList(self, username, processID):
205        """
206        addProcessToList method - adds a username key to the process list shelve db holding
207        holding a list containing the process ID and process start time.
208        """
209        if self.isUserRunningProcess(username)==0:
210            self._openListdb()
211            now=long(time.time())
212            self.listdb[username]=[processID, now]
213            self.listdb.sync()
214            self._closeListdb()
215        else:
216            raise "User is already running a process which has not yet completed."
217
218
219    def getProcessList(self):
220        """
221        getProcessList method - gets the list that we currently know about.
222        """
223        self._openListdb()
224       
225        rtDict={}
226        for user in self.listdb.keys():
227            rtDict[user]=self.listdb[user]
228
229
230        self._closeListdb()
231        return rtDict
232
233
234# Test routines:
235if __name__=="__main__":
236
237    if commands.getoutput('hostname').find('linux')<0: 
238        print "This test routine may not work on your machine, I suggest you tinker with it and make it relevant to your environment."
239        sys.exit()
240    # Initialise an instance using the process name 'kdeinit'
241    x=ProcessList("kdeinit")
242    print "Is the process list locked (0 or 1)?", x._isLocked()
243    print "Get the current list:"
244    print x.getProcessList()
245    print "Adding processes..."
246    #x.addProcessToList("hadsv", 6624)
247    #x.addProcessToList("hadsg", 6622)     
248    x.addProcessToList("hadfdgsd", 7000)       
249    print "Get the current list:"
250    print x.getProcessList()
251   
252   
253
254
255
Note: See TracBrowser for help on using the repository browser.