Source code for otf2.registry


# Generated by OTF2 Template Engine

from builtins import filter
from collections import defaultdict, OrderedDict
from itertools import chain
from functools import wraps
from six import string_types

import _otf2

from . import definitions
from .error import TraceReaderError, TraceWriterError
from .enums import Undefined, GroupType
from .definitions import ClockProperties


def _use_doc_from(doc):
    def decorator(func):
        doc_str = "Returns the {} definition with matching arguments\n".format(doc.__name__)
        if isinstance(doc, definitions._RefDefinition):
            doc_str += "If there is no matching definition, one will be created.\n"
        doc_str += "\n"
        doc_str += doc.__doc__

        func.__doc__ = doc_str
        return func
    return decorator


class _Registry(object):
    def __init__(self, definition_registry, default_type=None):
        self._definition_registry = definition_registry
        self._default_type = default_type
        self._extra_callbacks = {}

    def _callback_gen(self, definition_type=None):
        if definition_type is None:
            definition_type = self._default_type

        def callback(definition_registry, *args):
            definition = definition_type._construct(definition_registry, *args)
            try:
                self._register(definition)
            except KeyError:
                raise TraceReaderError("Duplicate definition: {}".format(definition))
        self._extra_callbacks[definition_type] = callback
        return callback

    def create(self, *args, **kwargs):
        t = kwargs.pop('_type', self._default_type)
        obj = t(self, *args, **kwargs)
        self._register(obj)
        return obj


class _ListRegistry(_Registry):
    def __init__(self, definition_registry, default_type=None):
        self._elements = []
        super(_ListRegistry, self).__init__(definition_registry, default_type)

    def _register(self, obj):
        self._elements.append(obj)

    def __iter__(self):
        """ Do not try to add elements during iteration """
        for elem in self._elements:
            yield elem


class _RefRegistry(_Registry):
    """
    All objects recorded by this registry must have:
    - a ref (id) of type int as first constructor parameter.
      This must not be changed once an event with that ref is written in the trace
    - a name of type str as a second constructor parameter.
      If this is changed, the _elements_by_name must be updated
     """
    def __init__(self, definition_registry, undefined_ref, default_type=None):
        self._elements_by_key = dict()
        self._elements_by_ref = OrderedDict({undefined_ref.value: None})

        self._ref = -1
        self._extra_callbacks = dict()
        super(_RefRegistry, self).__init__(definition_registry, default_type)

    def _next_ref(self):
        self._ref += 1
        return self._ref

    def create(self, *args, **kwargs):
        ref = self._next_ref()
        return super(_RefRegistry, self).create(ref, *args, **kwargs)

    def get(self, *args, **kwargs):
        t = kwargs.pop('_type', self._default_type)
        key = t._new_key(self, *args, **kwargs)
        try:
            return self._elements_by_key[key]
        except KeyError:
            pass
        return self.create(*args, _type=t, **kwargs)

    def _register(self, obj):
        if obj._ref in self._elements_by_ref:
            raise KeyError("Trying to register definition with existing reference.")
        self._elements_by_key[obj._key] = obj
        self._elements_by_ref[obj._ref] = obj
        # Maybe redundant, don't care
        self._ref = max(self._ref, obj._ref)

    def __iter__(self):
        """ Do not try to add elements during iteration """
        for elem in self._elements_by_ref.values():
            # Skip the Undefined entry
            if elem is not None:
                yield elem

    def __getitem__(self, ref):
        return self._elements_by_ref[ref]

    def __contains__(self, item):
        return item._key in self._elements_by_key

    def __len__(self):
        return len(self._elements_by_ref) - 1


class _StringRegistry(_RefRegistry):
    """
    This is a special registry for strings.
    """
    def __init__(self, definition_registry):
        super(_StringRegistry, self).__init__(definition_registry, Undefined.STRING,
                                              definitions.String)

    def __getitem__(self, ref):
        if self._elements_by_ref[ref] is None:
            return None
        return self._elements_by_ref[ref].name

    def get_ref(self, name, writer=None):
        """
        Get a definition object, and write it in the writer if it was not yet created.
        This means, that all previously created definitions should already be written to the writer.
        Returns the ref of the definition for simplicity.
        """
        # Avoid converting unicode stuff to str with Python2
        # The low level interface will handle any basestring correctly
        if not isinstance(name, string_types):
            name = str(name)
        key = definitions.String._new_key(self, name)
        try:
            return self._elements_by_key[key]._ref
        except KeyError:
            pass
        obj = self.create(name, _type=definitions.String)
        if writer:
            obj.write(writer, self._definition_registry)
        return obj._ref


