bitbake: prserv/serv: Multithread the server

This makes the PR server multithreaded and able to handle multiple connections
at once which means its no longer a build bottle neck when serving one connection
at a time. I've experimented and database connection for each thread seems to
cause the least issues, pushing the contention for sqllite to handle itself.

This means moving the db/table connection code into the actual function methods.
It doesn't abstract well as a function since we need the db object around for
the lifetime of the function as well as the table else we lose the connection.

(Bitbake rev: bf9be2029b2bded5f532bdda4c38ae3dff5d1cf6)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie 2013-08-28 16:10:09 +00:00
parent 06d7664590
commit d5e860be4c
1 changed files with 15 additions and 9 deletions

View File

@ -31,19 +31,20 @@ class Handler(SimpleXMLRPCRequestHandler):
PIDPREFIX = "/tmp/PRServer_%s_%s.pid" PIDPREFIX = "/tmp/PRServer_%s_%s.pid"
singleton = None singleton = None
class PRServer(SimpleXMLRPCServer): import SocketServer
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
pass
class PRServer(SimpleThreadedXMLRPCServer):
def __init__(self, dbfile, logfile, interface, daemon=True): def __init__(self, dbfile, logfile, interface, daemon=True):
''' constructor ''' ''' constructor '''
SimpleXMLRPCServer.__init__(self, interface, SimpleThreadedXMLRPCServer.__init__(self, interface,
requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True) logRequests=False, allow_none=True)
self.dbfile=dbfile self.dbfile=dbfile
self.daemon=daemon self.daemon=daemon
self.logfile=logfile self.logfile=logfile
self.working_thread=None self.working_thread=None
self.host, self.port = self.socket.getsockname() self.host, self.port = self.socket.getsockname()
self.db=prserv.db.PRData(dbfile)
self.table=self.db["PRMAIN"]
self.pidfile=PIDPREFIX % (self.host, self.port) self.pidfile=PIDPREFIX % (self.host, self.port)
self.register_function(self.getPR, "getPR") self.register_function(self.getPR, "getPR")
@ -55,13 +56,17 @@ class PRServer(SimpleXMLRPCServer):
def export(self, version=None, pkgarch=None, checksum=None, colinfo=True): def export(self, version=None, pkgarch=None, checksum=None, colinfo=True):
try: try:
return self.table.export(version, pkgarch, checksum, colinfo) db = prserv.db.PRData(self.dbfile)
table = db["PRMAIN"]
return table.export(version, pkgarch, checksum, colinfo)
except sqlite3.Error as exc: except sqlite3.Error as exc:
logger.error(str(exc)) logger.error(str(exc))
return None return None
def importone(self, version, pkgarch, checksum, value): def importone(self, version, pkgarch, checksum, value):
return self.table.importone(version, pkgarch, checksum, value) db = prserv.db.PRData(self.dbfile)
table = db["PRMAIN"]
return table.importone(version, pkgarch, checksum, value)
def ping(self): def ping(self):
return not self.quit return not self.quit
@ -71,7 +76,9 @@ class PRServer(SimpleXMLRPCServer):
def getPR(self, version, pkgarch, checksum): def getPR(self, version, pkgarch, checksum):
try: try:
return self.table.getValue(version, pkgarch, checksum) db = prserv.db.PRData(self.dbfile)
table = db["PRMAIN"]
return table.getValue(version, pkgarch, checksum)
except prserv.NotFoundError: except prserv.NotFoundError:
logger.error("can not find value for (%s, %s)",version, checksum) logger.error("can not find value for (%s, %s)",version, checksum)
return None return None
@ -177,7 +184,6 @@ class PRServSingleton(object):
self.prserv = PRServer(self.dbfile, self.logfile, self.interface) self.prserv = PRServer(self.dbfile, self.logfile, self.interface)
self.prserv.start() self.prserv.start()
self.host, self.port = self.prserv.getinfo() self.host, self.port = self.prserv.getinfo()
del self.prserv.db
def getinfo(self): def getinfo(self):
return (self.host, self.port) return (self.host, self.port)