69c95da081c70767fbd6fc8b575ab3ae3826d6f2
[sfa.git] / gacks / gackshandle.py
1 ##
2 # This module implements Gacks handles
3 ##
4
5 import sys
6
7 ##
8 # GacksHandle is an object representing a handle. A handle is the following
9 # tuple:
10 #
11 #    (id, unitstart, unitstop, timestart, timestop)
12 #
13 #    id is a text identifier for the resource, for example "CPU"
14 #
15 #    unitstart and unitstop form an interval [unitstart, unitstop) in unit
16 #    space. For example, [0, 10) could represent 10% of a CPU.
17 #
18 #    timestart and timestop form an interval [timestart, timestop) in time
19 #    space.
20 #
21 #    If unitstop==INFINITY, or timestop==INFINITY, then it is treated as infinity
22 #
23 # The GacksHandle also doubles as an RSPEC
24
25 INFINITY = "inf" #sys.maxint
26
27 class GacksHandle:
28     def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, string=None):
29         self.id = id
30         self.unitStart = unitStart
31         self.unitStop = unitStop
32         self.timeStart = timeStart
33         self.timeStop = timeStop
34         if string:
35             self.load_from_string(string)
36
37     def as_string(self):
38         return str(self.id) + "#" + \
39                str(self.unitStart) + "-" + str(self.unitStop) + "#" + \
40                str(self.timeStart) + "-" + str(self.timeStop)
41
42     def parse_range(self, str):
43         parts = str.split("-")
44         if len(parts)!=2:
45             raise ValueError
46
47         if parts[0] != INFINITY:
48             parts[0] = int(parts[0])
49
50         if parts[1] != INFINITY:
51             parts[1] = int(parts[1])
52
53         return parts
54
55     def load_from_string(self, str):
56         parts = str.split("#")
57
58         self.id = parts[0]
59
60         if len(parts) > 1:
61             (self.unitStart, self.unitStop) = self.parse_range(parts[1])
62
63         if len(parts) > 2:
64             (self.timeStart, self.timeStop) = self.parse_range(parts[2])
65
66     def get_quantity(self):
67         if self.unitStop == INFINITY:
68             return INFINITY
69         else:
70             return self.unitStop-self.unitStart
71
72     def get_duration(self):
73         if self.timeStop == INFINITY:
74             return INFINITY
75         else:
76             return self.timeStop-self.timeStart
77
78     def dump(self):
79         print str(self.id) + ": " + \
80               "units " + str(self.unitStart) + "-" + str(self.unitStop) + \
81               "time " + str(self.timeStart) + "-" + str(self.timeStop)
82
83     def clone(self):
84         return GacksHandle(self.id, self.unitStart, self.unitStop,
85                            self.timeStart, self.timeStop)
86
87     def split(self, unit=None, time=None):
88         h1 = self.clone()
89         h2 = self.clone()
90
91         if unit:
92             h1.unitStop = unit
93             h2.unitStart = unit
94
95         if time:
96             h1.timeStop = time
97             h2.timeStart = time
98
99         return (h1, h2)
100
101
102 class GacksRecord(GacksHandle):
103     def __init__(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, allocatorHRNs=[], consumerHRN=None):
104         GacksHandle.__init__(self, id, unitStart, unitStop, timeStart, timeStop)
105         self.allocatorHRNs = allocatorHRNs
106         self.consumerHRN = consumerHRN
107
108     def dump(self):
109         GacksHandle.dump(self)
110         print "  allocators:", ", ".join(self.allocatorHRNs)
111         print "  consumer:", self.consumerHRN
112
113     def clone(self):
114         return GacksRecord(self.id, self.unitStart, self.unitStop,
115                            self.timeStart, self.timeStop,
116                            self.allocatorHRNs, self.consumerHRN)
117
118     def set_allocator(self, callerHRN, allocatorHRN, which, where):
119         # build up a list of the positions of callerHRN inside of the
120         # allocator list
121
122         positions = []
123         for i, hrn in enumerate(self.allocatorHRNs):
124             if hrn == callerHRN:
125                 positions.append(i)
126
127         pos = positions[which]
128
129         # truncate the allocator list at the appropriate place.
130         # if where==True,
131         #     keep callerHRN in the list and append allocatorHRN after
132         # otherwise,
133         #     remove callerHRN and replace with allocatorHRN
134
135         if where:
136             self.allocatorHRNs = self.allocatorHRNs[:(pos+1)]
137         else:
138             self.allocatorHRNs = self.allocatorHRNs[:pos]
139
140         self.allocatorHRNs.append(allocatorHRN)
141
142     def get_allocators(self):
143         return self.allocatorHRNs[:]
144
145     def set_consumer(self, consumerHRN):
146         self.consumerHRN = consumerHRN
147
148     def get_consumer(self):
149         return self.consumerHRN
150
151