mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
286 lines
16 KiB
HTML
286 lines
16 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<meta content="text/html; charset=ISO-8859-1"
|
|
http-equiv="content-type">
|
|
<title>DSF Data Model</title>
|
|
</head>
|
|
<body>
|
|
<h2>DSF Data Model</h2>
|
|
<b><span style="font-size: 12pt; font-family: "Times New Roman";">Version
|
|
1.0<br>
|
|
Pawel Piech<br>
|
|
© 2006, Wind River Systems.<span style=""> </span>Release
|
|
under EPL version 1.0.</span></b>
|
|
<h3>Overview</h3>
|
|
<p>The data model aspect of DSF is only partially complete as compared
|
|
to the Concurrency and Services Models. The goals for its design
|
|
are:<br>
|
|
</p>
|
|
<ol>
|
|
<li><span style="font-style: italic;">Separate the structure of the
|
|
data in the services from the model used for presentation in views.</span>
|
|
This seems like a basic model-viewer separation, which is something
|
|
that we theoretically have already. But in reality the current
|
|
platform debug model APIs closely correspond to how the data is
|
|
laid out in debug views, and even with the flexible hierarchy views it
|
|
is
|
|
difficult to provide alternative layouts.</li>
|
|
<li><span style="font-style: italic;">Allow for a modular
|
|
implementation of services that contribute to the data model.</span>
|
|
<br>
|
|
</li>
|
|
<li><span style="font-style: italic;">Perform well with large
|
|
data sets.</span></li>
|
|
<li><span style="font-style: italic;">Make the data model interfaces
|
|
convenient to use by other services as well as by views.</span>
|
|
Some interim designs of DSF data model APIs were very well suited for
|
|
populating views (though asynchronous) content and label provider, but
|
|
were very difficult to use for other purposes, such as by another
|
|
service, or a client that creates a dialog. This led to services
|
|
implementing two sets of interfaces for the same data, which was more
|
|
expensive to develop and maintain.<br>
|
|
</li>
|
|
<li><span style="font-style: italic;">Allow for easy changes to the
|
|
layout of data in views.</span> This is from the point of view of
|
|
a debugger implementer that would like to modify the standard layout of
|
|
debugger data. <br>
|
|
</li>
|
|
<li><span style="font-style: italic;">Allow the users to modify the
|
|
layout of data in views.</span> And this is a logical extension
|
|
of the previous goal.</li>
|
|
</ol>
|
|
<p> </p>
|
|
That's a pretty ambitious set of goals to keep in mind, which partly
|
|
explains why the design is not fully complete yet. In particular,
|
|
the last goal doesn't have any implementation at this point. But
|
|
other than that the, we believe that our current design mostly
|
|
meets the other goals. It remains to be seen how well it will
|
|
hold up
|
|
beyond a prototype implementation.<br>
|
|
<p>The DSF data model is divided into two parts: a non-UI part that
|
|
helps services expose data in a consistent form, and a UI part that
|
|
helps viewers present the data. They are described separately in
|
|
the two sections below.<br>
|
|
</p>
|
|
<h3>Timers Example</h3>
|
|
<p>A <a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/examples/timers/package-summary.html">"timers
|
|
example"</a> is included with the DSF plugins which
|
|
demonstrates the use of data model and view model
|
|
APIs. It is probably much easier to digest this document
|
|
when referring to this example for usage.<br>
|
|
</p>
|
|
<h3>Data Model API (<a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/model/package-summary.html"><span
|
|
style="font-family: monospace;">org.eclipse.dd.dsf.model</span></a>)<br>
|
|
</h3>
|
|
As stated before, the aim of this API is to allow services to provide
|
|
data with just enough common information, so that it can be easily
|
|
presented in the view, but with a simple enough design, so that the
|
|
data can be accessed by non-viewer clients. The type of data in
|
|
services can vary greatly from service to service, some data for
|
|
example:<br>
|
|
<ul>
|
|
<li>service data might be extremely large and thus may only be
|
|
retrieved from a back end process in small chunks, while some service
|
|
data might be always stored locally in the service<br>
|
|
</li>
|
|
<li>data might take a very long time to retrieve, or it could be
|
|
instantaneous<br>
|
|
</li>
|
|
<li>some services might support canceling of the request while it is
|
|
being processed, while other services might not<br>
|
|
</li>
|
|
<li>some data may change very frequently, other data may not change
|
|
at all<br>
|
|
</li>
|
|
</ul>
|
|
The data model API tries to find a common denominator for these
|
|
divergent properties and imposes the following restrictions:<br>
|
|
<ol>
|
|
<li>Each "chunk" of data that comes from a service has a
|
|
corresponding <span style="font-family: monospace;">IDataModelContext </span>(Data Model Context)
|
|
object.<br>
|
|
</li>
|
|
<li>The DM-Context objects are to be generated by the data model services (<span
|
|
style="font-family: monospace;">IDataModelService</span>) with either
|
|
synchronous or asynchronous methods, and taking whatever arguments are
|
|
needed. Put differently, how DM-Contexts are created is up to the
|
|
service.</li>
|
|
<li>The service will provide a method for retrieving each "chunk" of
|
|
model data (<span style="font-family: monospace;">IDataModelData</span>)
|
|
using a method that requires no other arguments besides the DM-Contexts.</li>
|
|
</ol>
|
|
<h4>DM-Context (<span style="font-family: monospace;">IMContext</span>)<br>
|
|
</h4>
|
|
The DM-Contexts are the most
|
|
important part of this design, so they warrant a closer look. The
|
|
interface is listed below:<br>
|
|
<pre> public interface IDataModelContext<V extends IDataModelData> extends IAdaptable {<br> public String getSessionId();<br> public String getServiceFilter();<br> public IDataModelContext[] getParents();<br> }<br></pre>
|
|
First of all the object extends <span style="font-family: monospace;">IAdaptable</span>,
|
|
which allows clients to use these objects as handles that are stored
|
|
with UI components. However the implementation of <span
|
|
style="font-family: monospace;">IDataModelData.getAdapter()</span>
|
|
presents a particular challenge. If the standard platform method
|
|
of retrieving an adapter is used (<span style="font-family: monospace;">PlatformObject.getAdapter()</span>),
|
|
then there can only be one adapter registered for a given DM-Context class,
|
|
which has to be shared by all the DSF sessions that are running
|
|
concurrently. Thus one debugger that implements a <span
|
|
style="font-family: monospace;">IStack.IFrameDMContext</span>, would have to
|
|
have the same instance of<span style="font-family: monospace;">
|
|
IAsynchronousLabelAdapter</span> as another debugger implementation
|
|
that is running at the same time. To overcome this problem, DSF
|
|
provides a method for registering adapters with a session using <span
|
|
style="font-family: monospace;">DsfSession.registerModelAdapter()</span>,
|
|
instead of with the platform (<span style="font-family: monospace;">Platform.getAdapterManager().registerAdapters()</span>).
|
|
<br>
|
|
<p>The <span style="font-family: monospace; font-weight: bold;">getSessionId()</span>
|
|
method serves two purposes. First, it allows the
|
|
<span style="font-family: monospace;">IAdapter.getAdapter()</span>
|
|
implementation to work as described above. Second, it allows clients to
|
|
access the correct dispatch thread (<span
|
|
style="font-family: monospace;">DsfSession.getSession(id).getExecutor()</span>)
|
|
for calling the service that the DM-Context originated from. <br>
|
|
</p>
|
|
<p>The <span style="font-family: monospace; font-weight: bold;">getServiceFilter()</span>
|
|
method is actually included to allow future development. It is
|
|
intended to allow the client to precisely identify the service that
|
|
the DM-Context originated from, without having to examine the exact class type
|
|
of the DM-Context. But this functionality will not really be needed
|
|
until we start writing generic/data-driven clients.<br>
|
|
</p>
|
|
<p>The <span style="font-family: monospace; font-weight: bold;">getParents()</span>
|
|
method allows the DM-Context to be connected together into something that can
|
|
be considered a "model". Of course, most debugger data objects,
|
|
require the context of other objects in order to make sense: stack
|
|
frame is meaningless without the thread, debug symbols belong to a
|
|
module, which belongs to a process, etc. In other words, there is
|
|
some natural hierarchy to the data in debug services which needs to be
|
|
accessible through the data model APIs. This hierarchy may be the
|
|
same hierarchy that is to be shown in some debug views, but it doesn't
|
|
have to be. More importantly, this hierarchy should allow for a
|
|
clean separation of debug services, and for a clear dependency graph
|
|
between these services. </p>
|
|
<h3>View Model API (<a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/ui/model/package-summary.html"><span
|
|
style="font-family: monospace;">org.eclipse.dd.dsf.ui.model</span></a>)<br>
|
|
</h3>
|
|
This is the component which allows the DSF data model to be presented
|
|
in
|
|
the views with different/configurable layouts. It is tightly
|
|
integrated with the recently added (and still provisional)
|
|
flexible-hierarchy viewers in the <span style="font-family: monospace;">org.eclipse.debug.ui</span>
|
|
plugin (see EclipseCon 2006 <a
|
|
href="http://www.eclipsecon.org/2006/Sub.do?id=31">presentation</a>
|
|
for more details). Actually, the platform flexible hierarchy
|
|
framework already provides all the adapter interfaces needed to present
|
|
the DSF data model in the viewers, and it is possible to do
|
|
that. However the flexible hierarchy views were not specifically
|
|
designed for DSF, and there are a few ugly patterns that emerge when
|
|
using them with DSF data model interfaces directly:<br>
|
|
<ul>
|
|
<li>Because of the nature of IAdaptable pattern, the flexible
|
|
hierarchy label and content adapters have to have a single instance
|
|
that works for all views that the objects appear in. This leads
|
|
to a lot of if-else statements, which make the implementation difficult
|
|
to follow.<br>
|
|
</li>
|
|
<li>There is a single adapter for all DSF data model elements in the
|
|
tree (from the same session), so the adapters have even more if-else
|
|
statements to handle the different elements in the viewer.</li>
|
|
<li>Most of DSF adapter work needs to be performed in the dispatch
|
|
thread, so each handler starts with a re-dispatch call.</li>
|
|
<li>In all of this, the logic which determines the hierarchy of
|
|
elements in the viewer is very hard to follow.</li>
|
|
</ul>
|
|
The view model API tries to address these issues in the following way:<br>
|
|
<ol>
|
|
<li>It divides the adapter work for different views in separate <span
|
|
style="font-family: monospace;">ViewModelProvider</span> objects.</li>
|
|
<li>It defines the view layout in an object-oriented manner using the
|
|
<span style="font-family: monospace;">IViewModelLayoutNode</span>
|
|
objects.</li>
|
|
<li>It consolidates the logic of switching to dispatch thread in one
|
|
place, and allows the <span style="font-family: monospace;">ViewModelProvider</span>
|
|
objects to work only in dispatch thread.<br>
|
|
</li>
|
|
</ol>
|
|
<h4><span style="font-family: monospace;">IViewModelLayoutNode</span></h4>
|
|
The core of the logic in this design lies in the implementation of the <span
|
|
style="font-family: monospace;">IViewModelLayoutNode</span> objects.
|
|
This interface is listed below:<br>
|
|
<pre>public interface IViewModelLayoutNode {<br> public IViewModelLayoutNode[] getChildNodes();<br> public void hasElements(IViewModelContext parentVmc, GetDataDone<Boolean> done);<br> public void getElements(final IViewModelContext parentVmc, GetDataDone<IViewModelContext[]> done);<br> public void retrieveLabel(IViewModelContext vmc, final ILabelRequestMonitor result);<br> public boolean hasDeltaFlags(IDataModelEvent e);<br> public void buildDelta(IDataModelEvent e, ViewModelDelta parent, Done done);<br> public void sessionDispose();<br>}<br></pre>
|
|
The <span style="font-family: monospace; font-weight: bold;">getChildNodes()</span>
|
|
method allows these layout nodes to be combined into a tree structure,
|
|
which mimics the layout of elements in the view. What the
|
|
children are depends on the implementation, some may be configurable
|
|
and
|
|
some may be fixed.<br>
|
|
<br>
|
|
The <span style="font-family: monospace; font-weight: bold;">hasElements()</span>
|
|
and <span style="font-family: monospace; font-weight: bold;">getElements()</span>
|
|
methods generate the actual elements that will appear in the
|
|
view. The methods are analogous to the flexible hierarchy API
|
|
methods: <span style="font-family: monospace;">IAsynchronousContentAdapter.isContainer()</span>
|
|
and <span style="font-family: monospace;">IAsynchronousContentAdapter.retrieveChildren()</span>
|
|
and are pretty straightforward to implement. Also <span
|
|
style="font-weight: bold; font-family: monospace;">retrieveLabel()</span>
|
|
is directly analogous to
|
|
IAsynchronousLabelAdapter.retrieveLabel(). <br>
|
|
<br>
|
|
The <span style="font-family: monospace; font-weight: bold;">hasDeltaFlags()</span>
|
|
and <span style="font-weight: bold; font-family: monospace;">buildDelta()</span>
|
|
are used to generate model deltas in response to service events. These
|
|
are discussed in the next section.<br>
|
|
<br>
|
|
Finally, in most cases the elements in the views correspond
|
|
directly to an <span style="font-family: monospace;">IDataModelContext</span>
|
|
(DM-Context) objects of a specific type. In those cases, the <span
|
|
style="font-family: monospace;">DMContextVMLayoutNode</span>
|
|
abstract class implements the common functionality in that pattern.<br>
|
|
<h4>Model deltas</h4>
|
|
The <span style="font-family: monospace;">hasDeltaFlags()</span> and <span
|
|
style="font-family: monospace;">buildDelta()</span> methods are used
|
|
to implement the <span style="font-family: monospace;">IModelProxy </span>adapter,
|
|
and are the most tricky aspect of this design. The difficulty is
|
|
that the flexible hierarchy views require that the <span
|
|
style="font-family: monospace;">IModelProxy </span>translate data
|
|
model-specific events, into generic model deltas that can be
|
|
interpreted by the viewer. The deltas (<span
|
|
style="font-family: monospace;">IModelDelta</span>) are tree
|
|
structures which are supposed to mirror the structure of nodes in the
|
|
tree, and which contain flags that tell the viewer what has changed in
|
|
the view and how.<a href="#Asterix">*</a> This means that if the
|
|
model proxy receives an event for some <span
|
|
style="font-family: monospace;">IDataModelContext</span> (DM-Context) object,
|
|
it needs to know if this object is in the viewer's tree, and what is
|
|
the full path (or paths) that leads to this object. <br>
|
|
<p>The model delta is generated by first calling the top layout node's <span
|
|
style="font-family: monospace;">hasDeltaFlags()</span> with the
|
|
received event, which then can either return <span
|
|
style="font-family: monospace;">true </span>or ask any of its
|
|
children if they have deltas (which in turn returns true or calls its
|
|
children, etc). If a node returns <span
|
|
style="font-family: monospace;">true </span>for <span
|
|
style="font-family: monospace;">hasDeltaFlags()</span>, then the
|
|
asynchronous <span style="font-family: monospace;">buildDelta()</span>
|
|
is called with the event and a parent delta node, to generate the delta
|
|
elements and flags for its node. Once the layout node generates
|
|
its delta objects, it still needs to call its children, which in turn
|
|
add their delta information, and so on.<br>
|
|
</p>
|
|
<p><a name="Asterix"></a>* It's not strictly true that a full path to
|
|
an element always has to be present for model delta's to work. If
|
|
the full path is not present, the viewer will try to find the element
|
|
using an internal map that it keeps of all of the elements it
|
|
knows.
|
|
But since the viewer is lazy loading, it is possible (and likely) that
|
|
the element affected by an event is not even known to the viewer at
|
|
time of the event, and for some delta actions, <span
|
|
style="font-family: monospace;">IModelDelta.SELECT</span> and <span
|
|
style="font-family: monospace;">IModelDelta.EXPAND</span>, this is not
|
|
acceptable.<br>
|
|
</p>
|
|
</body>
|
|
</html>
|