Commit | Line | Data |
---|---|---|
de9b991b JR |
1 | import os |
2 | import logging | |
3 | import yaml | |
fe7b987e | 4 | import pickle |
de9b991b JR |
5 | |
6 | import lttng_ivc.utils.project as Project | |
fe7b987e | 7 | import lttng_ivc.settings as Settings |
de9b991b | 8 | |
cb87ff89 | 9 | from lttng_ivc.utils.utils import sha256_checksum |
de9b991b JR |
10 | |
11 | _logger = logging.getLogger('project.factory') | |
de9b991b JR |
12 | _project_constructor = { |
13 | 'babeltrace': Project.Babeltrace, | |
14 | 'lttng-modules': Project.Lttng_modules, | |
15 | 'lttng-tools': Project.Lttng_tools, | |
16 | 'lttng-ust': Project.Lttng_ust, | |
17 | } | |
18 | ||
fe7b987e JR |
19 | __projects_cache = {} |
20 | ||
cb87ff89 JR |
21 | _project_py_checksum = sha256_checksum(Settings.project_py_file_location) |
22 | ||
de9b991b | 23 | _markers = None |
fe7b987e JR |
24 | with open(Settings.run_configuration_file, 'r') as stream: |
25 | # This is voluntary static across calls, no need to perform this | |
de9b991b JR |
26 | # every time. |
27 | _markers = yaml.load(stream) | |
28 | ||
29 | ||
fe7b987e | 30 | def get_fresh(label, tmpdir): |
de9b991b JR |
31 | if label not in _markers: |
32 | # TODO: specialized exception, handle it caller-side so the caller | |
33 | # can decide to skip or fail test. | |
34 | raise Exception('Label is no present') | |
35 | marker = _markers[label] | |
36 | constructor = _project_constructor[marker['project']] | |
37 | path = marker['path'] | |
38 | sha1 = marker['sha1'] | |
39 | return constructor(label, path, sha1, tmpdir) | |
fe7b987e JR |
40 | |
41 | ||
42 | def _validate_pickle(pickle, label): | |
97d494b0 | 43 | _logger.debug("Checking validate for {} {}".format(pickle, |
cb87ff89 JR |
44 | label)) |
45 | if pickle._py_file_checksum != _project_py_checksum: | |
46 | _logger.warn("Project py file changed".format(pickle.label, | |
47 | label)) | |
48 | return False | |
49 | ||
fe7b987e JR |
50 | if pickle.label != label: |
51 | _logger.warn("Label {} and {} are not the same".format(pickle.label, | |
cb87ff89 | 52 | label)) |
fe7b987e JR |
53 | return False |
54 | if pickle.sha1 != _markers[label]['sha1']: | |
55 | _logger.warn("Sha1 {} and {} are not the same".format(pickle.sha1, | |
56 | _markers[label]['sha1'])) | |
57 | return False | |
58 | ||
59 | deps = _markers[label]['deps'] | |
60 | if len(deps) != len(pickle.dependencies): | |
61 | _logger.warn("Len {} and {} are not the same".format(len(deps), | |
62 | len(pickle.dependencies))) | |
63 | return False | |
64 | for dep in deps: | |
65 | if dep not in pickle.dependencies: | |
66 | _logger.warn("Dep {} is not in {}".format(dep, | |
67 | pickle.dependencies)) | |
68 | return False | |
69 | else: | |
70 | _logger.debug("Calling validate {} {}".format(pickle.dependencies[dep], | |
71 | dep)) | |
72 | valid = _validate_pickle(pickle.dependencies[dep], dep) | |
73 | if not valid: | |
74 | return False | |
75 | return True | |
76 | ||
77 | ||
78 | def get_precook(label): | |
79 | """ | |
80 | Retrieve a precooked immutable projects from a cache if present | |
81 | otherwise the project is built, installed and cached for future access. | |
82 | """ | |
83 | if label not in _markers: | |
84 | # TODO: specialized exception, handle it caller-side so the caller | |
85 | # can decide to skip or fail test. | |
86 | raise Exception('Label is no present') | |
87 | marker = _markers[label] | |
88 | constructor = _project_constructor[marker['project']] | |
89 | path = marker['path'] | |
90 | sha1 = marker['sha1'] | |
91 | deps = marker['deps'] | |
92 | ||
93 | # Cache path for the label | |
94 | cache_path = os.path.join(Settings.projects_cache_folder, label) | |
95 | pickle_path = os.path.join(cache_path, label+".pickle") | |
96 | ||
97 | # Check if Pickle Rick is present and valid. If so return it asap. | |
98 | if os.path.exists(pickle_path): | |
99 | with open(pickle_path, 'rb') as pickle_file: | |
100 | pickled = pickle.load(pickle_file) | |
101 | if _validate_pickle(pickled, label): | |
102 | return pickled | |
103 | else: | |
104 | pickled.cleanup() | |
105 | _logger.warn("Pickle for {} is invalid. Rebuilding".format(label)) | |
106 | ||
107 | project = constructor(label, path, sha1, cache_path) | |
108 | ||
109 | for dep in deps: | |
110 | obj_dep = get_precook(dep) | |
111 | project.dependencies[dep] = obj_dep | |
112 | ||
113 | project.autobuild() | |
114 | project._immutable = True | |
115 | with open(pickle_path, 'wb') as pickle_file: | |
116 | pickle.dump(project, pickle_file) | |
117 | ||
118 | return project |