From 305a4e0a30e68c0ca8b8b079c35230031dd88b98 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Thu, 9 Oct 2008 00:01:11 +0000 Subject: [PATCH] worked on splitting regions and implemented set_allocator / set_consumer --- gacks/gackscalendar.py | 70 +++++++++++---- gacks/gackshandle.py | 192 +++++++++++++++++++++++++++++++++++++++-- gacks/gacksrspec.py | 5 +- gacks/gacksserver.py | 72 +++++++++++++++- 4 files changed, 308 insertions(+), 31 deletions(-) diff --git a/gacks/gackscalendar.py b/gacks/gackscalendar.py index 33d3af9b..35cbdc83 100644 --- a/gacks/gackscalendar.py +++ b/gacks/gackscalendar.py @@ -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) + 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) + + diff --git a/gacks/gackshandle.py b/gacks/gackshandle.py index 69c95da0..9f551284 100644 --- a/gacks/gackshandle.py +++ b/gacks/gackshandle.py @@ -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 (xy) + +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 diff --git a/gacks/gacksrspec.py b/gacks/gacksrspec.py index 3bd1f0e2..f04932b9 100644 --- a/gacks/gacksrspec.py +++ b/gacks/gacksrspec.py @@ -1,2 +1,3 @@ -foo -bar +class GacksRspec: + def __init__(self): + pass diff --git a/gacks/gacksserver.py b/gacks/gacksserver.py index 730fc26f..5c589991 100644 --- a/gacks/gacksserver.py +++ b/gacks/gacksserver.py @@ -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 -- 2.43.0