You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by gi...@apache.org on 2020/12/29 13:22:03 UTC

[buildstream] 13/33: WIP: pickle: Job, ElementJob, Element, Source

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch aevri/picklable_jobs
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 7a47c4ee3a19f2a4f510b9d3acc9b4729713316a
Author: Angelos Evripiotis <je...@bloomberg.net>
AuthorDate: Tue Apr 2 13:21:29 2019 +0100

    WIP: pickle: Job, ElementJob, Element, Source
---
 src/buildstream/_scheduler/jobs/elementjob.py | 78 +++++++++++++++++++++++++++
 src/buildstream/_scheduler/jobs/job.py        |  9 ++++
 2 files changed, 87 insertions(+)

diff --git a/src/buildstream/_scheduler/jobs/elementjob.py b/src/buildstream/_scheduler/jobs/elementjob.py
index 29ff2b1..a684235 100644
--- a/src/buildstream/_scheduler/jobs/elementjob.py
+++ b/src/buildstream/_scheduler/jobs/elementjob.py
@@ -20,9 +20,77 @@ from ruamel import yaml
 
 from ..._message import MessageType
 
+from ..._artifact import Artifact
+
 from .job import Job, ChildJob
 
 
+# TODO: Make sure we only unpickle each element and source once, probably using
+# some global mechanism and context manager.
+
+
+def make_picklable_source_state(source):
+    print("Pickling source", source, repr(source))
+    # breakpoint()
+    meta_kind = source._meta_kind
+    project = source._get_project()
+    factory = project.config.source_factory
+    source_dict = source.__dict__.copy()
+    return {
+        'factory': factory,
+        'meta_kind': meta_kind,
+        'source_dict': source_dict,
+    }
+
+
+def make_source_from_picklable_source_state(state):
+    factory = state['factory']
+    meta_kind = state['meta_kind']
+    source_dict = state['source_dict']
+    # breakpoint()
+    source_cls, default_config = factory.lookup(meta_kind)
+    source = source_cls.__new__(source_cls)
+    source.__dict__ = source_dict
+    context = source._get_project()._context
+    print("Unpickled source", source, repr(source))
+    return source
+
+
+def make_picklable_element_state(element):
+    print("Pickling element", element, repr(element))
+    meta_kind = element._meta_kind
+    project = element._get_project()
+    factory = project.config.element_factory
+    element_dict = element.__dict__.copy()
+    # del element_dict['_Element__sources']
+    element_dict['_Element__sources'] = [
+        make_picklable_source_state(s)
+        for s in element.sources()
+    ]
+    del element_dict['_Element__artifact']
+    return {
+        'factory': factory,
+        'meta_kind': meta_kind,
+        'element_dict': element_dict,
+    }
+
+
+def make_element_from_picklable_element_state(state):
+    factory = state['factory']
+    meta_kind = state['meta_kind']
+    element_dict = state['element_dict']
+    element_cls, default_config = factory.lookup(meta_kind)
+    element = element_cls.__new__(element_cls)
+    element.__dict__ = element_dict
+    context = element._get_project()._context
+    element_dict['_Element__sources'] = [
+        make_source_from_picklable_source_state(s)
+        for s in element_dict['_Element__sources']
+    ]
+    element_dict['_Element__artifact'] = Artifact(element, context)
+    print("Unpickled element", element, repr(element))
+    return element
+
 # ElementJob()
 #
 # A job to run an element's commands. When this job is spawned
@@ -76,6 +144,16 @@ class ElementJob(Job):
         self.set_message_unique_id(element._unique_id)
         self.set_task_id(element._unique_id)
 
+    def __getstate__(self):
+        state = super().__getstate__()
+        state['_element'] = make_picklable_element_state(self._element)
+        return state
+
+    def __setstate__(self, state):
+        self.__dict__.update(state)
+        self._element = make_element_from_picklable_element_state(
+            self._element)
+
     @property
     def element(self):
         return self._element
diff --git a/src/buildstream/_scheduler/jobs/job.py b/src/buildstream/_scheduler/jobs/job.py
index c15ce04..799b55f 100644
--- a/src/buildstream/_scheduler/jobs/job.py
+++ b/src/buildstream/_scheduler/jobs/job.py
@@ -115,6 +115,15 @@ class Job():
         self._message_unique_id = None
         self._task_id = None
 
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        del state['_scheduler']
+        state['_scheduler_context'] = self._scheduler.context
+        del state['_process']
+        del state['queue']
+        del state['_watcher']
+        return state
+
     # spawn()
     #
     # Spawns the job.