summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/hashserv/tests.py
diff options
context:
space:
mode:
authorJoshua Watt <JPEWhacker@gmail.com>2021-10-07 14:32:00 -0500
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-10-11 11:00:06 +0100
commitc7c47bb0d2c2263c4668c4269c669b282d6168d9 (patch)
tree19767cdfc5be31dbdef064439700891d091853f6 /bitbake/lib/hashserv/tests.py
parentecb11a6848b4a86de3f04d7dcf12ce8ff6491a07 (diff)
downloadpoky-c7c47bb0d2c2263c4668c4269c669b282d6168d9.tar.gz
bitbake: hashserv: Fix diverging report race condition
Fixes the hashequivalence server to resolve the diverging report race error. This error occurs when the same task(hash) is run simultaneous on two different builders, and then the results are reported back but the hashes diverge (e.g. have different outhashes), and one outhash is equivalent to a hash and another is not. If taskhash was not originally in the database, the client will fallback to using the taskhash as the suggested unihash and the server will see reports come in like: taskhash: A unihash: A outhash: B taskhash: C unihash: C outhash: B taskhash: C unihash: C outhash: D Note that the second and third reports are the same taskhash, with diverging outhashes. Taskhash C should be equivalent to taskhash (and unihash) A because they share an outhash B, but the server would not do this when tasks were reported in the order shown. It became clear while trying to fix this that single large table to store all reported hashes was going to make these updates difficult since updating the unihash of all entries would be complex and time consuming. Instead, it makes more sense to split apart the database into two tables: One that maps taskhashes to unihashes and one that maps outhashes to taskhashes. This should hopefully improve the parsing query times as well since they only care about the taskhashes to unihashes table, at the cost of more complex INNER JOIN queries on the lesser used API. Note this change does delete existing hash equivlance data and starts a new database table rather than converting existing data. (Bitbake rev: dff5a17558e2476064e85f35bad1fd65fec23600) Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/hashserv/tests.py')
-rw-r--r--bitbake/lib/hashserv/tests.py60
1 files changed, 48 insertions, 12 deletions
diff --git a/bitbake/lib/hashserv/tests.py b/bitbake/lib/hashserv/tests.py
index 1fcfb6b929..efaf3bdf42 100644
--- a/bitbake/lib/hashserv/tests.py
+++ b/bitbake/lib/hashserv/tests.py
@@ -19,10 +19,10 @@ import time
19import signal 19import signal
20 20
21def server_prefunc(server, idx): 21def server_prefunc(server, idx):
22 logging.basicConfig(level=logging.DEBUG, filename='bbhashserv.log', filemode='w', 22 logging.basicConfig(level=logging.DEBUG, filename='bbhashserv-%d.log' % idx, filemode='w',
23 format='%(levelname)s %(filename)s:%(lineno)d %(message)s') 23 format='%(levelname)s %(filename)s:%(lineno)d %(message)s')
24 server.logger.debug("Running server %d" % idx) 24 server.logger.debug("Running server %d" % idx)
25 sys.stdout = open('bbhashserv-%d.log' % idx, 'w') 25 sys.stdout = open('bbhashserv-stdout-%d.log' % idx, 'w')
26 sys.stderr = sys.stdout 26 sys.stderr = sys.stdout
27 27
28class HashEquivalenceTestSetup(object): 28class HashEquivalenceTestSetup(object):
@@ -140,12 +140,17 @@ class HashEquivalenceCommonTests(object):
140 }) 140 })
141 self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash') 141 self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash')
142 142
143 result = self.client.get_taskhash(self.METHOD, taskhash, True) 143 result_unihash = self.client.get_taskhash(self.METHOD, taskhash, True)
144 self.assertEqual(result['taskhash'], taskhash) 144 self.assertEqual(result_unihash['taskhash'], taskhash)
145 self.assertEqual(result['unihash'], unihash) 145 self.assertEqual(result_unihash['unihash'], unihash)
146 self.assertEqual(result['method'], self.METHOD) 146 self.assertEqual(result_unihash['method'], self.METHOD)
147 self.assertEqual(result['outhash'], outhash) 147
148 self.assertEqual(result['outhash_siginfo'], siginfo) 148 result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash)
149 self.assertEqual(result_outhash['taskhash'], taskhash)
150 self.assertEqual(result_outhash['method'], self.METHOD)
151 self.assertEqual(result_outhash['unihash'], unihash)
152 self.assertEqual(result_outhash['outhash'], outhash)
153 self.assertEqual(result_outhash['outhash_siginfo'], siginfo)
149 154
150 def test_stress(self): 155 def test_stress(self):
151 def query_server(failures): 156 def query_server(failures):
@@ -260,6 +265,39 @@ class HashEquivalenceCommonTests(object):
260 result = down_client.report_unihash(taskhash6, self.METHOD, outhash5, unihash6) 265 result = down_client.report_unihash(taskhash6, self.METHOD, outhash5, unihash6)
261 self.assertEqual(result['unihash'], unihash5, 'Server failed to copy unihash from upstream') 266 self.assertEqual(result['unihash'], unihash5, 'Server failed to copy unihash from upstream')
262 267
268 # Tests read through from server with
269 taskhash7 = '9d81d76242cc7cfaf7bf74b94b9cd2e29324ed74'
270 outhash7 = '8470d56547eea6236d7c81a644ce74670ca0bbda998e13c629ef6bb3f0d60b69'
271 unihash7 = '05d2a63c81e32f0a36542ca677e8ad852365c538'
272 self.client.report_unihash(taskhash7, self.METHOD, outhash7, unihash7)
273
274 result = down_client.get_taskhash(self.METHOD, taskhash7, True)
275 self.assertEqual(result['unihash'], unihash7, 'Server failed to copy unihash from upstream')
276 self.assertEqual(result['outhash'], outhash7, 'Server failed to copy unihash from upstream')
277 self.assertEqual(result['taskhash'], taskhash7, 'Server failed to copy unihash from upstream')
278 self.assertEqual(result['method'], self.METHOD)
279
280 taskhash8 = '86978a4c8c71b9b487330b0152aade10c1ee58aa'
281 outhash8 = 'ca8c128e9d9e4a28ef24d0508aa20b5cf880604eacd8f65c0e366f7e0cc5fbcf'
282 unihash8 = 'd8bcf25369d40590ad7d08c84d538982f2023e01'
283 self.client.report_unihash(taskhash8, self.METHOD, outhash8, unihash8)
284
285 result = down_client.get_outhash(self.METHOD, outhash8, taskhash8)
286 self.assertEqual(result['unihash'], unihash8, 'Server failed to copy unihash from upstream')
287 self.assertEqual(result['outhash'], outhash8, 'Server failed to copy unihash from upstream')
288 self.assertEqual(result['taskhash'], taskhash8, 'Server failed to copy unihash from upstream')
289 self.assertEqual(result['method'], self.METHOD)
290
291 taskhash9 = 'ae6339531895ddf5b67e663e6a374ad8ec71d81c'
292 outhash9 = 'afc78172c81880ae10a1fec994b5b4ee33d196a001a1b66212a15ebe573e00b5'
293 unihash9 = '6662e699d6e3d894b24408ff9a4031ef9b038ee8'
294 self.client.report_unihash(taskhash9, self.METHOD, outhash9, unihash9)
295
296 result = down_client.get_taskhash(self.METHOD, taskhash9, False)
297 self.assertEqual(result['unihash'], unihash9, 'Server failed to copy unihash from upstream')
298 self.assertEqual(result['taskhash'], taskhash9, 'Server failed to copy unihash from upstream')
299 self.assertEqual(result['method'], self.METHOD)
300
263 def test_ro_server(self): 301 def test_ro_server(self):
264 (ro_client, ro_server) = self.start_server(dbpath=self.server.dbpath, read_only=True) 302 (ro_client, ro_server) = self.start_server(dbpath=self.server.dbpath, read_only=True)
265 303
@@ -287,10 +325,8 @@ class HashEquivalenceCommonTests(object):
287 325
288 326
289 def test_slow_server_start(self): 327 def test_slow_server_start(self):
290 """ 328 # Ensures that the server will exit correctly even if it gets a SIGTERM
291 Ensures that the server will exit correctly even if it gets a SIGTERM 329 # before entering the main loop
292 before entering the main loop
293 """
294 330
295 event = multiprocessing.Event() 331 event = multiprocessing.Event()
296 332