Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
#!/usr/bin/env python
2
 
3
# Written by kboy
4
 
5
# v 1.01 Mar 20, 06 
6
 
7
import commands, os, re, sys
8
from os import popen, getpid, remove
9
from sys import argv, stdout
10
from time import time, strftime
11
import thread, threading, time
12
 
13
DEBUG = False
14
 
15
if __debug__: LOGFILE=open(argv[1]+"tfQManager.log","w")
16
 
17
def run(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath):
18
 
19
    displayParams(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath)
20
 
21
    #Check to see if already running.
22
    lastPID = "0"
23
    try:
24
        f=open(qDirectory+"tfQManager.pid",'r')
25
        lastPID = f.readline().strip()
26
        f.close()
27
        if __debug__: traceMsg("Last QManager pid" + str(lastPID))
28
    except:
29
        pass
30
 
31
    if (int(lastPID) > 0):
32
        if (checkPIDStatus(lastPID) > 0):
33
            if __debug__: traceMsg("Already Running on pid:" + lastPID)
34
            raise KeyboardInterrupt
35
 
36
    if __debug__: traceMsg("QManager Starting")
37
 
38
    f=open(qDirectory+"tfQManager.pid",'w')
39
    f.write(str(getpid()) + "\n")
40
    f.flush()
41
    f.close()
42
 
43
    if __debug__: traceMsg("QManager PID :" + str(getpid()))
44
 
45
    # Extract from the execPath the Btphptornado.py script line.
46
    # this will be used during the process Counts to ensure we are 
47
    # unique from other running instances.
48
 
49
    ePath = execPath.split(" ")
50
    for x in ePath:
51
        if (re.search('btphptornado', x) > 0 ):
52
            btphp = x
53
    if __debug__: traceMsg("btphp ->"+btphp)
54
 
55
    if (re.search('btphptornado', btphp) > 0 ):
56
        try:    
57
            while 1:
58
 
59
                threadCount = checkThreadCount(btphp)
60
                if __debug__: traceMsg("CurrentThreadCount = " + str( threadCount ))
61
 
62
                #
63
                # Start Looping untill we have maxSvrThreads.
64
                # Or no Qinfo Files.
65
                #
66
 
67
                while int(threadCount) <= int(maxSvrThreads):
68
                    try:
69
                        # 
70
                        # Get the Next File.
71
                        # Check to see if we got a file back.
72
                        # if not break out of looping we don't have any files.
73
                        #
74
                        fileList = []
75
                        fileList = getFileList(qDirectory)
76
                        for currentFile in fileList:
77
                            if currentFile == "":
78
                                break
79
 
80
                            # set the name of the current statsFile
81
                            statsFile = currentFile.replace('/queue','').strip('.Qinfo')
82
                            if __debug__: traceMsg("statsFile = " + statsFile)
83
 
84
                            # 
85
                            # get the User name if we didn't get one 
86
                            # something was wrong with this file.
87
                            # 
88
                            currentUser = getUserName(statsFile)
89
                            if currentUser == "":
90
                                if __debug__: traceMsg("No User Found : " + currentFile)
91
                                # Prep StatsFile
92
                                updateStats(statsFile, '0')
93
                                removeFile(currentFile)
94
                                break
95
                            else:
96
                                if __debug__: traceMsg("Current User: " + currentUser)
97
 
98
                                #
99
                                # Now check user thread count
100
                                #
101
                                usrThreadCount = getUserThreadCount(currentUser, btphp)
102
 
103
                                #
104
                                # check UserThreadCount
105
                                #
106
                                if int(usrThreadCount) < int(maxUsrThreads):
107
                                    #
108
                                    # Now check to see if we start a new thread will we be over the max ?
109
                                    #
110
                                    threadCount = checkThreadCount(btphp)
111
                                    if int(threadCount) + 1 <= int(maxSvrThreads):
112
                                        if int(usrThreadCount) + 1 <= int(maxUsrThreads):
113
 
114
                                            cmdToRun = getCommandToRun(currentFile)
115
                                            #if __debug__: traceMsg(" Cmd :" + cmdToRun)
116
 
117
                                            if (re.search(currentUser,cmdToRun) == 0):
118
                                                if __debug__: traceMsg("Incorrect User found in Cmd")
119
                                                cmdToRun = ''
120
                                            if (re.search('\|',cmdToRun) > 0):
121
                                                if __debug__: traceMsg(" Failed pipe ")
122
                                                cmdToRun = ''
123
                                            else:
124
                                                cmdToRun = execPath + cmdToRun
125
 
126
                                            cmdToRun = cmdToRun.replace('TFQUSERNAME', currentUser)
