mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
363 lines
18 KiB
HTML
363 lines
18 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 Services Model</title>
|
|
</head>
|
|
<body>
|
|
<h2>DSF Services Model</h2>
|
|
<br>
|
|
<b><span style="font-size: 12pt; font-family: "Times New Roman";">Version
|
|
1.0<br>
|
|
Pawel Piech <br>
|
|
</span></b><b><span
|
|
style="font-size: 12pt; font-family: "Times New Roman";">© 2006,
|
|
Wind River Systems.<span style=""> </span>Release under EPL
|
|
version 1.0.</span></b><b><span
|
|
style="font-size: 12pt; font-family: "Times New Roman";"><br style="">
|
|
</span></b>
|
|
<p>Debugger Services Framework (DSF) is primarily a service framework
|
|
defining rules for how
|
|
services should be registered, discovered, organized into functional
|
|
groups, communicated with, and started/ended. These rules help to
|
|
organize the services into a functional system that efficiently
|
|
abstracts various debugger back end capabilities. </p>
|
|
<p>DSF services build on top of the OSGI services framework, so
|
|
it's important to understand OSGI services before looking at DSF
|
|
itself. For an overview of OSGI including services, see the <a
|
|
href="http://eclipsezilla.eclipsecon.org/php/attachment.php?bugid=185">presentation
|
|
on OSGI from EclipseCon 2006</a>. For detailed information, see
|
|
OSGI javadocs, primarily: <a style="font-family: monospace;"
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/package-summary.html">org.osgi.framework</a><a
|
|
style="font-family: monospace;"
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/ServiceRegistration.html">ServiceRegistration</a>,
|
|
<a
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/BundleContext.html"><span
|
|
style="font-family: monospace;">BundleContext</span></a>, <a
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/BundleContext.html"><span
|
|
style="font-family: monospace;">ServiceReference</span></a>, <a
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/Filter.html"><span
|
|
style="font-family: monospace;">Filter</span></a>, and <a
|
|
style="font-family: monospace;"
|
|
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/util/tracker/ServiceTracker.html">ServiceTracker</a>.
|
|
</p>
|
|
<h3>Services<br>
|
|
</h3>
|
|
In OSGI any class can be registered as a service. In DSF,
|
|
Services must implement the <a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/IDsfService.html"><span
|
|
style="font-family: monospace;">IDsfService</span></a>
|
|
interface, which requires that the service
|
|
provide:<br>
|
|
<ol>
|
|
<li>Access to the <span style="font-family: monospace;">DsfExecutor </span>that
|
|
has to be used to access service methods.</li>
|
|
<li>Full list of properties used to uniquely identify the service in
|
|
OSGI.</li>
|
|
<li>Startup and shutdown methods.</li>
|
|
</ol>
|
|
For the first two items, a service must use the data it received from
|
|
its constructor. For the third item, a service must register and
|
|
unregister itself with OSGI. But beyond that, this is all that
|
|
services have in common, everything else is up to the specific service
|
|
interface.<br>
|
|
<h3>Sessions (<a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/DsfSession.html"><span
|
|
style="font-family: monospace;">org.eclipse.dd.dsf.service.DsfSession</span></a>)<br>
|
|
</h3>
|
|
DSF services are organized into logical groups, called
|
|
sessions. Sessions are only necessary because we want multiple
|
|
instances of systems built with DSF services to run at the same
|
|
time This is because there is only a single OSGI service
|
|
registry, so if multiple services are registered with a given class
|
|
name, OSGI will not be able to distinguish between the two based on the
|
|
class name alone. So there is an additional property which is
|
|
used by every DSF service when registering with OSGI, <span
|
|
style="font-family: monospace;">IDsfService.PROP_SESSION_ID</span>.
|
|
<br>
|
|
<p>A <span style="font-family: monospace;">Session</span> object
|
|
(TODO: link javadoc) has the following data associated with it:<br>
|
|
</p>
|
|
<ul>
|
|
<li><span style="text-decoration: underline;">Session ID</span> - A <span
|
|
style="font-family: monospace;">String</span> object that is unique
|
|
among all other sessions. Its ID is used by services as the <span
|
|
style="font-family: monospace;">IDsfService.PROP_SESSION_ID</span>
|
|
property, and it is used by the client to obtain the <span
|
|
style="font-family: monospace;">Session</span> object instance.</li>
|
|
<li><span style="font-family: monospace; text-decoration: underline;">DsfExecutor</span>
|
|
- Each session has a single executor. This means that all the
|
|
services in a single session share the same executor and dispatch
|
|
thread, and conversely it means that when operating in the dispatch
|
|
thread, the state of all the services in a session will remain the same
|
|
until the end of a dispatch. Note: multiple sessions <span
|
|
style="font-style: italic;">could</span> share the same <span
|
|
style="font-family: monospace;">DsfExecutor</span>.</li>
|
|
<li><span style="text-decoration: underline;">Service startup counter</span>
|
|
- An integer counter which is read and incremented by every service
|
|
that is started in a session. This counter is used to determine
|
|
the dependency order among services, which is used by events.</li>
|
|
<li><span style="text-decoration: underline;">Event listener list</span>
|
|
- This will be covered in the "Events" section.</li>
|
|
<li><span style="text-decoration: underline;">Adapter list</span> - A
|
|
list of adapters, providing functionality analogous to runtime's <span
|
|
style="font-family: monospace;">org.eclipse.core.internal.runtime.AdapterManager</span>.
|
|
Sessions need to manage their own lists of adapters, so that <span
|
|
style="font-family: monospace;">IAdapter</span> objects which
|
|
originate from DSF services can provider different adapters, based
|
|
on the session that they originate from. This feature is covered
|
|
in detail in the "DSF Data Model" document.<br>
|
|
</li>
|
|
</ul>
|
|
<p>The Session class also has a number of static features used to
|
|
manage Session objects:</p>
|
|
<ul>
|
|
<li><span style="text-decoration: underline;">Session ID counter</span>
|
|
- Used to generate new session IDs.</li>
|
|
<li><span style="text-decoration: underline;">Methods for starting
|
|
and ending sessions</span> <br>
|
|
</li>
|
|
<li><span style="text-decoration: underline;">Session started/ended
|
|
event listener list</span> - This allows clients to be notified when
|
|
sessions are created or terminated, which is used mostly for clean-up
|
|
purposes.<br>
|
|
</li>
|
|
</ul>
|
|
<h3>Startup/Shutdown</h3>
|
|
Managing the startup and shutdown process is often the most complicated
|
|
aspect of modular systems. The details of how the startup and
|
|
shutdown processes should be performed are also highly dependent on the
|
|
specifics of the system and service implementations. To help
|
|
with this, DSF provides two simple guidelines:<br>
|
|
<ol>
|
|
<li><span style="text-decoration: underline;">There should be a clear
|
|
dependency tree of all services within a session</span> - When the
|
|
dependencies between services are clearly defined, it is possible to
|
|
bring-up and bring-down the services in an order that guarantees each
|
|
running service can access all of the services that it depends on.</li>
|
|
<li><span style="text-decoration: underline;">There needs to be a
|
|
single point of control, which brings up and shuts down all the
|
|
services.</span> - In other words, services should not initialize or
|
|
shut-down themselves, based on some global event that they are all
|
|
listening to. But rather an external piece of logic needs to be
|
|
in charge of performing this operation.</li>
|
|
</ol>
|
|
The main implication of the first guideline, is that each service can
|
|
get and hold onto references to other services, without having to
|
|
repeatedly check, whether the service references are still valid.
|
|
This is because if a given service is to be shut-down, all services
|
|
that depend on this service will already have been shut down. The
|
|
second guideline, simply ensures that startup and shutdown procedures
|
|
are clear and easy to follow.<br>
|
|
<h3><a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/DsfServicesTracker.html"><span
|
|
style="font-family: monospace;">org.eclipse.dd.dsf.service.DsfServicesTracker</span></a>
|
|
vs <a
|
|
href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/util/tracker/ServiceTracker.html"><span
|
|
style="font-family: monospace;">org.osgi.util.tracker.ServiceTracker</span></a></h3>
|
|
OSGI methods for obtaining and tracking services can be rather
|
|
complicated. To obtain a reference to a service, the client has
|
|
to:<br>
|
|
<ol>
|
|
<li>Get a reference to a <span style="font-family: monospace;">BundleContext
|
|
</span>object, which can be retrieved from the plugin class.</li>
|
|
<li>Obtain a service reference object by calling <span
|
|
style="font-family: monospace;">BundleContext.getServiceReference()</span>;</li>
|
|
<li>Obtain an instance of the service by calling <span
|
|
style="font-family: monospace;">BundleContext.getService(ServiceReference)</span>.</li>
|
|
</ol>
|
|
But worst of all, when the client is finished using the service, it has
|
|
to call <span style="font-family: monospace;">BundleContext.ungetService(ServiceReference)</span>,
|
|
because the bundle context counts the used references to a given
|
|
service. All this paperwork is useful for services which manage
|
|
their own life-cycle, and could be un-registered at any time. To
|
|
make managing references to these kinds of services, OSGI provides a
|
|
utility class, called <span style="font-family: monospace;">ServiceTracker</span>.
|
|
<br>
|
|
<p>For DSF services, the life cycle of the services is much more
|
|
predictable, but the process of obtaining a reference to a service is
|
|
just as onerous. DSF provides its own utility, which is
|
|
separate from the <span style="font-family: monospace;">ServiceTracker</span>,
|
|
named <span style="font-family: monospace;">DsfServicesTracker</span>.
|
|
The differences between the two are listed in table below:<br>
|
|
</p>
|
|
<table style="width: 100%; text-align: left;" border="1" cellpadding="3"
|
|
cellspacing="0">
|
|
<tbody>
|
|
<tr>
|
|
<th
|
|
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">Property<br>
|
|
</th>
|
|
<th
|
|
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">OSGI
|
|
<span style="font-family: monospace;">ServiceTracker</span><br
|
|
style="font-family: monospace;">
|
|
</th>
|
|
<th
|
|
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">DSF
|
|
<span style="font-family: monospace;">DsfServicesTracker</span><br>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Number
|
|
of services tracked<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">While
|
|
not strictly limited, it is optimized for tracking services of a single
|
|
class type, or more typically to track a single service reference.<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Designed
|
|
to track services within a single DSF session. <br>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">When
|
|
are service references obtained<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Obtain
|
|
references automatically as the services register themselves.<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Service
|
|
references are obtained as requested by the client, and cached.</td>
|
|
</tr>
|
|
<tr>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Synchronization<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Multi-thread
|
|
accessible. <br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Can
|
|
be accessed only on the session's dispatch thread.<br>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Clean-up<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Automatically
|
|
un-gets references for services that are shut down.<br>
|
|
</td>
|
|
<td
|
|
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Client
|
|
must listen to session events, and clean up as needed.<br>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p>Both trackers are useful. Service implementations that depend
|
|
on a number of other services are most likely to use DSF <span
|
|
style="font-family: monospace;">ServicesTracker</span>, while some
|
|
clients, which use a single service may find OSGI <span
|
|
style="font-family: monospace;">ServiceTracker </span>more suitable.<br>
|
|
</p>
|
|
<h3>Events</h3>
|
|
Events are the most un-conventional component of the services package
|
|
and probably most likely to need modifications to the design by the
|
|
community. The design goal of
|
|
the event system is to allow a hierarchy of event classes, where a
|
|
listener could register itself for a specific event class or for all
|
|
events which derive from a base class. The use case for this
|
|
behavior is in the data model, where we would like to have the ability
|
|
to capture all model-related events with a generic listener while at
|
|
the same time allowing for services to fully use class types. <br>
|
|
<p>The event model is made up of the following components:<br>
|
|
</p>
|
|
<ul>
|
|
<li><span style="font-weight: bold;"><span
|
|
style="font-family: monospace;">DsfServiceEventHandler </span>annotation</span>
|
|
- This is the only indicator that a given method is an event
|
|
listener. The class with the event handler doesn't have to
|
|
implement any interfaces, but it must be public, which is a big
|
|
drawback.</li>
|
|
<li><span style="font-weight: bold;"><span
|
|
style="font-family: monospace;">Session.addServiceEventListener</span>,
|
|
<span style="font-family: monospace;">Session.removeServiceEventListener</span>
|
|
methods</span> - These methods allow clients to register for an event
|
|
based on an event class and a service filter, where the filter can be
|
|
used to uniquely identify a service in case of services with multiple
|
|
instances of same class.</li>
|
|
<li><span style="font-weight: bold;"><span
|
|
style="font-family: monospace;">Session.dispatchEvent</span> method -</span>
|
|
This is the method that actually dispatches the event to the
|
|
listeners.
|
|
The method must be called by a service that generates the event.</li>
|
|
</ul>
|
|
There are only a few more notes about the events mechanism:<br>
|
|
<ol>
|
|
<li>The event is always dispatched in its own <span
|
|
style="font-family: monospace;">Runnable</span> submitted to
|
|
the session's <span style="font-family: monospace;">DsfExecutor</span>.</li>
|
|
<li>There is a slight convenience for clients not to have to register
|
|
for each type of event separately.</li>
|
|
<li>There is a slight inconvenience for clients, because anonymous
|
|
classes cannot be used as listeners, due to the public class
|
|
requirement.</li>
|
|
</ol>
|
|
<h3>Debugger Services (<a
|
|
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/debug/package-summary.html"><span
|
|
style="font-family: monospace;">org.eclipse.dd.dsf.debug</span></a>)<br>
|
|
</h3>
|
|
DSF framework includes a set of service interfaces for a typical
|
|
debugger implementation. Functionally, they are pretty much
|
|
equivalent to the platform debug interfaces, but they are structured in
|
|
a way that allows a debugger to implement only some of them. In
|
|
order for the startup and shutdown process to work effectively, the
|
|
dependencies between services need to be clearly defined. The
|
|
dependencies between the main service interfaces are shown in the graph
|
|
below:<br>
|
|
<img alt="" title="Debugger Services Dependencies"
|
|
src="dsf_services_model-1.png" style="width: 720px; height: 540px;"><br>
|
|
<p>It's also important to realize that it's unlikely that a single
|
|
hierarchy of interfaces will adequately fit all the various debugger
|
|
use cases, and it is likely that some interfaces will be needed which
|
|
partially duplicate functionality found in other interfaces.
|
|
An example of this in the proposed interface set are the interfaces
|
|
which are used to initiate a debugging session. The <span
|
|
style="font-family: monospace;">INativeProcesses</span> service is
|
|
intended as the simple abstraction for native debuggers, where a
|
|
debugger only needs an existing host process ID or an executable image
|
|
name. Based on this a <span style="font-family: monospace;">INativeProcess</span>
|
|
debugger implementation should be able to initiate a debugging session,
|
|
and return run-control, memory, and symbol contexts that are required
|
|
to carry out debugging operations. By comparison, <span
|
|
style="font-family: monospace;">IOS</span> and <span
|
|
style="font-family: monospace;">ITarget</span> are generic interfaces
|
|
which allow clients to manage multiple target definitions, to
|
|
examine a wide array of OS objects, and to attach a debugger to a
|
|
process or some other debuggable entity. <br>
|
|
<img alt="" title="Process Managment Services"
|
|
src="dsf_services_model-2.png" style="width: 720px; height: 540px;"><br>
|
|
</p>
|
|
<h4>Disclaimer</h4>
|
|
Drafting large APIs that are intended to have many implementations and
|
|
by clients is a notoriously difficult task. It is
|
|
impossible to expect that a first draft of such interfaces will not
|
|
require changes, and only time and multiple successful implementation
|
|
can validate them. While we can draw upon many examples of
|
|
debugger
|
|
APIs in Eclipse in and our commercial debugger, this is a new API with
|
|
a
|
|
prototype that exercises only a small portion of its interfaces.<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
<br>
|
|
</body>
|
|
</html>
|