blob: 48c7a2c96e70a615267383849996b937239e8d3d [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
<meta name="copyright" content="Copyright (c) IBM Corporation and others 2000, 2016. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." >
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<meta content="text/css" http-equiv="Content-Style-Type">
<link type="text/css" charset="ISO-8859-1" href="../book.css"
rel="STYLESHEET">
<title>Synchronization Support - Beyond the basics</title>
<link href="../book.css" type="text/css" rel="stylesheet">
</head>
<body style="background-color: rgb(255, 255, 255);">
<h2>Beyond the Basics</h2>
<p>If you plan on providing synchronization support and don't have an existing
mechanism for managing synchronization state, this section explains how to implementing
a Subscriber from scratch. This means that there is no existing synchronization
infrastructure and illustrates how to use some API that is provided to maintain
the synchronization state.<br>
</p>
<p>For the remainder of this example we will make use of a running
example. The source code can be found in the file system provider
package of the <a
href="http://git.eclipse.org/c/www.eclipse.org/eclipse.git/tree/platform-ui/plugins/org.eclipse.ui.examples.filesystem/">org.eclipse.ui.examples.filesystem</a>
plug-in. You should check the project out from the Git repository and
use as a reference while you are reading this tutorial. </p>
<h3>Implementing a Subscriber From Scratch</h3>
<p>This first example assumes that there is no existing infrastructure for maintaining
the synchronization state of the local workspace. When implementing a subscriber
from scratch, you can make use of some additional API provided in the <em>org.eclipse.team.core</em>
plug-in. The <a
href="../reference/api/org/eclipse/team/core/variants/package-summary.html">org.eclipse.team.core.variants</a>
package contains two subclasses of <a
href="../reference/api/org/eclipse/team/core/subscribers/Subscriber.html">Subscriber
</a>which can be used to simplify implementation. The first is <a
href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.html">ResourceVariantTreeSubscriber
</a>which will be discussed in the second example below. The second is a subclass
of the first: <a
href="../reference/api/org/eclipse/team/core/variants/ThreeWaySubscriber.html">ThreeWaySubscriber</a>.
This subscriber implementation provides several helpful classes for managing
the synchronization state of a local workspace. If you do not have any existing
infrastructure, this is a good place to start. </p>
<p>Implementing a subscriber from scratch will be illustrated using the file system
example available in the <a
href="http://git.eclipse.org/c/www.eclipse.org/eclipse.git/tree/platform-ui/plugins/org.eclipse.ui.examples.filesystem/">org.eclipse.ui.examples.filesystem</a>
plug-in. The code in the following description is kept to a minimum since it
is available from the Eclipse Git repository. Although not technically a three-way
subscriber, the file system example can still make good use of this infrastructure.
The FTP and WebDAV plug-ins also are built using this infrastructure.</p>
<h3>ThreeWaySubscriber</h3>
<p>For the file system example, we already had an implementation of a <a href="../reference/api/org/eclipse/team/core/RepositoryProvider.html">RepositoryProvider
</a>that associated a local project with a file system location where the local
contents were mirrored. FileSystemSubscriber was created as a subclass of <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySubscriber.html">ThreeWaySubscriber</a>
in order to make use of a <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>
to manage workspace synchronization state. Subclasses of this class must do
the following:</p>
<ul>
<li>create a <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>
instance to manage the local workspace synchronization state.</li>
<li>create an instance of a <a href="../reference/api/org/eclipse/team/core/variants/ThreeWayRemoteTree.html">ThreeWayRemoteTree</a>
subclass to provide remote tree refresh.
<ul>
<li>The class FileSystemRemoteTree was defined for this
purpose</li>
</ul></li>
<li>implement a method to create the resource variant handles used to
calculate the synchronization state.
<ul>
<li>The class FileSystemResourceVariant (a subclass of <a href="../reference/api/org/eclipse/team/core/variants/CachedResourceVariant.html">CachedResourceVariant</a>)
was defined for this</li>
</ul>
</li>
<li>implement the roots method
<ul>
<li>The roots for the subscriber are all the projects mapped to
the FileSystemProvider. Callbacks were added to FileSystemProvider
in order to allow the FileSystemSubscriber to generate change
events when projects are mapped and unmapped.</li>
</ul>
</li>
</ul>
<p>In addition to the subscriber implementation, the get and put
operations for the file system provider were modified to update the
synchronization state in the ThreeWaySynchronizer. The
operations are implemented in the class
org.eclipse.team.examples.filesystem.FileSystemOperations.</p>
<h3>ThreeWaySynchronizer</h3>
<p><a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>
manages the synchronization state between the local workspace and a remote location.
It caches and persists the local, base and remote timestamps in order to support
the efficient calculation of the synchronization state of a resource. It also
fires change notifications to any registered listeners. The <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySubscriber.html">ThreeWaySubscriber</a>
translates these change events into the proper format to be sent to listeners
registered with the subscriber.</p>
<p>The <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>
makes use of Core scheduling rules and locks to ensure thread safety and provide
change notification batching.</p>
<h3>ThreeWayRemoteTree</h3>
<p>A <a href="../reference/api/org/eclipse/team/core/variants/ThreeWayRemoteTree.html">ThreeWayRemoteTree</a>
is a subclass of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTree.html">ResourceVariantTree</a>
that is tailored to the <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySubscriber.html">ThreeWaySubscriber</a>.
It must be overridden by clients to provide the mechanism for fetching the remote
state from the server. <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTree.html">ResourceVariantTree</a>
is discussed in more detail in the next example.</p>
<h3>CachedResourceVariant</h3>
<p>A <a href="../reference/api/org/eclipse/team/core/variants/CachedResourceVariant.html">CachedResourceVariant</a>
is a partial implementation of IResourceVariant that caches any fetched contents
for a period of time (currently 1 hour). This is helpful since the contents
may be accessed several times in a short period of time (for example, to determine
the synchronization state and display the contents in a compare editor). Subclasses
must still provide the unique content identifier along with the byte array that
can be persisted in order to recreate the resource variant handle.</p>
<h3>Building on Top of Existing Workspace Synchronization</h3>
<p>Many repository providers may already have a mechanism for managing their synchronization
state (e.g. if they have existing plug-ins). The <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.html">ResourceVariantTreeSubscriber</a>
and its related classes provide the ability to build on top of an existing synchronization
infrastructure. For example, this is the superclass of all of the Git subscribers.</p>
<h4>ResourceVariantTreeSubscriber</h4>
<p>As was mentioned in the previous example, the <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySubscriber.html">ThreeWaySubscriber</a>
is a subclass of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.html">ResourceVariantTreeSubscriber</a>
that provides local workspace synchronization using a <a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>.
Subclasses of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.html">ResourceVariantTreeSubscriber</a>
must provide:</p>
<ul>
<li>
<p>Subclasses of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTree.html">ResourceVariantTree</a>
(or <a href="../reference/api/org/eclipse/team/core/variants/AbstractResourceVariantTree.html">AbstractResourceVariantTree</a>)
that provide the behavior for traversing and refreshing the remote resource
variants and, for subscribers that support three-way comparisons, the base
resource variants.</p>
</li>
<li>An implementation of <a href="../reference/api/org/eclipse/team/core/variants/IResourceVariantComparator.html">IResourceVariantComparator</a>
that performs the two-way or three-way comparison for a local resource and
its base and remote resource variants.It is common to also provide a subclass
of <a href="../reference/api/org/eclipse/team/core/synchronize/SyncInfo.html">SyncInfo</a>
in order to customize the synchronization state determination algorithm. </li>
<li>An implementation of the roots method for providing the roots of the subscriber
and an implementation of the isSupervised method for determining what resources
are supervised by the subscriber.</li>
</ul>
<p>The other capabilities of the subscriber are implemented using these
facilities.</p>
<h4>ResourceVariantTree</h4>
<p><a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantTree.html">ResourceVariantTree</a>
is a concrete implementation of <a href="../reference/api/org/eclipse/team/core/variants/IResourceVariantTree.html">IResourceVariantTree</a>
that provides the following:</p>
<ul>
<li>traversal of the resource variant tree</li>
<li>logic to merge the previous resource variant tree state with the
current fetched state.</li>
<li>caching of the resource variant tree using a <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantByteStore.html">ResourceVariantByteStore</a>.</li>
</ul>
<p>The following must be implemented by subclasses:</p>
<ul>
<li>creation of resource variant handles from the cached bytes that
represent a resource variant</li>
<li>fetching of the current remote state from the server</li>
<li>creation of the byte store instance used to cache the bytes that
uniquely identify a resource variant</li>
</ul>
<p>Concrete implementations of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantByteStore.html">ResourceVariantByteStore</a>
are provided that persist bytes across workbench invocations (<a href="../reference/api/org/eclipse/team/core/variants/PersistantResourceVariantByteStore.html">PersistantResourceVariantByteStore</a>)
or cached the bytes only for the current session (<a href="../reference/api/org/eclipse/team/core/variants/SessionResourceVariantByteStore.html">SessionResourceVariantByteStore</a>).
However, building a subscriber on top of an existing workspace synchronization
infrastructure will typically require the implementation of <a href="../reference/api/org/eclipse/team/core/variants/ResourceVariantByteStore.html">ResourceVariantByteStore</a>
subclasses that interface with the underlying synchronizer. For example the
<a href="../reference/api/org/eclipse/team/core/variants/ThreeWayRemoteTree.html">ThreeWayRemoteTree</a>
makes use of a byte store implementation that stores the remote bytes in the
<a href="../reference/api/org/eclipse/team/core/variants/ThreeWaySynchronizer.html">ThreeWaySynchronizer</a>.</p>
<p>The creation of resource variant handles for this example does not differ from
the previous example except that the handles are requested from a resource variant
tree instance instead of the subscriber.</p>
</body>
</html>