127
                                            #if __debug__: traceMsg(" Cmd :" + cmdToRun)
128
 
129
                                            if cmdToRun != "":
130
                                                #PrepStatsFile
131
                                                updateStats(statsFile, '1')
132
 
133
                                                if __debug__: traceMsg("Fire off command")
134
                                                try:
135
                                                    garbage = doCommand(cmdToRun)
136
 
137
                                                    # 
138
                                                    # wait until the torrent process starts 
139
                                                    # and creates a pid file.
140
                                                    # once this happens we can remove the Qinfo.
141
                                                    # 
142
                                                    while 1:
143
                                                        try:
144
                                                            time.sleep(2)
145
                                                            f=open(statsFile+".pid",'r')
146
                                                            f.close()
147
                                                            break
148
                                                        except:
149
                                                            continue
150
 
151
                                                    # Ok this one started Remove Qinfo File.
152
                                                    if __debug__: traceMsg("Removing : " + currentFile)
153
                                                    removeFile(currentFile)
154
                                                except:
155
                                                    continue
156
                                            else:
157
                                                # 
158
                                                # Something wrong with command file.
159
                                                # 
160
                                                if __debug__: traceMsg("Unable to obtain valid cmdToRun : " + currentFile)
161
                                                removeFile(currentFile)
162
                                        else:
163
                                            if __debug__: traceMsg("Skipping this file since the User has to many threads")
164
                                            if __debug__: traceMsg("Skipping : " + currentFile)
165
 
166
                                    else:
167
                                        if __debug__: traceMsg("Skipping this file since the Server has to many threads")
168
                                        if __debug__: traceMsg("Skipping : " + currentFile)
169
                        break
170
 
171
                    except:
172
                        break
173
 
174
                    threadCount = checkThreadCount(btphp)
175
                    if __debug__: traceMsg("CurrentThreadCount = " + str( threadCount ))
176
 
177
                if __debug__: traceMsg("Sleeping...")
178
                time.sleep(float(sleepInterval))
179
        except:
180
            removeFile(qDirectory+"tfQManager.pid")
181
    else:
182
        LOG = True
183
        if __debug__: traceMsg("Only supported client is btphptornado.")
184
        removeFile(qDirectory+"tfQManager.pid")
185
 
186
 
187
def checkThreadCount(btphp):
188
 
189
    if __debug__: traceMsg("->checkTreadCount")
190
 
191
    psLine = []
192
    line = ""
193
    counter = 0
194
    list = doCommand("ps x -o pid,ppid,command -ww | grep '" + btphp + "' | grep -v tfQManager | grep -v grep")
195
 
196
    try:
197
        for c in list:
198
            line += c
199
            if c == '\n':
200
                psLine.append(line.strip())
201
                line = ""
202
 
203
        # look for the grep line
204
        for line in psLine:
205
            if (re.search('btphptornado.py',line) > 0):
206
                # now see if this is the main process and not a child.
207
                if (re.search(' 1 /',line) > 0):
208
                    counter += 1
209
                    if __debug__: traceMsg(" -- Counted -- ")
210
            if __debug__: traceMsg(line)
211
 
212
    except:
213
        counter = 0
214
 
215
    return counter
216
 
217
def checkPIDStatus(pid):
218
 
219
    if __debug__: traceMsg("->checkPIDStatus (" + pid + ")")
220
 
221
    counter = 0
222
    list = doCommand("ps -p "+pid+" -o pid= -ww")
223
 
224
    try:
225
        counter = len(list)
226
    except:
227
        counter = 0
228
 
229
    return counter
230
 
231
 
232
def getUserThreadCount(userName, btphp):
233
 
234
    if __debug__: traceMsg("->getUserThreadCount (" + userName + ")")
235
 
236
    psLine = []
237
    line = ""
238
    counter = 0
239
    list = doCommand("ps x -o pid,ppid,command -ww | grep '" + btphp + "' | grep -v tfQManager | grep -v grep")
240
 
241
    try:
242
        for c in list:
243
            line += c
244
            if c == '\n':
245
                psLine.append(line.strip())
246
                line = ""
247
 
248
        # look for the grep line
249
        for line in psLine:
250
            if (re.search('btphptornado.py',line) > 0):
251
                # now see if this is the main process and not a child.
252
                if (re.search(' 1 /',line) > 0):
253
                    # look for the userName
254
                    if re.search(userName,line) > 0:
255
                        counter += 1
256
                        if __debug__: traceMsg(" -- Counted -- ")
257
            if __debug__: traceMsg(line)
258
    except:
259
        counter = 0
260
 
261
    if __debug__: traceMsg("->getUserThreadCount is (" + str(counter)+")")
