+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)
+
+
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
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):
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
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
-foo
-bar
+class GacksRspec:
+ def __init__(self):
+ pass
from record import *
from geniticket import *
+from gacksexcep import *
+from gackscalendar import *
+
##
# GacksServer is a GeniServer that serves component interface requests.
#
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