source: TI03-DataExtractor/branches/old_stuff/dx_source/for_usr_local/dx/processList.py @ 793

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/branches/old_stuff/dx_source/for_usr_local/dx/processList.py@793
Revision 793, 7.3 KB checked in by astephen, 13 years ago (diff)

Put all the old code in the old_stuff branch.

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