Ejemplo n.º 1
0
        def node_upgrade(self, master, data, step):
            """
                Sent to spares to upgrade to full copy
            """
            with self.storage.getlock(None).writelock:
                if self.state.instancetype < SPARE:
                    raise GRSException(
                        "Received request to upgrade when not a spare")

                unwrapped = self.network.unwrapbinary(data)
                self.storage.set_full_dataset(unwrapped)
                self.state.me.instancetype = REPLICA
                self.state.current_step = step
                self.state.checkpoint_id()
Ejemplo n.º 2
0
        def open(self,
                 path,
                 flags,
                 additional_mode=[],
                 internal={'local': None}):
            """
            File open operation

            No creation (O_CREAT, O_EXCL) and by default also no truncation (O_TRUNC) flags will be passed to open(). 
            If an application specifies O_TRUNC, fuse first calls truncate() and then open(). Only if 'atomic_o_trunc'
             has been specified and kernel version is 2.6.24 or later, O_TRUNC is passed on to open.

            Unless the 'default_permissions' mount option is given, open should check if the operation is permitted 
            for the given flags. Optionally open may also return an arbitrary filehandle in the fuse_file_info structure, 
            which will be passed to all file operations.           
            
            NOTE: The internal parameter is disregarded and only included to present a consistent API
            """
            if 'remote' in internal:
                raise GRSException("Open is never called remotely")

            accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR

            if isinstance(additional_mode, int):  # HACK
                additional_mode = [additional_mode]

            # The reason why we need to replicate opens is because it can be used to make a file of size 0. (O_CREAT)
            if (flags & accmode) != os.O_RDONLY:
                self.logger.debug(
                    "%s, %s, %s, %s, %s" %
                    (internal, "open", path, flags, list(additional_mode)))
                retval = self.dispatcher.do_write_op(internal, "open", path,
                                                     flags,
                                                     list(additional_mode))
            else:
                retval = self.dispatcher.do_read_op(internal, "open",
                                                    path, flags,
                                                    list(additional_mode))

            if retval <= 0:
                raise IOError(abs(retval), "Error ROFS", path)
            else:
                self._oft_add(path, flags, tuple(additional_mode), retval)

            return (path, flags, additional_mode)
Ejemplo n.º 3
0
        def election_finished(self, group_update):
            with (self.storage.getlock(None).writelock):
                self.logger.info(
                    "Received election finished, group update %s" %
                    (group_update))
                for peer in group_update:
                    #self.logger.debug("election_finished: updating %s !! " % peer)
                    (server, port, score, instancetype) = peer
                    existing = self.state.find((server, port))
                    if existing is None:
                        raise GRSException(
                            "Election_finished received. Could not find peer %s in group of %s!"
                            % (peer, self.state.group))
                    existing.score = score
                    existing.instancetype = instancetype

            self.state.must_run_election = False
            self.__election_finished()
Ejemplo n.º 4
0
        def network_update_notification(self, cmd, arg):
            """
            Used to receive updates from other network parties. 
            Does NOT ask for an election - that is the job of the originating party.
            """
            self.logger.info("network_update_notification cmd=%s, arg={%s}",
                             cmd, arg)
            if cmd == 'PEER_DOWN':
                arg = tuple(arg)
                if self.state.me.connection == arg:
                    raise GRSException(
                        "Internal error: invalid kill attempt from remote peer"
                    )

                self._handle_dead_peer(arg, False)
            elif cmd == 'PEER_UP':
                arg = tuple(arg)
                if self.state.me.connection == arg:
                    self.logger.error("PEER_UP received about myself")
                    return
                new_peer = Peer(connection=arg)
                self._add_new_peer(new_peer)
Ejemplo n.º 5
0
        def _connect_to_known_peers(self):
            """
            Connects to any peers that we might know of that aren't already connected.
            
            A state lock should be in place when entering this function
            """
            hold_election = False

            for unconnected_peer in self.state.unconnected_nodes:
                self.logger.debug("Connecting to %s" % str(unconnected_peer))
                retval = self.network.connect_to_peer(
                    unconnected_peer, self.state.identification)
                if retval is None:
                    self.logger.warn("Transmission failure '%s', dropping. Group is now %s" % \
                        (str(unconnected_peer), self.state.group))
                    self.state.group.remove(unconnected_peer)
                    self.state._mark_can_replicate()
                    continue

                (link, data) = retval
                unconnected_peer.link = link
                if unconnected_peer.recontact:
                    self.state.must_run_election = True

                if data is None:
                    # rebound request - just ignore it.
                    self.logger.debug(
                        "Received counter-connect from %s, returning" %
                        str(unconnected_peer.connection))
                    continue

                (me_type, step, score, others, remote_instancetype) = data
                self.logger.info(
                    "_connect_to_known_peers data package (me %d/remote %d) %s"
                    % (me_type, remote_instancetype, data))
                if me_type == -1:
                    continue

                unconnected_peer.link = link

                unconnected_peer.score = score
                unconnected_peer.recontact = False

                if me_type == -2:
                    unconnected_peer.instancetype = SPARE

                # FIXME make it so that spares cannot dictate to us
                if me_type == SPARE:
                    self.state.me.instancetype = SPARE
                elif me_type == REPLICA:
                    self.state.me.instancetype = REPLICA
                    hold_election = True
                else:
                    raise GRSException(
                        "Unknown me_type %s in %s when connecting to %s" %
                        (me_type, data, unconnected_peer.connection))

                for other in others:
                    new_peer = Peer(connection=tuple(other), recontact=True)
                    if self.state.find(new_peer.connection) is None:
                        self._add_new_peer(new_peer)