mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
DM user usages - 1st pass fixes (recalc and clear)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12046 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -509,6 +509,12 @@
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="personDaoBootstrap" class="org.alfresco.repo.security.person.PersonDaoBootstrap" >
|
||||
<property name="personDaoImpl">
|
||||
<ref bean="personDaoImpl"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Start the quartz scheduler -->
|
||||
|
||||
<bean id="schedulerStarter" class="org.alfresco.util.SchedulerStarterBean" >
|
||||
@@ -567,12 +573,6 @@
|
||||
<property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="personDaoBootstrap" class="org.alfresco.repo.security.person.PersonDaoBootstrap" >
|
||||
<property name="personDaoImpl">
|
||||
<ref bean="personDaoImpl"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Startup Message -->
|
||||
|
||||
<bean id="startupLog" class="org.alfresco.repo.descriptor.DescriptorStartupLog">
|
||||
|
@@ -669,6 +669,20 @@
|
||||
p.string_value = :propStringValue
|
||||
</sql-query>
|
||||
|
||||
<query name="node.GetNodesWithCreatorAndStore">
|
||||
select
|
||||
node.id,
|
||||
node.store.protocol,
|
||||
node.store.identifier,
|
||||
node.uuid
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.NodeImpl as node
|
||||
where
|
||||
node.store.protocol = :storeProtocol and
|
||||
node.store.identifier = :storeIdentifier and
|
||||
node.auditableProperties.auditCreator = :userName
|
||||
</query>
|
||||
|
||||
<query name="node.GetNodesWithPropertyValuesByActualType">
|
||||
select
|
||||
node
|
||||
|
@@ -393,6 +393,20 @@ public interface NodeDaoService
|
||||
String value,
|
||||
NodePropertyHandler handler);
|
||||
|
||||
/**
|
||||
* Iterate over all nodes that have a given creator
|
||||
*
|
||||
* @param storeRef the store to search in
|
||||
* @param userName the user to match
|
||||
* @param handler the callback to use while iterating over the URLs
|
||||
* @return Returns the values for the given owner
|
||||
*/
|
||||
@DirtySessionAnnotation(markDirty=true)
|
||||
public void getNodesWithCreatorAndStore(
|
||||
StoreRef storeRef,
|
||||
String userName,
|
||||
NodeRefQueryCallback resultsCallback);
|
||||
|
||||
/**
|
||||
* Iterate over all property values for the given type definition. This will also dig out values that
|
||||
* were persisted as type <b>d:any</b>.
|
||||
|
@@ -142,6 +142,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
private static final String QUERY_GET_TARGET_ASSOCS = "node.GetTargetAssocs";
|
||||
private static final String QUERY_GET_SOURCE_ASSOCS = "node.GetSourceAssocs";
|
||||
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_STRING_AND_STORE = "node.GetNodesWithPropertyValuesByStringAndStore";
|
||||
private static final String QUERY_GET_NODES_WITH_CREATOR_AND_STORE = "node.GetNodesWithCreatorAndStore";
|
||||
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_ACTUAL_TYPE = "node.GetNodesWithPropertyValuesByActualType";
|
||||
private static final String QUERY_GET_SERVER_BY_IPADDRESS = "server.getServerByIpAddress";
|
||||
|
||||
@@ -2709,6 +2710,42 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
}
|
||||
|
||||
public void getNodesWithCreatorAndStore(
|
||||
final StoreRef storeRef,
|
||||
final String userName,
|
||||
final NodeRefQueryCallback resultsCallback)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session
|
||||
.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODES_WITH_CREATOR_AND_STORE)
|
||||
.setString("storeProtocol", storeRef.getProtocol())
|
||||
.setString("storeIdentifier", storeRef.getIdentifier())
|
||||
.setString("userName", userName)
|
||||
;
|
||||
DirtySessionMethodInterceptor.setQueryFlushMode(session, query);
|
||||
return query.scroll(ScrollMode.FORWARD_ONLY);
|
||||
}
|
||||
};
|
||||
ScrollableResults queryResults = null;
|
||||
try
|
||||
{
|
||||
queryResults = (ScrollableResults) getHibernateTemplate().execute(callback);
|
||||
processNodeResults(queryResults, resultsCallback);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (queryResults != null)
|
||||
{
|
||||
queryResults.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Done
|
||||
}
|
||||
|
||||
public void getPropertyValuesByActualType(DataTypeDefinition actualDataTypeDefinition, NodePropertyHandler handler)
|
||||
{
|
||||
// get the in-database string representation of the actual type
|
||||
|
@@ -25,6 +25,7 @@
|
||||
package org.alfresco.repo.usage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -32,11 +33,11 @@ import java.util.Set;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.db.NodeDaoService;
|
||||
import org.alfresco.repo.node.db.NodeDaoService.NodePropertyHandler;
|
||||
import org.alfresco.repo.node.db.NodeDaoService.NodeRefQueryCallback;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.tenant.Tenant;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.TransactionServiceImpl;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
@@ -47,6 +48,7 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.usage.UsageService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.lang.mutable.MutableLong;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -184,63 +186,102 @@ public class UserUsageTrackingComponent
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAllUsages()
|
||||
private void clearAllUsages()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.debug("Disabled - clear usages for all users ...");
|
||||
logger.info("Disabled - clear non-missing user usages ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Integer> clearAllUsages = new RetryingTransactionCallback<Integer>()
|
||||
RetryingTransactionCallback<List<NodeRef>> getPersonRefs = new RetryingTransactionCallback<List<NodeRef>>()
|
||||
{
|
||||
public Integer execute() throws Throwable
|
||||
public List<NodeRef> execute() throws Throwable
|
||||
{
|
||||
Set<NodeRef> allPeople = personService.getAllPeople();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found " + allPeople.size() + " people");
|
||||
}
|
||||
|
||||
List<NodeRef> personRefsToClear = new ArrayList<NodeRef>();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT, null);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
Long currentUsage = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
|
||||
if (currentUsage != null)
|
||||
{
|
||||
personRefsToClear.add(personNodeRef);
|
||||
}
|
||||
}
|
||||
return allPeople.size();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found " + personRefsToClear.size() + " users to clear");
|
||||
}
|
||||
|
||||
return personRefsToClear;
|
||||
}
|
||||
};
|
||||
// execute in txn
|
||||
int count = txnHelper.doInTransaction(clearAllUsages, false);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
|
||||
// execute in READ-ONLY txn
|
||||
List<NodeRef> personRefsToClear = transactionService.getRetryingTransactionHelper().doInTransaction(getPersonRefs, true);
|
||||
|
||||
for (NodeRef personNodeRef : personRefsToClear)
|
||||
{
|
||||
logger.debug("... cleared usages for " + count + " users");
|
||||
clearUsage(personNodeRef);
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("... cleared non-missing usages for " + personRefsToClear.size() + " users");
|
||||
}
|
||||
}
|
||||
|
||||
public void calculateMissingUsages()
|
||||
private void clearUsage(final NodeRef personNodeRef)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
RetryingTransactionCallback<Integer> clearPersonUsage = new RetryingTransactionCallback<Integer>()
|
||||
{
|
||||
logger.debug("Enabled - calculate missing usages ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
public Integer execute() throws Throwable
|
||||
{
|
||||
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT, null);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Cleared usage for person ("+ personNodeRef+")");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// execute in READ-WRITE txn
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(clearPersonUsage, false);
|
||||
}
|
||||
|
||||
private void calculateMissingUsages()
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("Enabled - calculate missing user usages ...");
|
||||
}
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Set<String>> getAllPeople = new RetryingTransactionCallback<Set<String>>()
|
||||
{
|
||||
public Set<String> execute() throws Throwable
|
||||
{
|
||||
Set<NodeRef> allPeople = personService.getAllPeople();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found " + allPeople.size() + " people");
|
||||
}
|
||||
|
||||
Set<String> userNames = new HashSet<String>();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
// Cater for Lucene indexes being stale
|
||||
if (!nodeService.exists(personNodeRef))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Long currentUsage = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
|
||||
if (currentUsage == null)
|
||||
{
|
||||
@@ -248,11 +289,18 @@ public class UserUsageTrackingComponent
|
||||
userNames.add(userName);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found " + userNames.size() + " users to recalculate");
|
||||
}
|
||||
|
||||
return userNames;
|
||||
}
|
||||
};
|
||||
|
||||
// execute in READ-ONLY txn
|
||||
final Set<String> userNames = txnHelper.doInTransaction(getAllPeople, true);
|
||||
Set<String> userNames = transactionService.getRetryingTransactionHelper().doInTransaction(getAllPeople, true);
|
||||
|
||||
for (final String userName : userNames)
|
||||
{
|
||||
@@ -266,9 +314,9 @@ public class UserUsageTrackingComponent
|
||||
}, tenantAdminService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantAdminService.getUserDomain(userName)));
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.debug("... calculated missing usages for " + userNames.size() + " users");
|
||||
logger.info("... calculated missing usages for " + userNames.size() + " users");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,18 +327,12 @@ public class UserUsageTrackingComponent
|
||||
*
|
||||
* @param username the username to for which calcualte usages
|
||||
*/
|
||||
public void recalculateUsage(final String username)
|
||||
{
|
||||
final RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
private void recalculateUsage(final String username)
|
||||
{
|
||||
RetryingTransactionCallback<Long> calculatePersonCurrentUsage = new RetryingTransactionCallback<Long>()
|
||||
{
|
||||
public Long execute() throws Throwable
|
||||
{
|
||||
// QNameEntity ownerQnameEntity = qnameDAO.getQNameEntity(ContentModel.PROP_OWNER);
|
||||
// QNameEntity contentQnameEntity = qnameDAO.getQNameEntity(ContentModel.PROP_CONTENT);
|
||||
//
|
||||
List<String> stores = contentUsageImpl.getStores();
|
||||
final MutableLong totalUsage = new MutableLong(0L);
|
||||
|
||||
@@ -298,11 +340,11 @@ public class UserUsageTrackingComponent
|
||||
{
|
||||
final StoreRef storeRef = new StoreRef(store);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.debug("Recalc usage (" + username + ") store=" + storeRef);
|
||||
logger.trace("Recalc usage (" + username + ") store=" + storeRef);
|
||||
}
|
||||
|
||||
|
||||
NodePropertyHandler propOwnerHandler = new NodePropertyHandler()
|
||||
{
|
||||
public void handle(NodeRef nodeRef, QName nodeTypeQName, QName propertyQName, Serializable value)
|
||||
@@ -323,25 +365,19 @@ public class UserUsageTrackingComponent
|
||||
};
|
||||
nodeDaoService.getPropertyValuesByPropertyAndValue(storeRef, ContentModel.PROP_OWNER, username, propOwnerHandler);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
// get nodes for which user is creator (ignore those with owner)
|
||||
NodeRefQueryCallback nodeCreatorHandler = new NodeRefQueryCallback()
|
||||
{
|
||||
logger.debug("Recalc usage (" + username + ") store=" + storeRef);
|
||||
}
|
||||
|
||||
NodePropertyHandler propCreatorHandler = new NodePropertyHandler()
|
||||
{
|
||||
public void handle(NodeRef nodeRef, QName nodeTypeQName, QName propertyQName, Serializable value)
|
||||
public boolean handle(Pair<Long, NodeRef> nodePair)
|
||||
{
|
||||
if (!nodeTypeQName.equals(ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
// It is not content
|
||||
return;
|
||||
}
|
||||
NodeRef nodeRef = nodePair.getSecond();
|
||||
|
||||
if (nodeService.getProperty(nodeRef, ContentModel.PROP_OWNER) != null)
|
||||
{
|
||||
// There is an owner property so we will have process this already
|
||||
return;
|
||||
// There is an owner property so we will have processed this already
|
||||
return true; // continue to next node (more required)
|
||||
}
|
||||
|
||||
ContentData contentData = DefaultTypeConverter.INSTANCE.convert(
|
||||
ContentData.class,
|
||||
nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT));
|
||||
@@ -350,42 +386,38 @@ public class UserUsageTrackingComponent
|
||||
long currentTotalUsage = totalUsage.longValue();
|
||||
totalUsage.setValue(currentTotalUsage + contentData.getSize());
|
||||
}
|
||||
return true; // continue to next node (more required)
|
||||
}
|
||||
};
|
||||
nodeDaoService.getPropertyValuesByPropertyAndValue(storeRef, ContentModel.PROP_OWNER, username, propCreatorHandler);
|
||||
nodeDaoService.getNodesWithCreatorAndStore(storeRef, username, nodeCreatorHandler);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
long quotaSize = contentUsageImpl.getUserQuota(username);
|
||||
logger.debug("Recalc usage ("+ username+") totalUsage="+totalUsage+", quota="+quotaSize);
|
||||
logger.trace("Recalc usage ("+ username+") totalUsage="+totalUsage+", quota="+quotaSize);
|
||||
}
|
||||
|
||||
return totalUsage.longValue();
|
||||
}
|
||||
};
|
||||
// execute in READ-ONLY txn
|
||||
final Long currentUsage = txnHelper.doInTransaction(calculatePersonCurrentUsage, true);
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
// execute in READ-ONLY txn
|
||||
final Long currentUsage = transactionService.getRetryingTransactionHelper().doInTransaction(calculatePersonCurrentUsage, true);
|
||||
|
||||
RetryingTransactionCallback<Object> updatePersonCurrentUsage = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
NodeRef personNodeRef = personService.getPerson(username);
|
||||
if (!nodeService.exists(personNodeRef))
|
||||
{
|
||||
// Ignore
|
||||
return null;
|
||||
}
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// execute in txn
|
||||
txnHelper.doInTransaction(updatePersonCurrentUsage, false);
|
||||
// execute in READ-WRITE txn
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(updatePersonCurrentUsage, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,9 +426,6 @@ public class UserUsageTrackingComponent
|
||||
private void collapseUsages()
|
||||
{
|
||||
// Collapse usage deltas (if a person has initial usage set)
|
||||
final RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Object> collapseUsages = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
@@ -425,9 +454,9 @@ public class UserUsageTrackingComponent
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.debug("Collapsed usage: username=" + userName + ", usage=" + currentUsage);
|
||||
logger.trace("Collapsed usage: username=" + userName + ", usage=" + currentUsage);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -446,7 +475,7 @@ public class UserUsageTrackingComponent
|
||||
}
|
||||
};
|
||||
|
||||
// execute in txn
|
||||
txnHelper.doInTransaction(collapseUsages, false);
|
||||
// execute in READ-WRITE txn
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(collapseUsages, false);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user