worked on splitting regions and implemented set_allocator / set_consumer
authorScott Baker <bakers@cs.arizona.edu>
Thu, 9 Oct 2008 00:01:11 +0000 (00:01 +0000)
committerScott Baker <bakers@cs.arizona.edu>
Thu, 9 Oct 2008 00:01:11 +0000 (00:01 +0000)
gacks/gackscalendar.py
gacks/gackshandle.py
gacks/gacksrspec.py
gacks/gacksserver.py

index 33d3af9..35cbdc8 100644 (file)
@@ -1,56 +1,92 @@
+from gacksexcep import *
+from gackshandle import *
+
 class GacksCalendar:
     def __init__(self):
         pass
 
-    def query(self, id, unitStart, unitStop, timeStart, timeStop):
+    def query(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY):
         pass
 
     def insert_record(self, item):
         pass
 
+    def query_handles(self, handles):
+        results = []
+        for handle in handles:
+            items = query(handle.id, handle.unitStart, handle.unitStop, handle.timeStart, handle.timeStop)
+            for item in items:
+                if not item.is_in_list(results):
+                    results.append(item)
+        return results
+
+    def update_record(self, item):
+        remove_record(item)
+        insert_record(item)
+
 class GacksListCalendar(GacksCalendar):
     def __init__(self):
         self.items = []
 
-    def test_id(x, y):
+    def test_id(self, x, y):
         if not x:
             return True
         else:
             return (x == y)
 
-    def test_lesser(x, y):
+    def test_lesser(self, x, y):
         if not x:
             return True
-        else if y==INFINITY:
+        elif y==INFINITY:
             return True
         else:
             return (x<y)
 
-    def test_greater_equal(x, y):
+    def test_greater(self, x, y):
         if not x:
             return True
-        else if x==INFINITY:
+        elif x==INFINITY:
             return True
-        else if y==INFINITY:
+        elif y==INFINITY:
             return False
         else:
-            return (x>=y)
+            return (x>y)
 
-    def query(self, id, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY):
+    def query(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY):
         list = []
         for item in self.items:
-            if test_id(id, item.id) and
-               test_lesser(unitStart, item.unitStop) and
-               test_greater_equal(unitStop, item.unitStart) and
-               test_lesser(timeStart, item.timeStop) and
-               test_greater_equal(timeStop, item.timeStart):
-                 list = list + item
+            if self.test_id(id, item.id) and \
+               self.test_lesser(unitStart, item.unitStop) and \
+               self.test_greater(unitStop, item.unitStart) and \
+               self.test_lesser(timeStart, item.timeStop) and \
+               self.test_greater(timeStop, item.timeStart):
+                 list.append(item)
         return list
 
+    def find_record(self, item_to_delete):
+        list = []
+        for item in self.items:
+            if item.is_same_cell(item_to_delete):
+                list.append(item)
+
+        if not list:
+            return None
+
+        if len(list) > 1:
+            raise GacksMultipleRecordCollision(item_to_delete.as_string())
+
+        return list[0]
+
     def insert_record(self, item):
         conflicts = self.query(item.id, item.unitStart, item.unitStop, item.timeStart, item.timeStop)
-        for conflict in conflicts:
-            self.items.remove(conflict)
+        if conflicts:
+            raise GacksConflictingInsert(item.as_string())
 
         self.items.append(item)
 
+    def remove_record(self, item):
+         existing_record = self.find_record(item)
+         if existing_record:
+             self.items.remove(existing_record)
+
+
index 69c95da..9f55128 100644 (file)
@@ -24,6 +24,27 @@ import sys
 
 INFINITY = "inf" #sys.maxint
 
+def is_lesser_equal(x, y):
+    if x==y:
+        return True
+    if x==INFINITY:
+        return False
+    if y==INFINITY:
+        return True
+    return (x<y)
+
+def is_greater_equal(x, y):
+    if x==y:
+        return True
+    if y==INFINITY:
+        return False
+    if x==INFINITY:
+        return True
+    return (x>y)
+
+def interval_contains(start1, stop1, start2, stop2):
+    return is_lesser_equal(start1, start2) and is_greater_equal(stop1, stop2)
+
 class GacksHandle:
     def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, string=None):
         self.id = id
@@ -84,20 +105,131 @@ class GacksHandle:
         return GacksHandle(self.id, self.unitStart, self.unitStop,
                            self.timeStart, self.timeStop)
 
