summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorLianhao Lu <lianhao.lu@intel.com>2012-01-10 14:13:49 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-01-11 10:36:20 +0000
commit30a9bc6c92a8920d6e9c4a4b93b83bdbe5d48e78 (patch)
tree6cce4db7619f35e16cdab7961ef44adfdd859b9e /bitbake
parent4a8a3c503fd896593b787c26edbe46a7324e494e (diff)
downloadpoky-30a9bc6c92a8920d6e9c4a4b93b83bdbe5d48e78.tar.gz
bitbake/PRservice: Added no_hist mode and export/import.
[YOCTO #1556] 1. Added the package_arch into the index to the DB table. Because the change in PACKAGE_ARCH will results in different checksum, and it is better to have seperate PR value domains for differnt PACKAGE_ARCH of the same pakcage. 2. Changed the PR service to operate in no history mode. In this mode, the for a given query tuple (version, pkgarch, checksum), the returned value will be the largest among all the values of the same (version, pkgarch). This means the PR value returned can NOT be decremented. 3. Added export function. For each (version, pkgarch) tuple, only the record with the maximum value will be exported. 4. Added import function. The record will only be imported if the imported value is larger than the value stored in the DB with the same (version, pkgarch, checksum) tuple. (Bitbake rev: 379567ee879dcdc09a51f7f1212bde1076147a6f) Signed-off-by: Lianhao Lu <lianhao.lu@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-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