Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

# -*- coding: utf-8 -*- 

# 

# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com> 

# 

# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with 

# the additional special exception to link portions of this program with the OpenSSL library. 

# See LICENSE for more details. 

# 

 

""" 

 

The AlertManager handles all the libtorrent alerts. 

 

This should typically only be used by the Core. Plugins should utilize the 

`:mod:EventManager` for similar functionality. 

 

""" 

 

import logging 

 

from twisted.internet import reactor 

 

import deluge.component as component 

from deluge._libtorrent import lt 

from deluge.common import decode_string 

 

log = logging.getLogger(__name__) 

 

 

class AlertManager(component.Component): 

    """AlertManager fetches and processes libtorrent alerts""" 

    def __init__(self): 

        log.debug("AlertManager init...") 

        component.Component.__init__(self, "AlertManager", interval=0.3) 

        self.session = component.get("Core").session 

 

        # Increase the alert queue size so that alerts don't get lost. 

        self.alert_queue_size = 10000 

        self.set_alert_queue_size(self.alert_queue_size) 

 

        self.session.set_alert_mask( 

            lt.alert.category_t.error_notification | 

            lt.alert.category_t.port_mapping_notification | 

            lt.alert.category_t.storage_notification | 

            lt.alert.category_t.tracker_notification | 

            lt.alert.category_t.status_notification | 

            lt.alert.category_t.ip_block_notification | 

            lt.alert.category_t.performance_warning) 

 

        # handlers is a dictionary of lists {"alert_type": [handler1,h2,..]} 

        self.handlers = {} 

        self.delayed_calls = [] 

        self.wait_on_handler = False 

 

    def update(self): 

        self.delayed_calls = [dc for dc in self.delayed_calls if dc.active()] 

        self.handle_alerts(wait=self.wait_on_handler) 

 

    def stop(self): 

        for delayed_call in self.delayed_calls: 

            if delayed_call.active(): 

                delayed_call.cancel() 

        self.delayed_calls = [] 

 

    def register_handler(self, alert_type, handler): 

        """ 

        Registers a function that will be called when 'alert_type' is pop'd 

        in handle_alerts.  The handler function should look like: handler(alert) 

        Where 'alert' is the actual alert object from libtorrent. 

 

        :param alert_type: str, this is string representation of the alert name 

        :param handler: func(alert), the function to be called when the alert is raised 

        """ 

80        if alert_type not in self.handlers: 

            # There is no entry for this alert type yet, so lets make it with an 

            # empty list. 

            self.handlers[alert_type] = [] 

 

        # Append the handler to the list in the handlers dictionary 

        self.handlers[alert_type].append(handler) 

        log.debug("Registered handler for alert %s", alert_type) 

 

    def deregister_handler(self, handler): 

        """ 

        De-registers the `:param:handler` function from all alert types. 

 

        :param handler: func, the handler function to deregister 

        """ 

        # Iterate through all handlers and remove 'handler' where found 

        for (dummy_key, value) in self.handlers.items(): 

            if handler in value: 

                # Handler is in this alert type list 

                value.remove(handler) 

 

    def handle_alerts(self, wait=False): 

        """Pops all libtorrent alerts in the session queue and handles them appropriately. 

 

        Args: 

            wait (bool): If True the handler functions will be run straight away and 

                waited to return before processing the next alert. 

        """ 

        alerts = self.session.pop_alerts() 

        if not alerts: 

            return 

 

        num_alerts = len(alerts) 

108        if log.isEnabledFor(logging.DEBUG): 

            log.debug("Alerts queued: %s", num_alerts) 

110        if num_alerts > 0.9 * self.alert_queue_size: 

            log.warning("Warning total alerts queued, %s, passes 90%% of queue size.", num_alerts) 

 

        # Loop through all alerts in the queue 

        for alert in alerts: 

            alert_type = type(alert).__name__ 

            # Display the alert message 

117            if log.isEnabledFor(logging.DEBUG): 

                log.debug("%s: %s", alert_type, decode_string(alert.message())) 

            # Call any handlers for this alert type 

            if alert_type in self.handlers: 

                for handler in self.handlers[alert_type]: 

124                    if not wait: 

                        self.delayed_calls.append(reactor.callLater(0, handler, alert)) 

                    else: 

                        handler(alert) 

 

    def set_alert_queue_size(self, queue_size): 

        """Sets the maximum size of the libtorrent alert queue""" 

        log.info("Alert Queue Size set to %s", queue_size) 

        self.alert_queue_size = queue_size 

        settings = self.session.get_settings() 

        settings["alert_queue_size"] = self.alert_queue_size 

        self.session.set_settings(settings)