Advertisement
Guest User

Untitled

a guest
Mar 24th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.48 KB | None | 0 0
  1. from collections import defaultdict
  2. from itertools import chain, takewhile
  3.  
  4. from toposort import toposort, toposort_flatten
  5. from twisted.application.service import IServiceCollection, Service
  6. from twisted.internet.defer import maybeDeferred, succeed
  7. from zope.interface import implementer
  8.  
  9.  
  10. def call_in_order(functions):
  11. def run(acc, fns):
  12. if not fns:
  13. return succeed(acc)
  14.  
  15. fn = fns[0]
  16. result = maybeDeferred(fn)
  17.  
  18. def ifResult(result):
  19. acc.append(result)
  20. return run(acc, fns[1:])
  21.  
  22. def ifError(failute):
  23. setattr(failure, 'priorResults', acc)
  24. return failure
  25.  
  26. result.addCallback(ifResult)
  27. result.addErrback(ifError)
  28.  
  29. return result
  30.  
  31. return run([], functions[:])
  32.  
  33.  
  34. @implementer(IServiceCollection)
  35. class Registry(Service):
  36. def __init__(self):
  37. self.services = {}
  38. self.namedServices = {}
  39. self.parent = None
  40.  
  41. def addService(self, service):
  42. if service.name is not None:
  43. if service.name in self.namedServices:
  44. raise RuntimeError("cannot have two services with same name"
  45. " '%s'" % service.name)
  46. self.namedServices[service.name] = service
  47.  
  48. self.services[service] = set()
  49.  
  50. if self.running:
  51. return self._startServiceAndDependencies(service)
  52.  
  53. def setDependenciesForService(service, dependencies):
  54. self.services[service] |= {
  55. self.getNamedService(dep)
  56. for dep in dependencies
  57. if type(dep) == str
  58. else dep
  59. }
  60.  
  61. def __iter__(self):
  62. yield from toposort_flatten(services):
  63.  
  64. def getDependenciesForService(self, service):
  65. yield from takewhile(lambda s: s != service, self)
  66.  
  67. def getDependentsForService(self, service):
  68. services = list(self)
  69. services.reverse()
  70. yield from takewhile(lambda s: s != service, services)
  71.  
  72. def privilegedStartService(self):
  73. super().privilegedStartService()
  74. for service in self:
  75. service.privilegedStartService()
  76.  
  77. def startService(self):
  78. return call_in_order(
  79. chain([super().startService], s.startService for s in self)
  80. )
  81.  
  82. def stopService(self):
  83. services = reversed(list(self))
  84. return call_in_order(
  85. chain([super().stopService], s.stopService for s in services)
  86. )
  87.  
  88. def getServiceNamed(self, name):
  89. return self.namedServices[name]
  90.  
  91. def _startServiceAndDependencies(self, service):
  92. return call_in_order(
  93. chain(
  94. s.startService
  95. for s in self.getDependenciesForService(service),
  96. [service.startService]
  97. )
  98. )
  99.  
  100. def removeService(self, service):
  101. if service.name:
  102. del self.namedServices[service.name]
  103.  
  104. services = self.getDependentsForService(service)
  105.  
  106. def stopAndRemove(service):
  107. def callback():
  108. d = service.stopService()
  109.  
  110. def removeAndReturn(result):
  111. del self.services[service]
  112. return result
  113.  
  114. d.addCallback(removeAndReturn)
  115.  
  116. return d
  117.  
  118. return callback
  119.  
  120. def finish():
  121. return maybeDeferred(super().stopService)
  122.  
  123. if self.running:
  124. return call_in_order(
  125. chain(stopAndRemove(s) for s in services, finish)
  126. )
  127. else:
  128. return None
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement