Exemple #1
0
    def _setNextRotation(self, now=None):
        """Helper function: calculate the time when we next rotate the log."""
        # ???? Lock to 24-hour cycle

        # This is a little weird.  We won't save *until*:
        #       - .75 * rotateInterval seconds are accumulated.
        #  AND  - rotateInterval seconds have elapsed since the last
        #         rotation.
        #
        # IF the rotation interval is divisible by one hour, we also
        #  round to the hour, up to 5 minutes down and 55 up.
        if not now: now = time()

        accumulatedTime = self.accumulatedTime + (now - self.lastSave)
        secToGo = max(0, self.rotateInterval * 0.75 - accumulatedTime)
        self.nextRotation = max(self.lastRotation + self.rotateInterval,
                                now + secToGo)

        if self.nextRotation < now:
            self.nextRotation = now

        if (self.rotateInterval % 3600) == 0:
            mid = previousMidnight(self.nextRotation)
            rest = self.nextRotation - mid
            self.nextRotation = mid + 3600 * floorDiv(rest+55*60, 3600)
Exemple #2
0
    def _setNextRotation(self, now=None):
        """Helper function: calculate the time when we next rotate the log."""
        # ???? Lock to 24-hour cycle

        # This is a little weird.  We won't save *until*:
        #       - .75 * rotateInterval seconds are accumulated.
        #  AND  - rotateInterval seconds have elapsed since the last
        #         rotation.
        #
        # IF the rotation interval is divisible by one hour, we also
        #  round to the hour, up to 5 minutes down and 55 up.
        if not now: now = time()

        accumulatedTime = self.accumulatedTime + (now - self.lastSave)
        secToGo = max(0, self.rotateInterval * 0.75 - accumulatedTime)
        self.nextRotation = max(self.lastRotation + self.rotateInterval,
                                now + secToGo)

        if self.nextRotation < now:
            self.nextRotation = now

        if (self.rotateInterval % 3600) == 0:
            mid = previousMidnight(self.nextRotation)
            rest = self.nextRotation - mid
            self.nextRotation = mid + 3600 * floorDiv(rest + 55 * 60, 3600)
Exemple #3
0
class PollAsyncServer(SelectAsyncServer):
    """Subclass of SelectAsyncServer that uses 'poll' where available.  This
       is more efficient, but less universal."""
    def __init__(self):
        SelectAsyncServer.__init__(self)
        self.poll = select.poll()
        self.EVENT_MASK = {
            (0, 0): 0,
            (1, 0): select.POLLIN + select.POLLERR,
            (0, 1): select.POLLOUT + select.POLLERR,
            (0, 2): select.POLLOUT + select.POLLERR,
            (1, 1): select.POLLIN + select.POLLOUT + select.POLLERR,
            (1, 2): select.POLLIN + select.POLLOUT + select.POLLERR
        }

    def process(self, timeout):
        if self.bucket is not None and self.bucket <= 0:
            time.sleep(timeout)
            return
        try:
            # (watch out: poll takes a timeout in msec, but select takes a
            #  timeout in sec.)
            events = self.poll.poll(timeout * 1000)
        except select.error, e:
            if e[0] == errno.EINTR:
                return
            else:
                raise e
        if not events:
            return
        if self.bucket is None:
            cap = None
        else:
            cap = floorDiv(self.bucket, len(events))
        #print events, self.connections.keys()
        for fd, mask in events:
            c = self.connections[fd]
            wr, ww, isopen, n = c.process(
                mask & select.POLLIN, mask & select.POLLOUT,
                mask & (select.POLLERR | select.POLLHUP), cap)
            if cap is not None:
                self.bucket -= n
            if not isopen:
                #print "unregister",fd
                self.poll.unregister(fd)
                del self.connections[fd]
                continue
            #print "register",fd
            self.poll.register(fd, self.EVENT_MASK[wr, ww])
Exemple #4
0
        for s in directory.getAllServers():
            d = s.getDigest()
            serversByDir[fp].append(d)
            if not serverMap.has_key(d):
                serverMap[d] = s

        del directory.servers[:] # Save RAM
        if goodDirectories.has_key(fp):
            log.warn("Multiple directories with fingerprint %s; ignoring one from %s",
                     fp, goodDirectories[fp][0])
        goodDirectories[fp] = (src, directory)

    goodVotes = [ v for _,v in goodDirectories.values() ]

    # Next -- what is the result of the vote? (easy cases)
    threshold = floorDiv(len(voters)+1, 2)
    includedClientVersions = commonElements(
        [ d['Recommended-Software']['MixminionClient'] for d in goodVotes ],
        threshold)
    includedServerVersions = commonElements(
        [ d['Recommended-Software']['MixminionServer'] for d in goodVotes ],
        threshold)
    includedRecommended = commonElements(
        [ d['Directory-Info']['Recommended-Servers'] for d in goodVotes ],
        threshold)

    # Hard part -- what servers go in?

    # Identities go in if they have a consistant nickname, and most voters
    # include them.
    identNickname = {}
