summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/prserv/db.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/prserv/db.py')
-rw-r--r--bitbake/lib/prserv/db.py242
1 files changed, 242 insertions, 0 deletions
diff --git a/bitbake/lib/prserv/db.py b/bitbake/lib/prserv/db.py
new file mode 100644
index 0000000..86eafe3
--- /dev/null
+++ b/bitbake/lib/prserv/db.py
@@ -0,0 +1,242 @@
1import logging
2import os.path
3import errno
4import prserv
5import time
6
7try:
8 import sqlite3
9except ImportError:
10 from pysqlite2 import dbapi2 as sqlite3
11
12logger = logging.getLogger("BitBake.PRserv")
13
14sqlversion = sqlite3.sqlite_version_info
15if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
16 raise Exception("sqlite3 version 3.3.0 or later is required.")
17
18class PRTable(object):
19 def __init__(self, conn, table, nohist):
20 self.conn = conn
21 self.nohist = nohist
22 if nohist:
23 self.table = "%s_nohist" % table
24 else:
25 self.table = "%s_hist" % table
26
27 self._execute("CREATE TABLE IF NOT EXISTS %s \
28 (version TEXT NOT NULL, \
29 pkgarch TEXT NOT NULL, \
30 checksum TEXT NOT NULL, \
31 value INTEGER, \
32 PRIMARY KEY (version, pkgarch, checksum));" % self.table)
33
34 def _execute(self, *query):
35 """Execute a query, waiting to acquire a lock if necessary"""
36 start = time.time()
37 end = start + 20
38 while True:
39 try:
40 return self.conn.execute(*query)
41 except sqlite3.OperationalError as exc:
42 if 'is locked' in str(exc) and end > time.time():
43 continue
44 raise exc
45
46 def sync(self):
47 self.conn.commit()
48 self._execute("BEGIN EXCLUSIVE TRANSACTION")
49
50 def _getValueHist(self, version, pkgarch, checksum):
51 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
52 (version, pkgarch, checksum))
53 row=data.fetchone()
54 if row != None:
55 return row[0]
56 else:
57 #no value found, try to insert
58 try:
59 self._execute("INSERT INTO %s VALUES (?, ?, ?, (select ifnull(max(value)+1,0) from %s where version=? AND pkgarch=?));"
60 % (self.table,self.table),
61 (version,pkgarch, checksum,version, pkgarch))
62 except sqlite3.IntegrityError as exc:
63 logger.error(str(exc))
64
65 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
66 (version, pkgarch, checksum))
67 row=data.fetchone()
68 if row != None:
69 return row[0]
70 else:
71 raise prserv.NotFoundError
72
73 def _getValueNohist(self, version, pkgarch, checksum):
74 data=self._execute("SELECT value FROM %s \
75 WHERE version=? AND pkgarch=? AND checksum=? AND \
76 value >= (select max(value) from %s where version=? AND pkgarch=?);"
77 % (self.table, self.table),
78 (version, pkgarch, checksum, version, pkgarch))
79 row=data.fetchone()
80 if row != None:
81 return row[0]
82 else:
83 #no value found, try to insert
84 try:
85 self._execute("INSERT OR REPLACE INTO %s VALUES (?, ?, ?, (select ifnull(max(value)+1,0) from %s where version=? AND pkgarch=?));"
86 % (self.table,self.table),
87 (version, pkgarch, checksum, version, pkgarch))
88 except sqlite3.IntegrityError as exc:
89 logger.error(str(exc))
90 self.conn.rollback()
91
92 data=self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
93 (version, pkgarch, checksum))
94 row=data.fetchone()
95 if row != None:
96 return row[0]
97 else:
98 raise prserv.NotFoundError
99
100 def getValue(self, version, pkgarch, checksum):
101 if self.nohist:
102 return self._getValueNohist(version, pkgarch, checksum)
103 else:
104 return self._getValueHist(version, pkgarch, checksum)
105
106 def _importHist(self, version, pkgarch, checksum, value):
107 val = None
108 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
109 (version, pkgarch, checksum))
110 row = data.fetchone()
111 if row != None:
112 val=row[0]
113 else:
114 #no value found, try to insert
115 try:
116 self._execute("INSERT INTO %s VALUES (?, ?, ?, ?);" % (self.table),
117 (version, pkgarch, checksum, value))
118 except sqlite3.IntegrityError as exc:
119 logger.error(str(exc))
120
121 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=?;" % self.table,
122 (version, pkgarch, checksum))
123 row = data.fetchone()
124 if row != None:
125 val = row[0]
126 return val
127
128 def _importNohist(self, version, pkgarch, checksum, value):
129 try:
130 #try to insert
131 self._execute("INSERT INTO %s VALUES (?, ?, ?, ?);" % (self.table),
132 (version, pkgarch, checksum,value))
133 except sqlite3.IntegrityError as exc:
134 #already have the record, try to update
135 try:
136 self._execute("UPDATE %s SET value=? WHERE version=? AND pkgarch=? AND checksum=? AND value<?"
137 % (self.table),
138 (value,version,pkgarch,checksum,value))
139 except sqlite3.IntegrityError as exc:
140 logger.error(str(exc))
141
142 data = self._execute("SELECT value FROM %s WHERE version=? AND pkgarch=? AND checksum=? AND value>=?;" % self.table,
143 (version,pkgarch,checksum,value))
144 row=data.fetchone()
145 if row != None:
146 return row[0]
147 else:
148 return None
149
150 def importone(self, version, pkgarch, checksum, value):
151 if self.nohist:
152 return self._importNohist(version, pkgarch, checksum, value)
153 else:
154 return self._importHist(version, pkgarch, checksum, value)
155
156 def export(self, version, pkgarch, checksum, colinfo):
157 metainfo = {}
158 #column info
159 if colinfo:
160 metainfo['tbl_name'] = self.table
161 metainfo['core_ver'] = prserv.__version__
162 metainfo['col_info'] = []
163 data = self._execute("PRAGMA table_info(%s);" % self.table)
164 for row in data:
165 col = {}
166 col['name'] = row['name']
167 col['type'] = row['type']
168 col['notnull'] = row['notnull']
169 col['dflt_value'] = row['dflt_value']
170 col['pk'] = row['pk']
171 metainfo['col_info'].append(col)
172
173 #data info
174 datainfo = []
175
176 if self.nohist:
177 sqlstmt = "SELECT T1.version, T1.pkgarch, T1.checksum, T1.value FROM %s as T1, \
178 (SELECT version,pkgarch,max(value) as maxvalue FROM %s GROUP BY version,pkgarch) as T2 \
179 WHERE T1.version=T2.version AND T1.pkgarch=T2.pkgarch AND T1.value=T2.maxvalue " % (self.table, self.table)
180 else:
181 sqlstmt = "SELECT * FROM %s as T1 WHERE 1=1 " % self.table
182 sqlarg = []
183 where = ""
184 if version:
185 where += "AND T1.version=? "
186 sqlarg.append(str(version))
187 if pkgarch:
188 where += "AND T1.pkgarch=? "
189 sqlarg.append(str(pkgarch))
190 if checksum:
191 where += "AND T1.checksum=? "
192 sqlarg.append(str(checksum))
193
194 sqlstmt += where + ";"
195
196 if len(sqlarg):
197 data = self._execute(sqlstmt, tuple(sqlarg))
198 else:
199 data = self._execute(sqlstmt)
200 for row in data:
201 if row['version']:
202 col = {}
203 col['version'] = row['version']
204 col['pkgarch'] = row['pkgarch']
205 col['checksum'] = row['checksum']
206 col['value'] = row['value']
207 datainfo.append(col)
208 return (metainfo, datainfo)
209
210class PRData(object):
211 """Object representing the PR database"""
212 def __init__(self, filename, nohist=True):
213 self.filename=os.path.abspath(filename)
214 self.nohist=nohist
215 #build directory hierarchy
216 try:
217 os.makedirs(os.path.dirname(self.filename))
218 except OSError as e:
219 if e.errno != errno.EEXIST:
220 raise e
221 self.connection=sqlite3.connect(self.filename, isolation_level="EXCLUSIVE", check_same_thread = False)
222 self.connection.row_factory=sqlite3.Row
223 self._tables={}
224
225 def __del__(self):
226 self.connection.close()
227
228 def __getitem__(self,tblname):
229 if not isinstance(tblname, basestring):
230 raise TypeError("tblname argument must be a string, not '%s'" %
231 type(tblname))
232 if tblname in self._tables:
233 return self._tables[tblname]
234 else:
235 tableobj = self._tables[tblname] = PRTable(self.connection, tblname, self.nohist)
236 return tableobj
237
238 def __delitem__(self, tblname):
239 if tblname in self._tables:
240 del self._tables[tblname]
241 logger.info("drop table %s" % (tblname))
242 self.connection.execute("DROP TABLE IF EXISTS %s;" % tblname)