use a prefix tree to decide which registry to send the request to. The prefix tree...
authorTony Mack <tmack@cs.princeton.edu>
Wed, 12 Aug 2009 03:18:07 +0000 (03:18 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Wed, 12 Aug 2009 03:18:07 +0000 (03:18 +0000)
sfa/methods/list.py
sfa/util/prefixTree.py [new file with mode: 0755]

index efbf8d3..e9be62e 100644 (file)
@@ -6,8 +6,8 @@ from sfa.util.method import Method
 from sfa.util.parameter import Parameter, Mixed
 from sfa.trust.auth import Auth
 from sfa.util.record import GeniRecord
-
 from sfa.server.registry import Registries
+from sfa.util.prefixTree import prefixTree
 
 class list(Method):
     """
@@ -31,20 +31,36 @@ class list(Method):
         
         self.api.auth.check(cred, 'list')
         records = []
-        try:
-            if not self.api.auth.hierarchy.auth_exists(hrn):
-                raise MissingAuthority(hrn)
-            table = self.api.auth.get_auth_table(hrn)   
-            records = table.list()
-        except MissingAuthority:
-            # is this a foreign authority
-            registries = Registries(self.api)
+
+        # load all know registry names into a prefix tree and attempt to find
+        # the longest matching prefix  
+        registries = Registries(self.api)
+        hrns = registries.keys()
+        tree = prefixTree()
+        tree.load(hrns)
+        registry_hrn = tree.best_match(hrn)
+
+        #if there was no match then this record belongs to an unknow registry
+        if not registry_hrn:
+            raise MissingAuthority(hrn)
+        
+        # if the best match (longest matching hrn) is not the local registry,
+        # forward the request
+        if registry_hrn != self.api.hrn:
             credential = self.api.getCredential()
-            for registry in registries:
-                if hrn.startswith(registry) and registry not in [self.api.hrn]:
-                    record_list = registries[registry].list(credential, hrn)
-                    for record in record_list:
-                        records.append(record.as_dict()) 
+            try:
+                record_list = registries[registry_hrn].list(credential, hrn)
+                records = [record.as_dict() for record in record_list]
+                if records:
                     return records
+            except:
+                pass
+
+        # if we still havnt found the record yet, try the local registry
+        if not self.api.auth.hierarchy.auth_exists(hrn):
+            raise MissingAuthority(hrn)
         
+        table = self.api.auth.get_auth_table(hrn)
+        records = table.list()
+          
         return records
diff --git a/sfa/util/prefixTree.py b/sfa/util/prefixTree.py
new file mode 100755 (executable)
index 0000000..93b0c5c
--- /dev/null
@@ -0,0 +1,97 @@
+class prefixNode:
+
+    def __init__(self, prefix):
+        self.prefix = prefix
+        self.children = []
+    
+
+class prefixTree:
+    
+    def __init__(self):
+        self.root = prefixNode("")
+
+    def insert(self, prefix, node = None):
+        """
+        insert a prefix into the tree
+        """
+        if not node:
+            node = self.root
+
+        parts = prefix.split(".")
+        length = len(parts)
+
+        if length > 1:
+            for i in range(1, length + 1):
+                name = ".".join(parts[:i])
+                if not self.exists(name) and not name == prefix:
+                    self.insert(name)
+         
+        if prefix.startswith(node.prefix):
+            if prefix == node.prefix:
+                pass
+            elif not node.children:
+                node.children.append(prefixNode(prefix))
+            else:
+                inserted  = False
+                for child in node.children:
+                    if prefix.startswith(child.prefix):
+                        self.insert(prefix, child)
+                        inserted = True
+                if not inserted:
+                    node.children.append(prefixNode(prefix)) 
+
+    def load(self, prefix_list):
+        """
+        load a list of prefixes into the tree
+        """
+        for prefix in prefix_list:
+            self.insert(prefix)
+
+    def exists(self, prefix, node = None):
+        """
+        returns true if the specified prefix exists anywhere in the tree,
+        false if it doesnt. 
+        """
+        if not node:
+            node = self.root
+
+        if not prefix.startswith(node.prefix):
+            return False
+        elif node.prefix == prefix:
+            return True
+        elif not node.children:
+            return False
+        else:
+            for child in node.children:
+                if prefix.startswith(child.prefix):
+                    return self.exists(prefix, child)
+
+    def best_match(self, prefix, node = None):
+        """
+        searches the tree and returns the prefix that best matches the 
+        specified prefix  
+        """
+        if not node:
+            node = self.root
+        
+        if prefix.startswith(node.prefix):
+            if not node.children:
+                return node.prefix
+            for child in node.children:
+                if prefix.startswith(child.prefix):
+                    return self.best_match(prefix, child)
+            return node.prefix
+         
+    def dump(self, node = None):
+        """
+        print the tree
+        """
+        if not node:
+            node = self.root
+            print node.prefix
+
+        for child in node.children:
+            print child.prefix, 
+         
+        for child in node.children:
+            self.dump(child)