[elbe-devel] [PATCH 19/32] Nuke ASCIIDocLog from RPCAPTCache

dion at linutronix.de dion at linutronix.de
Fri Jun 14 22:13:33 CEST 2019


From: Olivier Dion <dion at linutronix.de>

Just like 'do', 'get_rpcaptcache' will return its outputs to the
logging file descriptor.  This has the same problems has 'do', for not
being thread safe.

* Decorator

  The 'MyMan::register' decorator was added to allow registration of
  'RPCAPTCache' to the 'BaseManager'.  This is the same scheme used in
  an other patch for the finetuning section.

  This decorator also call 'MyMan::wrap_with_logging', which is a
  decorator factory.

** MyMan::wrap_with_logging

   Ok so this is where the magic happen.  By iterating over all public
   methods, i.e. methods with name that doesn't have the "__" prefix,
   we can decorate all of these methods in one place!  No need to
   manually add the decorator to each methods.  This could be use in
   the _esoap_ actions ..

   The decorator will print the method's name followed by ">>>>>\n".
   It will then call the wrapped method and then print "<<<<<\n".

   It would also be possible to catch any exception there, allowing
   better control over errors.

*** Example

    command:
    ``````````````````````````````````````````````````````````````````
    rpc = get_rpcaptcache(**kwargs)
    rpc.mark_install("bash", 5)
    ``````````````````````````````````````````````````````````````````

    output (something similar):
    ``````````````````````````````````````````````````````````````````
    RPCAPTCache mark_install
    >>>>>
    Mark for install "bash"
    <<<<<
    ``````````````````````````````````````````````````````````````````

Signed-off-by: Olivier Dion <dion at linutronix.de>
---
 elbepack/cdroms.py      |  6 ++--
 elbepack/elbeproject.py | 11 +++---
 elbepack/rpcaptcache.py | 89 ++++++++++++++++++++++++++++++++-----------------
 3 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/elbepack/cdroms.py b/elbepack/cdroms.py
index 8f0723f4..6f6d80a8 100644
--- a/elbepack/cdroms.py
+++ b/elbepack/cdroms.py
@@ -48,7 +48,7 @@ def mk_source_cdrom(
                         cdrom_size,
                         mirror)
 
-    cache = get_rpcaptcache(rfs, "aptcache.log", arch)
+    cache = get_rpcaptcache(rfs, arch)
     cache.update()
     pkglist = cache.get_installed_pkgs()
 
@@ -149,7 +149,7 @@ def mk_binary_cdrom(
                                target_repo_path, cdrom_size, mirror)
 
     if xml is not None:
-        cache = get_rpcaptcache(rfs, "aptcache.log", arch)
+        cache = get_rpcaptcache(rfs, arch)
         for p in xml.node("debootstrappkgs"):
             pkg = XMLPackage(p, arch)
             try:
@@ -178,7 +178,7 @@ def mk_binary_cdrom(
                     pkg.installed_version +
                     " missing name or version")
 
-    cache = get_rpcaptcache(rfs, "aptcache.log", arch)
+    cache = get_rpcaptcache(rfs, arch)
     pkglist = cache.get_installed_pkgs()
     for pkg in pkglist:
         try:
diff --git a/elbepack/elbeproject.py b/elbepack/elbeproject.py
index a0ecb989..046bcbf5 100644
--- a/elbepack/elbeproject.py
+++ b/elbepack/elbeproject.py
@@ -806,13 +806,10 @@ class ElbeProject (object):
             arch = env.arch
 
         if env.rpcaptcache is None:
-            env.rpcaptcache = get_rpcaptcache(
-                env.rfs,
-                self.log.fp.name,
-                arch,
-                self.rpcaptcache_notifier,
-                norecommend,
-                self.xml.prj.has('noauth'))
+            env.rpcaptcache = get_rpcaptcache(env.rfs, arch,
+                                              self.rpcaptcache_notifier,
+                                              norecommend,
+                                              self.xml.prj.has('noauth'))
         return env.rpcaptcache
 
     def drop_rpcaptcache(self, env=None):
diff --git a/elbepack/rpcaptcache.py b/elbepack/rpcaptcache.py
index d4f4a794..afbe6824 100644
--- a/elbepack/rpcaptcache.py
+++ b/elbepack/rpcaptcache.py
@@ -21,6 +21,55 @@ from elbepack.aptprogress import (ElbeAcquireProgress, ElbeInstallProgress,
                                   ElbeOpProgress)
 from elbepack.aptpkgutils import getalldeps, APTPackage
 
