Interface TraceObject

All Superinterfaces:
TraceUniqueObject
All Known Implementing Classes:
DBTraceObject

public interface TraceObject extends TraceUniqueObject
A record of a target object in a debugger

This object supports querying for and obtaining the interfaces which constitute what the object is and define how the client may interact with it. The object may also have children, e.g., a process should likely have threads.

This interface is the focal point of the "debug target model." A debugger may present itself as an arbitrary directory of "target objects." The root object is typically the debugger's session, and one its attributes is a collection for its attached targets. These objects, including the root object, may implement any number of interfaces extending TraceObjectInterface. These interfaces comprise the type and behavior of the object. An object's children comprise its elements (for collection-like objects) and attributes. Every object in the directory has a path. Each element ("key") in the path identifies an index (if the child is an element) or a name (if the child is an attribute). It is the implementation's responsibility to ensure each object's path correctly identifies that same object in the model directory. The root has the empty path. Every object must have a unique path; thus, every object must have a unique key among its sibling.

The objects are arranged in a directory with links permitted. Links come in the form of object-valued attributes or elements where the path does not match the object value's path. Thus, the overall structure remains a tree, but by resolving links, the model may be treated as a directed graph, likely containing cycles.

The implementation must guarantee that distinct TraceObjects from the same model do not share the same path. That is, checking for object identity is sufficient to check that two variables refer to the same object.

Various conventions govern where the client/user should search to obtain a given interface in the context of some target object. For example, if the user is interacting with a thread, and wishes to access that thread's memory, it needs to follow a given search order to find the appropriate target object(s), if they exist, implementing the desired interface. See TraceObjectSchema.searchForSuitable(TraceObjectSchema, KeyPath) for details. In summary, the order is:

  1. The object itself: Test if the context target object supports the desired interface. If it does, take it.
  2. Aggregate objects: If the object is marked with TraceAggregate, collect all attributes supporting the desired interface. If there are any, take them. This step is applied recursively if any child attribute is also marked with TraceAggregate.
  3. Ancestry: Apply these same steps to the object's (canonical) parent, recursively.

For some situations, exactly one object is required. In that case, take the first obtained by applying the above rules. In other situations, multiple objects may be acceptable. Again, apply the rules until a sufficient collection of objects is obtained. If an object is in conflict with another, take the first encountered. This situation may be appropriate if, e.g., multiple target memories present disjoint regions. There should not be conflicts among sibling. If there are, then either the model or the query is not sound. The order siblings considered should not matter.

This relatively free structure and corresponding conventions allow for debuggers to present a model which closely reflects the structure of its session. For example, the following structure may be presented by a user-space debugger for a desktop operating system:

Note that this interface does not provide target-related operations, but only a means of modifying the database. The target connector, if this trace is still "live," should have a handle to this same trace and so can update the records as events occur in the debugger session and keep the target state up to date. Commands for manipulating the target and/or session itself are provided by that connector.

  • Field Details

  • Method Details

    • getTrace

      Trace getTrace()
      Get the trace containing this object
      Returns:
      the trace
    • getKey

      long getKey()
      Get the database key for this object
      Returns:
      the key
    • getRoot

      TraceObject getRoot()
      Get the root of the tree containing this object
      Returns:
      the root
    • getCanonicalPath

      KeyPath getCanonicalPath()
      Get the canonical path of this object
      Returns:
      the path
    • getLife

      Lifespan.LifeSet getLife()
      Get all ranges of this object's life

      Essentially, this is the union of the lifespans of all canonical parent values

      Returns:
      the range set for snaps at which this object is considered "inserted."
    • isAlive

      boolean isAlive(long snap)
      Check if the object is alive at the given snap

      This is preferable to getLife(), when we only need to check one snap

      Parameters:
      snap - the snap
      Returns:
      true if alive, false if not
    • isAlive

      boolean isAlive(Lifespan span)
      Check if the object is alive at all in the given span
      Parameters:
      span - the span
      Returns:
      true if alive, false if not
    • insert

      Inserts this object at its canonical path for the given lifespan

      Any ancestor which does not exist is created. Values' lifespans are added or expanded to contain the given lifespan. Only the canonical path is considered when looking for existing ancestry.

      Parameters:
      lifespan - the minimum lifespan of edges from the root to this object
      resolution - the rule for handling duplicate keys when setting values.
      Returns:
      the value path from root to the newly inserted object
    • remove

      void remove(Lifespan span)
      Remove this object from its canonical path for the given lifespan

      Truncate the lifespans of this object's canonical parent value by the given span. If the parent value's lifespan is contained in the given span, the parent value will be deleted.

      Parameters:
      span - the span during which this object should be removed
    • removeTree

      void removeTree(Lifespan span)
      Remove this object and its successors from their canonical paths for the given span

      Truncate the lifespans of this object's parent values and all canonical values succeeding this object. If a truncated value's lifespan is contained in the given span, the value will be deleted.

      Parameters:
      span - the span during which this object and its canonical successors should be removed
    • getCanonicalParent

      TraceObjectValue getCanonicalParent(long snap)
      Get the parent value along this object's canonical path for a given snapshot

      To be the canonical parent value at a given snapshot, three things must be true: 1) The parent object must have this object's path with the final key removed. 2) The parent value's entry key must be equal to the final key of this object's path. 3) The value's lifespan must contain the given snapshot. If no value satisfies these, null is returned, and the object and its subtree are said to be "detached" at the given snapshot.

      Parameters:
      snap - the snapshot key
      Returns:
      the canonical parent value, or null
    • getCanonicalParents

      Stream<? extends TraceObjectValue> getCanonicalParents(Lifespan lifespan)
      Get the parent values along this object's canonical path for a given lifespan

      To be a canonical parent in a given lifespan, three things must be true: 1) The parent object must have this object's path with the final key removed. 2) The parent value's entry key must be equal to the final key of this object's path. 3) The value's lifespan must intersect the given lifespan. If the result is empty, the object and its subtree are said to be "detatched" during the given lifespan.

      Parameters:
      lifespan - the lifespan to consider
      Returns:
      the stream of canonical parents
    • isRoot

      boolean isRoot()
      Check if this object is the root
      Returns:
      true if root
    • getAllPaths

      Stream<? extends TraceObjectValPath> getAllPaths(Lifespan span)
      Get all paths actually leading to this object, from the root, within the given span

      Aliased keys are excluded.

      Parameters:
      span - the span which every value entry on each path must intersect
      Returns:
      the paths
    • getInterfaces

      Collection<Class<? extends TraceObjectInterface>> getInterfaces()
      Get all the interface classes provided by this object, according to the schema
      Returns:
      the collection of interface classes
    • queryInterface

      <I extends TraceObjectInterface> I queryInterface(Class<I> iface)
      Request the specified interface provided by this object
      Type Parameters:
      I - the type of the interface
      Parameters:
      iface - the class of the interface
      Returns:
      the interface, or null if not provided
    • getParents

      Collection<? extends TraceObjectValue> getParents(Lifespan span)
      Get all values intersecting the given span and whose child is this object

      Aliased keys are excluded.

      Parameters:
      span - the span
      Returns:
      the parent values
    • getValues

      Collection<? extends TraceObjectValue> getValues(Lifespan span)
      Get all values (elements and attributes) of this object intersecting the given span

      Aliased keys are excluded.

      Parameters:
      span - the span
      Returns:
      the values
    • getValues

      Collection<? extends TraceObjectValue> getValues(Lifespan span, String key)
      Get values with the given key intersecting the given span

      If the key is an alias, the target key's values are retrieved instead.

      Parameters:
      span - the span
      key - the key
      Returns:
      the collection of values
    • getOrderedValues

      Stream<? extends TraceObjectValue> getOrderedValues(Lifespan span, String key, boolean forward)
      Get values with the given key intersecting the given span ordered by time

      If the key is an alias, the target key's values are retrieved instead.

      Parameters:
      span - the span
      key - the key
      forward - true to order from least- to most-recent, false for most- to least-recent
      Returns:
      the stream of values
    • getElements

      Collection<? extends TraceObjectValue> getElements(Lifespan span)
      Get all elements of this object intersecting the given span
      Parameters:
      span - the span
      Returns:
      the element values
    • getAttributes

      Collection<? extends TraceObjectValue> getAttributes(Lifespan span)
      Get all attributes of this object intersecting the given span

      Aliased keys are excluded.

      Parameters:
      span - the span
      Returns:
      the attribute values
    • getValue

      TraceObjectValue getValue(long snap, String key)
      Get the value for the given snap and key

      If the key is an alias, the target key's value is retrieved instead.

      Parameters:
      snap - the snap
      key - the key
      Returns:
      the value entry
    • getElement

      TraceObjectValue getElement(long snap, String index)
      Get the value for the given snap and element index

      This is equivalent to getValue(long, String), but converts index to a key, i.e., adds brackets.

      Parameters:
      snap - the snap
      index - the index
      Returns:
      the value entry
    • getElement

      TraceObjectValue getElement(long snap, long index)
      Get the value for the given snap and element index

      This is equivalent to getElement(long, String), but converts index to a string in decimal.

      Parameters:
      snap - the snap
      index - the index
      Returns:
      the value entry
    • getAttribute

      TraceObjectValue getAttribute(long snap, String name)
      Get the value for the given snap and attribute name

      This is equivalent to getValue(long, String), except it validates that name is not an index.

      Parameters:
      snap - the snap
      name - the name
      Returns:
      the value entry
    • getAncestorsRoot

      Stream<? extends TraceObjectValPath> getAncestorsRoot(Lifespan span, PathFilter rootFilter)
      Stream all ancestor values of this object matching the given filter, intersecting the given span

      Aliased keys are excluded. The filter should be formulated to use the aliases' target attributes.

      Parameters:
      span - a span which values along the path must intersect
      rootFilter - the filter for matching path keys, relative to the root
      Returns:
      the stream of matching paths to values
    • getAncestors

      Stream<? extends TraceObjectValPath> getAncestors(Lifespan span, PathFilter relativeFilter)
      Stream all ancestor values of this object matching the given filter, intersecting the given span

      Aliased keys are excluded. The filter should be formulated to use the aliases' target attributes.

      Parameters:
      span - a span which values along the path must intersect
      relativeFilter - the filter for matching path keys, relative to this object
      Returns:
      the stream of matching paths to values
    • getSuccessors

      Stream<? extends TraceObjectValPath> getSuccessors(Lifespan span, PathFilter relativeFilter)
      Stream all successor values of this object matching the given filter, intersecting the given span

      Aliased keys are excluded. The filter should be formulated to use the aliases' target attributes.

      Parameters:
      span - a span which values along the path must intersect
      relativeFilter - the filter for matching path keys, relative to this object
      Returns:
      the stream of matching paths to values
    • getOrderedSuccessors

      Stream<? extends TraceObjectValPath> getOrderedSuccessors(Lifespan span, KeyPath relativePath, boolean forward)
      Stream all successor values of this object at the given relative path, intersecting the given span, ordered by time.

      Aliased keys are excluded. The filter should be formulated to use the aliases' target attributes.

      Parameters:
      span - the span which values along the path must intersect
      relativePath - the path relative to this object
      forward - true to order from least- to most-recent, false for most- to least-recent
      Returns:
      the stream of value paths
    • getCanonicalSuccessors

      Stream<? extends TraceObjectValPath> getCanonicalSuccessors(PathFilter relativeFilter)
      Stream all canonical successor values of this object matching the given filter

      If an object has a disjoint life, i.e., multiple canonical parents, then only the least-recent of those is traversed. Aliased keys are excluded; those can't be canonical anyway. By definition, a primitive value is not canonical, even if it is the final value in the path.

      Parameters:
      relativeFilter - filter on the relative path from this object to desired successors
      Returns:
      the stream of value paths
    • setValue

      TraceObjectValue setValue(Lifespan lifespan, String key, Object value, TraceObject.ConflictResolution resolution)
      Set a value for the given lifespan

      If the key is an alias, the target key's value is set instead.

      Parameters:
      lifespan - the lifespan of the value
      key - the key to set
      value - the new value
      resolution - determines how to resolve duplicate keys with intersecting lifespans
      Returns:
      the created value entry
      Throws:
      DuplicateKeyException - if there are denied duplicate keys
    • setValue

      TraceObjectValue setValue(Lifespan lifespan, String key, Object value)
      Set a value for the given lifespan, truncating existing entries

      Setting a value of null effectively deletes the value for the given lifespan and returns null. Values of the same key intersecting the given lifespan or either truncated or deleted. If the key is an alias, the target key's value is set instead.

      Parameters:
      lifespan - the lifespan of the value
      key - the key to set
      value - the new value
      Returns:
      the created value entry, or null
    • setAttribute

      TraceObjectValue setAttribute(Lifespan lifespan, String name, Object value)
      Set an attribute for the given lifespan

      This is equivalent to setValue(Lifespan, String, Object), except it verifies the key is an attribute name.

      Parameters:
      lifespan - the lifespan of the attribute
      name - the name to set
      value - the new value
      Returns:
      the created value entry
    • setElement

      TraceObjectValue setElement(Lifespan lifespan, String index, Object value)
      Set an element for the given lifespan

      This is equivalent to setValue(Lifespan, String, Object), except it converts the index to a key, i.e., add brackets.

      Parameters:
      lifespan - the lifespan of the element
      index - the index to set
      value - the new value
      Returns:
      the created value entry
    • setElement

      TraceObjectValue setElement(Lifespan lifespan, long index, Object value)
      Set an element for the given lifespan
      Parameters:
      lifespan - the lifespan of the element
      index - the index to set
      value - the new value
      Returns:
      the created value entry
    • getSchema

      TraceObjectSchema getSchema()
      Get the schema for this object
      Returns:
      the schema
    • findAncestorsInterface

      Stream<? extends TraceObjectValPath> findAncestorsInterface(Lifespan span, Class<? extends TraceObjectInterface> iface)
      Search for ancestors having the given interface
      Parameters:
      span - the span which the found objects must intersect
      iface - the interface class
      Returns:
      the stream of found paths to values
    • queryAncestorsInterface

      <I extends TraceObjectInterface> Stream<I> queryAncestorsInterface(Lifespan span, Class<I> iface)
      Search for ancestors having the given interface and retrieve those interfaces
      Type Parameters:
      I - the interface type
      Parameters:
      span - the span which the found objects must intersect
      iface - the interface class
      Returns:
      the stream of interfaces
    • findCanonicalAncestorsInterface

      Stream<? extends TraceObject> findCanonicalAncestorsInterface(Class<? extends TraceObjectInterface> iface)
      Search for ancestors on the canonical path having the given interface

      The object may not yet be inserted at its canonical path.

      Parameters:
      iface - the interface class
      Returns:
      the stream of objects
    • queryCanonicalAncestorsInterface

      <I extends TraceObjectInterface> Stream<I> queryCanonicalAncestorsInterface(Class<I> iface)
      Search for ancestors on the canonical path having the given interface and retrieve those interfaces

      The object may not yet be inserted at its canonical path.

      Type Parameters:
      I - the interface type
      Parameters:
      iface - the interface class
      Returns:
      the stream of interfaces
    • findSuccessorsInterface

      Stream<? extends TraceObjectValPath> findSuccessorsInterface(Lifespan span, Class<? extends TraceObjectInterface> iface, boolean requireCanonical)
      Search for successors having the given interface
      Parameters:
      span - the span which the found paths must intersect
      iface - the interface class
      requireCanonical - if the objects must be found within their canonical container
      Returns:
      the stream of found paths to values
    • querySuccessorsInterface

      <I extends TraceObjectInterface> Stream<I> querySuccessorsInterface(Lifespan span, Class<I> iface, boolean requireCanonical)
      Search for successors having the given interface and retrieve those interfaces
      Type Parameters:
      I - the interface type
      Parameters:
      span - the span which the found objects must intersect
      iface - the interface class
      requireCanonical - if the objects must be found within their canonical container
      Returns:
      the stream of interfaces
    • delete

      void delete()
      Delete this object along with parent and child value entries referring to it

      Warning: This will remove the object from the manager entirely, not just over a given span. In general, this is used for cleaning and maintenance. Consider remove(Lifespan) or TraceObjectValue.delete() instead. Note, this does not delete the child objects or any successors. It is not recommended to invoke this on the root object, since it cannot be replaced without first clearing the manager.

    • isDeleted

      boolean isDeleted()
      Check if this object has been deleted
      Specified by:
      isDeleted in interface TraceUniqueObject
      Returns:
      true if the object has been deleted
    • isMethod

      default boolean isMethod(long snap)
      Check if the child represents a method at the given snap
      Parameters:
      snap - the snap
      Returns:
      true if a method
    • findSuitableInterface

      default TraceObject findSuitableInterface(Class<? extends TraceObjectInterface> iface)
      Search for a suitable object having the given interface

      This operates by examining the schema for a unique suitable path, without regard to lifespans. If needed, the caller should inspect the object's life.

      Parameters:
      iface - the interface
      Returns:
      the suitable object, or null if not found
    • findSuitableContainerInterface

      default TraceObject findSuitableContainerInterface(Class<? extends TraceObjectInterface> iface)
      Search for a suitable canonical container of the given interface
      Parameters:
      iface - the interface
      Returns:
      the container, or null if not found
    • findSuitableSchema

      default TraceObject findSuitableSchema(TraceObjectSchema schema)
      Search for a suitable object having the given schema

      This operates by examining the schema for a unique suitable path, without regard to lifespans. If needed, the caller should inspect the object's life.

      Parameters:
      schema - the schema
      Returns:
      the suitable object, or null if not found
    • findRegisterContainer

      default TraceObject findRegisterContainer(int frameLevel)
      Search for a suitable register container
      Parameters:
      frameLevel - the frame level. Must be 0 if not applicable
      Returns:
      the register container, or null
      See Also:
    • getExecutionState

      default TraceExecutionState getExecutionState(long snap)
      Get the execution state, if applicable, of this object

      This searches for the conventional stateful object defining this object's execution state. If such an object does not exist, null is returned. If one does exist, then its execution state at the given snap is returned. If that state is null, it is assumed TraceExecutionState.INACTIVE.

      Parameters:
      snap - the snap
      Returns:
      the state or null