-    def split(self, unit=None, time=None):
+    def split_subset(self, suStart, suStop, stStart, stStop):
+        # an arbitrary rectangle can have a subset removed by slicing it into
+        # five pieces:
+        #    h1 = top
+        #    h2 = left
+        #    h3 = right
+        #    h4 = bottom
+        #    s = subset (middle) that was sliced out
+
         h1 = self.clone()
         h2 = self.clone()
+        h3 = self.clone()
+        h4 = self.clone()
+        s = self.clone()
+
+        if not suStart:
+            suStart = self.unitStart
+        if not suStop:
+            suStop = self.unitStop
+        if not stStart:
+            stStart = self.timeStart
+        if not stStop:
+            stStop = self.timeStop
+
+        h1.unitStop = suStart
+
+        h2.unitStart = suStart
+        h2.unitStop = suStop
+        h2.timeStop = stStart
+
+        h3.unitStart = suStart
+        h3.unitStop = suStop
+        h3.timeStart = stStop
+
+        h4.unitStart = suStop
+
+        s.unitStart = suStart
+        s.unitStop = suStop
+        s.timeStart = stStart
+        s.timeStop = stStop
+
+        results = [s, h1, h2, h3, h4]
+        valid_results = []
+        for result in results:
+            if result.get_quantity()>0 and result.get_duration()>0:
+                valid_results.append(result)
+
+        return valid_results
+
+    def split_subset_old(self, uStart, uStop, tStart, tStop):
+        results = [self]
+        if uStart:
+            results1 = []
+            for i in results:
+                results1.extend(i.split_unit(uStart))
+            results = results1
+        if uStop:
+            results1 = []
+            for i in results:
+                results1.extend(i.split_unit(uStop))
+            results = results1
+        if tStart:
+            results1 = []
+            for i in results:
+                results1.extend(i.split_time(tStart))
+            results = results1
+        if tStop:
+            results1 = []
+            for i in results:
+                results1.extend(i.split_time(tStop))
+            results = results1
+        return results
+
+    def split_unit(self, unit):
+        if is_lesser_equal(unit, self.unitStart) or is_greater_equal(unit, self.unitStop):
+            return [self]
+
+        h2 = self.clone()
+
+        self.unitStop = unit
+        h2.unitStart = unit
+
+        return [self, h2]
+
+    def split_time(self, time):
+        if is_lesser_equal(time, self.timeStart) or is_greater_equal(time, self.timeStop):
+            return [self]
+
+        h2 = self.clone()
 
-        if unit:
-            h1.unitStop = unit
-            h2.unitStart = unit
+        self.timeStop = time
+        h2.timeStart = time
 
-        if time:
-            h1.timeStop = time
-            h2.timeStart = time
+        return [self, h2]
 
-        return (h1, h2)
+    def is_superset(self, handle):
+        if self.id != handle.id:
+            return False
 
+        if not interval_contains(self.timeStart, self.timeStop, handle.timeStart, handle.timeStop):
+            return False
+
+        if not interval_contains(self.unitStart, self.unitStop, self.timeStart, self.timeStop):
+            return False
+
+        return True
+
+    def is_proper_superset(self, handle):
+        return self.is_superset(handle) and (not self.is_same_cell(handle))
+
+    def is_same_cell(self, handle):
+        return (self.id == handle.id) and \
+               (self.unitStart == handle.unitStart) and \
+               (self.unitStop == handle.unitStop) and \
+               (self.timeStart == handle.timeStart) and \
+               (self.timeStop == handle.timeStop)
+
+    def is_same(self, handle):
+        return self.is_same_cell(handle)
+
+    def is_in_list(self, handle_list):
+        for handle in handle_list:
+            if is_same(self, handle):
+                return True
+        return False
 
 class GacksRecord(GacksHandle):
     def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, allocatorHRNs=[], consumerHRN=None):
@@ -140,7 +272,10 @@ class GacksRecord(GacksHandle):
         self.allocatorHRNs.append(allocatorHRN)
 
     def get_allocators(self):
-        return self.allocatorHRNs[:]
+        return self.allocatorHRNs
+
+    def contains_allocator(self, allocatorHRN):
+        return (allocatorHRN in self.allocatorHRNs)
 
     def set_consumer(self, consumerHRN):
         self.consumerHRN = consumerHRN
@@ -148,4 +283,43 @@ class GacksRecord(GacksHandle):
     def get_consumer(self):
         return self.consumerHRN
 
