0,0 → 1,430 |
#!/usr/bin/env python |
|
# Written by kboy |
|
# v 1.01 Mar 20, 06 |
|
import commands, os, re, sys |
from os import popen, getpid, remove |
from sys import argv, stdout |
from time import time, strftime |
import thread, threading, time |
|
DEBUG = False |
|
if __debug__: LOGFILE=open(argv[1]+"tfQManager.log","w") |
|
def run(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath): |
|
displayParams(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath) |
|
#Check to see if already running. |
lastPID = "0" |
try: |
f=open(qDirectory+"tfQManager.pid",'r') |
lastPID = f.readline().strip() |
f.close() |
if __debug__: traceMsg("Last QManager pid" + str(lastPID)) |
except: |
pass |
|
if (int(lastPID) > 0): |
if (checkPIDStatus(lastPID) > 0): |
if __debug__: traceMsg("Already Running on pid:" + lastPID) |
raise KeyboardInterrupt |
|
if __debug__: traceMsg("QManager Starting") |
|
f=open(qDirectory+"tfQManager.pid",'w') |
f.write(str(getpid()) + "\n") |
f.flush() |
f.close() |
|
if __debug__: traceMsg("QManager PID :" + str(getpid())) |
|
# Extract from the execPath the Btphptornado.py script line. |
# this will be used during the process Counts to ensure we are |
# unique from other running instances. |
|
ePath = execPath.split(" ") |
for x in ePath: |
if (re.search('btphptornado', x) > 0 ): |
btphp = x |
if __debug__: traceMsg("btphp ->"+btphp) |
|
if (re.search('btphptornado', btphp) > 0 ): |
try: |
while 1: |
|
threadCount = checkThreadCount(btphp) |
if __debug__: traceMsg("CurrentThreadCount = " + str( threadCount )) |
|
# |
# Start Looping untill we have maxSvrThreads. |
# Or no Qinfo Files. |
# |
|
while int(threadCount) <= int(maxSvrThreads): |
try: |
# |
# Get the Next File. |
# Check to see if we got a file back. |
# if not break out of looping we don't have any files. |
# |
fileList = [] |
fileList = getFileList(qDirectory) |
for currentFile in fileList: |
if currentFile == "": |
break |
|
# set the name of the current statsFile |
statsFile = currentFile.replace('/queue','').strip('.Qinfo') |
if __debug__: traceMsg("statsFile = " + statsFile) |
|
# |
# get the User name if we didn't get one |
# something was wrong with this file. |
# |
currentUser = getUserName(statsFile) |
if currentUser == "": |
if __debug__: traceMsg("No User Found : " + currentFile) |
# Prep StatsFile |
updateStats(statsFile, '0') |
removeFile(currentFile) |
break |
else: |
if __debug__: traceMsg("Current User: " + currentUser) |
|
# |
# Now check user thread count |
# |
usrThreadCount = getUserThreadCount(currentUser, btphp) |
|
# |
# check UserThreadCount |
# |
if int(usrThreadCount) < int(maxUsrThreads): |
# |
# Now check to see if we start a new thread will we be over the max ? |
# |
threadCount = checkThreadCount(btphp) |
if int(threadCount) + 1 <= int(maxSvrThreads): |
if int(usrThreadCount) + 1 <= int(maxUsrThreads): |
|
cmdToRun = getCommandToRun(currentFile) |
#if __debug__: traceMsg(" Cmd :" + cmdToRun) |
|
if (re.search(currentUser,cmdToRun) == 0): |
if __debug__: traceMsg("Incorrect User found in Cmd") |
cmdToRun = '' |
if (re.search('\|',cmdToRun) > 0): |
if __debug__: traceMsg(" Failed pipe ") |
cmdToRun = '' |
else: |
cmdToRun = execPath + cmdToRun |
|
cmdToRun = cmdToRun.replace('TFQUSERNAME', currentUser) |
#if __debug__: traceMsg(" Cmd :" + cmdToRun) |
|
if cmdToRun != "": |
#PrepStatsFile |
updateStats(statsFile, '1') |
|
if __debug__: traceMsg("Fire off command") |
try: |
garbage = doCommand(cmdToRun) |
|
# |
# wait until the torrent process starts |
# and creates a pid file. |
# once this happens we can remove the Qinfo. |
# |
while 1: |
try: |
time.sleep(2) |
f=open(statsFile+".pid",'r') |
f.close() |
break |
except: |
continue |
|
# Ok this one started Remove Qinfo File. |
if __debug__: traceMsg("Removing : " + currentFile) |
removeFile(currentFile) |
except: |
continue |
else: |
# |
# Something wrong with command file. |
# |
if __debug__: traceMsg("Unable to obtain valid cmdToRun : " + currentFile) |
removeFile(currentFile) |
else: |
if __debug__: traceMsg("Skipping this file since the User has to many threads") |
if __debug__: traceMsg("Skipping : " + currentFile) |
|
else: |
if __debug__: traceMsg("Skipping this file since the Server has to many threads") |
if __debug__: traceMsg("Skipping : " + currentFile) |
break |
|
except: |
break |
|
threadCount = checkThreadCount(btphp) |
if __debug__: traceMsg("CurrentThreadCount = " + str( threadCount )) |
|
if __debug__: traceMsg("Sleeping...") |
time.sleep(float(sleepInterval)) |
except: |
removeFile(qDirectory+"tfQManager.pid") |
else: |
LOG = True |
if __debug__: traceMsg("Only supported client is btphptornado.") |
removeFile(qDirectory+"tfQManager.pid") |
|
|
def checkThreadCount(btphp): |
|
if __debug__: traceMsg("->checkTreadCount") |
|
psLine = [] |
line = "" |
counter = 0 |
list = doCommand("ps x -o pid,ppid,command -ww | grep '" + btphp + "' | grep -v tfQManager | grep -v grep") |
|
try: |
for c in list: |
line += c |
if c == '\n': |
psLine.append(line.strip()) |
line = "" |
|
# look for the grep line |
for line in psLine: |
if (re.search('btphptornado.py',line) > 0): |
# now see if this is the main process and not a child. |
if (re.search(' 1 /',line) > 0): |
counter += 1 |
if __debug__: traceMsg(" -- Counted -- ") |
if __debug__: traceMsg(line) |
|
except: |
counter = 0 |
|
return counter |
|
def checkPIDStatus(pid): |
|
if __debug__: traceMsg("->checkPIDStatus (" + pid + ")") |
|
counter = 0 |
list = doCommand("ps -p "+pid+" -o pid= -ww") |
|
try: |
counter = len(list) |
except: |
counter = 0 |
|
return counter |
|
|
def getUserThreadCount(userName, btphp): |
|
if __debug__: traceMsg("->getUserThreadCount (" + userName + ")") |
|
psLine = [] |
line = "" |
counter = 0 |
list = doCommand("ps x -o pid,ppid,command -ww | grep '" + btphp + "' | grep -v tfQManager | grep -v grep") |
|
try: |
for c in list: |
line += c |
if c == '\n': |
psLine.append(line.strip()) |
line = "" |
|
# look for the grep line |
for line in psLine: |
if (re.search('btphptornado.py',line) > 0): |
# now see if this is the main process and not a child. |
if (re.search(' 1 /',line) > 0): |
# look for the userName |
if re.search(userName,line) > 0: |
counter += 1 |
if __debug__: traceMsg(" -- Counted -- ") |
if __debug__: traceMsg(line) |
except: |
counter = 0 |
|
if __debug__: traceMsg("->getUserThreadCount is (" + str(counter)+")") |
|
return counter |
|
def removeFile(currentFile): |
|
if __debug__: traceMsg("->removeFile (" + currentFile + ")") |
os.remove(currentFile) |
|
return |
|
def doCommand( command ): |
|
if __debug__: traceMsg("->doCommand (" + command + ")") |
|
# |
# Fire off a command returning the output |
# |
return popen(command).read() |
|
|
def doCommandPID( command ): |
|
if __debug__: traceMsg("->doCommandPID (" + command + ")") |
|
# |
# Fire off a command returning the pid |
# |
#return popen2.Popen4(command).pid |
garbage = doCommand(command) |
|
return getPIDofCmd(command) |
|
|
def getPIDofCmd(command): |
|
if __debug__: traceMsg("->getPIDofCmd (" + command + ")") |
|
cmdPID = "" |
psLine = [] |
endOfPID = False |
line = "" |
|
list = doCommand("ps x -ww | grep \'"+command+"\' | grep -v grep") |
|
if DEBUG: |
print list |
|
try: |
for c in list: |
line += c |
if c == '\n': |
psLine.append(line.strip(' ')) |
|
# look for the grep line |
for line in psLine: |
for e in line: |
if e.isdigit() and endOfPID == False: |
cmdPID += e |
else: |
endOfPID = True |
break |
except: |
cmdPID = "0" |
|
if __debug__: traceMsg(cmdPID) |
|
return cmdPID |
|
def getCommandToRun(currentFile): |
|
if __debug__: traceMsg("->getCommandToRun (" + currentFile + ")") |
|
#Open the File and return the Command to Run. |
cmdToExec = "" |
|
try: |
f=open(currentFile,'r') |
cmdToExec = f.readline() |
f.close |
|
except: |
cmdToExec = "" |
|
return cmdToExec |
|
|
def getFileList(fDirectory): |
|
if __debug__: traceMsg("->getFileList (" + fDirectory + ")") |
|
# Get the list of Qinfo files. |
fileList = [] |
|
try: |
times = {} |
|
for fName in os.listdir(fDirectory): |
if re.search('\.Qinfo',fName) > 0: |
p = os.path.join(fDirectory,fName) |
times.setdefault(str(os.path.getmtime(p)),[]).append(p) |
|
l = times.keys() |
l.sort() |
|
for i in l: |
for f in times[i]: |
fileList.append(f) |
except: |
fileList = "" |
|
return fileList |
|
|
def getUserName(fName): |
|
if __debug__: traceMsg("->getUserName (" + fName + ")") |
|
userName = "" |
|
try: |
f=open(fName,'r') |
garbage = f.readline() |
garbage = f.readline() |
garbage = f.readline() |
garbage = f.readline() |
garbage = f.readline() |
userName = f.readline().strip() |
f.close() |
|
if __debug__: traceMsg("userName : " + userName) |
|
except: |
userName = "" |
|
return userName |
|
|
def updateStats(fName, status = '1'): |
|
if __debug__: traceMsg("->updateStats (" + fName + ")") |
|
fp=open(fName,'r+') |
fp.seek(0) |
fp.write(status) |
fp.flush() |
fp.close |
|
|
def displayParams(qDirectory,maxSvrThreads,maxUsrThreads,sleepInterval,execPath): |
|
if __debug__: |
traceMsg("qDir : " + qDirectory) |
traceMsg("maxSvr : " + str(maxSvrThreads)) |
traceMsg("maxUsr : " + str(maxUsrThreads)) |
traceMsg("sleepI : " + str(sleepInterval)) |
traceMsg("execPath : " + str(execPath)) |
return |
|
|
def traceMsg(msg): |
if DEBUG: |
print msg |
if __debug__: |
LOGFILE.write(msg + "\n") |
LOGFILE.flush() |
|
|
if __name__ == '__main__': |
run(argv[1],argv[2],argv[3],argv[4],argv[5]) |