com.arjuna.webservices.base.processors.ReactivatedObjectProcessor Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a full listing
* of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2008,
* @author JBoss Inc.
*/
package com.arjuna.webservices.base.processors;
/**
* A specialization of ActivatedObjectProcessor which allows for ghost entries to
* be left in the table after deletion. A ghost entry cannot be retrieved by a normal
* getObject(id) which will return null, indicating that no object with the supplied id
* exists. However, the ghost's presence can be detected using getGhost(id).
*
* Ghost entries are used to identify objects which have failed to be terminated due to an
* unavailable participant or coordinator and so are still present in an unprocessed log record.
* When recovery processing recreates a participant the recovered instance replaces the
* ghost entry, ensuring that sbsequent messages update the participant whose recovery is
* being driven by the coordinator.
*/
public class ReactivatedObjectProcessor extends ActivatedObjectProcessor {
/**
* a private object used to identify a ghost entry
*/
static final private Object tombstone = new Object();
/**
* Activate the object.
*
* @param object The object.
* @param identifier The identifier.
*/
public synchronized void activateObject(Object object, String identifier) {
super.activateObject(object, identifier);
}
/**
* Deactivate the object.
*
* @param object The object.
*/
public synchronized void deactivateObject(Object object) {
deactivateObject(object, false);
}
/**
* Deactivate the object.
*
* @param object The object.
*/
public synchronized void deactivateObject(Object object, boolean leaveGhost) {
if (leaveGhost) {
final String identifier = (String)identifierMap.get(object);
super.deactivateObject(object);
objectMap.put(identifier, tombstone);
} else {
super.deactivateObject(object);
}
}
/**
* Get the object with the specified identifier.
*
* @param identifier The identifier.
* @return The participant or null if not known.
*/
public synchronized Object getObject(String identifier) {
final Object object = super.getObject(identifier);
if (object == tombstone) {
return null;
}
return object;
}
/**
* check if there is a ghost entry for this object
*
* @param identifier
* @return true iff there is a ghost entry for this object
*/
public synchronized boolean getGhost(String identifier)
{
if (reactivationProcessingStarted) {
final Object object = super.getObject(identifier);
return (object == tombstone);
} else {
// until we have been notified of at least one complete recovery scan pass we have
// to assume that any identifier may have an entry in the log so we return true
return true;
}
}
/**
* a global flag which is false at boot and is set to true once a recovery log scan for XTS
* data has completed
*/
static boolean reactivationProcessingStarted = false;
/**
* notify completion of a recovery log scan for XTS data
*/
static public void setReactivationProcessingStarted()
{
reactivationProcessingStarted = true;
}
}