+from elbepack.log import log
+
+
+class MyMan(BaseManager):
+
+    @staticmethod
+    def do_logging(header):
+        def wrapper(func):
+            def decorate(*args, **kwargs):
+                fd = os.sys.stdout.fileno()
+                os.write(fd, "\n%s\n>>>>>\n" % header)
+                os.fsync(fd)
+                ret = func(*args, **kwargs)
+                os.write(os.sys.stdout.fileno(), "<<<<<\n")
+                os.fsync(fd)
+                return ret
+            return decorate
+        return wrapper
+
+    @staticmethod
+    def wrap_with_logging(cls):
+        for attr in cls.__dict__:
+            c = getattr(cls, attr)
+            if callable(c) and not attr.startswith("__"):
+                header = "%s %s" % (cls.__name__, attr)
+                setattr(cls, attr, MyMan.do_logging(header)(c))
+
+    @staticmethod
+    def register(typeid):
+        def _register(cls):
+            BaseManager.register(typeid, cls)
+            MyMan.wrap_with_logging(cls)
+            return cls
+        return _register
+
+    @staticmethod
+    def redirect_outputs(fd):
+        os.dup2(fd, os.sys.stdout.fileno())
+        os.dup2(fd, os.sys.stderr.fileno())
+        os.sys.stdout = os.fdopen(os.sys.stdout.fileno(), "w", 1)
+        os.sys.stderr = os.fdopen(os.sys.stderr.fileno(), "w", 1)
+        os.sys.__stdout__ = os.sys.stdout
+        os.sys.__stderr__ = os.sys.stderr
+
+
+    def start(self):
+        fp = open(log.filename, "ab", 0)
+        super(MyMan, self).start(MyMan.redirect_outputs, [fp.fileno()])
+
 class InChRootObject(object):
     def __init__(self, rfs):
         self.rfs = rfs
@@ -28,23 +77,14 @@ class InChRootObject(object):
         self.finalizer = Finalize(self, self.rfs.leave_chroot, exitpriority=10)
 
 
+ at MyMan.register("RPCAPTCache")
 class RPCAPTCache(InChRootObject):
+
     # pylint: disable=too-many-public-methods
-    def __init__(
-            self,
-            rfs,
-            log,
-            arch,
-            notifier=None,
-            norecommend=False,
-            noauth=True):
+    def __init__(self, rfs, arch,
+                 notifier=None, norecommend=False, noauth=True):
 
         # pylint: disable=too-many-arguments
-
-        sys.stdout = open(log, 'a', buffering=0)
-        sys.stderr = open(log, 'a', buffering=0)
-        self.logfile = open(log, 'a', buffering=0)
-
         InChRootObject.__init__(self, rfs)
 
         self.notifier = notifier
@@ -99,6 +139,7 @@ class RPCAPTCache(InChRootObject):
         return ret
 
     def mark_install(self, pkgname, version, from_user=True, nodeps=False):
+        print('Mark for install "%s"' % pkgname)
         p = self.cache[pkgname]
         if version:
             p.candidate = p.versions[version]
@@ -165,8 +206,9 @@ class RPCAPTCache(InChRootObject):
     def commit(self):
         os.environ["DEBIAN_FRONTEND"] = "noninteractive"
         os.environ["DEBONF_NONINTERACTIVE_SEEN"] = "true"
+        print("Commiting changes ...")
         self.cache.commit(ElbeAcquireProgress(),
-                          ElbeInstallProgress(fileno=self.logfile.fileno()))
+                          ElbeInstallProgress(fileno=sys.stdout.fileno()))
         self.cache.open(progress=ElbeOpProgress())
 
     def clear(self):
@@ -275,21 +317,8 @@ class RPCAPTCache(InChRootObject):
                                                unpack=False)
             return self.rfs.fname(rel_filename)
 
-
-class MyMan(BaseManager):
-    pass
-
-
-MyMan.register("RPCAPTCache", RPCAPTCache)
-
-
-def get_rpcaptcache(
-        rfs,
-        log,
-        arch,
-        notifier=None,
-        norecommend=False,
-        noauth=True):
+def get_rpcaptcache(rfs, arch,
+                    notifier=None, norecommend=False, noauth=True):
 
     # pylint: disable=too-many-arguments
 
@@ -301,4 +330,4 @@ def get_rpcaptcache(
     # MyMan.register()
     #
     # pylint: disable=no-member
-    return mm.RPCAPTCache(rfs, log, arch, notifier, norecommend, noauth)
+    return mm.RPCAPTCache(rfs, arch, notifier, norecommend, noauth)
-- 
2.11.0




More information about the elbe-devel mailing list