Пример #1
0
class ConsistHash(object):
    def __init__(self, size=0xffff):
        self.size = size # set consistent hash circul size
        self.rbt = RBTree()  # red black tree

    def insert_host(self, host):
        host_id = host.get_id(self.size)
        self.rbt.insert(host_id, host)

    def remove_host(self, host):
        host_id = host.get_id(self.size)
        self.rbt.remove(host_id)

    @staticmethod
    def _find_upper(root, elem):
        if root is None:
            return -1

        if elem == root.key:
            return root.key
        elif elem < root.key:
            maybe_max = find_upper(root.left, elem)
            if _not_exists(maybe_max):
                return root.key
            return maybe_max
        else:
            maybe_max = find_upper(root.right, elem)
            if _not_exists(maybe_max):
                return -1
            return maybe_max

    def find_host(self, id):
        id %= self.size
        idx = self._find_upper(self.rbt._root, id)
        if idx == -1:  # id larger than max id
            # assert tree is not empty
            return self.rbt.min_item()[1]
        return self.rbt.get_value(idx)
Пример #2
0
class ExponentiallyDecayingSample(object):
    RESCALE_THRESHOLD = 60 * 60

    def __init__(self, reservoir_size, alpha):
        self.values = RBTree()
        self.counter = Atomic(0)
        self.next_scale_time = Atomic(0)
        self.alpha = alpha
        self.reservoir_size = reservoir_size
        self.lock = RLock()
        self.clear()

    def clear(self):
        with self.lock:
            self.values.clear()
            self.counter.value = 0
            self.next_scale_time.value = time() + self.RESCALE_THRESHOLD
            self.start_time = time()

    def size(self):
        count = self.counter.value
        if count < self.reservoir_size:
            return count
        return self.reservoir_size

    def __len__(self):
        return self.size()

    def snapshot(self):
        with self.lock:
            return Snapshot(list(self.values.values()))

    def weight(self, timestamp):
        return math.exp(self.alpha * timestamp)

    def rescale(self, now, next_time):
        if self.next_scale_time.compare_and_swap(next_time, now + self.RESCALE_THRESHOLD):
            with self.lock:
                old_start_time = self.start_time
                self.start_time = time()
                for key in list(self.values.keys()):
                    value = self.values.remove(key)
                self.values[key * math.exp(-self.alpha * (self.start_time - old_start_time))] = value

    def update(self, value, timestamp=None):
        if not timestamp:
            timestamp = time()
        with self.lock:
            try:
                priority = self.weight(timestamp - self.start_time) / random.random()
            except OverflowError:
                priority = sys.float_info.max
            new_count = self.counter.update(lambda v: v + 1)

            if math.isnan(priority):
                return

            if new_count <= self.reservoir_size:
                self.values[priority] = value
            else:
                first_priority = self.values.root.key
                if first_priority < priority:
                    if priority in self.values:
                        self.values[priority] = value
                        if not self.values.remove(first_priority):
                            first_priority = self.values.root()
Пример #3
0
class ExponentiallyDecayingSample(object):
    RESCALE_THRESHOLD = 60 * 60

    def __init__(self, reservoir_size, alpha):
        self.values = RBTree()
        self.counter = Atomic(0)
        self.next_scale_time = Atomic(0)
        self.alpha = alpha
        self.reservoir_size = reservoir_size
        self.lock = RLock()
        self.clear()

    def clear(self):
        with self.lock:
            self.values.clear()
            self.counter.value = 0
            self.next_scale_time.value = time() + self.RESCALE_THRESHOLD
            self.start_time = time()

    def size(self):
        count = self.counter.value
        if count < self.reservoir_size:
            return count
        return self.reservoir_size

    def __len__(self):
        return self.size()

    def snapshot(self):
        with self.lock:
            return Snapshot(list(self.values.values()))

    def weight(self, timestamp):
        return math.exp(self.alpha * timestamp)

    def rescale(self, now, next_time):
        if self.next_scale_time.compare_and_swap(next_time,
                                                 now + self.RESCALE_THRESHOLD):
            with self.lock:
                old_start_time = self.start_time
                self.start_time = time()
                for key in list(self.values.keys()):
                    value = self.values.remove(key)
                self.values[key * math.exp(
                    -self.alpha * (self.start_time - old_start_time))] = value

    def update(self, value, timestamp=None):
        if not timestamp:
            timestamp = time()
        with self.lock:
            try:
                priority = self.weight(timestamp -
                                       self.start_time) / random.random()
            except OverflowError:
                priority = sys.float_info.max
            new_count = self.counter.update(lambda v: v + 1)

            if math.isnan(priority):
                return

            if new_count <= self.reservoir_size:
                self.values[priority] = value
            else:
                first_priority = self.values.root.key
                if first_priority < priority:
                    if priority in self.values:
                        self.values[priority] = value
                        if not self.values.remove(first_priority):
                            first_priority = self.values.root()