source: TI04-geosplat/trunk/pygss/ProcessList.py @ 798

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI04-geosplat/trunk/pygss/ProcessList.py@6809
Revision 798, 7.3 KB checked in by astephen, 14 years ago (diff)

Latest working version with install method.
Can accept more than one file but doesn't combine variables yet.

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.