[jbosscache-commits] JBoss Cache SVN: r8183 - in core/trunk/src/main/java/org/jboss/cache: commands/remote and 1 other directory.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Sat Aug 15 18:25:40 EDT 2009
Author: bstansberry at jboss.com
Date: 2009-08-15 18:25:40 -0400 (Sat, 15 Aug 2009)
New Revision: 8183
Modified:
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java
Log:
[JBCACHE-1530] Attempt to clean defunct data backup regions if DataGravitationCleanupCommand comes in recently after the region was created
Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2009-08-14 19:31:20 UTC (rev 8182)
+++ core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2009-08-15 22:25:40 UTC (rev 8183)
@@ -80,6 +80,7 @@
import java.util.Vector;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -175,6 +176,8 @@
private boolean receivedBuddyInfo;
private DataContainer dataContainer;
private BuddyFqnTransformer buddyFqnTransformer;
+
+ private ConcurrentMap<String, Set<DefunctDataHistory>> defunctDataHistory = new ConcurrentHashMap<String, Set<DefunctDataHistory>>();
public BuddyManager()
{
@@ -713,6 +716,50 @@
}
return owners;
}
+
+ public List<Fqn<?>> getNewlyDeadBackupFqns(Fqn<?> backupFqn)
+ {
+ if (buddyFqnTransformer.isDeadBackupFqn(backupFqn))
+ {
+ return null;
+ }
+
+ if (!buddyFqnTransformer.isBackupFqn(backupFqn) || backupFqn.size() < BUDDY_BACKUP_SUBTREE_FQN.size() + 2)
+ {
+ return null;
+ }
+
+ List<Fqn<?>> result = null;
+ String owner = (String) backupFqn.get(BUDDY_BACKUP_SUBTREE_FQN.size());
+ Set<DefunctDataHistory> historySet = defunctDataHistory.get(owner);
+ if (historySet != null)
+ {
+ Fqn<?> coreFqn = null;
+ for (Iterator<DefunctDataHistory> it = historySet.iterator(); it.hasNext(); )
+ {
+ DefunctDataHistory gen = it.next();
+ if (gen.isStale())
+ {
+ it.remove();
+ }
+ else
+ {
+ if (result == null)
+ {
+ result = new ArrayList<Fqn<?>>();
+ }
+ if (coreFqn == null)
+ {
+ coreFqn = buddyFqnTransformer.getActualFqn(backupFqn);
+ }
+ Fqn<?> base = Fqn.fromRelativeElements(BUDDY_BACKUP_SUBTREE_FQN, gen.owner, Integer.valueOf(gen.generation));
+ result.add(Fqn.fromRelativeFqn(base, coreFqn));
+ }
+ }
+ }
+
+ return result;
+ }
// -------------- static util methods ------------------
@@ -1102,15 +1149,29 @@
{
Fqn defunctBackupRootFqn = getDefunctBackupRootFqn(dataOwner);
- if (trace) log.trace("Migrating defunct data. Backup root is " + backupRoot);
+ if (log.isDebugEnabled()) log.debug("Migrating defunct data. Backup root is " + backupRoot + ". New backup root is " + defunctBackupRootFqn);
if (trace) log.trace("Children of backup root are " + backupRoot.getChildren());
+ String ownerName = buddyFqnTransformer.getGroupNameFromAddress(dataOwner);
+
+ Set<DefunctDataHistory> newHistorySet = new ConcurrentHashSet<DefunctDataHistory>();
+ Set<DefunctDataHistory> historySet = defunctDataHistory.putIfAbsent(ownerName, newHistorySet);
+ if (historySet == null)
+ {
+ historySet = newHistorySet;
+ }
+
+ DefunctDataHistory history = new DefunctDataHistory(ownerName, (Integer) defunctBackupRootFqn.getLastElement(), System.currentTimeMillis());
+ historySet.add(history);
+
for (Object child : backupRoot.getChildren())
{
Fqn childFqn = ((Node) child).getFqn();
cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache.move(childFqn, defunctBackupRootFqn);
}
+
+ history.recordDataMoved();
cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
backupRoot.getParentDirect().removeChild(backupRoot.getFqn().getLastElement());
@@ -1323,4 +1384,36 @@
{
return buddyGroupsIParticipateIn.toString();
}
+
+ private class DefunctDataHistory
+ {
+ private final String owner;
+ private final int generation;
+ private final long timestamp;
+ private long dataMoved;
+ private long moveElapsedTime;
+
+ private DefunctDataHistory(String owner, int generation, long timestamp)
+ {
+ this.owner = owner;
+ this.generation = generation;
+ this.timestamp = timestamp;
+ }
+
+ private void recordDataMoved()
+ {
+ this.dataMoved = System.currentTimeMillis();
+ this.moveElapsedTime = this.dataMoved - this.timestamp;
+ }
+
+ private boolean isStale()
+ {
+ if (dataMoved == 0)
+ return false;
+
+ long max = Math.max(BuddyManager.this.configuration.getLockAcquisitionTimeout(), 60000);
+ max = max + moveElapsedTime;
+ return System.currentTimeMillis() - max < dataMoved;
+ }
+ }
}
\ No newline at end of file
Modified: core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java 2009-08-14 19:31:20 UTC (rev 8182)
+++ core/trunk/src/main/java/org/jboss/cache/commands/remote/DataGravitationCleanupCommand.java 2009-08-15 22:25:40 UTC (rev 8183)
@@ -105,20 +105,23 @@
Object result = executeRemove(gtx, backup);
if (wasNodeRemoved(result))
{
- // if this is a DIRECT child of a DEAD buddy backup region, then remove the empty dead region structural node.
- Fqn deadBackupRootFqn = null;
- if (buddyFqnTransformer.isDeadBackupFqn(backup) && buddyFqnTransformer.isDeadBackupRoot(backup.getAncestor(backup.size() - 2))
- && !dataContainer.hasChildren((deadBackupRootFqn = backup.getParent())))
+ cleanEmptyDeadRegion(gtx, backup);
+ }
+ else
+ {
+ // JBCACHE-1530 -- check for race where node was moved to a
+ // xxx:DEAD region just after we returned it as a GravitateResult
+ List<Fqn<?>> deadFqns = buddyManager.getNewlyDeadBackupFqns(backup);
+ if (deadFqns != null)
{
- if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
- executeRemove(gtx, deadBackupRootFqn);
-
- // now check the grand parent and see if we are free of versions
- deadBackupRootFqn = deadBackupRootFqn.getParent();
- if (!dataContainer.hasChildren(deadBackupRootFqn))
+ for (Fqn<?> dead : deadFqns)
{
- if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
- executeRemove(gtx, deadBackupRootFqn);
+ result = executeRemove(gtx, dead);
+ if (wasNodeRemoved(result))
+ {
+ cleanEmptyDeadRegion(gtx, dead);
+ break;
+ }
}
}
}
@@ -138,6 +141,26 @@
return null;
}
+ private void cleanEmptyDeadRegion(GlobalTransaction gtx, Fqn backupFqn) throws Throwable
+ {
+ // if this is a DIRECT child of a DEAD buddy backup region, then remove the empty dead region structural node.
+ Fqn deadBackupRootFqn = null;
+ if (buddyFqnTransformer.isDeadBackupFqn(backupFqn) && buddyFqnTransformer.isDeadBackupRoot(backup.getAncestor(backupFqn.size() - 2))
+ && !dataContainer.hasChildren((deadBackupRootFqn = backupFqn.getParent())))
+ {
+ if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
+ executeRemove(gtx, deadBackupRootFqn);
+
+ // now check the grand parent and see if we are free of versions
+ deadBackupRootFqn = deadBackupRootFqn.getParent();
+ if (!dataContainer.hasChildren(deadBackupRootFqn))
+ {
+ if (trace) log.trace("Removing dead backup region " + deadBackupRootFqn);
+ executeRemove(gtx, deadBackupRootFqn);
+ }
+ }
+ }
+
/**
* Returns true if such a node was removed.
*/
More information about the jbosscache-commits
mailing list