summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/tinfoil.py
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2020-03-23 12:43:25 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-03-24 22:01:03 +0000
commitd53958766e2c766b95b3947f69b64c409ed433d8 (patch)
tree45e943ca7b1cce938d730cf17cdbb4e472082258 /bitbake/lib/bb/tinfoil.py
parent89705a60f3b566743703c3a7597ccc4507293dd9 (diff)
downloadpoky-d53958766e2c766b95b3947f69b64c409ed433d8.tar.gz
bitbake: tinfoil: Simplify remote datastore connections
The current approach to remote datastores used in tinfoil is breaking. For example, adding a devupstream extension to a recipe with a git upstream, making it the preferred version and then running "devtool modify" on it causes get_srcrev() circular dependency issues. The problem is the override handling in the datastore is broken. This gets broken since remotedata:recieve_datastore() sets d.dict but doesn't update d.overridedata (or d.inchistory or d.varhistory). We could play whack-a-mole but the current implementation seems to be flawed to me. It also doesn't cover, or only partially covers some datastore operations and each needs new dedicated command API. Instead, step back and reimplement the way the datastore connector works. With this change, the datastore is either remote or local but the data is not spread on two sides of the connection. All the API is proxied over the connection by a single function for the datastore (and two to support variable history and include history). This code does not support using the datastore as a parameter to any data store functions. We did have one case of that but its just bad code and can be replaced. The result is something which is much simpler and less invasive to the datastore code itself, meaning its behaviour should be much more consistent. The existing tests for the remote data no longer make any sense and are removed. The one bug this code would have is if key/value pairs are returned over the IPC and those values contained a DataSmart object since we don't recurse into return values to find such things. Nothing appears to do that currently so lets worry about it if its ever an issue. This change should simplfy a ton of other issues and avoid a ton of other bugs so is a huge net gain. Tested with bitbake's and OE's selftests. (Bitbake rev: 85e03a64dd0a4ebe71009ec4bdf4192c04a9786e) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/tinfoil.py')
-rw-r--r--bitbake/lib/bb/tinfoil.py115
1 files changed, 55 insertions, 60 deletions
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py
index 70b381e351..4fbad0774e 100644
--- a/bitbake/lib/bb/tinfoil.py
+++ b/bitbake/lib/bb/tinfoil.py
@@ -13,6 +13,7 @@ import sys
13import atexit 13import atexit
14import re 14import re
15from collections import OrderedDict, defaultdict 15from collections import OrderedDict, defaultdict
16from functools import partial
16 17
17import bb.cache 18import bb.cache
18import bb.cooker 19import bb.cooker
@@ -44,66 +45,64 @@ class TinfoilUIException(Exception):
44class TinfoilCommandFailed(Exception): 45class TinfoilCommandFailed(Exception):
45 """Exception raised when run_command fails""" 46 """Exception raised when run_command fails"""
46 47
48class TinfoilDataStoreConnectorVarHistory:
49 def __init__(self, tinfoil, dsindex):
50 self.tinfoil = tinfoil
51 self.dsindex = dsindex
52
53 def remoteCommand(self, cmd, *args, **kwargs):
54 return self.tinfoil.run_command('dataStoreConnectorVarHistCmd', self.dsindex, cmd, args, kwargs)
55
56 def __getattr__(self, name):
57 if not hasattr(bb.data_smart.VariableHistory, name):
58 raise AttributeError("VariableHistory has no such method %s" % name)
59
60 newfunc = partial(self.remoteCommand, name)
61 setattr(self, name, newfunc)
62 return newfunc
63
64class TinfoilDataStoreConnectorIncHistory:
65 def __init__(self, tinfoil, dsindex):
66 self.tinfoil = tinfoil
67 self.dsindex = dsindex
68
69 def remoteCommand(self, cmd, *args, **kwargs):
70 return self.tinfoil.run_command('dataStoreConnectorIncHistCmd', self.dsindex, cmd, args, kwargs)
71
72 def __getattr__(self, name):
73 if not hasattr(bb.data_smart.IncludeHistory, name):
74 raise AttributeError("IncludeHistory has no such method %s" % name)
75
76 newfunc = partial(self.remoteCommand, name)
77 setattr(self, name, newfunc)
78 return newfunc
79
47class TinfoilDataStoreConnector: 80class TinfoilDataStoreConnector:
48 """Connector object used to enable access to datastore objects via tinfoil""" 81 """
82 Connector object used to enable access to datastore objects via tinfoil
83 Method calls are transmitted to the remote datastore for processing, if a datastore is
84 returned we return a connector object for the new store
85 """
49 86
50 def __init__(self, tinfoil, dsindex): 87 def __init__(self, tinfoil, dsindex):
51 self.tinfoil = tinfoil 88 self.tinfoil = tinfoil
52 self.dsindex = dsindex 89 self.dsindex = dsindex
53 def getVar(self, name): 90 self.varhistory = TinfoilDataStoreConnectorVarHistory(tinfoil, dsindex)
54 value = self.tinfoil.run_command('dataStoreConnectorFindVar', self.dsindex, name) 91 self.inchistory = TinfoilDataStoreConnectorIncHistory(tinfoil, dsindex)
55 overrides = None 92
56 if isinstance(value, dict): 93 def remoteCommand(self, cmd, *args, **kwargs):
57 if '_connector_origtype' in value: 94 ret = self.tinfoil.run_command('dataStoreConnectorCmd', self.dsindex, cmd, args, kwargs)
58 value['_content'] = self.tinfoil._reconvert_type(value['_content'], value['_connector_origtype']) 95 if isinstance(ret, bb.command.DataStoreConnectionHandle):
59 del value['_connector_origtype'] 96 return TinfoilDataStoreConnector(self.tinfoil, ret.dsindex)
60 if '_connector_overrides' in value:
61 overrides = value['_connector_overrides']
62 del value['_connector_overrides']
63 return value, overrides
64 def getKeys(self):
65 return set(self.tinfoil.run_command('dataStoreConnectorGetKeys', self.dsindex))
66 def getVarHistory(self, name):
67 return self.tinfoil.run_command('dataStoreConnectorGetVarHistory', self.dsindex, name)
68 def expandPythonRef(self, varname, expr, d):
69 ds = bb.remotedata.RemoteDatastores.transmit_datastore(d)
70 ret = self.tinfoil.run_command('dataStoreConnectorExpandPythonRef', ds, varname, expr)
71 return ret 97 return ret
72 def setVar(self, varname, value): 98
73 if self.dsindex is None: 99 def __getattr__(self, name):
74 self.tinfoil.run_command('setVariable', varname, value) 100 if not hasattr(bb.data._dict_type, name):
75 else: 101 raise AttributeError("Data store has no such method %s" % name)
76 # Not currently implemented - indicate that setting should 102
77 # be redirected to local side 103 newfunc = partial(self.remoteCommand, name)
78 return True 104 setattr(self, name, newfunc)
79 def setVarFlag(self, varname, flagname, value): 105 return newfunc
80 if self.dsindex is None:
81 self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value)
82 else:
83 # Not currently implemented - indicate that setting should
84 # be redirected to local side
85 return True
86 def delVar(self, varname):
87 if self.dsindex is None:
88 self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname)
89 else:
90 # Not currently implemented - indicate that setting should
91 # be redirected to local side
92 return True
93 def delVarFlag(self, varname, flagname):
94 if self.dsindex is None:
95 self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname)
96 else:
97 # Not currently implemented - indicate that setting should
98 # be redirected to local side
99 return True
100 def renameVar(self, name, newname):
101 if self.dsindex is None:
102 self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname)
103 else:
104 # Not currently implemented - indicate that setting should
105 # be redirected to local side
106 return True
107 106
108class TinfoilCookerAdapter: 107class TinfoilCookerAdapter:
109 """ 108 """
@@ -412,9 +411,7 @@ class Tinfoil:
412 self.run_actions(config_params) 411 self.run_actions(config_params)
413 self.recipes_parsed = True 412 self.recipes_parsed = True
414 413
415 self.config_data = bb.data.init() 414 self.config_data = TinfoilDataStoreConnector(self, 0)
416 connector = TinfoilDataStoreConnector(self, None)
417 self.config_data.setVar('_remote_data', connector)
418 self.cooker = TinfoilCookerAdapter(self) 415 self.cooker = TinfoilCookerAdapter(self)
419 self.cooker_data = self.cooker.recipecaches[''] 416 self.cooker_data = self.cooker.recipecaches['']
420 else: 417 else:
@@ -842,9 +839,7 @@ class Tinfoil:
842 newobj = origtype(obj) 839 newobj = origtype(obj)
843 840
844 if isinstance(newobj, bb.command.DataStoreConnectionHandle): 841 if isinstance(newobj, bb.command.DataStoreConnectionHandle):
845 connector = TinfoilDataStoreConnector(self, newobj.dsindex) 842 newobj = TinfoilDataStoreConnector(self, newobj.dsindex)
846 newobj = bb.data.init()
847 newobj.setVar('_remote_data', connector)
848 843
849 return newobj 844 return newobj
850 845