+def strings_to_handles(strings):
 
+    # if given a newline-separated list of strings, then expand it into a list
+    if isinstance(strings, str):
+        expanded_strings = strings.split("\n")
+    elif isinstance(strings, list):
+        expanded_strings = strings
+    else:
+        raise TypeError
+
+    # eliminate any blank strings from the list
+    non_blank_strings = []
+    for string in expanded_strings:
+        if string:
+            non_blank_strings.append(string)
+
+    handles = []
+    for line in non_blank_strings:
+        handle = GacksHandle(string = rspec)
+        handles.append(handle)
+
+    return handles
+
+def handles_to_strings(handles):
+    strings = []
+    for handle in handles:
+        strings.append(handle.as_string())
+    return strings
+
+def rspec_to_handles(rspec):
+    return strings_to_handles(rspec)
+
+def find_handle_in_list(list, uStart, uStop, tStart, tStop):
+    for item in list:
+        if item.unitStart == uStart and \
+           item.unitStop == uStop and \
+           item.timeStart == tStart and \
+           item.timeStop == tStop:
+            return item
+    return None
index 3bd1f0e..f04932b 100644 (file)
@@ -1,2 +1,3 @@
-foo
-bar
+class GacksRspec:
+    def __init__(self):
+        pass
index 730fc26..5c58999 100644 (file)
@@ -16,6 +16,9 @@ from misc import *
 from record import *
 from geniticket import *
 
+from gacksexcep import *
+from gackscalendar import *
+
 ##
 # GacksServer is a GeniServer that serves component interface requests.
 #
@@ -41,10 +44,73 @@ class GacksServer(GeniServer):
         self.server.register_function(self.get_handle)
 
     def get_handle(self, rspec):
-        pass
+        handles = rspec_to_handles(rspec)
+        return handles_to_strings(handles)
+
+    def set_allocator(self, callerGID_str, handle_strs, allocatorGID_str, which, where, reqsig)
+        callerGID = GID(callerGID_str)
+        allocatorGID = GID(allocatorGID_str)
+
+        # TODO: verify callerGID ssl key
+
+        callerGID.verify_chain(self.trusted_cert_list)
+        allocatorGID.verify_chain(self.trusted_cert_list)
+
+        handles = strings_to_handles(handle_strs)
+        for handle in handles:
+            # find the existing records that overlap the handle
+            existing_recs = self.calendar.query_handles([handle])
+
+            if not existing_recs:
+                raise GacksResourceNotFound(hand.as_string())
+
+            # TODO: Merge existing_recs
+
+            for item in existing_recs:
+                if not item.contains_allocator(callerGID->get_name()):
+                    raise CallerNotAllocator(item.as_string())
+                if not item.is_superset(handle):
+                    raise RequestSpansReservations(handle.as_string() + " on " + item.as_string())
+
+            leftovers = []
+            results = []
+            for item in existing_recs:
+                if item.is_proper_supserset(handle):
+                    parts = item.clone().split_subset(handle.unitStart, handle.unitStop, handle.timeStart, handle.timeStop)
+                    results.extend(parts[0])
+                    leftovers.extend(parts[1:])
+                else:
+                    results.extend(item)
+
+            for item in existing_recs:
+                calendar.remove_record(item)
+
+            for item in leftovers:
+                calendar.insert_record(item)
+
+            for item in results:
+                item.set_allocator(callerGID->get_name(), allocatorGID->get_name(), which, where)
+                calendar.insert_record(item)
+
+    def set_consumer(self, callerGID_str, handle_strs, cred_str, reqsig):
+        callerGID = GID(string = callerGID_str)
+        cred = Credential(string = cred_str)
+
+        # TODO: verify callerGID ssl key
+
+        callerGID.verify_chain(self.trusted_cert_list)
+        cred.verify_chain(self.trusted_cert_list)
+
+        handles = strings_to_handles(handle_strs)
+        for handle in handles:
+            existing_recs = self.calendar.query_handles([handle])
+
+            if not existing_recs:
+                raise GacksResourceNotFound(hand.as_string())
 
-    def set_allocator(self, callerGid, Handle, allocatorGid, which, where, reqsig)
-        pass
+            for rec in existing_recs:
+                rec.set_consumer(cred.objectGID.get_name())
+                calendar.update_record(rec)
 
 if __name__ == "__main__":
     global TrustedRoots