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 2010/06/24 18:57:02 UTC
svn commit: r957626 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
./ session/
Author: jukka
Date: Thu Jun 24 16:57:01 2010
New Revision: 957626
URL: http://svn.apache.org/viewvc?rev=957626&view=rev
Log:
JCR-890: concurrent read-only access to a session
Handle Session.logout() in a way that prevents concurrent session access.
Also move the SessionContext argument from perform() to a member variable of SessionOperation.
Removed:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/ActiveSessionState.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/ClosedSessionState.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemRefreshOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionRefreshOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionSaveOperation.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionState.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Thu Jun 24 16:57:01 2010
@@ -384,7 +384,7 @@ public abstract class ItemImpl implement
public void save() throws RepositoryException {
// check state of this instance
sanityCheck();
- perform(new ItemSaveOperation(getItemState()));
+ perform(new ItemSaveOperation(sessionContext, getItemState()));
}
/**
@@ -399,7 +399,7 @@ public abstract class ItemImpl implement
// of all descendant non-transient instances; maybe also
// have to reset stale ItemState instances
} else {
- perform(new ItemRefreshOperation(getItemState()));
+ perform(new ItemRefreshOperation(sessionContext, getItemState()));
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemRefreshOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemRefreshOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemRefreshOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemRefreshOperation.java Thu Jun 24 16:57:01 2010
@@ -22,13 +22,13 @@ public class ItemRefreshOperation extend
private final ItemState state;
- public ItemRefreshOperation(ItemState state) {
- super("item refresh");
+ public ItemRefreshOperation(SessionContext context, ItemState state) {
+ super("item refresh", context);
this.state = state;
}
@Override
- public void perform(SessionContext context) throws RepositoryException {
+ public void perform() throws RepositoryException {
SessionItemStateManager stateMgr = context.getItemStateManager();
// Optimisation for the root node
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java Thu Jun 24 16:57:01 2010
@@ -82,13 +82,13 @@ class ItemSaveOperation extends SessionO
private final ItemState state;
- public ItemSaveOperation(ItemState state) {
- super("item save");
+ public ItemSaveOperation(SessionContext context, ItemState state) {
+ super("item save", context);
this.state = state;
}
@Override
- public void perform(SessionContext context) throws RepositoryException {
+ public void perform() throws RepositoryException {
SessionItemStateManager stateMgr = context.getItemStateManager();
/**
@@ -97,7 +97,7 @@ class ItemSaveOperation extends SessionO
*/
Collection<ItemState> dirty;
try {
- dirty = getTransientStates(stateMgr);
+ dirty = getTransientStates();
} catch (ConcurrentModificationException e) {
String msg = "Concurrent modification; session is closed";
log.error(msg, e);
@@ -113,7 +113,7 @@ class ItemSaveOperation extends SessionO
* build list of transient descendants in the attic
* (i.e. those marked as 'removed')
*/
- Collection<ItemState> removed = getRemovedStates(stateMgr);
+ Collection<ItemState> removed = getRemovedStates();
// All affected item states. The keys are used to look up whether
// an item is affected, and the values are iterated through below
@@ -214,7 +214,7 @@ class ItemSaveOperation extends SessionO
// validate access and node type constraints
// (this will also validate child removals)
- validateTransientItems(context, dirty, removed);
+ validateTransientItems(dirty, removed);
// start the update operation
try {
@@ -226,20 +226,20 @@ class ItemSaveOperation extends SessionO
boolean succeeded = false;
try {
// process transient items marked as 'removed'
- removeTransientItems(stateMgr, removed);
+ removeTransientItems(removed);
// process transient items that have change in mixins
- processShareableNodes(context, dirty);
+ processShareableNodes(dirty);
// initialize version histories for new nodes (might generate new transient state)
- if (initVersionHistories(context, dirty)) {
+ if (initVersionHistories(dirty)) {
// re-build the list of transient states because the previous call
// generated new transient state
- dirty = getTransientStates(stateMgr);
+ dirty = getTransientStates();
}
// process 'new' or 'modified' transient states
- persistTransientItems(context.getItemManager(), dirty);
+ persistTransientItems(dirty);
// dispose the transient states marked 'new' or 'modified'
// at this point item state data is pushed down one level,
@@ -272,7 +272,7 @@ class ItemSaveOperation extends SessionO
// applied by persistTransientItems() and we need to
// restore transient state, i.e. undo the effect of
// persistTransientItems()
- restoreTransientItems(context, dirty);
+ restoreTransientItems(dirty);
}
}
@@ -297,8 +297,7 @@ class ItemSaveOperation extends SessionO
* @throws InvalidItemStateException
* @throws RepositoryException
*/
- private Collection<ItemState> getTransientStates(
- SessionItemStateManager stateMgr)
+ private Collection<ItemState> getTransientStates()
throws InvalidItemStateException, RepositoryException {
// list of transient states that should be persisted
ArrayList<ItemState> dirty = new ArrayList<ItemState>();
@@ -306,7 +305,7 @@ class ItemSaveOperation extends SessionO
if (state.isNode()) {
// build list of 'new' or 'modified' descendants
for (ItemState transientState
- : stateMgr.getDescendantTransientItemStates(state.getId())) {
+ : context.getItemStateManager().getDescendantTransientItemStates(state.getId())) {
// fail-fast test: check status of transient state
switch (transientState.getStatus()) {
case ItemState.STATUS_NEW:
@@ -385,13 +384,12 @@ class ItemSaveOperation extends SessionO
* @throws InvalidItemStateException
* @throws RepositoryException
*/
- private Collection<ItemState> getRemovedStates(
- SessionItemStateManager stateMgr)
+ private Collection<ItemState> getRemovedStates()
throws InvalidItemStateException, RepositoryException {
if (state.isNode()) {
ArrayList<ItemState> removed = new ArrayList<ItemState>();
for (ItemState transientState
- : stateMgr.getDescendantTransientItemStatesInAttic(state.getId())) {
+ : context.getItemStateManager().getDescendantTransientItemStatesInAttic(state.getId())) {
// check if stale
switch (transientState.getStatus()) {
case ItemState.STATUS_STALE_MODIFIED:
@@ -435,7 +433,6 @@ class ItemSaveOperation extends SessionO
* and in Property.setValue (for properties to be modified).
*/
private void validateTransientItems(
- SessionContext context,
Iterable<ItemState> dirty, Iterable<ItemState> removed)
throws RepositoryException {
SessionImpl session = context.getSessionImpl();
@@ -494,7 +491,7 @@ class ItemSaveOperation extends SessionO
// primary type
NodeTypeImpl pnt = ntMgr.getNodeType(nodeState.getNodeTypeName());
// effective node type (primary type incl. mixins)
- EffectiveNodeType ent = getEffectiveNodeType(context, nodeState);
+ EffectiveNodeType ent = getEffectiveNodeType(nodeState);
/**
* if the transient node was added (i.e. if it is 'new') or if
* its primary type has changed, check its node type against the
@@ -712,17 +709,13 @@ class ItemSaveOperation extends SessionO
* walk through list of transient items marked 'removed' and
* definitively remove each one
*/
- private void removeTransientItems(
- SessionItemStateManager stateMgr, Iterable<ItemState> states) {
+ private void removeTransientItems(Iterable<ItemState> states) {
for (ItemState transientState : states) {
ItemState persistentState = transientState.getOverlayedState();
- /**
- * remove persistent state
- *
- * this will indirectly (through stateDestroyed listener method)
- * permanently invalidate all Item instances wrapping it
- */
- stateMgr.destroy(persistentState);
+ // remove persistent state
+ // this will indirectly (through stateDestroyed listener method)
+ // permanently invalidate all Item instances wrapping it
+ context.getItemStateManager().destroy(persistentState);
}
}
@@ -736,8 +729,7 @@ class ItemSaveOperation extends SessionO
* has been removed, throw.</li>
* </ul>
*/
- private void processShareableNodes(
- SessionContext context, Iterable<ItemState> states)
+ private void processShareableNodes(Iterable<ItemState> states)
throws RepositoryException {
for (ItemState is : states) {
if (is.isNode()) {
@@ -745,10 +737,10 @@ class ItemSaveOperation extends SessionO
boolean wasShareable = false;
if (ns.hasOverlayedState()) {
NodeState old = (NodeState) ns.getOverlayedState();
- EffectiveNodeType ntOld = getEffectiveNodeType(context, old);
+ EffectiveNodeType ntOld = getEffectiveNodeType(old);
wasShareable = ntOld.includesNodeType(NameConstants.MIX_SHAREABLE);
}
- EffectiveNodeType ntNew = getEffectiveNodeType(context, ns);
+ EffectiveNodeType ntNew = getEffectiveNodeType(ns);
boolean isShareable = ntNew.includesNodeType(NameConstants.MIX_SHAREABLE);
if (!wasShareable && isShareable) {
@@ -773,8 +765,7 @@ class ItemSaveOperation extends SessionO
* @return true if this call generated new transient state; otherwise false
* @throws RepositoryException
*/
- private boolean initVersionHistories(
- SessionContext context, Iterable<ItemState> states)
+ private boolean initVersionHistories(Iterable<ItemState> states)
throws RepositoryException {
SessionImpl session = context.getSessionImpl();
ItemManager itemMgr = context.getItemManager();
@@ -784,7 +775,7 @@ class ItemSaveOperation extends SessionO
for (ItemState itemState : states) {
if (itemState.isNode()) {
NodeState nodeState = (NodeState) itemState;
- EffectiveNodeType nt = getEffectiveNodeType(context, nodeState);
+ EffectiveNodeType nt = getEffectiveNodeType(nodeState);
if (nt.includesNodeType(NameConstants.MIX_VERSIONABLE)) {
if (!nodeState.hasPropertyName(NameConstants.JCR_VERSIONHISTORY)) {
NodeImpl node = (NodeImpl) itemMgr.getItem(itemState.getId());
@@ -839,9 +830,9 @@ class ItemSaveOperation extends SessionO
/**
* walk through list of transient items and persist each one
*/
- private void persistTransientItems(
- ItemManager itemMgr, Iterable<ItemState> states)
+ private void persistTransientItems(Iterable<ItemState> states)
throws RepositoryException {
+ ItemManager itemMgr = context.getItemManager();
for (ItemState state : states) {
// persist state of transient item
itemMgr.getItem(state.getId()).makePersistent();
@@ -851,8 +842,7 @@ class ItemSaveOperation extends SessionO
/**
* walk through list of transient states and re-apply transient changes
*/
- private void restoreTransientItems(
- SessionContext context, Iterable<ItemState> items) {
+ private void restoreTransientItems(Iterable<ItemState> items) {
ItemManager itemMgr = context.getItemManager();
SessionItemStateManager stateMgr = context.getItemStateManager();
@@ -907,8 +897,7 @@ class ItemSaveOperation extends SessionO
* @return the effective node type
* @throws RepositoryException
*/
- private EffectiveNodeType getEffectiveNodeType(
- SessionContext context, NodeState state)
+ private EffectiveNodeType getEffectiveNodeType(NodeState state)
throws RepositoryException {
try {
NodeTypeRegistry registry =
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Thu Jun 24 16:57:01 2010
@@ -1579,7 +1579,7 @@ public class NodeImpl extends ItemImpl i
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
SetPropertyOperation operation =
- new SetPropertyOperation(name, value, false);
+ new SetPropertyOperation(sessionContext, name, value, false);
sessionContext.getSessionState().perform(operation);
return operation.getProperty();
}
@@ -2165,8 +2165,8 @@ public class NodeImpl extends ItemImpl i
if (value != null && value.getType() != type) {
value = ValueHelper.convert(value, type, getValueFactory());
}
- SetPropertyOperation operation =
- new SetPropertyOperation(session.getQName(name), value, true);
+ SetPropertyOperation operation = new SetPropertyOperation(
+ sessionContext, session.getQName(name), value, true);
sessionContext.getSessionState().perform(operation);
return operation.getProperty();
}
@@ -2174,8 +2174,8 @@ public class NodeImpl extends ItemImpl i
/** Wrapper around {@link SetPropertyOperation} */
public Property setProperty(String name, Value value)
throws RepositoryException {
- SetPropertyOperation operation =
- new SetPropertyOperation(session.getQName(name), value, false);
+ SetPropertyOperation operation = new SetPropertyOperation(
+ sessionContext, session.getQName(name), value, false);
sessionContext.getSessionState().perform(operation);
return operation.getProperty();
}
@@ -2271,8 +2271,9 @@ public class NodeImpl extends ItemImpl i
* @param enforceType <code>true</code> to enforce the value type
*/
public SetPropertyOperation(
+ SessionContext sessionContext,
Name name, Value value, boolean enforceType) {
- super("setProperty()");
+ super("setProperty()", sessionContext);
this.name = name;
this.value = value;
this.enforceType = enforceType;
@@ -2305,7 +2306,7 @@ public class NodeImpl extends ItemImpl i
* @throws RepositoryException if another error occurs.
*/
@Override
- public void perform(SessionContext context) throws RepositoryException {
+ public void perform() throws RepositoryException {
itemSanityCheck();
// check pre-conditions for setting property
checkSetProperty();
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Thu Jun 24 16:57:01 2010
@@ -34,8 +34,6 @@ import org.apache.jackrabbit.core.securi
import org.apache.jackrabbit.core.security.SecurityConstants;
import org.apache.jackrabbit.core.security.authentication.AuthContext;
import org.apache.jackrabbit.core.security.authorization.Permission;
-import org.apache.jackrabbit.core.session.ActiveSessionState;
-import org.apache.jackrabbit.core.session.ClosedSessionState;
import org.apache.jackrabbit.core.session.SessionContext;
import org.apache.jackrabbit.core.session.SessionOperation;
import org.apache.jackrabbit.core.session.SessionRefreshOperation;
@@ -243,7 +241,6 @@ public class SessionImpl extends Abstrac
WorkspaceConfig wspConfig)
throws AccessDeniedException, RepositoryException {
this.context = new SessionContext(repositoryContext, this);
- this.context.setSessionState(new ActiveSessionState(context));
this.repositoryContext = repositoryContext;
this.subject = subject;
@@ -851,14 +848,15 @@ public class SessionImpl extends Abstrac
* {@inheritDoc}
*/
public void save() throws RepositoryException {
- perform(new SessionSaveOperation());
+ perform(new SessionSaveOperation(context));
}
/**
* {@inheritDoc}
*/
public void refresh(boolean keepChanges) throws RepositoryException {
- perform(new SessionRefreshOperation(keepChanges, clusterSyncOnRefresh()));
+ perform(new SessionRefreshOperation(
+ context, keepChanges, clusterSyncOnRefresh()));
}
/**
@@ -892,7 +890,8 @@ public class SessionImpl extends Abstrac
*/
public void move(String srcAbsPath, String destAbsPath)
throws RepositoryException {
- perform(new SessionMoveOperation(this, srcAbsPath, destAbsPath));
+ perform(new SessionMoveOperation(
+ context, this, srcAbsPath, destAbsPath));
}
/**
@@ -960,56 +959,51 @@ public class SessionImpl extends Abstrac
}
/**
- * {@inheritDoc}
+ * Invalidates this session and releases all associated resources.
*/
@Override
- public synchronized void logout() {
- if (!isLive()) {
- // ignore
- return;
- }
-
- // JCR-798: Remove all registered event listeners to avoid concurrent
- // access to session internals by the event delivery or even listeners
- removeRegisteredEventListeners();
-
- // discard any pending changes first as those might
- // interfere with subsequent operations
- context.getItemStateManager().disposeAllTransientItemStates();
-
- // notify listeners that session is about to be closed
- notifyLoggingOut();
-
- // dispose session item state manager
- context.getItemStateManager().dispose();
- // dispose item manager
- context.getItemManager().dispose();
- // dispose workspace
- wsp.dispose();
+ public void logout() {
+ if (context.getSessionState().close()) {
+ // JCR-798: Remove all registered event listeners to avoid concurrent
+ // access to session internals by the event delivery or even listeners
+ removeRegisteredEventListeners();
+
+ // discard any pending changes first as those might
+ // interfere with subsequent operations
+ context.getItemStateManager().disposeAllTransientItemStates();
+
+ // notify listeners that session is about to be closed
+ notifyLoggingOut();
+
+ // dispose session item state manager
+ context.getItemStateManager().dispose();
+ // dispose item manager
+ context.getItemManager().dispose();
+ // dispose workspace
+ wsp.dispose();
- // invalidate session
- context.setSessionState(new ClosedSessionState());
+ // logout JAAS subject
+ if (loginContext != null) {
+ try {
+ loginContext.logout();
+ } catch (javax.security.auth.login.LoginException le) {
+ log.warn("failed to logout current subject: " + le.getMessage());
+ }
+ loginContext = null;
+ }
- // logout JAAS subject
- if (loginContext != null) {
try {
- loginContext.logout();
- } catch (javax.security.auth.login.LoginException le) {
- log.warn("failed to logout current subject: " + le.getMessage());
+ context.getAccessManager().close();
+ } catch (Exception e) {
+ log.warn("error while closing AccessManager", e);
}
- loginContext = null;
- }
- try {
- context.getAccessManager().close();
- } catch (Exception e) {
- log.warn("error while closing AccessManager", e);
+ // finally notify listeners that session has been closed
+ notifyLoggedOut();
}
-
- // finally notify listeners that session has been closed
- notifyLoggedOut();
}
+
/**
* {@inheritDoc}
*/
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java Thu Jun 24 16:57:01 2010
@@ -54,9 +54,10 @@ public class SessionMoveOperation extend
private final Path.Element destName;
public SessionMoveOperation(
+ SessionContext sessionContext,
PathResolver resolver, String srcAbsPath, String destAbsPath)
throws RepositoryException {
- super("move");
+ super("move", sessionContext);
this.srcAbsPath = srcAbsPath;
this.srcPath = getAbsolutePath(resolver, srcAbsPath);
@@ -104,7 +105,8 @@ public class SessionMoveOperation extend
}
}
- public void perform(SessionContext context) throws RepositoryException {
+ @Override
+ public void perform() throws RepositoryException {
// Get node instances
NodeImpl targetNode = getNode(context, srcPath, srcAbsPath);
NodeImpl srcParentNode =
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java Thu Jun 24 16:57:01 2010
@@ -32,7 +32,10 @@ public class SessionContext {
private final SessionImpl session;
- private volatile SessionState state;
+ /**
+ * The state of this session.
+ */
+ private final SessionState state;
/**
* The item state manager of this session
@@ -60,6 +63,7 @@ public class SessionContext {
assert session != null;
this.repositoryContext = repositoryContext;
this.session = session;
+ this.state = new SessionState();
}
public RepositoryContext getRepositoryContext() {
@@ -93,10 +97,6 @@ public class SessionContext {
return state;
}
- public void setSessionState(SessionState state) {
- this.state = state;
- }
-
public SessionItemStateManager getItemStateManager() {
assert itemStateManager != null;
return itemStateManager;
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionOperation.java Thu Jun 24 16:57:01 2010
@@ -23,23 +23,30 @@ import javax.jcr.RepositoryException;
* {@link SessionState} interface to implement generic controls like
* synchronization and liveness checks on all session operation.
*/
-public class SessionOperation {
+public abstract class SessionOperation {
private final String name;
- public SessionOperation(String name) {
+ protected final SessionContext context;
+
+ /**
+ * Creates a new session operation.
+ *
+ * @param name operation name
+ * @param context component context of the session
+ */
+ protected SessionOperation(String name, SessionContext context) {
this.name = name;
+ this.context = context;
}
/**
* Performs this operation. The default implementation does nothing;
* subclasses should override this method to implement custom operations.
*
- * @param context component context of the session
* @throws RepositoryException if the operation fails
*/
- public void perform(SessionContext context) throws RepositoryException {
- }
+ public abstract void perform() throws RepositoryException;
/**
* Returns the name of this operation.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionRefreshOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionRefreshOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionRefreshOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionRefreshOperation.java Thu Jun 24 16:57:01 2010
@@ -30,14 +30,15 @@ public class SessionRefreshOperation ext
private final boolean clusterSync;
- public SessionRefreshOperation(boolean keepChanges, boolean clusterSync) {
- super("refresh");
+ public SessionRefreshOperation(
+ SessionContext context, boolean keepChanges, boolean clusterSync) {
+ super("refresh", context);
this.keepChanges = keepChanges;
this.clusterSync = clusterSync;
}
@Override
- public void perform(SessionContext context) throws RepositoryException {
+ public void perform() throws RepositoryException {
// JCR-1753: Ensure that we are up to date with cluster changes
ClusterNode cluster = context.getRepositoryContext().getClusterNode();
if (cluster != null && clusterSync) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionSaveOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionSaveOperation.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionSaveOperation.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionSaveOperation.java Thu Jun 24 16:57:01 2010
@@ -23,13 +23,12 @@ import org.apache.jackrabbit.core.id.Nod
public class SessionSaveOperation extends SessionOperation {
- public SessionSaveOperation() {
- super("save");
+ public SessionSaveOperation(SessionContext context) {
+ super("save", context);
}
@Override
- public void perform(SessionContext context)
- throws RepositoryException {
+ public void perform() throws RepositoryException {
NodeId id;
// JCR-2425: check whether session is allowed to read root node
if (context.getSessionImpl().hasPermission("/", Session.ACTION_READ)) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionState.java?rev=957626&r1=957625&r2=957626&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionState.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionState.java Thu Jun 24 16:57:01 2010
@@ -16,13 +16,35 @@
*/
package org.apache.jackrabbit.core.session;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* The internal state of a session.
*/
-public interface SessionState {
+public class SessionState {
+
+ /**
+ * Logger instance.
+ */
+ private static final Logger log =
+ LoggerFactory.getLogger(SessionState.class);
+
+ /**
+ * The lock used to guarantee synchronized execution of repository
+ * operations. An explicit lock is used instead of normal Java
+ * synchronization in order to be able to log attempts to concurrently
+ * use a session. TODO: Check if this is a performance issue!
+ */
+ private final Lock lock = new ReentrantLock();
+
+ private volatile Exception closed = null;
/**
* Checks whether this session is alive.
@@ -31,22 +53,63 @@ public interface SessionState {
* @return <code>true</code> if the session is alive,
* <code>false</code> otherwise
*/
- boolean isAlive();
+ public boolean isAlive() {
+ return closed == null;
+ }
/**
* Throws an exception if this session is not alive.
*
* @throws RepositoryException throw if this session is not alive
*/
- void checkAlive() throws RepositoryException;
+ public void checkAlive() throws RepositoryException {
+ if (!isAlive()) {
+ throw new RepositoryException(
+ "This session has been closed. See the chained exception"
+ + " for a trace of where the session was closed", closed);
+ }
+ }
/**
- * Performs the given session operation.
+ * Performs the given operation within a synchronized block.
*
- * @param operation the session operation
- * @throws RepositoryException if the operation fails or can not
- * for some other reason be performed
+ * @throws RepositoryException if the operation fails
*/
- void perform(SessionOperation operation) throws RepositoryException;
+ public void perform(SessionOperation operation) throws RepositoryException {
+ if (!lock.tryLock()) {
+ log.warn("Attempt to perform {} while another thread is"
+ + " concurrently accessing the session. Blocking until"
+ + " the other thread is finished using this session.",
+ operation);
+ lock.lock();
+ }
+ try {
+ checkAlive();
+ log.debug("Performing {}", operation);
+ operation.perform();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean close() {
+ if (!lock.tryLock()) {
+ log.warn("Attempt to close a session while another thread is"
+ + " concurrently accessing the session. Blocking until"
+ + " the other thread is finished using this session.");
+ lock.lock();
+ }
+ try {
+ if (isAlive()) {
+ closed = new Exception();
+ return true;
+ } else {
+ log.warn("This session has already been closed", closed);
+ return false;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
}