Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jboss.jbossts.xts.recovery.participant.at;
  
  
 
 import java.util.*;
A class which manages the table of recovered participant records.
 
 public class XTSATRecoveryManagerImple extends XTSATRecoveryManager {
    
constructor for use by ATParticipantRecoveryModule and ATCoordinatorRecoveryModule

Parameters:
txLog
 
     public XTSATRecoveryManagerImple(TxLog txLog)
     {
         this. = txLog;
     }

    
register an application specific recovery module which acts as a helper to recreate a WS-AT durable participant from the participant's recovery data saved at prepare

Parameters:
module the module which will be used to identify and recreate participants for the application
Throws:
java.lang.NullPointerException if the supplied module is null
 
     public void registerRecoveryModule(XTSATRecoveryModule modulethrows NullPointerException
     {
         // TODO other sanity checks?
         if (module == null) {
             throw new NullPointerException("XTSATRecoveryModule value must be non-null");
         }
         synchronized () {
             .add(module);
         }
     }

    
unregister an application specific recovery module previously registered as a helper to recretae WS-AT durable participants

Parameters:
module the module to be unregistered
Throws:
java.util.NoSuchElementException if the module is not currently registered
 
     public void unregisterRecoveryModule(XTSATRecoveryModule modulethrows NoSuchElementException {
 
         synchronized () {
             if (!.remove(module)) {
                 throw new NoSuchElementException();
             }
         }
     }

    
save the supplied participant recovery record to persistent storage

Parameters:
participantRecoveryRecord
 
     public boolean writeParticipantRecoveryRecord(ATParticipantRecoveryRecord participantRecoveryRecord)
     {
         OutputObjectState oos = new OutputObjectState();
         // we need to be able to retrieve the class of the participant record so we can
         // create an instancde to load the rest of the participant specific data
         try {
             oos.packString(participantRecoveryRecord.getClass().getCanonicalName());
         } catch (IOException ioe) {
             ..warn_participant_at_XTSATRecoveryModule_1(participantRecoveryRecord.getId(), ioe);
             return false;
         }
 
         if (participantRecoveryRecord.saveState(oos)) {
             Uid uid = new Uid();
             try {
                 .write_committed(uidoos);
                 // we need to be able to identify the uid from the participant id
                 // in order to delete it later
                 .put(participantRecoveryRecord.getId(), uid);
                 return true;
             } catch (ObjectStoreException ose) {
                 ..warn_participant_at_XTSATRecoveryModule_1(participantRecoveryRecord.getId(), ose);
             }
         }
 
         return false;
     }

    
remove any participant recovery record with the supplied id from persistent storage

Parameters:
id the id of the participant whose recovery details are being deleted
    public boolean deleteParticipantRecoveryRecord(String id)
    {
        Uid uid = .get(id);
        if (uid != null) {
            try {
                .remove_committed(uid);
                .remove(id);
                return true;
            } catch (ObjectStoreException ose) {
                ..warn_participant_at_XTSATRecoveryModule_2(uididose);
            }
        }
        return false;
    }

    
test whether the supplied uid identifies an active participant or a recovered but inactive participant n.b. this method is not synchronized because of two assumptions: first, that uids are never reused; and second that only recovery scanning (as a minimum, for a given recovery record type) is single-threaded. Correctness of the first assumption ensures there are no races with participant processor threads, the second races between recovery threads.

Parameters:
uid
    public boolean isParticipantPresent(Uid uid)
    {
        return (.get(uid) != null); 
    }

    
add a recovered participant record to the table of unrecovered participants which need to be recreated following recovery

Parameters:
uid the uid under which the participant was saved in the file store
participantRecoveryRecord the in-memory representation of the recovery record saved to disk
    public void addParticipantRecoveryRecord(Uid uidATParticipantRecoveryRecord participantRecoveryRecord)
    {
        String participantId = participantRecoveryRecord.getId();
        if (.get(participantId) == null && !participantRecoveryRecord.isActive()) {
            // ok, we have not seen this entry before so add it to the list
            .put(participantIdparticipantRecoveryRecord);
            .put(participantIduid);
        }
    }

    
see if a participant recovery record with a given id exists in the table of participants which need to be recreated following recovery

Parameters:
id the identifier of the participant being sought
Returns:
the participant recovery record with the supplied id or null if it is not found
    {
        return .get(id);
    }

    
process all entries in the recovered participant map and attempt to recreate the application participant and activate it
    public void recoverParticipants()
    {
        // the first scan has been performed so allow processing of commit and rollback requests
        // for unknown ids to proceed now
        // we operate on a copy of the recovery modules to avoid the list being modified
        // by register and unregister operations while we are iterating over it
        // we should probably also make sure unregister does not proceed until
        // the current scan is complete . . .
        List<XTSATRecoveryModulerecoveryModulesCopy;
        synchronized () {
            recoveryModulesCopy = new ArrayList<XTSATRecoveryModule>();
        }
        // iterate through the participant recovery records and try to convert them to
        // a durable participant. if successful activate the participant and then remove the
        // recovery entry. note that since recovery is single threaded we can be sure that
        // no concurrent modifications will be made to the table while we are iterating and,
        // possibly, deleting via the iterator
        Iterator<ATParticipantRecoveryRecordparticipantIterator = iterator();
        while(participantIterator.hasNext()) {
            ATParticipantRecoveryRecord participantRecoveryRecord = participantIterator.next();
            if (participantRecoveryRecord.isActive()) {
                // this participant must have already been activated by a by a previous
                // scan and been reloaded by this scan so just remove the entry
                participantIterator.remove();
            } else {
                Iterator<XTSATRecoveryModulemoduleIterator = recoveryModulesCopy.iterator();
                boolean found = false;
                while (!found && moduleIterator.hasNext()) {
                    XTSATRecoveryModule module = moduleIterator.next();
                    try {
                        if (participantRecoveryRecord.restoreParticipant(module)) {
                            // ok, this participant has recovered so tell it to
                            // activate and *then* remove it from the hashmap. this makes
                            // sure we don't open a window where an incoming
                            // commit may fail to find the object in either table
                            found = true;
                            participantRecoveryRecord.activate();
                            participantIterator.remove();
                        }
                    } catch (Exception e) {
                        // we foudn a helper but it failed to convert the participant record -- log a warning
                        // but leave the participant in the table for next time in case the helper has merely
                        // suffered a transient failure
                        found = true;
                        ..warn_participant_at_XTSATRecoveryModule_3(participantRecoveryRecord.getId(), e);
                    }
                }
                if (!found) {
                    // we failed to find a helper to convert a participant record so log a warning
                    // but leave it in the table for next time
                    ..warn_participant_at_XTSATRecoveryModule_4(participantRecoveryRecord.getId());
                }
            }
        }
        // now let all the recovery modules know that we have completed a scan
        Iterator<XTSATRecoveryModulemoduleIterator = recoveryModulesCopy.iterator();
        while (moduleIterator.hasNext()) {
            XTSATRecoveryModule recoveryModule = moduleIterator.next();
            recoveryModule.endScan();
        }
        // ok, see if we are now in a position to cull any prepared subordinate transactions
        cullOrphanedSubordinates();
    }

    
look for recovered subordinate transactions which do not have an associated proxy participant rolling back any that are found. this only needs doing once after the first participant and subordinate transaction recovery passes have both completed
    private void cullOrphanedSubordinates()
    {
            return;
        }
         = true;
        SubordinateATCoordinator[] coordinators = SubordinateATCoordinator.listRecoveredCoordinators();
        for (SubordinateATCoordinator coordinator : coordinators) {
            if (coordinator.getSubordinateType().equals(.) && coordinator.isOrphaned()) {
                ..warn_participant_at_XTSATRecoveryModule_5(coordinator.get_uid());
                coordinator.rollback();
            }
        }
    }
    
    
return an iterator over the collection of entries in the table. n.b. this iterates direct over the table so any deletions performed during iteration need to be done via the iterator and need to be sure to avoid concurrent modification

Returns:
    private synchronized Iterator<ATParticipantRecoveryRecorditerator()
    {
        return .values().iterator();
    }

    
set a global flag indicating that the first AT participant recovery scan has been performed.
    private synchronized void setParticipantRecoveryStarted()
    {
         = true;
    }

    
test whether the first AT participant recovery scan has completed. this indicates whether there may or may not still be unknown participant recovery records on disk. If the first scan has not yet completed then a commit or rollback message for an unknown participant must be dropped. If it has then a commit or rollback for an unknown participant must be acknowledged with, respectively, a committed or aborted message.
    public synchronized boolean isParticipantRecoveryStarted()
    {
        return ;
    }

    
test whether the first AT coordinator recovery scan has completed. this indicates whether there may or may not still be unknown AT transcation records on disk. If the first scan has not yet completed then a prepare message for an unknown participant must be dropped. If it has then a perpare for an unknown participant must be acknowledged with a rollback message.
    public synchronized boolean isCoordinatorRecoveryStarted() {
        return ;
    }

    
test whether the first AT subordinate coordinator recovery scan has completed. this indicates whether there may or may not still be unknown AT subtransaction records on disk. If the first scan has not yet completed then a commit for an unknown subtransaction must raise an exception delaying commit of the parent transaction.
    public synchronized boolean isSubordinateCoordinatorRecoveryStarted() {
    }

    
record the fact that the first AT coordinator recovery scan has completed.
    public synchronized void setCoordinatorRecoveryStarted() {
         = true;
    }

    
record the fact that the first AT subordinate coordinator recovery scan has completed.
    public synchronized void setSubordinateCoordinatorRecoveryStarted() {
        // see if we are now in a position to cull any orphaned subordinate transactions
        cullOrphanedSubordinates();
    }

    
a global flag indicating whether the first AT participant recovery scan has been performed.
    private boolean participantRecoveryStarted = false;

    
a global flag indicating whether the first AT coordinator recovery scan has been performed.
    private boolean coordinatorRecoveryStarted = false;

    
a global flag indicating whether the first AT subordinate coordinator recovery scan has been performed.
    private boolean subordinateCoordinatorRecoveryStarted = false;

    
a global flag indicating whether we have already reconciled the list of subordinate transactions against their proxy participants looking for any orphans
    private boolean culledOrphanSubordinates = false;

    
a map from participant ids to participant recovery records
a map from participant id to the uid under which the participant has been saved in the persistent store
    private HashMap<StringUiduidMap = new HashMap<StringUid>();

    
a map from participant ids to participant recover records
    private final List<XTSATRecoveryModulerecoveryModules = new ArrayList<XTSATRecoveryModule>();

    
the tx object store to be used for saving and deleting participant details
    private TxLog txLog;
    private final static String type = ATParticipantRecoveryRecord.type();
New to GrepCode? Check out our FAQ X