mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
MT - fix user usages for tenants
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8197 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -50,6 +50,8 @@ import org.alfresco.repo.node.db.DbNodeServiceImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.usage.UserUsageBootstrapJob;
|
||||
import org.alfresco.repo.usage.UserUsageTrackingComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowDeployer;
|
||||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||
@@ -870,6 +872,10 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten
|
||||
props.put("alfresco_user_store.guestusername", getTenantGuestUser(tenantDomain));
|
||||
|
||||
spacesImporterBootstrap.bootstrap();
|
||||
|
||||
// calculate any missing usages
|
||||
UserUsageTrackingComponent userUsageTrackingComponent = (UserUsageTrackingComponent)getApplicationContext().getBean(UserUsageBootstrapJob.KEY_COMPONENT);
|
||||
userUsageTrackingComponent.bootstrapInternal();
|
||||
|
||||
logger.debug("Bootstrapped store: " + tenantService.getBaseName(bootstrapStoreRef));
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -63,6 +64,7 @@ public class ContentUsageImpl implements ContentUsageService,
|
||||
private PolicyComponent policyComponent;
|
||||
private UsageService usageService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private TenantService tenantService;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
@@ -92,6 +94,11 @@ public class ContentUsageImpl implements ContentUsageService,
|
||||
{
|
||||
this.authenticationComponent = authenticationComponent;
|
||||
}
|
||||
|
||||
public void setTenantService(TenantService tenantService)
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
@@ -144,7 +151,7 @@ public class ContentUsageImpl implements ContentUsageService,
|
||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||
if (stores.contains(nodeRef.getStoreRef().toString()))
|
||||
if (stores.contains(tenantService.getBaseName(nodeRef.getStoreRef()).toString()))
|
||||
{
|
||||
// Get content size
|
||||
|
||||
@@ -180,7 +187,7 @@ public class ContentUsageImpl implements ContentUsageService,
|
||||
Map<QName, Serializable> before,
|
||||
Map<QName, Serializable> after)
|
||||
{
|
||||
if (stores.contains(nodeRef.getStoreRef().toString()))
|
||||
if (stores.contains(tenantService.getBaseName(nodeRef.getStoreRef()).toString()))
|
||||
{
|
||||
// Check for change in content size
|
||||
|
||||
@@ -273,7 +280,7 @@ public class ContentUsageImpl implements ContentUsageService,
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
if (stores.contains(nodeRef.getStoreRef().toString()))
|
||||
if (stores.contains(tenantService.getBaseName(nodeRef.getStoreRef()).toString()))
|
||||
{
|
||||
// TODO use data dictionary to get content property
|
||||
ContentData contentData = (ContentData)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||
|
@@ -85,11 +85,11 @@ public class UsageServiceImpl implements UsageService
|
||||
{
|
||||
Set<Node> nodes = usageDeltaDao.getUsageDeltaNodes();
|
||||
|
||||
// convert nodes to nodeRefs
|
||||
// convert nodes to nodeRefs (tenant-specific)
|
||||
Set<NodeRef> results = new HashSet<NodeRef>(nodes.size());
|
||||
for (Node node : nodes)
|
||||
{
|
||||
results.add(tenantService.getBaseName(node.getNodeRef()));
|
||||
results.add(node.getNodeRef());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ import org.quartz.JobExecutionException;
|
||||
*/
|
||||
public class UserUsageBootstrapJob implements Job
|
||||
{
|
||||
private static final String KEY_COMPONENT = "userUsageBootstrapComponent";
|
||||
public static final String KEY_COMPONENT = "userUsageTrackingComponent";
|
||||
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
@@ -50,7 +50,7 @@ public class UserUsageBootstrapJob implements Job
|
||||
{
|
||||
throw new JobExecutionException("Missing job data: " + KEY_COMPONENT);
|
||||
}
|
||||
// perform the content usage calculations
|
||||
usageComponent.execute();
|
||||
// perform the content usage bootstrap
|
||||
usageComponent.bootstrap();
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ import org.quartz.JobExecutionException;
|
||||
*/
|
||||
public class UserUsageCollapseJob implements Job
|
||||
{
|
||||
private static final String KEY_COMPONENT = "userUsageCollapseComponent";
|
||||
private static final String KEY_COMPONENT = "userUsageTrackingComponent";
|
||||
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
|
@@ -33,6 +33,10 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.node.db.NodeDaoService;
|
||||
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.TenantDeployerService;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.TransactionServiceImpl;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
@@ -58,8 +62,6 @@ public class UserUsageTrackingComponent
|
||||
|
||||
private static boolean busy = false;
|
||||
|
||||
private boolean bootstrap = false;
|
||||
|
||||
private NodeDaoService nodeDaoService;
|
||||
private TransactionServiceImpl transactionService;
|
||||
private ContentUsageImpl contentUsageImpl;
|
||||
@@ -67,6 +69,8 @@ public class UserUsageTrackingComponent
|
||||
private PersonService personService;
|
||||
private NodeService nodeService;
|
||||
private UsageService usageService;
|
||||
private TenantDeployerService tenantDeployerService;
|
||||
private TenantService tenantService;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
@@ -86,11 +90,6 @@ public class UserUsageTrackingComponent
|
||||
this.contentUsageImpl = contentUsageImpl;
|
||||
}
|
||||
|
||||
public void setBootstrap(boolean bootstrap)
|
||||
{
|
||||
this.bootstrap = bootstrap;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
@@ -106,159 +105,164 @@ public class UserUsageTrackingComponent
|
||||
this.usageService = usageService;
|
||||
}
|
||||
|
||||
public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
|
||||
{
|
||||
this.tenantDeployerService = tenantDeployerService;
|
||||
}
|
||||
|
||||
public void setTenantService(TenantService tenantService)
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void execute()
|
||||
{
|
||||
try
|
||||
if (enabled == true)
|
||||
{
|
||||
if (! busy && ! enabled)
|
||||
{
|
||||
busy = true;
|
||||
|
||||
// disabled - remove all usages
|
||||
if (bootstrap == true)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Disabled - clear usages for all users ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Integer> clearAllUsages = new RetryingTransactionCallback<Integer>()
|
||||
{
|
||||
public Integer execute() throws Throwable
|
||||
{
|
||||
Set<NodeRef> allPeople = personService.getAllPeople();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT, null);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
}
|
||||
return allPeople.size();
|
||||
}
|
||||
};
|
||||
// execute in txn
|
||||
int count = txnHelper.doInTransaction(clearAllUsages, false);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("... cleared usages for " + count + " users");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (! busy && enabled)
|
||||
{
|
||||
busy = true;
|
||||
|
||||
if (bootstrap == true)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Enabled - calculate missing usages ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// 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();
|
||||
Set<String> userNames = new HashSet<String>();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
Long currentUsage = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
|
||||
if (currentUsage == null)
|
||||
{
|
||||
String userName = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_USERNAME);
|
||||
userNames.add(userName);
|
||||
}
|
||||
}
|
||||
return userNames;
|
||||
}
|
||||
};
|
||||
// execute in READ-ONLY txn
|
||||
final Set<String> userNames = txnHelper.doInTransaction(getAllPeople, true);
|
||||
|
||||
for (String userName : userNames)
|
||||
{
|
||||
recalculateUsage(userName);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("... calculated missing usages for " + userNames.size() + " users");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collapse usage deltas (if a person has initial usage set)
|
||||
final RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction and run as System user
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
return txnHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
// Get distinct candidates
|
||||
Set<NodeRef> usageNodeRefs = usageService.getUsageDeltaNodes();
|
||||
|
||||
for(NodeRef usageNodeRef : usageNodeRefs)
|
||||
{
|
||||
QName nodeType = nodeService.getType(usageNodeRef);
|
||||
|
||||
if (nodeType.equals(ContentModel.TYPE_PERSON))
|
||||
{
|
||||
NodeRef personNodeRef = usageNodeRef;
|
||||
String userName = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_USERNAME);
|
||||
|
||||
long currentUsage = contentUsageImpl.getUserStoredUsage(personNodeRef);
|
||||
if (currentUsage != -1)
|
||||
{
|
||||
// collapse the usage deltas
|
||||
currentUsage = contentUsageImpl.getUserUsage(userName);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Collapsed usage: username=" + userName + ", usage=" + currentUsage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("Initial usage for user has not yet been calculated: " + userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
if (! busy)
|
||||
{
|
||||
try
|
||||
{
|
||||
busy = true;
|
||||
|
||||
// collapse usages - note: for MT environment, will collapse for all tenants
|
||||
collapseUsages();
|
||||
}
|
||||
finally
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
}
|
||||
|
||||
// called once on startup
|
||||
public void bootstrap()
|
||||
{
|
||||
// default domain
|
||||
bootstrapInternal();
|
||||
|
||||
if (tenantService.isEnabled())
|
||||
{
|
||||
List<Tenant> tenants = tenantDeployerService.getAllTenants();
|
||||
for (Tenant tenant : tenants)
|
||||
{
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
bootstrapInternal();
|
||||
return null;
|
||||
}
|
||||
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenant.getTenantDomain()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void bootstrapInternal()
|
||||
{
|
||||
if (! busy)
|
||||
{
|
||||
try
|
||||
{
|
||||
busy = true;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
// enabled - calculate missing usages
|
||||
calculateMissingUsages();
|
||||
}
|
||||
else
|
||||
{
|
||||
// disabled - remove all usages
|
||||
clearAllUsages();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAllUsages()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
busy = false;
|
||||
logger.debug("Disabled - clear usages for all users ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Integer> clearAllUsages = new RetryingTransactionCallback<Integer>()
|
||||
{
|
||||
public Integer execute() throws Throwable
|
||||
{
|
||||
Set<NodeRef> allPeople = personService.getAllPeople();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
nodeService.setProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT, null);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
}
|
||||
return allPeople.size();
|
||||
}
|
||||
};
|
||||
// execute in txn
|
||||
int count = txnHelper.doInTransaction(clearAllUsages, false);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("... cleared usages for " + count + " users");
|
||||
}
|
||||
}
|
||||
|
||||
public void calculateMissingUsages()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Enabled - calculate missing usages ...");
|
||||
}
|
||||
|
||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// 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();
|
||||
Set<String> userNames = new HashSet<String>();
|
||||
|
||||
for (NodeRef personNodeRef : allPeople)
|
||||
{
|
||||
Long currentUsage = (Long)nodeService.getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
|
||||
if (currentUsage == null)
|
||||
{
|
||||
String userName = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_USERNAME);
|
||||
userNames.add(userName);
|
||||
}
|
||||
}
|
||||
return userNames;
|
||||
}
|
||||
};
|
||||
// execute in READ-ONLY txn
|
||||
final Set<String> userNames = txnHelper.doInTransaction(getAllPeople, true);
|
||||
|
||||
for (String userName : userNames)
|
||||
{
|
||||
recalculateUsage(userName);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("... calculated missing usages for " + userNames.size() + " users");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,22 +327,81 @@ public class UserUsageTrackingComponent
|
||||
// execute in READ-ONLY txn
|
||||
final Long currentUsage = txnHelper.doInTransaction(calculatePersonCurrentUsage, true);
|
||||
|
||||
// wrap to make the request in a transaction and run as System user
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
// wrap to make the request in a transaction
|
||||
RetryingTransactionCallback<Object> updatePersonCurrentUsage = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
return txnHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
NodeRef personNodeRef = personService.getPerson(userName);
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
NodeRef personNodeRef = personService.getPerson(userName);
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
};
|
||||
|
||||
// execute in txn
|
||||
txnHelper.doInTransaction(updatePersonCurrentUsage, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse usages - note: for MT environment, will collapse all tenants
|
||||
*/
|
||||
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
|
||||
{
|
||||
// Get distinct candidates
|
||||
Set<NodeRef> usageNodeRefs = usageService.getUsageDeltaNodes();
|
||||
|
||||
for(final NodeRef usageNodeRef : usageNodeRefs)
|
||||
{
|
||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
QName nodeType = nodeService.getType(usageNodeRef);
|
||||
|
||||
if (nodeType.equals(ContentModel.TYPE_PERSON))
|
||||
{
|
||||
NodeRef personNodeRef = usageNodeRef;
|
||||
String userName = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_USERNAME);
|
||||
|
||||
long currentUsage = contentUsageImpl.getUserStoredUsage(personNodeRef);
|
||||
if (currentUsage != -1)
|
||||
{
|
||||
// collapse the usage deltas
|
||||
currentUsage = contentUsageImpl.getUserUsage(userName);
|
||||
usageService.deleteDeltas(personNodeRef);
|
||||
contentUsageImpl.setUserStoredUsage(personNodeRef, currentUsage);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Collapsed usage: username=" + userName + ", usage=" + currentUsage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("Initial usage for user has not yet been calculated: " + userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantService.getDomain(usageNodeRef.getStoreRef().getIdentifier())));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// execute in txn
|
||||
txnHelper.doInTransaction(collapseUsages, false);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user