You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/05/26 12:26:14 UTC
svn commit: r778645 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/version/
test/java/org/apache/jackrabbit/core/version/
Author: jukka
Date: Tue May 26 10:26:13 2009
New Revision: 778645
URL: http://svn.apache.org/viewvc?rev=778645&view=rev
Log:
JCR-134: Unreferenced VersionHistory should be deleted automatically
Applied patch contributed by Sébastien Launay
Added:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java?rev=778645&r1=778644&r2=778645&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java Tue May 26 10:26:13 2009
@@ -40,8 +40,8 @@
/**
* Base implementation of the {@link VersionManager} interface.
* <p/>
- * All read operations must aquire the read lock before reading, all write
- * operations must aquire the write lock.
+ * All read operations must acquire the read lock before reading, all write
+ * operations must acquire the write lock.
*/
abstract class AbstractVersionManager implements VersionManager {
@@ -291,7 +291,7 @@
/**
* Returns the item with the given persistent id. Subclass responsibility.
* <p/>
- * Please note, that the overridden method must aquire the readlock before
+ * Please note, that the overridden method must acquire the readlock before
* reading the state manager.
*
* @param id the id of the item
@@ -312,18 +312,31 @@
/**
* Checks if there are item references (from outside the version storage)
- * that reference the given version item. Subclass responsiblity.
+ * that reference the given node. Subclass responsibility.
* <p/>
- * Please note, that the overridden method must aquire the readlock before
+ * Please note, that the overridden method must acquire the readlock before
* reading the state manager.
*
- * @param item version item
+ * @param id the id of the node
* @return <code>true</code> if there are item references from outside the
* version storage; <code>false</code> otherwise.
* @throws RepositoryException if an error occurs while reading from the
* repository.
*/
- protected abstract boolean hasItemReferences(InternalVersionItem item)
+ protected abstract boolean hasItemReferences(NodeId id)
+ throws RepositoryException;
+
+ /**
+ * Returns the node with the given persistent id. Subclass responsibility.
+ * <p/>
+ * Please note, that the overridden method must acquire the readlock before
+ * reading the state manager.
+ *
+ * @param id the id of the node
+ * @throws RepositoryException if an error occurs while reading from the
+ * repository.
+ */
+ protected abstract NodeStateEx getNodeStateEx(NodeId id)
throws RepositoryException;
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java?rev=778645&r1=778644&r2=778645&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java Tue May 26 10:26:13 2009
@@ -375,7 +375,7 @@
throw new VersionException(msg);
}
// check if any references (from outside the version storage) exist on this version
- if (vMgr.hasItemReferences(v)) {
+ if (vMgr.hasItemReferences(v.getId())) {
throw new ReferentialIntegrityException("Unable to remove version. At least once referenced.");
}
@@ -396,8 +396,25 @@
nameCache.remove(versionName);
vMgr.versionDestroyed(v);
- // store changes
- node.store();
+ // Check if this was the last version in addition to the root version
+ if (!vMgr.hasItemReferences(node.getNodeId())) {
+ log.debug("Current version history has no references");
+ NodeStateEx[] childNodes = node.getChildNodes();
+
+ // Check if there is only root version and version labels nodes
+ if (childNodes.length == 2) {
+ log.debug("Removing orphan version history as it contains only two children");
+ NodeStateEx parentNode = vMgr.getNodeStateEx(node.getParentId());
+ // Remove version history node
+ parentNode.removeNode(node.getName());
+ // store changes for this node and his children
+ parentNode.store();
+ }
+ } else {
+ log.debug("Current version history has at least one reference");
+ // store changes
+ node.store();
+ }
// now also remove from labelCache
for (int i = 0; i < labels.length; i++) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=778645&r1=778644&r2=778645&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Tue May 26 10:26:13 2009
@@ -411,14 +411,19 @@
/**
* {@inheritDoc}
*/
- protected boolean hasItemReferences(InternalVersionItem item)
+ protected boolean hasItemReferences(NodeId id)
+ throws RepositoryException {
+ return stateMgr.hasNodeReferences(new NodeReferencesId(id));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected NodeStateEx getNodeStateEx(NodeId parentNodeId)
throws RepositoryException {
try {
- NodeReferences refs = stateMgr.getNodeReferences(
- new NodeReferencesId(item.getId()));
- return refs.hasReferences();
- } catch (NoSuchItemStateException e) {
- return false;
+ NodeState state = (NodeState) stateMgr.getItemState(parentNodeId);
+ return new NodeStateEx(stateMgr, ntReg, state, null);
} catch (ItemStateException e) {
throw new RepositoryException(e);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java?rev=778645&r1=778644&r2=778645&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java Tue May 26 10:26:13 2009
@@ -370,9 +370,22 @@
/**
* {@inheritDoc}
*/
- protected boolean hasItemReferences(InternalVersionItem item)
+ protected boolean hasItemReferences(NodeId id)
throws RepositoryException {
- return session.getNodeById(item.getId()).getReferences().hasNext();
+ return session.getNodeById(id).getReferences().hasNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected NodeStateEx getNodeStateEx(NodeId parentNodeId)
+ throws RepositoryException {
+ try {
+ NodeState state = (NodeState) stateMgr.getItemState(parentNodeId);
+ return new NodeStateEx(stateMgr, ntReg, state, null);
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
}
/**
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java?rev=778645&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java Tue May 26 10:26:13 2009
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.version;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Workspace;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * Test case for JCR-134.
+ */
+public class RemoveOrphanVersionHistoryTest extends AbstractJCRTest {
+
+ /**
+ * Test orphan version history cleaning in a single workspace.
+ * @throws RepositoryException if an error occurs.
+ */
+ public void testRemoveOrphanVersionHistory() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixVersionable);
+ testRootNode.save();
+ Session session = n.getSession();
+ VersionHistory vh = n.getVersionHistory();
+ String vhUuid = vh.getUUID();
+ assertExists(session, vhUuid);
+
+ // First version
+ Version v10 = n.checkin();
+ n.checkout();
+
+ // Second version
+ Version v11 = n.checkin();
+ n.checkout();
+
+ // Remove node
+ n.remove();
+ testRootNode.save();
+ assertExists(session, vhUuid);
+
+ // Remove the first version
+ vh.removeVersion(v10.getName());
+ assertExists(session, vhUuid);
+
+ // Remove the second and last version
+ vh.removeVersion(v11.getName());
+
+ try {
+ session.getNodeByUUID(vhUuid);
+ fail("Orphan version history must have been removed");
+ } catch (ItemNotFoundException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * Test orphan version history cleaning in multiple workspace.
+ * @throws RepositoryException if an error occurs.
+ */
+ public void testWorkspaceRemoveOrphanVersionHistory() throws RepositoryException {
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixVersionable);
+ testRootNode.save();
+ Session session = n.getSession();
+ VersionHistory vh = n.getVersionHistory();
+ String vhUuid = vh.getUUID();
+ assertExists(session, vhUuid);
+
+ // First version
+ Version v10 = n.checkin();
+ n.checkout();
+
+ Workspace defaultWorkspace = n.getSession().getWorkspace();
+ Session otherWsSession = n.getSession().getRepository().login(new SimpleCredentials("superuser", "".toCharArray()), workspaceName);
+ // Clone the node in another workspace
+ otherWsSession.getWorkspace().clone(defaultWorkspace.getName(), n.getPath(), n.getPath(), false);
+ Node otherWsRootNode = otherWsSession.getRootNode();
+ Node clonedNode = otherWsRootNode.getNode(n.getPath().substring(1));
+ // Ensure that version histories are the same
+ assertEquals(vhUuid, clonedNode.getVersionHistory().getUUID());
+
+ Version v11 = clonedNode.checkin();
+ clonedNode.checkout();
+
+ // Remove node
+ n.remove();
+ testRootNode.save();
+ assertExists(session, vhUuid);
+ assertExists(otherWsSession, vhUuid);
+
+ // Remove the first version
+ vh.removeVersion(v10.getName());
+ assertExists(session, vhUuid);
+ assertExists(otherWsSession, vhUuid);
+
+ // Remove cloned node
+ clonedNode.remove();
+ otherWsRootNode.save();
+ assertExists(session, vhUuid);
+ assertExists(otherWsSession, vhUuid);
+
+ // Remove the last version
+ vh.removeVersion(v11.getName());
+
+ try {
+ session.getNodeByUUID(vhUuid);
+ fail("Orphan version history must have been removed from the default workspace");
+ } catch (ItemNotFoundException e) {
+ // Expected
+ }
+
+ try {
+ otherWsSession.getNodeByUUID(vhUuid);
+ fail("Orphan version history must have been removed from the other workspace");
+ } catch (ItemNotFoundException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * Assert that a node exists in a session.
+ * @param session the session.
+ * @param uuid the node's UUID.
+ * @throws RepositoryException if an error occurs.
+ */
+ protected void assertExists(Session session, String uuid) throws RepositoryException
+ {
+ try {
+ session.getNodeByUUID(uuid);
+ } catch (ItemNotFoundException e) {
+ fail("Unknown uuid: " + uuid);
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/version/RemoveOrphanVersionHistoryTest.java
------------------------------------------------------------------------------
svn:eol-style = native