blob: d91b2dd0390efcec743354338a4f0bf9d3adba7d [file] [log] [blame]
/*
* Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.felix.service.coordinator;
import java.util.Collection;
/**
A Coordinator service coordinates activities between different parties. The Coordinator can create Coordination
objects. Once a Coordination object is created, it can be pushed on a thread local stack {@link Coordination#push()} as
an implicit parameter for calls to other parties, or it can be passed as an argument. The current top of the thread
local stack can be obtained with #peek(). The addParticipant(Participant) method on this service or the
Coordination.addParticipant(Participant) method can be used to participate in a Coordination. Participants
participate only in a single Coordination, if a Participant object is added to a second Coordination the
Coordination.addParticipant(Participant) method is blocked until the first Coordination is terminated. A
Coordination ends correctly when the Coordination.end() method is called before termination or when the
Coordination fails due to a timeout or a failure. If the Coordination ends correctly, all its participants are called on
the Participant.ended(Coordination) method, in all other cases the Participant.failed(Coordination) is
called. The typical usage of the Coordinator service is as follows:
<pre>
Coordination coordination = coordinator.begin("mycoordination",0);
try {
doWork();
}
finally {
coordination.end();
}
</pre>
In the doWork() method, code can be called that requires a callback at the end of the Coordination. The doWork
method can then add a Participant to the coordination. This code is for a Participant.
<pre>
void doWork() {
if (coordinator.addParticipant(this)) {
beginWork();
}
else {
beginWork();
finishWork();
}
}
void ended() {
finishWork();
}
void failed() {
undoWork();
}
</pre>
Life cycle. All Coordinations that are begun through this service must automatically fail before this service is
ungotten.
*
* @ThreadSafe
* @Provisional
*/
@Deprecated
public interface Coordinator
{
/**
* Create a new Coordination that is not associated with the current thread.
* Parameters:
*
* @param name The name of this coordination, a name does not have to be
* unique.
* @param timeout Timeout in milliseconds, less or equal than 0 means no
* timeout
* @return The new Coordination object, never <code>null</code>
* @throws SecurityException This method requires the
* {@link CoordinationPermission#INITIATE} action, no bundle
* check is done.
* @throws IllegalArgumentException when the name does not match the Bundle
* Symbolic Name pattern
*/
Coordination create(String name, int timeout);
/**
* Provide a mutable snapshot collection of all Coordination objects
* currently not terminated. Coordinations in
* this list can have terminated before this list is returned or any time
* thereafter. The returned collection must
* only contain the Coordinations for which the caller has
* {@link CoordinationPermission#ADMIN}, without this
* permission an empty list must be returned.
*
* @return a list of Coordination objects filtered by
* {@link CoordinationPermission#ADMIN}
*/
Collection<Coordination> getCoordinations();
/**
* Always fail the current Coordination, if it exists. If this is no current
* Coordination return <code>false</code>. Otherwise return the result of
* {@link Coordination#fail(Throwable)}, which is <code>true</code> in the
* case this call terminates the Coordination and <code>false</code>
* otherwise.
*
* <pre>
* false - No current Coordination
* false - Current Coordination was already terminated
* true - Current Coordination got terminated due to this call
* </pre>
*
* @param reason The reason for failure, must not be <code>null</code>.
* @return <code>true</code> if there was a current Coordination and it was
* terminated, otherwise <code>false</code>.
*/
boolean fail(Throwable reason);
/**
* Return the current Coordination or <code>null</code>. The current
* Coordination is the top of the thread local stack of Coordinations. If
* the stack is empty, there is no current Coordination.
*
* @return <code>null</code> when the thread local stack is empty, otherwise
* the top of the thread local stack of
* Coordinations.
*/
Coordination peek();
/**
* Begin a new Coordination and push it on the thread local stack with
* {@link Coordination#push()}.
*
* @param name The name of this coordination, a name does not have to be
* unique.
* @param timeoutInMillis Timeout in milliseconds, less or equal than 0
* means no timeout
* @return A new Coordination object
* @throws SecurityException This method requires the
* {@link CoordinationPermission#INITIATE} action, no bundle
* check is done.
* @throws IllegalArgumentException when the name does not match the Bundle
* Symbolic Name pattern
*/
Coordination begin(String name, int timeoutInMillis);
/**
* Pop the top of the thread local stack of Coordinations. If no current
* Coordination is present, return <code>null</code>.
*
* @return The top of the stack or <code>null</code>
*/
Coordination pop();
/**
* Participate in the current Coordination and return <code>true</code> or
* return <code>false</code> if there is none. This method calls
* {@link #peek()}, if it is <code>null</code>, it will return
* <code>false</code>. Otherwise it will call
* {@link Coordination#addParticipant(Participant)}.
*
* @param participant The participant of the Coordination
* @return <code>true</code> if there was a current Coordination that could
* be successfully used to participate, otherwise <code>false</code>
* .
* @throws CoordinationException This exception should normally not be
* caught by the caller but allowed to bubble up to the
* initiator of the coordination, it is therefore a
* <code>RuntimeException</code>. It signals that this
* participant could not participate the current coordination.
* This can be cause by the following reasons:
* <ol>
* <li>{@link CoordinationException#DEADLOCK_DETECTED}</li>
* <li>{@link CoordinationException#ALREADY_ENDED}</li>
* <li>{@link CoordinationException#TIMEOUT}</li>
* <li>{@link CoordinationException#UNKNOWN}</li>
* </ol>
* @throws SecurityException This method requires the
* {@link CoordinationPermission#PARTICIPATE} action for the
* current
* Coordination, if any.
*/
boolean addParticipant(Participant participant) throws CoordinationException;
/**
* Answer the coordination associated with the given id if it exists.
*
* @param id The id of the requested Coordination
* @return a Coordination with the given ID or <code>null</code> when
* Coordination cannot be found because it never existed or had
* terminated before this call.
* @throws SecurityException if the caller has no
* {@link CoordinationPermission#ADMIN} for the requested
* Coordination.
*/
Coordination getCoordination(long id);
}