mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
ACS-2850: fix for intermittent failure on expiryLock test (#1083)
* ACS-2850: fix for intermittent failure on expiryLock test First issue was int rounding of '(expirationDate - new Date())/1000', which for really close values of timeout set and passed through lockInfo could be rounded down to 0. Replaced by a rounding up formula. Second issue was treating timeout == 0 as timeout.infinite. WebDav Infinite timeout has it's own marker "-1", in case of 0, lock was automatically turned into infinite time lock, while it should be an exception instead as creating a lock for 0s timeout is a programming error - the lock would immediatelly be expired upon creation (perhaps even with a date in the past, seeing as the expiryDate is filled). Changes made clarify the intent behind calling the method instead of obfuscating it by passing the int value through date operations
This commit is contained in:
committed by
GitHub
parent
cd8b3594aa
commit
f5c1e26a9b
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -390,8 +390,9 @@ public class LockInfoImpl implements Serializable, LockInfo
|
||||
else
|
||||
{
|
||||
Date now = dateNow();
|
||||
long timeout = ((expires.getTime() - now.getTime()) / 1000);
|
||||
return timeout;
|
||||
long remainingTimeoutInSecondsRoundedUp = (Math.max(expires.getTime() - now.getTime(), 0) + 999) / 1000;
|
||||
|
||||
return remainingTimeoutInSecondsRoundedUp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -449,30 +449,18 @@ public class LockMethod extends WebDAVMethod
|
||||
*/
|
||||
protected final void createLock(FileInfo lockNode, String userName) throws WebDAVServerException
|
||||
{
|
||||
// Create Lock token
|
||||
lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName);
|
||||
|
||||
if (createExclusive)
|
||||
{
|
||||
// Lock the node
|
||||
lockInfo.setTimeoutSeconds(getLockTimeout());
|
||||
lockInfo.setExclusiveLockToken(lockToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!createExclusive) {
|
||||
// Shared lock creation should already have been prohibited when parsing the request body
|
||||
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
}
|
||||
|
||||
// Store lock depth
|
||||
lockToken = WebDAV.makeLockToken(lockNode.getNodeRef(), userName);
|
||||
lockInfo.setExclusiveLockToken(lockToken);
|
||||
lockInfo.setDepth(WebDAV.getDepthName(m_depth));
|
||||
// Store lock scope (shared/exclusive)
|
||||
String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED;
|
||||
lockInfo.setScope(scope);
|
||||
// Store the owner of this lock
|
||||
lockInfo.setScope(WebDAV.XML_EXCLUSIVE);
|
||||
lockInfo.setOwner(userName);
|
||||
// Lock the node
|
||||
getDAVLockService().lock(lockNode.getNodeRef(), lockInfo);
|
||||
|
||||
getDAVLockService().lock(lockNode.getNodeRef(), lockInfo, getLockTimeout());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -57,6 +57,8 @@ public interface WebDAVLockService
|
||||
|
||||
void lock(NodeRef nodeRef, LockInfo lockInfo);
|
||||
|
||||
void lock(NodeRef nodeRef, LockInfo lockInfo, int timeout);
|
||||
|
||||
/**
|
||||
* Shared method for webdav/vti to unlock node. Unlocked node is automatically removed from
|
||||
* current sessions's locked resources list.
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -32,7 +32,6 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.lock.LockUtils;
|
||||
import org.alfresco.repo.lock.mem.Lifetime;
|
||||
import org.alfresco.repo.lock.mem.LockState;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -237,33 +236,67 @@ public class WebDAVLockServiceImpl implements WebDAVLockService
|
||||
}
|
||||
}
|
||||
|
||||
public void lock(NodeRef nodeRef, LockInfo lockInfo)
|
||||
public void lock(NodeRef nodeRef, LockInfo lockInfo) {
|
||||
int timeout = (int) lockInfo.getRemainingTimeoutSeconds();
|
||||
lock(nodeRef, lockInfo, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared method for webdav/vti protocols to lock node. If node is locked for more than 24 hours it is automatically added
|
||||
* to the current session locked resources list.
|
||||
*
|
||||
* @param nodeRef the node to lock
|
||||
* @param userName userName
|
||||
* @param timeout the number of seconds before the locks expires
|
||||
*/
|
||||
@Override
|
||||
public void lock(NodeRef nodeRef, String userName, int timeout)
|
||||
{
|
||||
boolean performSessionBehavior = false;
|
||||
long timeout;
|
||||
|
||||
timeout = lockInfo.getRemainingTimeoutSeconds();
|
||||
LockInfo lockInfo = createLock(nodeRef, userName, true);
|
||||
lock(nodeRef, lockInfo, timeout);
|
||||
}
|
||||
|
||||
public void lock(NodeRef nodeRef, LockInfo lockInfo, int timeout)
|
||||
{
|
||||
// ALF-11777 fix, do not lock node for more than 24 hours (webdav and vti)
|
||||
if (timeout >= WebDAV.TIMEOUT_24_HOURS || timeout == WebDAV.TIMEOUT_INFINITY)
|
||||
boolean performSessionBehavior = false;
|
||||
if (timeout > WebDAV.TIMEOUT_24_HOURS || timeout == WebDAV.TIMEOUT_INFINITY)
|
||||
{
|
||||
timeout = WebDAV.TIMEOUT_24_HOURS;
|
||||
lockInfo.setTimeoutSeconds((int) timeout);
|
||||
performSessionBehavior = true;
|
||||
}
|
||||
|
||||
validateLockTimeout(timeout);
|
||||
lockInner(nodeRef, lockInfo, timeout);
|
||||
|
||||
if (performSessionBehavior)
|
||||
{
|
||||
performLockSessionBehavior(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLockTimeout(int timeout) {
|
||||
if (timeout != WebDAV.TIMEOUT_INFINITY && timeout == LockService.TIMEOUT_INFINITY) {
|
||||
throw new IllegalArgumentException("Timeout == " + LockService.TIMEOUT_INFINITY +
|
||||
" is treated as permanence for locks. For maximum allowed timeout set " + WebDAV.TIMEOUT_INFINITY);
|
||||
}
|
||||
}
|
||||
|
||||
private void lockInner(NodeRef nodeRef, LockInfo lockInfo, int timeout) {
|
||||
//Update/set true expiry date of a lock to be used in additional information
|
||||
lockInfo.setTimeoutSeconds(timeout);
|
||||
|
||||
// TODO: lock children according to depth? lock type?
|
||||
final String additionalInfo = lockInfo.toJSON();
|
||||
lockService.lock(nodeRef, LockType.WRITE_LOCK, (int) timeout, Lifetime.EPHEMERAL, additionalInfo);
|
||||
|
||||
lockService.lock(nodeRef, LockType.WRITE_LOCK, timeout, Lifetime.EPHEMERAL, additionalInfo);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(nodeRef + " was locked for " + timeout + " seconds.");
|
||||
}
|
||||
}
|
||||
|
||||
if (performSessionBehavior)
|
||||
{
|
||||
private void performLockSessionBehavior(NodeRef nodeRef) {
|
||||
HttpSession session = currentSession.get();
|
||||
|
||||
if (session == null)
|
||||
@@ -282,22 +315,6 @@ public class WebDAVLockServiceImpl implements WebDAVLockService
|
||||
logger.debug(nodeRef + " was added to the session " + session.getId() + " for post expiration processing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared method for webdav/vti protocols to lock node. If node is locked for more than 24 hours it is automatically added
|
||||
* to the current session locked resources list.
|
||||
*
|
||||
* @param nodeRef the node to lock
|
||||
* @param userName userName
|
||||
* @param timeout the number of seconds before the locks expires
|
||||
*/
|
||||
@Override
|
||||
public void lock(NodeRef nodeRef, String userName, int timeout)
|
||||
{
|
||||
LockInfo lockInfo = createLock(nodeRef, userName, true, timeout);
|
||||
lock(nodeRef, lockInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared method for webdav/vti to unlock node. Unlocked node is automatically removed from
|
||||
@@ -444,19 +461,15 @@ public class WebDAVLockServiceImpl implements WebDAVLockService
|
||||
* @param nodeRef NodeRef
|
||||
* @param userName String
|
||||
* @param createExclusive boolean
|
||||
* @param timeoutSecs int
|
||||
*/
|
||||
private LockInfo createLock(NodeRef nodeRef, String userName, boolean createExclusive, int timeoutSecs)
|
||||
private LockInfo createLock(NodeRef nodeRef, String userName, boolean createExclusive)
|
||||
{
|
||||
// Create Lock token
|
||||
String lockToken = WebDAV.makeLockToken(nodeRef, userName);
|
||||
|
||||
LockInfo lockInfo = new LockInfoImpl();
|
||||
|
||||
if (createExclusive)
|
||||
{
|
||||
// Lock the node
|
||||
lockInfo.setTimeoutSeconds(timeoutSecs);
|
||||
lockInfo.setExclusiveLockToken(lockToken);
|
||||
}
|
||||
else
|
||||
@@ -464,15 +477,11 @@ public class WebDAVLockServiceImpl implements WebDAVLockService
|
||||
lockInfo.addSharedLockToken(lockToken);
|
||||
}
|
||||
|
||||
// Store lock depth
|
||||
lockInfo.setDepth(WebDAV.getDepthName(WebDAV.DEPTH_INFINITY));
|
||||
// Store lock scope (shared/exclusive)
|
||||
String scope = createExclusive ? WebDAV.XML_EXCLUSIVE : WebDAV.XML_SHARED;
|
||||
lockInfo.setScope(scope);
|
||||
// Store the owner of this lock
|
||||
lockInfo.setOwner(userName);
|
||||
|
||||
// TODO: to help with debugging/refactoring (remove later)
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (!currentUser.equals(userName))
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -321,7 +321,7 @@ public class LockServiceImpl implements LockService,
|
||||
public void lock(NodeRef nodeRef, LockType lockType)
|
||||
{
|
||||
// Lock with no expiration
|
||||
lock(nodeRef, lockType, 0);
|
||||
lock(nodeRef, lockType, TIMEOUT_INFINITY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,16 +371,8 @@ public class LockServiceImpl implements LockService,
|
||||
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, Lifetime lifetime, String additionalInfo)
|
||||
{
|
||||
invokeBeforeLock(nodeRef, lockType);
|
||||
if (lifetime.equals(Lifetime.EPHEMERAL) && (timeToExpire > MAX_EPHEMERAL_LOCK_SECONDS))
|
||||
{
|
||||
throw new IllegalArgumentException("Attempt to create ephemeral lock for " +
|
||||
timeToExpire + " seconds - exceeds maximum allowed time.");
|
||||
}
|
||||
if (lifetime.equals(Lifetime.EPHEMERAL) && (timeToExpire > ephemeralExpiryThreshold))
|
||||
{
|
||||
lifetime = Lifetime.PERSISTENT;
|
||||
}
|
||||
|
||||
validateTimeToExpire(timeToExpire, lifetime);
|
||||
lifetime = switchLifetimeMode(timeToExpire, lifetime);
|
||||
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
@@ -443,6 +435,22 @@ public class LockServiceImpl implements LockService,
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTimeToExpire(int timeToExpire, Lifetime lifetime) {
|
||||
if (lifetime.equals(Lifetime.EPHEMERAL) && (timeToExpire > MAX_EPHEMERAL_LOCK_SECONDS))
|
||||
{
|
||||
throw new IllegalArgumentException("Attempt to create ephemeral lock for " +
|
||||
timeToExpire + " seconds - exceeds maximum allowed time.");
|
||||
}
|
||||
}
|
||||
|
||||
private Lifetime switchLifetimeMode(int timeToExpire, Lifetime lifetime) {
|
||||
if (lifetime.equals(Lifetime.EPHEMERAL) && (timeToExpire > ephemeralExpiryThreshold))
|
||||
{
|
||||
return Lifetime.PERSISTENT;
|
||||
}
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
private void persistLockProps(NodeRef nodeRef, LockType lockType, Lifetime lifetime, String userName, Date expiryDate, String additionalInfo)
|
||||
{
|
||||
addToIgnoreSet(nodeRef);
|
||||
@@ -468,16 +476,16 @@ public class LockServiceImpl implements LockService,
|
||||
*/
|
||||
private Date makeExpiryDate(int timeToExpire)
|
||||
{
|
||||
// Set the expiry date
|
||||
Date expiryDate = null;
|
||||
if (timeToExpire > 0)
|
||||
{
|
||||
expiryDate = new Date();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(expiryDate);
|
||||
calendar.add(Calendar.SECOND, timeToExpire);
|
||||
expiryDate = calendar.getTime();
|
||||
boolean permanent = timeToExpire <= TIMEOUT_INFINITY;
|
||||
if (permanent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date());
|
||||
calendar.add(Calendar.SECOND, timeToExpire);
|
||||
Date expiryDate = calendar.getTime();
|
||||
|
||||
return expiryDate;
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -42,6 +42,8 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@AlfrescoPublicApi
|
||||
public interface LockService
|
||||
{
|
||||
int TIMEOUT_INFINITY = 0;
|
||||
|
||||
/**
|
||||
* Places a lock on a node.
|
||||
* <p>
|
||||
|
Reference in New Issue
Block a user