summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/bin/bitbake-prserv23
-rw-r--r--bitbake/lib/prserv/__init__.py5
-rw-r--r--bitbake/lib/prserv/db.py209
-rw-r--r--bitbake/lib/prserv/serv.py106
4 files changed, 263 insertions, 80 deletions
diff --git a/bitbake/bin/bitbake-prserv b/bitbake/bin/bitbake-prserv
index 14073caf38..a7ab55f736 100644
--- a/bitbake/bin/bitbake-prserv
+++ b/bitbake/bin/bitbake-prserv
@@ -16,31 +16,34 @@ PRPORT_DEFAULT=8585
16def main(): 16def main():
17 parser = optparse.OptionParser( 17 parser = optparse.OptionParser(
18 version="Bitbake PR Service Core version %s, %%prog version %s" % (prserv.__version__, __version__), 18 version="Bitbake PR Service Core version %s, %%prog version %s" % (prserv.__version__, __version__),
19 usage = "%prog [options]") 19 usage = "%prog < --start | --stop > [options]")
20 20
21 parser.add_option("-f", "--file", help="database filename(default prserv.db)", action="store", 21 parser.add_option("-f", "--file", help="database filename(default: prserv.db)", action="store",
22 dest="dbfile", type="string", default="prserv.db") 22 dest="dbfile", type="string", default="prserv.db")
23 parser.add_option("-l", "--log", help="log filename(default prserv.log)", action="store", 23 parser.add_option("-l", "--log", help="log filename(default: prserv.log)", action="store",
24 dest="logfile", type="string", default="prserv.log") 24 dest="logfile", type="string", default="prserv.log")
25 parser.add_option("--loglevel", help="logging level, i.e. CRITICAL, ERROR, WARNING, INFO, DEBUG", 25 parser.add_option("--loglevel", help="logging level, i.e. CRITICAL, ERROR, WARNING, INFO, DEBUG",
26 action = "store", type="string", dest="loglevel", default = "WARNING") 26 action = "store", type="string", dest="loglevel", default = "INFO")
27 parser.add_option("--start", help="start daemon", 27 parser.add_option("--start", help="start daemon",
28 action="store_true", dest="start", default="True") 28 action="store_true", dest="start")
29 parser.add_option("--stop", help="stop daemon", 29 parser.add_option("--stop", help="stop daemon",
30 action="store_false", dest="start") 30 action="store_true", dest="stop")
31 parser.add_option("--host", help="ip address to bind", action="store", 31 parser.add_option("--host", help="ip address to bind", action="store",
32 dest="host", type="string", default=PRHOST_DEFAULT) 32 dest="host", type="string", default=PRHOST_DEFAULT)
33 parser.add_option("--port", help="port number(default 8585)", action="store", 33 parser.add_option("--port", help="port number(default: 8585)", action="store",
34 dest="port", type="int", default=PRPORT_DEFAULT) 34 dest="port", type="int", default=PRPORT_DEFAULT)
35 35
36 options, args = parser.parse_args(sys.argv) 36 options, args = parser.parse_args(sys.argv)
37
38 prserv.init_logger(os.path.abspath(options.logfile),options.loglevel) 37 prserv.init_logger(os.path.abspath(options.logfile),options.loglevel)
39 38
40 if options.start: 39 if options.start:
41 prserv.serv.start_daemon(options) 40 ret=prserv.serv.start_daemon(dbfile=options.dbfile, interface=(options.host, options.port),
41 logfile=os.path.abspath(options.logfile))
42 elif options.stop:
43 ret=prserv.serv.stop_daemon(options.host, options.port)
42 else: 44 else:
43 prserv.serv.stop_daemon() 45 ret=parser.print_help()
46 return ret
44 47
45if __name__ == "__main__": 48if __name__ == "__main__":
46 try: 49 try:
diff --git a/bitbake/lib/prserv/__init__.py b/bitbake/lib/prserv/__init__.py
index 2837e135d7..c27fffe37b 100644
--- a/bitbake/lib/prserv/__init__.py
+++ b/bitbake/lib/prserv/__init__.py
@@ -7,5 +7,8 @@ def init_logger(logfile, loglevel):
7 numeric_level = getattr(logging, loglevel.upper(), None) 7 numeric_level = getattr(logging, loglevel.upper(), None)
8 if not isinstance(numeric_level, int): 8 if not isinstance(numeric_level, int):
9 raise ValueError('Invalid log level: %s' % loglevel) 9 raise ValueError('Invalid log level: %s' % loglevel)
10 logging.basicConfig(level=numeric_level, filename=logfile) 10 FORMAT = '%(asctime)-15s %(message)s'
11 logging.basicConfig(level=numeric_level, filename=logfile, format=FORMAT)
11 12
13class NotFoundError(StandardError):
14 pass \ No newline at end of file
diff --git a/bitbake/lib/prserv/db.py b/bitbake/lib/prserv/db.py
index bbee9316b2..f267daed13 100644
--- a/bitbake/lib/prserv/db.py
+++ b/bitbake/lib/prserv/db.py
@@ -1,9 +1,7 @@
1import logging 1import logging
2import os.path 2import os.path
3import errno 3import errno
4import sys 4import prserv
5import warnings
6import sqlite3
7 5
8try: 6try:
9 import sqlite3 7 import sqlite3
@@ -14,73 +12,220 @@ sqlversion = sqlite3.sqlite_version_info
14if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3): 12if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
15 raise Exception("sqlite3 version 3.3.0 or later is required.") 13 raise Exception("sqlite3 version 3.3.0 or later is required.")
16 14
17class NotFoundError(StandardError):
18 pass
19
20class PRTable(): 15class PRTable():
21 def __init__(self,cursor,table): 16 def __init__(self, conn, table, nohist):
22 self.cursor = cursor 17 self.conn = conn
23 self.table = table 18 self.nohist = nohist
19 if nohist:
20 self.table = "%s_nohist" % table
21 else:
22 self.table = "%s_hist" % table
24 23
25 #create the table
26 self._execute("CREATE TABLE IF NOT EXISTS %s \ 24 self._execute("CREATE TABLE IF NOT EXISTS %s \
27 (version TEXT NOT NULL, \ 25 (version TEXT NOT NULL, \
26 pkgarch TEXT NOT NULL, \
28 checksum TEXT NOT NULL, \ 27 checksum TEXT NOT NULL, \
29 value INTEGER, \ 28 value INTEGER, \
30 PRIMARY KEY (version,checksum));" 29 PRIMARY KEY (version, pkgarch, checksum));" % self.table)
31 % table)
32 30
33 def _execute(self, *query): 31 def _execute(self, *query):
34 """Execute a query, waiting to acquire a lock if necessary""" 32 """Execute a query, waiting to acquire a lock if necessary"""
35 count = 0 33 count = 0
36 while True: 34 while True:
37 try: 35 try:
38 return self.cursor.execute(*query) 36 return self.conn.execute(*query)
39 except sqlite3.OperationalError as exc: 37 except sqlite3.OperationalError as exc:
40 if 'database is locked' in str(exc) and count < 500: 38 if 'database is locked' in str(exc) and count < 500:
41 count = count + 1 39 count = count + 1
42 continue 40 continue
43 raise 41 raise exc
44 except sqlite3.IntegrityError as exc:
45 print "Integrity error %s" % str(exc)
46 break
47 42
48 def getValue(self, version, checksum): 43 def _getValueHist(self, version, pkgarch, checksum):
49 data=self._execute("SELECT value FROM %s WHERE version=? AND checksum=?;" % self.table, 44 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
50 (version,checksum)) 45 (version, pkgarch, checksum))
51 row=data.fetchone() 46 row=data.fetchone()
52 if row != None: 47 if row != None:
53 return row[0] 48 return row[0]
54 else: 49 else:
55 #no value found, try to insert 50 #no value found, try to insert
56 self._execute("INSERT INTO %s VALUES (?, ?, (select ifnull(max(value)+1,0) from %s where version=?));" 51 try:
52 self._execute("BEGIN")
53 self._execute("INSERT OR ROLLBACK INTO %s VALUES (?, ?, ?, (select ifnull(max(value)+1,0) from %s where version=? AND pkgarch=?));"
57 % (self.table,self.table), 54 % (self.table,self.table),
58 (version,checksum,version)) 55 (version,pkgarch, checksum,version, pkgarch))
59 data=self._execute("SELECT value FROM %s WHERE version=? AND checksum=?;" % self.table, 56 self.conn.commit()
60 (version,checksum)) 57 except sqlite3.IntegrityError as exc:
58 logging.error(str(exc))
59
60 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
61 (version, pkgarch, checksum))
62 row=data.fetchone()
63 if row != None:
64 return row[0]
65 else:
66 raise prserv.NotFoundError
67
68 def _getValueNohist(self, version, pkgarch, checksum):
69 data=self._execute("SELECT value FROM %s \
70 WHERE version=? AND pkgarch=? AND checksum=? AND \
71 value >= (select max(value) from %s where version=? AND pkgarch=?);"
72 % (self.table, self.table),
73 (version, pkgarch, checksum, version, pkgarch))
74 row=data.fetchone()
75 if row != None:
76 return row[0]
77 else:
78 #no value found, try to insert
79 try:
80 self._execute("BEGIN")
81 self._execute("INSERT OR REPLACE INTO %s VALUES (?, ?, ?, (select ifnull(max(value)+1,0) from %s where version=? AND pkgarch=?));"
82 % (self.table,self.table),
83 (version, pkgarch, checksum, version, pkgarch))
84 self.conn.commit()
85 except sqlite3.IntegrityError as exc:
86 logging.error(str(exc))
87 self.conn.rollback()
88
89 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
90 (version, pkgarch, checksum))
61 row=data.fetchone() 91 row=data.fetchone()
62 if row != None: 92 if row != None:
63 return row[0] 93 return row[0]
64 else: 94 else:
65 raise NotFoundError 95 raise prserv.NotFoundError
96
97 def getValue(self, version, pkgarch, checksum):
98 if self.nohist:
99 return self._getValueNohist(version, pkgarch, checksum)
100 else:
101 return self._getValueHist(version, pkgarch, checksum)
102
103 def _importHist(self, version, pkgarch, checksum, value):
104 val = None
105 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
106 (version, pkgarch, checksum))
107 row = data.fetchone()
108 if row != None:
109 val=row[0]
110 else:
111 #no value found, try to insert
112 try:
113 self._execute("BEGIN")
114 self._execute("INSERT OR ROLLBACK INTO %s VALUES (?, ?, ?, ?);" % (self.table),
115 (version, pkgarch, checksum, value))
116 self.conn.commit()
117 except sqlite3.IntegrityError as exc:
118 logging.error(str(exc))
119
120 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
121 (version, pkgarch, checksum))
122 row = data.fetchone()
123 if row != None:
124 val = row[0]
125 return val
126
127 def _importNohist(self, version, pkgarch, checksum, value):
128 try:
129 #try to insert
130 self._execute("BEGIN")
131 self._execute("INSERT OR ROLLBACK INTO %s VALUES (?, ?, ?, ?);" % (self.table),
132 (version, pkgarch, checksum,value))
133 self.conn.commit()
134 except sqlite3.IntegrityError as exc:
135 #already have the record, try to update
136 try:
137 self._execute("BEGIN")
138 self._execute("UPDATE %s SET value=? WHERE version=? AND pkgarch=? AND checksum=? AND value<?"
139 % (self.table),
140 (value,version,pkgarch,checksum,value))
141 self.conn.commit()
142 except sqlite3.IntegrityError as exc:
143 logging.error(str(exc))
144
145 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=? AND value>=?;" % self.table,
146 (version,pkgarch,checksum,value))
147 row=data.fetchone()
148 if row != None:
149 return row[0]
150 else:
151 return None
152
153 def importone(self, version, pkgarch, checksum, value):
154 if self.nohist:
155 return self._importNohist(version, pkgarch, checksum, value)
156 else:
157 return self._importHist(version, pkgarch, checksum, value)
158
159 def export(self, version, pkgarch, checksum, colinfo):
160 metainfo = {}
161 #column info
162 if colinfo:
163 metainfo['tbl_name'] = self.table
164 metainfo['core_ver'] = prserv.__version__
165 metainfo['col_info'] = []
166 data = self._execute("PRAGMA table_info(%s);" % self.table)
167 for row in data:
168 col = {}
169 col['name'] = row['name']
170 col['type'] = row['type']
171 col['notnull'] = row['notnull']
172 col['dflt_value'] = row['dflt_value']
173 col['pk'] = row['pk']
174 metainfo['col_info'].append(col)
175
176 #data info
177 datainfo = []
178
179 if self.nohist:
180 sqlstmt = "SELECT T1.version, T1.pkgarch, T1.checksum, T1.value FROM %s as T1, \
181 (SELECT version,pkgarch,max(value) as maxvalue FROM %s GROUP BY version,pkgarch) as T2 \
182 WHERE T1.version=T2.version AND T1.pkgarch=T2.pkgarch AND T1.value=T2.maxvalue " % (self.table, self.table)
183 else:
184 sqlstmt = "SELECT * FROM %s as T1 WHERE 1=1 " % self.table
185 sqlarg = []
186 where = ""
187 if version:
188 where += "AND T1.version=? "
189 sqlarg.append(str(version))
190 if pkgarch:
191 where += "AND T1.pkgarch=? "
192 sqlarg.append(str(pkgarch))
193 if checksum:
194 where += "AND T1.checksum=? "
195 sqlarg.append(str(checksum))
196
197 sqlstmt += where + ";"
198
199 if len(sqlarg):
200 data = self._execute(sqlstmt, tuple(sqlarg))
201 else:
202 data = self._execute(sqlstmt)
203 for row in data:
204 if row['version']:
205 col = {}
206 col['version'] = row['version']
207 col['pkgarch'] = row['pkgarch']
208 col['checksum'] = row['checksum']
209 col['value'] = row['value']
210 datainfo.append(col)
211 return (metainfo, datainfo)
66 212
67class PRData(object): 213class PRData(object):
68 """Object representing the PR database""" 214 """Object representing the PR database"""
69 def __init__(self, filename): 215 def __init__(self, filename, nohist=True):
70 self.filename=os.path.abspath(filename) 216 self.filename=os.path.abspath(filename)
217 self.nohist=nohist
71 #build directory hierarchy 218 #build directory hierarchy
72 try: 219 try:
73 os.makedirs(os.path.dirname(self.filename)) 220 os.makedirs(os.path.dirname(self.filename))
74 except OSError as e: 221 except OSError as e:
75 if e.errno != errno.EEXIST: 222 if e.errno != errno.EEXIST:
76 raise e 223 raise e
77 self.connection=sqlite3.connect(self.filename, timeout=5, 224 self.connection=sqlite3.connect(self.filename, isolation_level="DEFERRED")
78 isolation_level=None) 225 self.connection.row_factory=sqlite3.Row
79 self.cursor=self.connection.cursor()
80 self._tables={} 226 self._tables={}
81 227
82 def __del__(self): 228 def __del__(self):
83 print "PRData: closing DB %s" % self.filename
84 self.connection.close() 229 self.connection.close()
85 230
86 def __getitem__(self,tblname): 231 def __getitem__(self,tblname):
@@ -90,11 +235,11 @@ class PRData(object):
90 if tblname in self._tables: 235 if tblname in self._tables:
91 return self._tables[tblname] 236 return self._tables[tblname]
92 else: 237 else:
93 tableobj = self._tables[tblname] = PRTable(self.cursor, tblname) 238 tableobj = self._tables[tblname] = PRTable(self.connection, tblname, self.nohist)
94 return tableobj 239 return tableobj
95 240
96 def __delitem__(self, tblname): 241 def __delitem__(self, tblname):
97 if tblname in self._tables: 242 if tblname in self._tables:
98 del self._tables[tblname] 243 del self._tables[tblname]
99 logging.info("drop table %s" % (tblname)) 244 logging.info("drop table %s" % (tblname))
100 self.cursor.execute("DROP TABLE IF EXISTS %s;" % tblname) 245 self.connection.execute("DROP TABLE IF EXISTS %s;" % tblname)
diff --git a/bitbake/lib/prserv/serv.py b/bitbake/lib/prserv/serv.py
index 2f488f4898..7bcffa7744 100644
--- a/bitbake/lib/prserv/serv.py
+++ b/bitbake/lib/prserv/serv.py
@@ -21,6 +21,8 @@ class Handler(SimpleXMLRPCRequestHandler):
21 raise 21 raise
22 return value 22 return value
23 23
24PIDPREFIX = "/tmp/PRServer_%s_%s.pid"
25
24class PRServer(SimpleXMLRPCServer): 26class PRServer(SimpleXMLRPCServer):
25 pidfile="/tmp/PRServer.pid" 27 pidfile="/tmp/PRServer.pid"
26 def __init__(self, dbfile, logfile, interface, daemon=True): 28 def __init__(self, dbfile, logfile, interface, daemon=True):
@@ -34,20 +36,33 @@ class PRServer(SimpleXMLRPCServer):
34 self.host, self.port = self.socket.getsockname() 36 self.host, self.port = self.socket.getsockname()
35 self.db=prserv.db.PRData(dbfile) 37 self.db=prserv.db.PRData(dbfile)
36 self.table=self.db["PRMAIN"] 38 self.table=self.db["PRMAIN"]
39 self.pidfile=PIDPREFIX % interface
37 40
38 self.register_function(self.getPR, "getPR") 41 self.register_function(self.getPR, "getPR")
39 self.register_function(self.quit, "quit") 42 self.register_function(self.quit, "quit")
40 self.register_function(self.ping, "ping") 43 self.register_function(self.ping, "ping")
44 self.register_function(self.export, "export")
45 self.register_function(self.importone, "importone")
41 self.register_introspection_functions() 46 self.register_introspection_functions()
47
48 def export(self, version=None, pkgarch=None, checksum=None, colinfo=True):
49 try:
50 return self.table.export(version, pkgarch, checksum, colinfo)
51 except sqlite3.Error as exc:
52 logging.error(str(exc))
53 return None
54
55 def importone(self, version, pkgarch, checksum, value):
56 return self.table.importone(version, pkgarch, checksum, value)
42 57
43 def ping(self): 58 def ping(self):
44 return not self.quit 59 return not self.quit
45 60
46 def getPR(self, version, checksum): 61 def getPR(self, version, pkgarch, checksum):
47 try: 62 try:
48 return self.table.getValue(version,checksum) 63 return self.table.getValue(version, pkgarch, checksum)
49 except prserv.NotFoundError: 64 except prserv.NotFoundError:
50 logging.error("can not find value for (%s, %s)",version,checksum) 65 logging.error("can not find value for (%s, %s)",version, checksum)
51 return None 66 return None
52 except sqlite3.Error as exc: 67 except sqlite3.Error as exc:
53 logging.error(str(exc)) 68 logging.error(str(exc))
@@ -69,28 +84,34 @@ class PRServer(SimpleXMLRPCServer):
69 84
70 def start(self): 85 def start(self):
71 if self.daemon is True: 86 if self.daemon is True:
72 logging.info("PRServer: starting daemon...") 87 logging.info("PRServer: try to start daemon...")
73 self.daemonize() 88 self.daemonize()
74 else: 89 else:
75 logging.info("PRServer: starting...") 90 atexit.register(self.delpid)
91 pid = str(os.getpid())
92 pf = file(self.pidfile, 'w+')
93 pf.write("%s\n" % pid)
94 pf.write("%s\n" % self.host)
95 pf.write("%s\n" % self.port)
96 pf.close()
97 logging.info("PRServer: start success! DBfile: %s, IP: %s, PORT: %d" %
98 (self.dbfile, self.host, self.port))
76 self._serve_forever() 99 self._serve_forever()
77 100
78 def delpid(self): 101 def delpid(self):
79 os.remove(PRServer.pidfile) 102 os.remove(self.pidfile)
80 103
81 def daemonize(self): 104 def daemonize(self):
82 """ 105 """
83 See Advanced Programming in the UNIX, Sec 13.3 106 See Advanced Programming in the UNIX, Sec 13.3
84 """ 107 """
85 os.umask(0)
86
87 try: 108 try:
88 pid = os.fork() 109 pid = os.fork()
89 if pid > 0: 110 if pid > 0:
90 sys.exit(0) 111 #parent return instead of exit to give control
112 return
91 except OSError as e: 113 except OSError as e:
92 sys.stderr.write("1st fork failed: %d %s\n" % (e.errno, e.strerror)) 114 raise Exception("%s [%d]" % (e.strerror, e.errno))
93 sys.exit(1)
94 115
95 os.setsid() 116 os.setsid()
96 """ 117 """
@@ -102,9 +123,9 @@ class PRServer(SimpleXMLRPCServer):
102 if pid > 0: #parent 123 if pid > 0: #parent
103 sys.exit(0) 124 sys.exit(0)
104 except OSError as e: 125 except OSError as e:
105 sys.stderr.write("2nd fork failed: %d %s\n" % (e.errno, e.strerror)) 126 raise Exception("%s [%d]" % (e.strerror, e.errno))
106 sys.exit(1)
107 127
128 os.umask(0)
108 os.chdir("/") 129 os.chdir("/")
109 130
110 sys.stdout.flush() 131 sys.stdout.flush()
@@ -119,13 +140,15 @@ class PRServer(SimpleXMLRPCServer):
119 # write pidfile 140 # write pidfile
120 atexit.register(self.delpid) 141 atexit.register(self.delpid)
121 pid = str(os.getpid()) 142 pid = str(os.getpid())
122 pf = file(PRServer.pidfile, 'w+') 143 pf = file(self.pidfile, 'w')
123 pf.write("%s\n" % pid) 144 pf.write("%s\n" % pid)
124 pf.write("%s\n" % self.host)
125 pf.write("%s\n" % self.port)
126 pf.close() 145 pf.close()
127 146
147 logging.info("PRServer: starting daemon success! DBfile: %s, IP: %s, PORT: %s, PID: %s" %
148 (self.dbfile, self.host, self.port, pid))
149
128 self._serve_forever() 150 self._serve_forever()
151 exit(0)
129 152
130class PRServerConnection(): 153class PRServerConnection():
131 def __init__(self, host, port): 154 def __init__(self, host, port):
@@ -139,16 +162,22 @@ class PRServerConnection():
139 socket.setdefaulttimeout(2) 162 socket.setdefaulttimeout(2)
140 try: 163 try:
141 self.connection.quit() 164 self.connection.quit()
142 except: 165 except Exception as exc:
143 pass 166 sys.stderr.write("%s\n" % str(exc))
144 167
145 def getPR(self, version, checksum): 168 def getPR(self, version, pkgarch, checksum):
146 return self.connection.getPR(version, checksum) 169 return self.connection.getPR(version, pkgarch, checksum)
147 170
148 def ping(self): 171 def ping(self):
149 return self.connection.ping() 172 return self.connection.ping()
150 173
151def start_daemon(options): 174 def export(self,version=None, pkgarch=None, checksum=None, colinfo=True):
175 return self.connection.export(version, pkgarch, checksum, colinfo)
176
177 def importone(self, version, pkgarch, checksum, value):
178 return self.connection.importone(version, pkgarch, checksum, value)
179
180def start_daemon(dbfile, logfile, interface):
152 try: 181 try:
153 pf = file(PRServer.pidfile,'r') 182 pf = file(PRServer.pidfile,'r')
154 pid = int(pf.readline().strip()) 183 pid = int(pf.readline().strip())
@@ -159,40 +188,43 @@ def start_daemon(options):
159 if pid: 188 if pid:
160 sys.stderr.write("pidfile %s already exist. Daemon already running?\n" 189 sys.stderr.write("pidfile %s already exist. Daemon already running?\n"
161 % PRServer.pidfile) 190 % PRServer.pidfile)
162 sys.exit(1) 191 return 1
163 192
164 server = PRServer(options.dbfile, interface=(options.host, options.port), 193 server = PRServer(os.path.abspath(dbfile), os.path.abspath(logfile), interface)
165 logfile=os.path.abspath(options.logfile))
166 server.start() 194 server.start()
195 return 0
167 196
168def stop_daemon(): 197def stop_daemon(host, port):
198 pidfile = PIDPREFIX % (host, port)
169 try: 199 try:
170 pf = file(PRServer.pidfile,'r') 200 pf = file(pidfile,'r')
171 pid = int(pf.readline().strip()) 201 pid = int(pf.readline().strip())
172 host = pf.readline().strip()
173 port = int(pf.readline().strip())
174 pf.close() 202 pf.close()
175 except IOError: 203 except IOError:
176 pid = None 204 pid = None
177 205
178 if not pid: 206 if not pid:
179 sys.stderr.write("pidfile %s does not exist. Daemon not running?\n" 207 sys.stderr.write("pidfile %s does not exist. Daemon not running?\n"
180 % PRServer.pidfile) 208 % pidfile)
181 sys.exit(1) 209 return 1
182 210
183 PRServerConnection(host,port).terminate() 211 PRServerConnection(host, port).terminate()
184 time.sleep(0.5) 212 time.sleep(0.5)
185 213
186 try: 214 try:
187 while 1: 215 while 1:
188 os.kill(pid,signal.SIGTERM) 216 os.kill(pid,signal.SIGTERM)
189 time.sleep(0.1) 217 time.sleep(0.1)
190 except OSError as err: 218 except OSError as e:
191 err = str(err) 219 err = str(e)
192 if err.find("No such process") > 0: 220 if err.find("No such process") > 0:
193 if os.path.exists(PRServer.pidfile): 221 if os.path.exists(PRServer.pidfile):
194 os.remove(PRServer.pidfile) 222 os.remove(PRServer.pidfile)
195 else: 223 else:
196 print err 224 raise Exception("%s [%d]" % (e.strerror, e.errno))
197 sys.exit(1) 225
226 return 0
198 227
228def ping(host, port):
229 print PRServerConnection(host,port).ping()
230 return 0