[docs]class DefinitionRegistry(object): """ This class stores all definitions. """ def __init__(self): self.clock_properties = None self._strings = _StringRegistry(self) self._metrics = _RefRegistry(self, Undefined.METRIC) self._io_files = _RefRegistry(self, Undefined.IO_FILE) self._io_paradigms = _RefRegistry(self, Undefined.IO_PARADIGM, definitions.IoParadigm) self._attributes = _RefRegistry(self, Undefined.ATTRIBUTE, definitions.Attribute) self._system_tree_nodes = _RefRegistry(self, Undefined.SYSTEM_TREE_NODE, definitions.SystemTreeNode) self._location_groups = _RefRegistry(self, Undefined.LOCATION_GROUP, definitions.LocationGroup) self._locations = _RefRegistry(self, Undefined.LOCATION, definitions.Location) self._regions = _RefRegistry(self, Undefined.REGION, definitions.Region) self._callsites = _RefRegistry(self, Undefined.CALLSITE, definitions.Callsite) self._callpaths = _RefRegistry(self, Undefined.CALLPATH, definitions.Callpath) self._groups = _RefRegistry(self, Undefined.GROUP, definitions.Group) self._metric_members = _RefRegistry(self, Undefined.METRIC_MEMBER, definitions.MetricMember) self._comms = _RefRegistry(self, Undefined.COMM, definitions.Comm) self._parameters = _RefRegistry(self, Undefined.PARAMETER, definitions.Parameter) self._rma_wins = _RefRegistry(self, Undefined.RMA_WIN, definitions.RmaWin) self._cart_dimensions = _RefRegistry(self, Undefined.CART_DIMENSION, definitions.CartDimension) self._cart_topologies = _RefRegistry(self, Undefined.CART_TOPOLOGY, definitions.CartTopology) self._source_code_locations = _RefRegistry(self, Undefined.SOURCE_CODE_LOCATION, definitions.SourceCodeLocation) self._calling_contexts = _RefRegistry(self, Undefined.CALLING_CONTEXT, definitions.CallingContext) self._interrupt_generators = _RefRegistry(self, Undefined.INTERRUPT_GENERATOR, definitions.InterruptGenerator) self._io_handles = _RefRegistry(self, Undefined.IO_HANDLE, definitions.IoHandle) self._paradigms = _ListRegistry(self, definitions.Paradigm) self._paradigm_properties = _ListRegistry(self, definitions.ParadigmProperty) self._metric_class_recorders = _ListRegistry(self, definitions.MetricClassRecorder) self._system_tree_node_properties = _ListRegistry(self, definitions.SystemTreeNodeProperty) self._system_tree_node_domains = _ListRegistry(self, definitions.SystemTreeNodeDomain) self._location_group_properties = _ListRegistry(self, definitions.LocationGroupProperty) self._location_properties = _ListRegistry(self, definitions.LocationProperty) self._cart_coordinates = _ListRegistry(self, definitions.CartCoordinate) self._calling_context_properties = _ListRegistry(self, definitions.CallingContextProperty) self._io_file_properties = _ListRegistry(self, definitions.IoFileProperty) self._io_pre_created_handle_states = _ListRegistry(self, definitions.IoPreCreatedHandleState) self._callpath_parameters = _ListRegistry(self, definitions.CallpathParameter) def write(self, writer): # Warning, the order here is important. # That is sometimes not trivial: Groups can refer metrics, but metric instances can # refer to groups... So we first write the non-metric groups and then, after metrics, # the metric groups # Note: The split writing metric groups may violate the strong monotonic order of # definition reference # Note: We do not write metric classes and instances separately. The order given by the # reference will always reflect dependencies from instances on classes for thing in chain(self._strings, self._paradigms, self._attributes, self._system_tree_nodes, self._system_tree_node_properties, self._system_tree_node_domains, self._location_groups, self._location_group_properties, self._locations, self._location_properties, self._regions, filter(lambda g: g.group_type != GroupType.METRIC, self._groups), self._metric_members, self._metrics, self._metric_class_recorders, filter(lambda g: g.group_type == GroupType.METRIC, self._groups), self._comms, self._parameters, self._callsites, self._callpaths, self._callpath_parameters, self._rma_wins, self._cart_dimensions, self._cart_topologies, self._cart_coordinates, self._source_code_locations, self._calling_contexts, self._calling_context_properties, self._interrupt_generators, self._paradigm_properties, self._io_paradigms, self._io_files, self._io_file_properties, self._io_handles, self._io_pre_created_handle_states): thing.write(writer, self) # Make sure all location writers are created, otherwise files will be missing for location in self._locations: writer._archive.event_writer_from_location(location) def _set_global_def_reader_callbacks(self, cbs): _otf2.GlobalDefReaderCallbacks_SetClockPropertiesCallback( cbs, self._set_clock_properties) _otf2.GlobalDefReaderCallbacks_SetMetricClassCallback( cbs, self._metrics._callback_gen(definitions.MetricClass)) _otf2.GlobalDefReaderCallbacks_SetMetricInstanceCallback( cbs, self._metrics._callback_gen(definitions.MetricInstance)) _otf2.GlobalDefReaderCallbacks_SetIoRegularFileCallback( cbs, self._io_files._callback_gen(definitions.IoRegularFile)) _otf2.GlobalDefReaderCallbacks_SetIoDirectoryCallback( cbs, self._io_files._callback_gen(definitions.IoDirectory)) _otf2.GlobalDefReaderCallbacks_SetParadigmCallback( cbs, self._paradigms._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetParadigmPropertyCallback( cbs, self._paradigm_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetIoParadigmCallback( cbs, self._io_paradigms._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetStringCallback( cbs, self._strings._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetAttributeCallback( cbs, self._attributes._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetSystemTreeNodeCallback( cbs, self._system_tree_nodes._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetLocationGroupCallback( cbs, self._location_groups._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetLocationCallback( cbs, self._locations._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetRegionCallback( cbs, self._regions._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCallsiteCallback( cbs, self._callsites._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCallpathCallback( cbs, self._callpaths._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetGroupCallback( cbs, self._groups._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetMetricMemberCallback( cbs, self._metric_members._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCommCallback( cbs, self._comms._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetParameterCallback( cbs, self._parameters._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetRmaWinCallback( cbs, self._rma_wins._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetMetricClassRecorderCallback( cbs, self._metric_class_recorders._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetSystemTreeNodePropertyCallback( cbs, self._system_tree_node_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetSystemTreeNodeDomainCallback( cbs, self._system_tree_node_domains._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetLocationGroupPropertyCallback( cbs, self._location_group_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetLocationPropertyCallback( cbs, self._location_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCartDimensionCallback( cbs, self._cart_dimensions._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCartTopologyCallback( cbs, self._cart_topologies._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCartCoordinateCallback( cbs, self._cart_coordinates._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetSourceCodeLocationCallback( cbs, self._source_code_locations._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCallingContextCallback( cbs, self._calling_contexts._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCallingContextPropertyCallback( cbs, self._calling_context_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetInterruptGeneratorCallback( cbs, self._interrupt_generators._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetIoFilePropertyCallback( cbs, self._io_file_properties._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetIoHandleCallback( cbs, self._io_handles._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetIoPreCreatedHandleStateCallback( cbs, self._io_pre_created_handle_states._callback_gen()) _otf2.GlobalDefReaderCallbacks_SetCallpathParameterCallback( cbs, self._callpath_parameters._callback_gen()) def _set_clock_properties(self, _, *args): if self.clock_properties is not None: raise TraceReaderError("Duplicate ClockProperties entry.") self.clock_properties = ClockProperties(None, *args) def _string(self, name): """ This function is used internally to intern String definitions. They are not exposed publicly, instead, plain str objects are used """ assert type(name) is str return self._strings.get(name) def _get(self, def_type, ref): return self._registry_for_type(def_type)[ref] def _registry_for_type(self, def_type): if def_type is str: return self._strings return getattr(self, def_type._registry_name)
[docs] def metric(self, name, *args, **kwargs): """ A convenience method to create a magic metric. Details may change in future. :param str name: The name for the metric, required argument """ return self.metric_class([self.metric_member(name, *args, **kwargs)])
[docs] @_use_doc_from(definitions.MetricClass) def metric_class(self, *args, **kwargs): return self._metrics.get(*args, _type=definitions.MetricClass, **kwargs)
[docs] @_use_doc_from(definitions.MetricInstance) def metric_instance(self, *args, **kwargs): return self._metrics.get(*args, _type=definitions.MetricInstance, **kwargs)
[docs] @_use_doc_from(definitions.IoRegularFile) def io_regular_file(self, *args, **kwargs): return self._io_files.get(*args, _type=definitions.IoRegularFile, **kwargs)
[docs] @_use_doc_from(definitions.IoDirectory) def io_directory(self, *args, **kwargs): return self._io_files.get(*args, _type=definitions.IoDirectory, **kwargs)
[docs] @_use_doc_from(definitions.IoParadigm) def io_paradigm(self, *args, **kwargs): return self._io_paradigms.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Attribute) def attribute(self, *args, **kwargs): return self._attributes.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.SystemTreeNode) def system_tree_node(self, *args, **kwargs): return self._system_tree_nodes.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.LocationGroup) def location_group(self, *args, **kwargs): return self._location_groups.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Location) def location(self, *args, **kwargs): return self._locations.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Region) def region(self, *args, **kwargs): return self._regions.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Callsite) def callsite(self, *args, **kwargs): return self._callsites.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Callpath) def callpath(self, *args, **kwargs): return self._callpaths.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Group) def group(self, *args, **kwargs): return self._groups.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.MetricMember) def metric_member(self, *args, **kwargs): return self._metric_members.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Comm) def comm(self, *args, **kwargs): return self._comms.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Parameter) def parameter(self, *args, **kwargs): return self._parameters.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.RmaWin) def rma_win(self, *args, **kwargs): return self._rma_wins.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.CartDimension) def cart_dimension(self, *args, **kwargs): return self._cart_dimensions.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.CartTopology) def cart_topology(self, *args, **kwargs): return self._cart_topologies.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.SourceCodeLocation) def source_code_location(self, *args, **kwargs): return self._source_code_locations.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.CallingContext) def calling_context(self, *args, **kwargs): return self._calling_contexts.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.InterruptGenerator) def interrupt_generator(self, *args, **kwargs): return self._interrupt_generators.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.IoHandle) def io_handle(self, *args, **kwargs): return self._io_handles.get(*args, **kwargs)
[docs] @_use_doc_from(definitions.Paradigm) def paradigm(self, *args, **kwargs): return self._paradigms.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.ParadigmProperty) def paradigm_property(self, *args, **kwargs): return self._paradigm_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.MetricClassRecorder) def metric_class_recorder(self, *args, **kwargs): return self._metric_class_recorders.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.SystemTreeNodeProperty) def system_tree_node_property(self, *args, **kwargs): return self._system_tree_node_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.SystemTreeNodeDomain) def system_tree_node_domain(self, *args, **kwargs): return self._system_tree_node_domains.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.LocationGroupProperty) def location_group_property(self, *args, **kwargs): return self._location_group_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.LocationProperty) def location_property(self, *args, **kwargs): return self._location_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.CartCoordinate) def cart_coordinate(self, *args, **kwargs): return self._cart_coordinates.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.CallingContextProperty) def calling_context_property(self, *args, **kwargs): return self._calling_context_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.IoFileProperty) def io_file_property(self, *args, **kwargs): return self._io_file_properties.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.IoPreCreatedHandleState) def io_pre_created_handle_state(self, *args, **kwargs): return self._io_pre_created_handle_states.create(*args, **kwargs)
[docs] @_use_doc_from(definitions.CallpathParameter) def callpath_parameter(self, *args, **kwargs): return self._callpath_parameters.create(*args, **kwargs)
@property def strings(self): """ A :py:class:`_Registry` instance representing all String definitons. """ return self._strings @property def metric_classes(self): return filter(lambda m: isinstance(m, definitions.MetricClass), self._metrics) @property def metric_instances(self): return filter(lambda m: isinstance(m, definitions.MetricInstance), self._metrics) @property def io_regular_files(self): return filter(lambda m: isinstance(m, definitions.IoRegularFile), self._io_files) @property def io_directories(self): return filter(lambda m: isinstance(m, definitions.IoDirectory), self._io_files) @property def io_paradigms(self): """ A :py:class:`_Registry` instance representing all IoParadigm definitons. """ return self._io_paradigms @property def attributes(self): """ A :py:class:`_Registry` instance representing all Attribute definitons. """ return self._attributes @property def system_tree_nodes(self): """ A :py:class:`_Registry` instance representing all SystemTreeNode definitons. """ return self._system_tree_nodes @property def location_groups(self): """ A :py:class:`_Registry` instance representing all LocationGroup definitons. """ return self._location_groups @property def locations(self): """ A :py:class:`_Registry` instance representing all Location definitons. """ return self._locations @property def regions(self): """ A :py:class:`_Registry` instance representing all Region definitons. """ return self._regions @property def callsites(self): """ A :py:class:`_Registry` instance representing all Callsite definitons. """ return self._callsites @property def callpaths(self): """ A :py:class:`_Registry` instance representing all Callpath definitons. """ return self._callpaths @property def groups(self): """ A :py:class:`_Registry` instance representing all Group definitons. """ return self._groups @property def metric_members(self): """ A :py:class:`_Registry` instance representing all MetricMember definitons. """ return self._metric_members @property def metrics(self): """ A :py:class:`_Registry` instance representing all Metric definitons. """ return self._metrics @property def comms(self): """ A :py:class:`_Registry` instance representing all Comm definitons. """ return self._comms @property def parameters(self): """ A :py:class:`_Registry` instance representing all Parameter definitons. """ return self._parameters @property def rma_wins(self): """ A :py:class:`_Registry` instance representing all RmaWin definitons. """ return self._rma_wins @property def cart_dimensions(self): """ A :py:class:`_Registry` instance representing all CartDimension definitons. """ return self._cart_dimensions @property def cart_topologies(self): """ A :py:class:`_Registry` instance representing all CartTopology definitons. """ return self._cart_topologies @property def source_code_locations(self): """ A :py:class:`_Registry` instance representing all SourceCodeLocation definitons. """ return self._source_code_locations @property def calling_contexts(self): """ A :py:class:`_Registry` instance representing all CallingContext definitons. """ return self._calling_contexts @property def interrupt_generators(self): """ A :py:class:`_Registry` instance representing all InterruptGenerator definitons. """ return self._interrupt_generators @property def io_files(self): """ A :py:class:`_Registry` instance representing all IoFile definitons. """ return self._io_files @property def io_handles(self): """ A :py:class:`_Registry` instance representing all IoHandle definitons. """ return self._io_handles @property def paradigms(self): """ A :py:class:`_Registry` instance representing all Paradigm definitons. """ return self._paradigms @property def paradigm_properties(self): """ A :py:class:`_Registry` instance representing all ParadigmProperty definitons. """ return self._paradigm_properties @property def metric_class_recorders(self): """ A :py:class:`_Registry` instance representing all MetricClassRecorder definitons. """ return self._metric_class_recorders @property def system_tree_node_properties(self): """ A :py:class:`_Registry` instance representing all SystemTreeNodeProperty definitons. """ return self._system_tree_node_properties @property def system_tree_node_domains(self): """ A :py:class:`_Registry` instance representing all SystemTreeNodeDomain definitons. """ return self._system_tree_node_domains @property def location_group_properties(self): """ A :py:class:`_Registry` instance representing all LocationGroupProperty definitons. """ return self._location_group_properties @property def location_properties(self): """ A :py:class:`_Registry` instance representing all LocationProperty definitons. """ return self._location_properties @property def cart_coordinates(self): """ A :py:class:`_Registry` instance representing all CartCoordinate definitons. """ return self._cart_coordinates @property def calling_context_properties(self): """ A :py:class:`_Registry` instance representing all CallingContextProperty definitons. """ return self._calling_context_properties @property def io_file_properties(self): """ A :py:class:`_Registry` instance representing all IoFileProperty definitons. """ return self._io_file_properties @property def io_pre_created_handle_states(self): """ A :py:class:`_Registry` instance representing all IoPreCreatedHandleState definitons. """ return self._io_pre_created_handle_states @property def callpath_parameters(self): """ A :py:class:`_Registry` instance representing all CallpathParameter definitons. """ return self._callpath_parameters