262
 
263
    return counter
264
 
265
def removeFile(currentFile):
266
 
267
    if __debug__: traceMsg("->removeFile (" + currentFile + ")")
268
    os.remove(currentFile)
269
 
270
    return
271
 
272
def doCommand( command ): 
273
 
274
    if __debug__: traceMsg("->doCommand (" + command + ")")
275
 
276
    # 
277
    # Fire off a command returning the output
278
    #
279
    return popen(command).read()
280
 
281
 
282
def doCommandPID( command ): 
283
 
284
    if __debug__: traceMsg("->doCommandPID (" + command + ")")
285
 
286
    # 
287
    # Fire off a command returning the pid
288
    #
289
    #return popen2.Popen4(command).pid
290
    garbage = doCommand(command)
291
 
292
    return getPIDofCmd(command)
293
 
294
 
295
def getPIDofCmd(command):
296
 
297
    if __debug__: traceMsg("->getPIDofCmd (" + command + ")")
298
 
299
    cmdPID = ""
300
    psLine = []
301
    endOfPID = False
302
    line = ""
303
 
304
    list = doCommand("ps x -ww | grep \'"+command+"\' | grep -v grep")
305
 
306
    if DEBUG:
307
        print list
308
 
309
    try:
310
        for c in list:
311
            line += c
312
            if c == '\n':
313
                psLine.append(line.strip(' '))
314
 
315
        # look for the grep line
316
        for line in psLine:
317
            for e in line:
318
                if e.isdigit() and endOfPID == False:
319
                    cmdPID += e
320
                else:
321
                    endOfPID = True
322
                    break
323
    except:
324
        cmdPID = "0"
325
 
326
    if __debug__: traceMsg(cmdPID)
327
 
328
    return cmdPID
329
 
330
def getCommandToRun(currentFile):
331
 
332
    if __debug__: traceMsg("->getCommandToRun (" + currentFile + ")")
333
 
334
    #Open the File and return the Command to Run.
335
    cmdToExec = ""
336
 
337
    try:
338
        f=open(currentFile,'r')
339
        cmdToExec = f.readline()
340
        f.close
341
 
342
    except:
343
        cmdToExec = ""
344
 
345
    return cmdToExec
346
 
347
 
348
def getFileList(fDirectory):
349
 
350
    if __debug__: traceMsg("->getFileList (" + fDirectory + ")")
351
 
352
    # Get the list of Qinfo files.
353
    fileList = []
354
 
355
    try:
356
        times = {}
357
 
358
        for fName in os.listdir(fDirectory):
359
            if re.search('\.Qinfo',fName) > 0:
360
                p = os.path.join(fDirectory,fName)
361
                times.setdefault(str(os.path.getmtime(p)),[]).append(p)
362
 
363
        l = times.keys()
364
        l.sort()
365
 
366
        for i in l:
367
            for f in times[i]:
368
                fileList.append(f)
369
    except:
370
        fileList = ""
371
 
372
    return fileList
373
 
374
 
375
def getUserName(fName):
376
 
377
    if __debug__: traceMsg("->getUserName (" + fName + ")")
378
 
379
    userName = ""
380
 
381
    try:
382
        f=open(fName,'r')
383
        garbage = f.readline()
384
        garbage = f.readline()
385
        garbage = f.readline()
386
        garbage = f.readline()
387
        garbage = f.readline()
388
        userName = f.readline().strip()
389
        f.close()
390
 
391
        if __debug__: traceMsg("userName : " + userName)
392
 
393
    except:
394
        userName = ""
395
 
396
    return userName
397
 
398
 
399
def updateStats(fName, status = '1'):
400
 
401
    if __debug__: traceMsg("->updateStats (" + fName + ")")
402
 
403
    fp=open(fName,'r+')
404
    fp.seek(0)
405
    fp.write(status)
406
    fp.flush()
407
    fp.close
408
 
409
 
410
def displayParams(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath):
411
 
412
    if __debug__: 
413
        traceMsg("qDir   : " + qDirectory)
414
        traceMsg("maxSvr : " + str(maxSvrThreads))
415
        traceMsg("maxUsr : " + str(maxUsrThreads))
416
        traceMsg("sleepI : " + str(sleepInterval))
417
        traceMsg("execPath : " + str(execPath))
418
    return
419
 
420
 
421
def traceMsg(msg):
422
    if DEBUG:
423
       print msg
424
    if __debug__:
425
       LOGFILE.write(msg + "\n")
426
       LOGFILE.flush()
427
 
428
 
429
if __name__ == '__main__':
430
    run(argv[1],argv[2],argv[3],argv[4],argv[5])