From 68e075d56245fa688fb2628227c2bd33140bb905 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Tue, 12 May 2015 14:23:55 -0500
Subject: [PATCH 36/54] Make a UdevEventManager singleton.

There should never be more than one instance of the event manager. This
makes it easy to manipulate the event mask from code that would not
otherwise have access to the event manager.

Add synchronization so it can be safely accessed from multiple threads.
---
 blivet/devicetree.py |  5 ++---
 blivet/event.py      |  9 ++++++++-
 blivet/handler.py    | 10 +++++-----
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index d14e2fd..022ed35 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -40,7 +40,7 @@ from .flags import flags
 from .populator import Populator
 from .storage_log import log_method_call, log_method_return
 from .threads import SynchronizedMeta
-from .event import UdevEventManager
+from .event import eventManager
 from .handler import EventHandler
 
 import logging
@@ -104,8 +104,7 @@ class DeviceTree(object):
 
         lvm.lvm_cc_resetFilter()
 
-        self.eventManager = UdevEventManager()
-        self.eventHandler = EventHandler(self, self.eventManager)
+        self.eventHandler = EventHandler(self)
 
         self._populator = Populator(self,
                                     conf=conf,
diff --git a/blivet/event.py b/blivet/event.py
index 85fe346..2f2ac49 100644
--- a/blivet/event.py
+++ b/blivet/event.py
@@ -31,6 +31,7 @@ from . import udev
 from . import util
 from .errors import EventManagerError, EventParamError, EventQueueEmptyError
 from .flags import flags
+from .threads import SynchronizedABCMeta
 
 import logging
 log = logging.getLogger("blivet")
@@ -157,9 +158,10 @@ class EventQueue(object):
 ##
 ## EventManager
 ##
-@add_metaclass(abc.ABCMeta)
+@add_metaclass(SynchronizedABCMeta)
 class EventManager(object):
     _event_queue_class = EventQueue
+    _unsynchronized_methods = ["handle_event", "enqueue_event"]
 
     def __init__(self, handler_cb=None, notify_cb=None):
         self._handler_cb = None
@@ -278,6 +280,9 @@ class UdevEventManager(EventManager):
 
         flags.uevents = False
 
+    def __call__(self, *args, **kwargs):
+        return self
+
     def enqueue_event(self, *args, **kwargs):
         event = UdevEvent(args[0], args[1])
         if flags.console_debug:
@@ -291,3 +296,5 @@ class UdevEventManager(EventManager):
         current_thread.name = current_thread.name.replace("Thread-",
                                                           "EventManager")
         super(UdevEventManager, self).handle_event(args[0], args[1])
+
+eventManager = UdevEventManager()
diff --git a/blivet/handler.py b/blivet/handler.py
index 1aee5cd..9e8d34c 100644
--- a/blivet/handler.py
+++ b/blivet/handler.py
@@ -28,6 +28,7 @@ from six import add_metaclass
 
 from . import udev
 from .errors import DeviceError, EventQueueEmptyError
+from .event import eventManager
 from .flags import flags
 from .formats import getFormat
 from .storage_log import log_method_call
@@ -38,16 +39,15 @@ log = logging.getLogger("blivet")
 
 @add_metaclass(SynchronizedMeta)
 class EventHandler(object):
-    def __init__(self, devicetree, manager):
+    def __init__(self, devicetree):
         self.devicetree = devicetree
-        self.manager = manager
-        self.manager.handler_cb = self.handleUevent
+        eventManager.handler_cb = self.handleUevent
 
     def handleUevent(self):
         """ Handle the next uevent in the queue. """
         log_method_call(self)
         try:
-            event = self.manager.next_event()
+            event = eventManager.next_event()
         except EventQueueEmptyError:
             log.debug("uevent queue is empty")
             return
@@ -121,7 +121,7 @@ class EventHandler(object):
     def _diskLabelChangeHandler(self, info, device):
         log.info("checking for changes to disklabel on %s", device.name)
         # update the partition list
-        self.manager.mask_event(device=udev.device_get_name(info),
+        eventManager.mask_event(device=udev.device_get_name(info),
                                 action="change", count=1)
         device.format.updatePartedDisk()
         udev_devices = [d for d in udev.get_devices()
-- 
2.1.0

