--- /dev/null
+##
+# This module implements Gacks handles
+##
+
+import sys
+
+##
+# GacksHandle is an object representing a handle. A handle is the following
+# tuple:
+#
+# (id, unitstart, unitstop, timestart, timestop)
+#
+# id is a text identifier for the resource, for example "CPU"
+#
+# unitstart and unitstop form an interval [unitstart, unitstop) in unit
+# space. For example, [0, 10) could represent 10% of a CPU.
+#
+# timestart and timestop form an interval [timestart, timestop) in time
+# space.
+#
+# If unitstop==INFINITY, or timestop==INFINITY, then it is treated as infinity
+#
+# The GacksHandle also doubles as an RSPEC
+
+INFINITY = "inf" #sys.maxint
+
+class GacksHandle:
+ def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, string=None):
+ self.id = id
+ self.unitStart = unitStart
+ self.unitStop = unitStop
+ self.timeStart = timeStart
+ self.timeStop = timeStop
+ if string:
+ self.load_from_string(string)
+
+ def as_string(self):
+ return str(self.id) + "#" + \
+ str(self.unitStart) + "-" + str(self.unitStop) + "#" + \
+ str(self.timeStart) + "-" + str(self.timeStop)
+
+ def parse_range(self, str):
+ parts = str.split("-")
+ if len(parts)!=2:
+ raise ValueError
+
+ if parts[0] != INFINITY:
+ parts[0] = int(parts[0])
+
+ if parts[1] != INFINITY:
+ parts[1] = int(parts[1])
+
+ return parts
+
+ def load_from_string(self, str):
+ parts = str.split("#")
+
+ self.id = parts[0]
+
+ if len(parts) > 1:
+ (self.unitStart, self.unitStop) = self.parse_range(parts[1])
+
+ if len(parts) > 2:
+ (self.timeStart, self.timeStop) = self.parse_range(parts[2])
+
+ def get_quantity(self):
+ if self.unitStop == INFINITY:
+ return INFINITY
+ else:
+ return self.unitStop-self.unitStart
+
+ def get_duration(self):
+ if self.timeStop == INFINITY:
+ return INFINITY
+ else:
+ return self.timeStop-self.timeStart
+
+ def dump(self):
+ print str(self.id) + ": " + \
+ "units " + str(self.unitStart) + "-" + str(self.unitStop) + \
+ "time " + str(self.timeStart) + "-" + str(self.timeStop)
+
+ def clone(self):
+ return GacksHandle(self.id, self.unitStart, self.unitStop,
+ self.timeStart, self.timeStop)
+
+ def split(self, unit=None, time=None):
+ h1 = self.clone()
+ h2 = self.clone()
+
+ if unit:
+ h1.unitStop = unit
+ h2.unitStart = unit
+
+ if time:
+ h1.timeStop = time
+ h2.timeStart = time
+
+ return (h1, h2)
+
+
+class GacksRecord(GacksHandle):
+ def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, allocatorHRNs=[], consumerHRN=None):
+ GacksHandle.__init__(self, id, unitStart, unitStop, timeStart, timeStop)
+ self.allocatorHRNs = allocatorHRNs
+ self.consumerHRN = consumerHRN
+
+ def dump(self):
+ GacksHandle.dump(self)
+ print " allocators:", ", ".join(self.allocatorHRNs)
+ print " consumer:", self.consumerHRN
+
+ def clone(self):
+ return GacksRecord(self.id, self.unitStart, self.unitStop,
+ self.timeStart, self.timeStop,
+ self.allocatorHRNs, self.consumerHRN)
+
+ def set_allocator(self, callerHRN, allocatorHRN, which, where):
+ # build up a list of the positions of callerHRN inside of the
+ # allocator list
+
+ positions = []
+ for i, hrn in enumerate(self.allocatorHRNs):
+ if hrn == callerHRN:
+ positions.append(i)
+
+ pos = positions[which]
+
+ # truncate the allocator list at the appropriate place.
+ # if where==True,
+ # keep callerHRN in the list and append allocatorHRN after
+ # otherwise,
+ # remove callerHRN and replace with allocatorHRN
+
+ if where:
+ self.allocatorHRNs = self.allocatorHRNs[:(pos+1)]
+ else:
+ self.allocatorHRNs = self.allocatorHRNs[:pos]
+
+ self.allocatorHRNs.append(allocatorHRN)
+
+ def get_allocators(self):
+ return self.allocatorHRNs[:]
+
+ def set_consumer(self, consumerHRN):
+ self.consumerHRN = consumerHRN
+
+ def get_consumer(self):
+ return self.consumerHRN
+
+