__init__.py 4.38 KB
Newer Older
Aurel's avatar
Aurel committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#
# Copyright (C) 2006-2009  Nexedi SA
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

18
from neo import logging
19

20
from neo import protocol
21 22
from neo.handler import EventHandler

23
class MasterHandler(EventHandler):
24
    """This class implements a generic part of the event handlers."""
25

26 27 28
    def handleProtocolError(self, conn, packet, message):
        logging.error('Protocol error %s %s' % (message, conn.getAddress()))

29
    def handleAskPrimaryMaster(self, conn, packet):
30 31 32 33 34 35 36
        if conn.getConnector() is None:
            # Connection can be closed by peer after he sent AskPrimaryMaster
            # if he finds the primary master before we answer him.
            # The connection gets closed before this message gets processed
            # because this message might have been queued, but connection
            # interruption takes effect as soon as received.
            return
37 38 39 40 41 42
        app = self.app
        if app.primary:
            primary_uuid = app.uuid
        elif app.primary_master_node is not None:
            primary_uuid = app.primary_master_node.getUUID()
        else:
43
            primary_uuid = None
44

45
        known_master_list = [(app.server, app.uuid, )]
46
        for n in app.nm.getMasterList():
47
            if n.getState() == protocol.BROKEN_STATE:
48
                continue
49
            known_master_list.append((n.getAddress(), n.getUUID(), ))
50
        conn.answer(protocol.answerPrimaryMaster(primary_uuid,
51 52
                                                 known_master_list),
                    packet.getId())
53

54
    def handleAskClusterState(self, conn, packet):
55
        assert conn.getUUID() is not None
56
        state = self.app.getClusterState()
57
        conn.answer(protocol.answerClusterState(state), packet.getId())
58

59 60
    def handleAskNodeInformation(self, conn, packet):
        self.app.sendNodesInformations(conn)
61
        conn.answer(protocol.answerNodeInformation([]), packet.getId())
62 63 64 65 66

    def handleAskPartitionTable(self, conn, packet, offset_list):
        assert len(offset_list) == 0
        app = self.app
        app.sendPartitionTable(conn)
67 68
        conn.answer(protocol.answerPartitionTable(app.pt.getID(), []),
                    packet.getId())
69

70

71 72 73 74
DISCONNECTED_STATE_DICT = {
    protocol.STORAGE_NODE_TYPE: protocol.TEMPORARILY_DOWN_STATE,
}

75 76 77
class BaseServiceHandler(MasterHandler):
    """This class deals with events for a service phase."""

78 79 80 81 82
    def handleNodeLost(self, conn, node):
        # This method provides a hook point overridable by service classes.
        # It is triggered when a connection to a node gets lost.
        pass

83
    def connectionLost(self, conn, new_state):
84
        node = self.app.nm.getByUUID(conn.getUUID())
85
        assert node is not None
86 87
        if new_state != protocol.BROKEN_STATE:
            new_state = DISCONNECTED_STATE_DICT.get(node.getType(), protocol.DOWN_STATE)
88
        if node.getState() == new_state:
89 90 91 92 93 94 95 96
            return
        if new_state != protocol.BROKEN_STATE and node.getState() == protocol.PENDING_STATE:
            # was in pending state, so drop it from the node manager to forget
            # it and do not set in running state when it comes back
            logging.info('drop a pending node from the node manager')
            self.app.nm.remove(node)
        node.setState(new_state)
        self.app.broadcastNodeInformation(node)
97 98
        # clean node related data in specialized handlers
        self.handleNodeLost(conn, node)
99

100 101
    def handleAskLastIDs(self, conn, packet):
        app = self.app
102
        conn.answer(protocol.answerLastIDs(app.loid, app.ltid, app.pt.getID()), packet.getId())
103 104 105 106

    def handleAskUnfinishedTransactions(self, conn, packet):
        app = self.app
        p = protocol.answerUnfinishedTransactions(app.finishing_transaction_dict.keys())
107
        conn.answer(p, packet.getId())
108