jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Fabián Mandelbaum <fmandelb...@gmail.com>
Subject Re: Lock stealing
Date Fri, 13 May 2011 12:41:19 GMT
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 :-)

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