class JobTracker(object): def __init__(self, name, trackers, cls=Monitor): self.name = name self.count = 0 self.trackers = OrderedDict() for n, getter in trackers: mon = cls("%s: %s" % (name, n)) self.trackers[n] = (mon, getter) def __getattr__(self, attr): if attr in self.trackers: return self.trackers[attr][0] else: raise AttributeError def record(self, agent, job): for mon, getter in self.trackers.itervalues(): mon.observe(getter(agent, job)) self.count += 1 def report(self): for mon, _ in self.trackers.itervalues(): print self._report(mon) def _report(self, tally): s = "mean %s: %.2f (%.2f)" if tally.count(): vars = (tally.name, tally.mean(), math.sqrt(tally.var())) else: vars = (tally.name, 0, 0) return s % vars
class FLA(object): """ FLA Object could be instanced using specific configuration or using static method fromfile() which will decompress given FLA file and parse needed configuration. """ def __init__(self, **kwargs): self.symbols = {} self.folders = OrderedDict() self.directory = kwargs.get('directory') or tempfile.mkdtemp() # Load default configuration default_config = { 'width': 760, 'height': 600, 'name': 'Empty', 'mimetype': 'application/vnd.adobe.xfl', 'xconf': open('%s/PublishSettings.xml' % TPL_PATH).read(), 'xdom': open('%s/DOMDocument.xml' % TPL_PATH).read() } # Update with function arguments default_config.update(kwargs) # Save kwargs as attributes for k, v in default_config.iteritems(): setattr(self, k, v) def __del__(self): # Remove unused temporary folder shutil.rmtree(self.directory) @classmethod def fromfile(klass, filepath): """ Creates a new FLA object parsing given file (full path please) """ _dir = tempfile.mkdtemp() funzip(filepath, _dir) if not os.path.isfile('%s/DOMDocument.xml' % _dir): raise InvalidFLAFile("%s is not a valid Flash CS5 file" % filepath) # Parse XML file xml = open('%s/DOMDocument.xml' % _dir).read() dom = fromstring(xml) xmlns = dom.tag.split('}')[0][1:] if dom.tag.startswith('{') else '' # Parse all library folders fla = FLA(name=os.path.basename(filepath).split('.')[0], directory=_dir) domfolders = dom.find("{%s}folders" % xmlns) if domfolders is not None: for folder in domfolders.getchildren(): path = folder.attrib['name'] uid = md5(path.encode('utf-8')).hexdigest() _fix_insensitive_path(os.path.join(_dir, 'LIBRARY', path)) fla.folders[path] = { 'name': path, 'itemID': "0000%s-0000%s" % (uid[:4], uid[4:8]) } # Parse all library symbols domsymbols = dom.find("{%s}symbols" % xmlns) if domsymbols is not None: childs = domsymbols.getchildren() for symbol in childs: name = symbol.attrib['href'][:-4] try: fla.symbols[name] = Symbol(symbol.attrib, fla.symbols, fla.directory) except IOError: # In some scenarios, there is referenced symbols that # doesn't exists on directory. continue return fla def __str__(self): # Visualization candy return "<FLA '%s' symbols=%d folders=%d>" % \ (self.name, len(self.symbols), len(self.folders)) def _replace_template(self, tpl, values): # Replace into given template (string) some dinamic values for k, v in values.iteritems(): if isinstance(v, unicode): v = v.encode('utf-8') if isinstance(v, str): tpl = tpl.replace("{{ %s }}" % k, v) return tpl def save(self, filepath): """ Read our not_saved record, craft xml, zip and save into given filepath """ self.name = os.path.basename(filepath).split('.')[0] xmlfolders = u'\n'.join(_tag_from_dict('DOMFolderItem', f)\ for f in self.folders.itervalues()) # Sort Items, to avoid some Flash Crashes (!!!) symbols = self.symbols.values() symbols.sort(key=lambda x: x.attrs['href']) xmlsymbols = u'\n'.join(s.to_xml() for s in symbols) xdom = self._replace_template(self.xdom, {'folders_xml': xmlfolders, 'symbols_xml': xmlsymbols}) xconf = self._replace_template(self.xconf, dict((k, getattr(self, k)) for k in dir(self) if k[0] != '_')) open('%s/mimetype' % self.directory, 'w').write(self.mimetype) open('%s/DOMDocument.xml' % self.directory, 'w').write(xdom) open('%s/PublishSettings.xml' % self.directory, 'w').write(xconf) open('%s/%s.xfl' % (self.directory, self.name), 'w').write('PROXY-CS5') # Make FLA file (Just a regular zip file) fzip(filepath, self.directory) @classmethod def from_symbols(klass, symbols, fladirectory=None, flainstance=None): paths = lambda n: [] \ if n == os.path.dirname(n) else paths(os.path.dirname(n)) + [n] newfla = flainstance or FLA(name='dynamic') newfla.symbols = symbols if fladirectory: newfla.directory = fladirectory for ohref, symbol in symbols.items(): href = os.path.dirname(symbol.attrs['href']) # Fill up folders automatically, based on symbols for path in paths(href): uid = md5(path.encode('utf-8')).hexdigest() newfla.folders[path] = { 'name': path, 'itemID': "0000%s-0000%s" % (uid[:4], uid[4:8]) } dest_file = "%s/LIBRARY/%s.xml" % (newfla.directory, ohref) dest_dir = os.path.dirname(dest_file) # Create directory if it does not exists if not os.path.isdir(dest_dir): os.makedirs(dest_dir) if os.path.dirname(symbol.xml) != dest_dir: shutil.copy(symbol.xml, dest_dir) newfla.symbols[ohref].xml = dest_file return newfla def __add__(self, other): """ Implement + operator to merge FLA files. This will be return a new copy of the object. """ if not isinstance(other, FLA): raise TypeError("You cannot add other than FLA object") symbols = dict(self.symbols, **other.symbols) return FLA.from_symbols(symbols) def append(self, other): """ Append symbols from other FLA files. This will not return a new copy of the object. """ if not isinstance(other, FLA): raise TypeError("You cannot add other than FLA object") symbols = dict(self.symbols, **other.symbols) return FLA.from_symbols(symbols, self.directory, self)
class GridModel(Model): "Basic model of the Grid" def __init__(self, size=100, load=1.0, regions=(4,4), coords=(100,100), run_times=6, arrival_dist = dists.expon, resource_sizes = dists.gamma(100, 10), job_sizes = dists.gamma(20, 4), job_durations = dists.gamma(100, 10), service_means = dists.normal(0.1), service_dist = dists.shaped_gamma(0.1), latency_means = dists.normal(0.1), latency_dist = dists.shaped_gamma(0.1), regional_latency = dists.gamma(0.2, 0.1), global_latency = dists.gamma(0.4, 0.1) ): # calculated results self.runtime = run_times * job_durations.mean total_capacity = size * resource_sizes.mean; max_jobs = total_capacity / float(job_sizes.mean); arrival_mean = job_durations.mean / float(max_jobs); self.inter_arrival_time = arrival_dist(arrival_mean / load) self.job_sizes = job_sizes self.job_durations = job_durations # store for stats self.size = size self.load = load # generate network self.graph = network.Network( coords, regions, latency_means, regional_latency, global_latency, latency_dist) # generate nodes, but no topology network.generate_nodes(self.graph, size) self.service_dist = service_dist self.service_means = service_means for node in self.graph.nodes_iter(): node.server = Server(node, service_dist(service_means())) node.resource = GridResource(node, int(resource_sizes())) self.mons = OrderedDict() self.mons["grid_util"] = Monitor("grid_util") self.mons["server_util"] = Monitor("server_util") self.mons["server_queue"] = Monitor("server_queue") @property def nodes(self): return self.graph.nodes() def random_node(self): return random.choice(self.nodes) def random_region_node(self, region): return random.choice([n for n in self.graph.nodes_iter() if n.region == region]) def new_job(self): return Job(self.job_sizes(), self.job_durations()) def collect_stats(self, tlast): self.mons["grid_util"].observe(stats.current_grid_util(self, tlast)) self.mons["server_util"].observe(stats.current_server_util(self, tlast)) self.mons["server_queue"].observe(stats.current_server_queue(self, tlast)) def get_series_mons(self): for mon in self.mons.itervalues(): yield mon