[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[minion-cvs] Change the rule for which descriptors get included in t...



Update of /home/minion/cvsroot/src/minion/lib/mixminion/directory
In directory moria.mit.edu:/tmp/cvs-serv31412/lib/mixminion/directory

Modified Files:
	ServerList.py 
Log Message:
Change the rule for which descriptors get included in the directory.

The old rule was:  If A and B supercede C over all time, don't include C.

The new rule is: If A and B supercede C _over the interveral of time
      for which the directory is generated_, don't included C.

This way, if the directory gets C (valid Jan-May), and then gets a
more recently published A (valid Jan-Feb) it won't include "C" when
generating a directory for Jan.

(whew!)



Index: ServerList.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/directory/ServerList.py,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- ServerList.py	30 May 2003 07:36:28 -0000	1.27
+++ ServerList.py	2 Jun 2003 20:55:23 -0000	1.28
@@ -98,7 +98,7 @@
             idCache = mixminion.directory.Directory.IDCache(
                 os.path.join(baseDir, "xx_idcache"))
         self.idCache = idCache
-        
+
         self.serverIDDir = os.path.join(self.baseDir, "server-ids")
         self.serverDir = os.path.join(self.baseDir, "servers")
         self.rejectDir = os.path.join(self.baseDir, "reject")
@@ -114,7 +114,7 @@
         createPrivateDir(self.archiveDir)
         createPrivateDir(self.dirArchiveDir)
         self.rescan()
-        
+
     def isServerKnown(self, server):
         """Return true iff the current server descriptor is known.  Raises
            MixError if we have a server descriptor with this name, but
@@ -141,7 +141,7 @@
                     LOG.warn("Server %s already known", nickname)
             except mixminion.directory.MismatchedID:
                 raise MixFatalError("Mismatched ID for server %s", nickname)
-                
+
             LOG.info("Learning identity for new server %s", nickname)
             self.idCache.insertServer(server)
             writePickled(os.path.join(self.serverIDDir,
@@ -225,7 +225,7 @@
             LOG.info("  (%s servers removed)", len(servers))
         finally:
             self._unlock()
-            
+
     def generateDirectory(self,
                           startAt, endAt, extraTime,
                           identityKey,
@@ -233,7 +233,7 @@
                           badServers=()):
         """Generate and sign a new directory, to be effective from <startAt>
            through <endAt>.  It includes all servers that are valid at
-           any time between <startAt> and <endAt>+>extraTime>.  The directory
+           any time between <startAt> and <endAt>+<extraTime>.  The directory
            is signed with <identityKey> """
         try:
             self._lock()
@@ -242,14 +242,43 @@
                 publicationTime = time.time()
             if previousMidnight(startAt) >= previousMidnight(endAt):
                 raise MixError("Validity range does not contain a full day.")
-            included = []
+
+            # First, sort all servers by nickname.
+            includedByNickname =  {}
             for fn, s in self.servers.items():
-                if not s.isValidAtPartOf(startAt, endAt+extraTime):
-                    continue
-                nickname = s.getNickname()
-                validAfter = s['Server']['Valid-After']
-                included.append((nickname, validAfter, fn))
+                nickname = s.getNickname().lower()
+                includedByNickname.setdefault(nickname, []).append((s, fn))
+
+            # Second, find all servers that are valid for part of the period,
+            # and that aren't superceded for the whole period.
+            timeRange = IntervalSet([(previousMidnight(startAt),
+                                      endAt+extraTime)])
 
+            for nickname, ss in includedByNickname.items():
+                # We prefer the most-recently-published descriptor.  If two
+                # are published at the same time, we prefer the one that
+                # expires last.
+                ss = [ (s['Server']['Published'],
+                        s['Server']['Valid-Until'],
+                        s, fn) for s,fn in ss]
+                ss.sort()
+                ss.reverse()
+                uncovered = timeRange.copy()
+                included = []
+                for _, _, s, fn in ss:
+                    valid = s.getIntervalSet()
+                    if (uncovered * valid):
+                        included.append((s, fn))
+                        uncovered -= valid
+                includedByNickname[nickname] = included
+
+            # Now sort the remaining servers by nickname, then by valid-after.
+            included = []
+            for ss in includedByNickname.values():
+                for s,fn in ss:
+                    nickname = s.getNickname()
+                    validAfter = s['Server']['Valid-After']
+                    included.append((nickname, validAfter, fn))
             included.sort()
 
             # FFFF We should probably not do all of this in RAM, but
@@ -317,7 +346,7 @@
             f.close()
         finally:
             self._unlock()
-            
+
     def getDirectoryFilename(self):
         """Return the filename of the most recently generated directory"""
         return os.path.join(self.baseDir, "directory")
@@ -363,7 +392,7 @@
             self.__buildNicknameMap()
         finally:
             self._unlock()
-            
+
     def rescan(self):
         """Reconstruct this ServerList object's internal state."""
         try:
@@ -416,7 +445,7 @@
             self.__buildNicknameMap()
         finally:
             self._unlock()
-            
+
     def __buildNicknameMap(self):
         """Helper method. Regenerate self.serversByNickname from
            self.servers