Exemple #5
0
        for s in directory.getAllServers():
            d = s.getDigest()
            serversByDir[fp].append(d)
            if not serverMap.has_key(d):
                serverMap[d] = s

        del directory.servers[:] # Save RAM
        if goodDirectories.has_key(fp):
            LOG.warn("Multiple directories with fingerprint %s; ignoring one from %s",
                     fp, goodDirectories[fp][0])
        goodDirectories[fp] = (src, directory)

    goodVotes = [ v for _,v in goodDirectories.values() ]

    # Next -- what is the result of the vote? (easy cases)
    threshold = floorDiv(len(voters)+1, 2)
    includedClientVersions = commonElements(
        [ d['Recommended-Software']['MixminionClient'] for d in goodVotes ],
        threshold)
    includedServerVersions = commonElements(
        [ d['Recommended-Software']['MixminionServer'] for d in goodVotes ],
        threshold)
    includedRecommended = commonElements(
        [ d['Directory-Info']['Recommended-Servers'] for d in goodVotes ],
        threshold)

    # Hard part -- what servers go in?

    # Identities go in if they have a consistant nickname, and most voters
    # include them.
    identNickname = {}
Exemple #6
0
class SelectAsyncServer:
    """AsyncServer is the core of a general-purpose asynchronous
       select-based server loop.  AsyncServer maintains lists of
       Connection objects that are waiting for reads and writes
       (respectively), and waits for their underlying sockets to be
       available for the desired operations.
       """
    ## Fields:
    # self.connections: a map from fd to Connection objects.
    # self.state: a map from fd to the latest wantRead,wantWrite tuples
    #    returned by the connection objects' process or getStatus methods.

    # self.bandwidthPerTick: How many bytes of bandwidth do we use per tick,
    #    on average?
    # self.maxBucket: How many bytes of bandwidth are we willing to use in
    #    a single 1-tick burst?
    # self.bucket: How many bytes are we willing to use in the next tick?
    #
    #   (NOTE: if no bandwidth limitation is used, the 3 fields above are
    #   set to None.)

    # How many seconds pass between the 'ticks' at which we increment
    # our bandwidth bucket?
    TICK_INTERVAL = 1.0

    def __init__(self):
        """Create a new AsyncServer with no readers or writers."""
        self._timeout = None
        self.connections = {}
        self.state = {}
        self.bandwidthPerTick = self.bucket = self.maxBucket = None

    def process(self, timeout):
        """If any relevant file descriptors become available within
           'timeout' seconds, call the appropriate methods on their
           connections and return immediately after. Otherwise, wait
           'timeout' seconds and return.

           If we receive an unblocked signal, return immediately.
           """
        readfds = []
        writefds = []
        exfds = []
        for fd, (wr, ww) in self.state.items():
            if wr: readfds.append(fd)
            if ww == 2: exfds.append(fd)
            if ww: writefds.append(fd)

        if not (readfds or writefds or exfds):
            # Windows 'select' doesn't timeout properly when we aren't
            # selecting on any FDs.  This should never happen to us,
            # but we'll check for it anyway.
            time.sleep(timeout)
            return

        if self.bucket is not None and self.bucket <= 0:
            time.sleep(timeout)
            return

        try:
            readfds, writefds, exfds = select.select(readfds, writefds, exfds,
                                                     timeout)
        except select.error, e:
            if e[0] == errno.EINTR:
                return
            else:
                raise e

        writefds += exfds

        active = []

        for fd, c in self.connections.items():
            r = fd in readfds
            w = fd in writefds
            if not (r or w):
                continue
            active.append((c, r, w, fd))

        if not active: return
        if self.bucket is None:
            cap = None
        else:
            cap = floorDiv(self.bucket, len(active))
        for c, r, w, fd in active:
            wr, ww, isopen, nbytes = c.process(r, w, 0, cap)
            if cap is not None:
                self.bucket -= nbytes
            if not isopen:
                del self.connections[fd]
                del self.state[fd]
                continue
            self.state[fd] = (wr, ww)