summaryrefslogtreecommitdiffstats
path: root/storperf/utilities/thread_gate.py
blob: 295b8be692a1de9171b85dd95ad8b4957a1d598f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
##############################################################################
# Copyright (c) 2016 Dell EMC and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
"""
Creates a gate object that allows synchronization between an arbitrary
number of callers.
"""
import logging
import time


class FailureToReportException(Exception):
    pass


class ThreadGate(object):

    def __init__(self, size, timeout=60):
        self.logger = logging.getLogger(__name__)
        self._gate_size = size
        self._timeout = timeout
        self._registrants = {}
        self._creation_time = time.time()

    """
    Calling this method returns a true or false, indicating that enough
    of the other registrants have reported in
    """

    def report(self, gate_id):
        now = time.time()
        self._registrants[gate_id] = now
        ready = True
        self.logger.debug("Gate report for %s", gate_id)

        total_missing = self._gate_size - len(self._registrants)
        if total_missing > 0:
            self.logger.debug("Not all registrants have reported in")
            time_since_creation = now - self._creation_time
            if (time_since_creation > (self._timeout * 2)):
                self.logger.error("%s registrant(s) have never reported in",
                                  total_missing)
                raise FailureToReportException
            return False

        for k, v in self._registrants.items():
            time_since_last_report = now - v
            if time_since_last_report > self._timeout:
                self.logger.debug("Registrant %s last reported %s ago",
                                  k, time_since_last_report)
                ready = False

        self.logger.debug("Gate pass? %s", ready)

        if ready:
            self._registrants.clear()

        return ready