jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Guggisberg <stefan.guggisb...@gmail.com>
Subject Re: Lock stealing
Date Fri, 13 May 2011 13:14:26 GMT
2011/5/13 Fabián Mandelbaum <fmandelbaum@gmail.com>:
> Hello Stefan,
>
> how will your proposal work with long-lived (a.k.a. not session-scoped) tokens?
>
> A common scenario in web applications is that the client issuing the
> lock request is not always able to save (cache, keep, whatever one
> wants to call it) the lock tokens, and thus would not be able to pass
> the token around like you suggest (it's not uncommon that a user
> closes the web browser tab or window that had the client application
> running onto, and away goes the lock tokens that client could have
> saved...). It's common for the web application backend to maintain a
> pool of JCR sessions, thus you cannot guarantee that you'll have
> access to the session that locked the item (thus the lock token is
> 'lost' somehow...)
>
> Hope to have been clear :-)

absolutely ;)

if you need to be able to 'break' somebody else's lock
you could e.g. override the following method:

o.a.jackrabbit.core..lock.checkUnlock(LockInfo info, Session session)

that way you can implement some sort of lock administrator session which
is able to unlock any open-scoped lock.

note that you'd have to subclass RepositoryImpl as well.

cheers
stefan

>
> On Fri, May 13, 2011 at 9:24 AM, Stefan Guggisberg
> <stefan.guggisberg@gmail.com> wrote:
>> On Fri, May 13, 2011 at 8:43 AM, Kamil Nezval <kamil.nezval@xitee.com> wrote:
>>> Hi,
>>>
>>> I'm trying to implement a "stealing" of a node's lock - one user will be
>>> able to unlock the nodes locked by other users.
>>
>> i prefer the term "transferring lock ownership"...
>>
>>> According to the JCR 2.0
>>> specification it should be possible to assign a lock to a current session
>>> using LockManager.addLockToken() method:
>>>
>>> "If the implementation does not support simultaneous lock ownership this
>>> method will
>>> transfer ownership of the lock corresponding to the specified lockToken to
>>> the
>>> current session, otherwise the current session will become an additional
>>> owner of
>>> that lock."
>>>
>>> So I've tried something like this:
>>>
>>> String nodePath = node.getPath();
>>> LockManager lockManager = jcrSession.getWorkspace().getLockManager();
>>> Lock nodeLock = lockManager.getLock(nodePath);
>>> String lockToken = nodeLock.getLockToken();
>>> lockManager.addLockToken(lockToken);
>>> lockManager.unlock(nodePath);
>>> lockManager.lock(nodePath, false, false, 1000, jcrSession.getUserID());
>>>
>>> But it doesn't work ("Cannot add lock token: lock already held by other
>>> session." exception). I've looked into a source code and it looks like the
>>> implementation doesn't follow the specification at all,
>>
>> the implementation is spec-compliant. the javadoc [1] clearly states
>> that a LockException is thrown
>>
>> "if the specified lock token is already held by another Session and
>> the implementation does not support simultaneous ownership of
>> open-scoped locks."
>>
>> before adding the token to the new session you have to remove the token
>> from the other session.
>>
>> cheers
>> stefan
>>
>> [1] http://www.day.com/maven/jsr170/javadocs/jcr-2.0/javax/jcr/lock/LockManager.html#addLockToken(java.lang.String)
>>
>>> see the code bellow
>>> (LockManagerImpl.java):
>>>
>>>        public void addLockToken(SessionImpl session, String lt) throws
>>> LockException, RepositoryException {
>>>        try {
>>>            NodeId id = LockInfo.parseLockToken(lt);
>>>
>>>            NodeImpl node = (NodeImpl)
>>> sysSession.getItemManager().getItem(id);
>>>            Path path = node.getPrimaryPath();
>>>            PathMap.Element<LockInfo> element = lockMap.map(path,
true);
>>>            if (element != null) {
>>>                LockInfo info = element.get();
>>>                if (info != null) {
>>>                    if (info.isLockHolder(session)) {
>>>                        // nothing to do
>>>                    } else if (info.getLockHolder() == null) {
>>>                        info.setLockHolder(session);
>>>                        if (info instanceof InternalLockInfo) {
>>>                            session.addListener((InternalLockInfo)
info);
>>>                        }
>>>                    } else {
>>>                        String msg = "Cannot add lock token: lock
already
>>> held by other session.";
>>>                        log.warn(msg);
>>>                        info.throwLockException(msg, session);
>>>                    }
>>>                }
>>>            }
>>>            // inform SessionLockManager
>>>            getSessionLockManager(session).lockTokenAdded(lt);
>>>        } catch (IllegalArgumentException e) {
>>>            String msg = "Bad lock token: " + e.getMessage();
>>>            log.warn(msg);
>>>            throw new LockException(msg);
>>>        }
>>>    }
>>>
>>> And it is also not possible to get a lock token if the current user is not
>>> the lock holder (LockImpl.java):
>>>
>>>    public String getLockToken() {
>>>        if (!info.isSessionScoped() && info.isLockHolder(node.getSession()))
>>> {
>>>            return info.getLockToken();
>>>        } else {
>>>            return null;
>>>        }
>>>    }
>>>
>>> So my question is whether it is somehow possible to implement a
>>> "lock-stealing" as described above.
>>>
>>> Thanks in advance.
>>>
>>> Regards
>>>
>>> Kamil
>>>
>>>
>>>
>>
>
>
>
> --
> Fabián Mandelbaum
> IS Engineer
>

Mime
View raw message