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