use of org.datanucleus.store.fieldmanager.ReachabilityFieldManager in project datanucleus-core by datanucleus.
the class ReachabilityAtCommitHandler method execute.
/**
* Method to perform the "persistence-by-reachability" at commit.
*/
public void execute() {
try {
this.executing = true;
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010032"));
}
// from makePersistent in this txn, or enlisted existing objects) then run reachability checks
if (!persistedIds.isEmpty() && !flushedNewIds.isEmpty()) {
Set currentReachables = new HashSet();
// Run "reachability" on all known persistent objects for this txn
Object[] ids = persistedIds.toArray();
Set objectNotFound = new HashSet();
for (int i = 0; i < ids.length; i++) {
if (!deletedIds.contains(ids[i])) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug("Performing reachability algorithm on object with id \"" + ids[i] + "\"");
}
try {
ObjectProvider op = ec.findObjectProvider(ec.findObject(ids[i], true, true, null));
if (!op.isDeleted() && !currentReachables.contains(ids[i])) {
// Make sure all of its relation fields are loaded before continuing. Is this necessary, since its enlisted?
op.loadUnloadedRelationFields();
// Add this object id since not yet reached
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007000", StringUtils.toJVMIDString(op.getObject()), ids[i], op.getLifecycleState()));
}
currentReachables.add(ids[i]);
// Go through all relation fields using ReachabilityFieldManager
ReachabilityFieldManager pcFM = new ReachabilityFieldManager(op, currentReachables);
int[] relationFieldNums = op.getClassMetaData().getRelationMemberPositions(ec.getClassLoaderResolver());
if (relationFieldNums != null && relationFieldNums.length > 0) {
op.provideFields(relationFieldNums, pcFM);
}
}
} catch (NucleusObjectNotFoundException ex) {
objectNotFound.add(ids[i]);
}
} else {
// Was deleted earlier so ignore
}
}
// Remove any of the "reachable" instances that are no longer "reachable"
flushedNewIds.removeAll(currentReachables);
Object[] nonReachableIds = flushedNewIds.toArray();
if (nonReachableIds != null && nonReachableIds.length > 0) {
// TODO See CORE-3276 for a possible change to this
for (int i = 0; i < nonReachableIds.length; i++) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010033", nonReachableIds[i]));
}
try {
if (!objectNotFound.contains(nonReachableIds[i])) {
ObjectProvider op = ec.findObjectProvider(ec.findObject(nonReachableIds[i], true, true, null));
if (!op.getLifecycleState().isDeleted() && !ec.getApiAdapter().isDetached(op.getObject())) {
// Null any relationships for relation fields of this object
op.replaceFields(op.getClassMetaData().getNonPKMemberPositions(), new NullifyRelationFieldManager(op));
ec.flush();
}
}
} catch (NucleusObjectNotFoundException ex) {
// just ignore if the object does not exist anymore
}
}
// B). Remove the objects
for (int i = 0; i < nonReachableIds.length; i++) {
try {
if (!objectNotFound.contains(nonReachableIds[i])) {
ObjectProvider op = ec.findObjectProvider(ec.findObject(nonReachableIds[i], true, true, null));
op.deletePersistent();
}
} catch (NucleusObjectNotFoundException ex) {
// just ignore if the file does not exist anymore
}
}
}
// Make sure any updates are flushed
ec.flushInternal(true);
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010034"));
}
} finally {
this.executing = false;
}
}
Aggregations