Feature/acs 1425 long running tmdq (#417)

* ACS-1425 Add store info to result

* ACS-1425 Fix unit tests
This commit is contained in:
Sara
2021-04-28 11:07:02 +01:00
committed by GitHub
parent 1b6e800733
commit ab6c831447
2 changed files with 495 additions and 459 deletions

View File

@@ -1,460 +1,480 @@
/* /*
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is * the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms: * provided under the following open source license terms:
* *
* Alfresco is free software: you can redistribute it and/or modify * Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Alfresco is distributed in the hope that it will be useful, * Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L% * #L%
*/ */
package org.alfresco.repo.search.impl.querymodel.impl.db; package org.alfresco.repo.search.impl.querymodel.impl.db;
import static org.alfresco.repo.domain.node.AbstractNodeDAOImpl.CACHE_REGION_NODES; import static org.alfresco.repo.domain.node.AbstractNodeDAOImpl.CACHE_REGION_NODES;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.concurrent.NotThreadSafe; import javax.annotation.concurrent.NotThreadSafe;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.patch.OptionalPatchApplicationCheckBootstrapBean; import org.alfresco.repo.admin.patch.OptionalPatchApplicationCheckBootstrapBean;
import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.cache.lookup.EntityLookupCache; import org.alfresco.repo.cache.lookup.EntityLookupCache;
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor; import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
import org.alfresco.repo.domain.node.Node; import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.permissions.AclCrudDAO; import org.alfresco.repo.domain.node.StoreEntity;
import org.alfresco.repo.domain.permissions.Authority; import org.alfresco.repo.domain.permissions.AclCrudDAO;
import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.domain.permissions.Authority;
import org.alfresco.repo.search.SimpleResultSetMetaData; import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet; import org.alfresco.repo.search.SimpleResultSetMetaData;
import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet;
import org.alfresco.repo.search.impl.querymodel.Query; import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext;
import org.alfresco.repo.search.impl.querymodel.QueryEngine; import org.alfresco.repo.search.impl.querymodel.Query;
import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; import org.alfresco.repo.search.impl.querymodel.QueryEngine;
import org.alfresco.repo.search.impl.querymodel.QueryModelException; import org.alfresco.repo.search.impl.querymodel.QueryEngineResults;
import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; import org.alfresco.repo.search.impl.querymodel.QueryModelException;
import org.alfresco.repo.search.impl.querymodel.QueryOptions; import org.alfresco.repo.search.impl.querymodel.QueryModelFactory;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.search.impl.querymodel.QueryOptions;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.PermissionEvaluationMode; import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.PermissionEvaluationMode;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.Pair; import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log; import org.alfresco.util.Pair;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log;
import org.apache.ibatis.session.ResultContext; import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.ResultContext;
import org.mybatis.spring.SqlSessionTemplate; import org.apache.ibatis.session.ResultHandler;
import org.mybatis.spring.SqlSessionTemplate;
/**
* @author Andy /**
*/ * @author Andy
@NotThreadSafe */
public class DBQueryEngine implements QueryEngine @NotThreadSafe
{ public class DBQueryEngine implements QueryEngine
protected static final Log logger = LogFactory.getLog(DBQueryEngine.class); {
protected static final Log logger = LogFactory.getLog(DBQueryEngine.class);
protected static final String SELECT_BY_DYNAMIC_QUERY = "alfresco.metadata.query.select_byDynamicQuery";
protected static final String SELECT_BY_DYNAMIC_QUERY = "alfresco.metadata.query.select_byDynamicQuery";
protected SqlSessionTemplate template;
protected SqlSessionTemplate template;
protected QNameDAO qnameDAO;
protected QNameDAO qnameDAO;
private NodeDAO nodeDAO;
private NodeDAO nodeDAO;
protected DictionaryService dictionaryService;
protected DictionaryService dictionaryService;
protected NamespaceService namespaceService;
protected NamespaceService namespaceService;
protected NodeService nodeService;
protected NodeService nodeService;
private TenantService tenantService;
private TenantService tenantService;
private OptionalPatchApplicationCheckBootstrapBean metadataIndexCheck2;
private OptionalPatchApplicationCheckBootstrapBean metadataIndexCheck2;
protected PermissionService permissionService;
protected PermissionService permissionService;
private int maxPermissionChecks;
private int maxPermissionChecks;
private long maxPermissionCheckTimeMillis;
private long maxPermissionCheckTimeMillis;
protected EntityLookupCache<Long, Node, NodeRef> nodesCache;
protected EntityLookupCache<Long, Node, NodeRef> nodesCache;
AclCrudDAO aclCrudDAO;
AclCrudDAO aclCrudDAO;
public void setAclCrudDAO(AclCrudDAO aclCrudDAO)
{ public void setAclCrudDAO(AclCrudDAO aclCrudDAO)
this.aclCrudDAO = aclCrudDAO; {
} this.aclCrudDAO = aclCrudDAO;
}
public void setMaxPermissionChecks(int maxPermissionChecks)
{ public void setMaxPermissionChecks(int maxPermissionChecks)
this.maxPermissionChecks = maxPermissionChecks; {
} this.maxPermissionChecks = maxPermissionChecks;
}
public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis)
{ public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis)
this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis; {
} this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis;
}
public void setTemplate(SqlSessionTemplate template)
{ public void setTemplate(SqlSessionTemplate template)
this.template = template; {
} this.template = template;
}
public void setPermissionService(PermissionService permissionService)
{ public void setPermissionService(PermissionService permissionService)
this.permissionService = permissionService; {
} this.permissionService = permissionService;
}
public void setMetadataIndexCheck2(OptionalPatchApplicationCheckBootstrapBean metadataIndexCheck2)
{ public void setMetadataIndexCheck2(OptionalPatchApplicationCheckBootstrapBean metadataIndexCheck2)
this.metadataIndexCheck2 = metadataIndexCheck2; {
} this.metadataIndexCheck2 = metadataIndexCheck2;
}
public void setTenantService(TenantService tenantService)
{ public void setTenantService(TenantService tenantService)
this.tenantService = tenantService; {
} this.tenantService = tenantService;
}
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{ public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
this.template = sqlSessionTemplate; {
} this.template = sqlSessionTemplate;
}
/**
* @param qnameDAO /**
* the qnameDAO to set * @param qnameDAO
*/ * the qnameDAO to set
public void setQnameDAO(QNameDAO qnameDAO) */
{ public void setQnameDAO(QNameDAO qnameDAO)
this.qnameDAO = qnameDAO; {
} this.qnameDAO = qnameDAO;
}
/**
* @param dictionaryService /**
* the dictionaryService to set * @param dictionaryService
*/ * the dictionaryService to set
public void setDictionaryService(DictionaryService dictionaryService) */
{ public void setDictionaryService(DictionaryService dictionaryService)
this.dictionaryService = dictionaryService; {
} this.dictionaryService = dictionaryService;
}
/**
* @param namespaceService /**
* the namespaceService to set * @param namespaceService
*/ * the namespaceService to set
public void setNamespaceService(NamespaceService namespaceService) */
{ public void setNamespaceService(NamespaceService namespaceService)
this.namespaceService = namespaceService; {
} this.namespaceService = namespaceService;
}
/**
* @param nodeService the nodeService to set /**
*/ * @param nodeService the nodeService to set
public void setNodeService(NodeService nodeService) */
{ public void setNodeService(NodeService nodeService)
this.nodeService = nodeService; {
} this.nodeService = nodeService;
}
/**
* @param nodeDAO the nodeDAO to set /**
*/ * @param nodeDAO the nodeDAO to set
public void setNodeDAO(NodeDAO nodeDAO) */
{ public void setNodeDAO(NodeDAO nodeDAO)
this.nodeDAO = nodeDAO; {
} this.nodeDAO = nodeDAO;
}
/*
* (non-Javadoc) /*
* @see * (non-Javadoc)
* org.alfresco.repo.search.impl.querymodel.QueryEngine#executeQuery(org.alfresco.repo.search.impl.querymodel.Query, * @see
* org.alfresco.repo.search.impl.querymodel.QueryOptions, * org.alfresco.repo.search.impl.querymodel.QueryEngine#executeQuery(org.alfresco.repo.search.impl.querymodel.Query,
* org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) * org.alfresco.repo.search.impl.querymodel.QueryOptions,
*/ * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext)
@Override */
public QueryEngineResults executeQuery(Query query, QueryOptions options, FunctionEvaluationContext functionContext) @Override
{ public QueryEngineResults executeQuery(Query query, QueryOptions options, FunctionEvaluationContext functionContext)
long start = 0; {
if (logger.isDebugEnabled()) long start = 0;
{ if (logger.isDebugEnabled())
start = System.currentTimeMillis(); {
logger.debug("Query request received"); start = System.currentTimeMillis();
} logger.debug("Query request received");
}
Set<String> selectorGroup = null;
if (query.getSource() != null) Set<String> selectorGroup = null;
{ if (query.getSource() != null)
List<Set<String>> selectorGroups = query.getSource().getSelectorGroups(functionContext); {
List<Set<String>> selectorGroups = query.getSource().getSelectorGroups(functionContext);
if (selectorGroups.size() == 0)
{ if (selectorGroups.size() == 0)
throw new QueryModelException("No selectors"); {
} throw new QueryModelException("No selectors");
}
if (selectorGroups.size() > 1)
{ if (selectorGroups.size() > 1)
throw new QueryModelException("Advanced join is not supported"); {
} throw new QueryModelException("Advanced join is not supported");
}
selectorGroup = selectorGroups.get(0);
} selectorGroup = selectorGroups.get(0);
}
DBQuery dbQuery = (DBQuery)query;
DBQuery dbQuery = (DBQuery)query;
if (options.getStores().size() > 1)
{ if (options.getStores().size() > 1)
throw new QueryModelException("Multi-store queries are not supported"); {
} throw new QueryModelException("Multi-store queries are not supported");
}
// MT
StoreRef storeRef = options.getStores().get(0); // MT
storeRef = storeRef != null ? tenantService.getName(storeRef) : null; StoreRef storeRef = options.getStores().get(0);
storeRef = storeRef != null ? tenantService.getName(storeRef) : null;
Pair<Long, StoreRef> store = nodeDAO.getStore(storeRef);
if (store == null) Pair<Long, StoreRef> store = nodeDAO.getStore(storeRef);
{ if (store == null)
throw new QueryModelException("Unknown store: "+storeRef); {
} throw new QueryModelException("Unknown store: "+storeRef);
dbQuery.setStoreId(store.getFirst()); }
Pair<Long, QName> sysDeletedType = qnameDAO.getQName(ContentModel.TYPE_DELETED); dbQuery.setStoreId(store.getFirst());
if (sysDeletedType == null) Pair<Long, QName> sysDeletedType = qnameDAO.getQName(ContentModel.TYPE_DELETED);
{ if (sysDeletedType == null)
dbQuery.setSysDeletedType(-1L); {
} dbQuery.setSysDeletedType(-1L);
else }
{ else
dbQuery.setSysDeletedType(sysDeletedType.getFirst()); {
} dbQuery.setSysDeletedType(sysDeletedType.getFirst());
}
Long sinceTxId = options.getSinceTxId();
if (sinceTxId == null) Long sinceTxId = options.getSinceTxId();
{ if (sinceTxId == null)
// By default, return search results for all transactions. {
sinceTxId = -1L; // By default, return search results for all transactions.
} sinceTxId = -1L;
dbQuery.setSinceTxId(sinceTxId); }
dbQuery.setSinceTxId(sinceTxId);
logger.debug("- query is being prepared");
dbQuery.prepare(namespaceService, dictionaryService, qnameDAO, nodeDAO, tenantService, selectorGroup, logger.debug("- query is being prepared");
null, functionContext, metadataIndexCheck2.getPatchApplied()); dbQuery.prepare(namespaceService, dictionaryService, qnameDAO, nodeDAO, tenantService, selectorGroup,
null, functionContext, metadataIndexCheck2.getPatchApplied());
ResultSet resultSet;
resultSet = selectNodesWithPermissions(options, dbQuery); ResultSet resultSet;
if (logger.isDebugEnabled()) resultSet = selectNodesWithPermissions(options, dbQuery);
{ if (logger.isDebugEnabled())
long ms = System.currentTimeMillis() - start; {
logger.debug("Selected " + resultSet.length() + " nodes with permission resolution in "+ms+" ms"); long ms = System.currentTimeMillis() - start;
} logger.debug("Selected " + resultSet.length() + " nodes with permission resolution in "+ms+" ms");
return asQueryEngineResults(resultSet); }
} return asQueryEngineResults(resultSet);
}
protected String pickQueryTemplate(QueryOptions options, DBQuery dbQuery)
{ protected String pickQueryTemplate(QueryOptions options, DBQuery dbQuery)
logger.debug("- using standard table for the query"); {
return SELECT_BY_DYNAMIC_QUERY; logger.debug("- using standard table for the query");
} return SELECT_BY_DYNAMIC_QUERY;
}
private ResultSet selectNodesWithPermissions(QueryOptions options, DBQuery dbQuery)
{ private ResultSet selectNodesWithPermissions(QueryOptions options, DBQuery dbQuery)
Authority authority = aclCrudDAO.getAuthority(AuthenticationUtil.getRunAsUser()); {
Authority authority = aclCrudDAO.getAuthority(AuthenticationUtil.getRunAsUser());
NodePermissionAssessor permissionAssessor = createAssessor(authority);
int maxPermsChecks = options.getMaxPermissionChecks() < 0 ? maxPermissionChecks : options.getMaxPermissionChecks(); NodePermissionAssessor permissionAssessor = createAssessor(authority);
long maxPermCheckTimeMillis = options.getMaxPermissionCheckTimeMillis() < 0 int maxPermsChecks = options.getMaxPermissionChecks() < 0 ? maxPermissionChecks : options.getMaxPermissionChecks();
? maxPermissionCheckTimeMillis long maxPermCheckTimeMillis = options.getMaxPermissionCheckTimeMillis() < 0
: options.getMaxPermissionCheckTimeMillis(); ? maxPermissionCheckTimeMillis
permissionAssessor.setMaxPermissionChecks(maxPermsChecks); : options.getMaxPermissionCheckTimeMillis();
permissionAssessor.setMaxPermissionCheckTimeMillis(maxPermCheckTimeMillis); permissionAssessor.setMaxPermissionChecks(maxPermsChecks);
permissionAssessor.setMaxPermissionCheckTimeMillis(maxPermCheckTimeMillis);
FilteringResultSet resultSet = acceleratedNodeSelection(options, dbQuery, permissionAssessor);
FilteringResultSet resultSet = acceleratedNodeSelection(options, dbQuery, permissionAssessor);
PagingLuceneResultSet plrs = new PagingLuceneResultSet(resultSet, options.getAsSearchParmeters(), nodeService);
plrs.setTrimmedResultSet(true); PagingLuceneResultSet plrs = new PagingLuceneResultSet(resultSet, options.getAsSearchParmeters(), nodeService);
return plrs; plrs.setTrimmedResultSet(true);
} return plrs;
}
protected NodePermissionAssessor createAssessor(Authority authority)
{ protected NodePermissionAssessor createAssessor(Authority authority)
return new NodePermissionAssessor(nodeService, permissionService, authority, nodesCache); {
} return new NodePermissionAssessor(nodeService, permissionService, authority, nodesCache);
}
FilteringResultSet acceleratedNodeSelection(QueryOptions options, DBQuery dbQuery, NodePermissionAssessor permissionAssessor)
{ FilteringResultSet acceleratedNodeSelection(QueryOptions options, DBQuery dbQuery, NodePermissionAssessor permissionAssessor)
List<Node> nodes = new ArrayList<>(); {
int requiredNodes = computeRequiredNodesCount(options); List<Node> nodes = new ArrayList<>();
int requiredNodes = computeRequiredNodesCount(options);
logger.debug("- query sent to the database");
template.select(pickQueryTemplate(options, dbQuery), dbQuery, new ResultHandler<Node>() logger.debug("- query sent to the database");
{ template.select(pickQueryTemplate(options, dbQuery), dbQuery, new ResultHandler<Node>()
@Override {
public void handleResult(ResultContext<? extends Node> context) @Override
{ public void handleResult(ResultContext<? extends Node> context)
doHandleResult(permissionAssessor, nodes, requiredNodes, context); {
} doHandleResult(permissionAssessor, nodes, requiredNodes, context);
}
private void doHandleResult(NodePermissionAssessor permissionAssessor, List<Node> nodes,
int requiredNodes, ResultContext<? extends Node> context) private void doHandleResult(NodePermissionAssessor permissionAssessor, List<Node> nodes,
{ int requiredNodes, ResultContext<? extends Node> context)
if (nodes.size() >= requiredNodes) {
{ if (nodes.size() >= requiredNodes)
context.stop(); {
return; context.stop();
} return;
}
Node node = context.getResultObject();
Node node = context.getResultObject();
boolean shouldCache = nodes.size() >= options.getSkipCount(); addStoreInfo(node);
if(shouldCache)
{ boolean shouldCache = nodes.size() >= options.getSkipCount();
logger.debug("- selected node "+nodes.size()+": "+node.getUuid()+" "+node.getId()); if(shouldCache)
nodesCache.setValue(node.getId(), node); {
} logger.debug("- selected node "+nodes.size()+": "+node.getUuid()+" "+node.getId());
else nodesCache.setValue(node.getId(), node);
{ }
logger.debug("- skipped node "+nodes.size()+": "+node.getUuid()+" "+node.getId()); else
} {
logger.debug("- skipped node "+nodes.size()+": "+node.getUuid()+" "+node.getId());
if (permissionAssessor.isIncluded(node)) }
{
nodes.add(shouldCache ? node : null); if (permissionAssessor.isIncluded(node))
} {
nodes.add(shouldCache ? node : null);
if (permissionAssessor.shouldQuitChecks()) }
{
context.stop(); if (permissionAssessor.shouldQuitChecks())
return; {
} context.stop();
} return;
}); }
}
int numberFound = nodes.size(); });
nodes.removeAll(Collections.singleton(null));
int numberFound = nodes.size();
DBResultSet rs = createResultSet(options, nodes, numberFound); nodes.removeAll(Collections.singleton(null));
FilteringResultSet frs = new FilteringResultSet(rs, formInclusionMask(nodes));
frs.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.UNLIMITED, PermissionEvaluationMode.EAGER, rs.getResultSetMetaData().getSearchParameters())); DBResultSet rs = createResultSet(options, nodes, numberFound);
FilteringResultSet frs = new FilteringResultSet(rs, formInclusionMask(nodes));
logger.debug("- query is completed, "+nodes.size()+" nodes loaded"); frs.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.UNLIMITED, PermissionEvaluationMode.EAGER, rs.getResultSetMetaData().getSearchParameters()));
return frs;
} logger.debug("- query is completed, "+nodes.size()+" nodes loaded");
return frs;
private DBResultSet createResultSet(QueryOptions options, List<Node> nodes, int numberFound) }
{
DBResultSet dbResultSet = new DBResultSet(options.getAsSearchParmeters(), nodes, nodeDAO, nodeService, tenantService, Integer.MAX_VALUE); private DBResultSet createResultSet(QueryOptions options, List<Node> nodes, int numberFound)
dbResultSet.setNumberFound(numberFound); {
return dbResultSet; DBResultSet dbResultSet = new DBResultSet(options.getAsSearchParmeters(), nodes, nodeDAO, nodeService, tenantService, Integer.MAX_VALUE);
} dbResultSet.setNumberFound(numberFound);
return dbResultSet;
private int computeRequiredNodesCount(QueryOptions options) }
{
int maxItems = options.getMaxItems(); private int computeRequiredNodesCount(QueryOptions options)
if (maxItems == -1 || maxItems == Integer.MAX_VALUE) {
{ int maxItems = options.getMaxItems();
return Integer.MAX_VALUE; if (maxItems == -1 || maxItems == Integer.MAX_VALUE)
} {
return Integer.MAX_VALUE;
return maxItems + options.getSkipCount() + 1; }
}
return maxItems + options.getSkipCount() + 1;
private BitSet formInclusionMask(List<Node> nodes) }
{
BitSet inclusionMask = new BitSet(nodes.size()); private BitSet formInclusionMask(List<Node> nodes)
for (int i=0; i < nodes.size(); i++) {
{ BitSet inclusionMask = new BitSet(nodes.size());
inclusionMask.set(i, true); for (int i=0; i < nodes.size(); i++)
} {
return inclusionMask; inclusionMask.set(i, true);
} }
return inclusionMask;
}
private QueryEngineResults asQueryEngineResults(ResultSet paged)
{
HashSet<String> key = new HashSet<>(); private QueryEngineResults asQueryEngineResults(ResultSet paged)
key.add(""); {
Map<Set<String>, ResultSet> answer = new HashMap<>(); HashSet<String> key = new HashSet<>();
answer.put(key, paged); key.add("");
Map<Set<String>, ResultSet> answer = new HashMap<>();
return new QueryEngineResults(answer); answer.put(key, paged);
}
return new QueryEngineResults(answer);
/* }
* (non-Javadoc)
* @see org.alfresco.repo.search.impl.querymodel.QueryEngine#getQueryModelFactory() /*
*/ * (non-Javadoc)
@Override * @see org.alfresco.repo.search.impl.querymodel.QueryEngine#getQueryModelFactory()
public QueryModelFactory getQueryModelFactory() */
{ @Override
return new DBQueryModelFactory(); public QueryModelFactory getQueryModelFactory()
} {
return new DBQueryModelFactory();
/** }
* Injection of nodes cache for clean-up and warm up when required
* @param cache The node cache to set /**
*/ * Injection of nodes cache for clean-up and warm up when required
public void setNodesCache(SimpleCache<Serializable, Serializable> cache) * @param cache The node cache to set
{ */
this.nodesCache = new EntityLookupCache<>( public void setNodesCache(SimpleCache<Serializable, Serializable> cache)
cache, {
CACHE_REGION_NODES, this.nodesCache = new EntityLookupCache<>(
new ReadonlyLocalCallbackDAO()); cache,
} CACHE_REGION_NODES,
new ReadonlyLocalCallbackDAO());
void setNodesCache(EntityLookupCache<Long, Node, NodeRef> nodesCache) }
{
this.nodesCache = nodesCache; void setNodesCache(EntityLookupCache<Long, Node, NodeRef> nodesCache)
} {
this.nodesCache = nodesCache;
private class ReadonlyLocalCallbackDAO extends EntityLookupCallbackDAOAdaptor<Long, Node, NodeRef> }
{
@Override private class ReadonlyLocalCallbackDAO extends EntityLookupCallbackDAOAdaptor<Long, Node, NodeRef>
public Pair<Long, Node> createValue(Node value) {
{ @Override
throw new UnsupportedOperationException("Node creation is done externally: " + value); public Pair<Long, Node> createValue(Node value)
} {
throw new UnsupportedOperationException("Node creation is done externally: " + value);
@Override }
public Pair<Long, Node> findByKey(Long nodeId)
{ @Override
return null; public Pair<Long, Node> findByKey(Long nodeId)
} {
return null;
@Override }
public NodeRef getValueKey(Node value)
{ @Override
return value.getNodeRef(); public NodeRef getValueKey(Node value)
} {
} return value.getNodeRef();
}
}
private void addStoreInfo(Node node)
{
StoreEntity storeEntity = node.getStore();
logger.debug("Adding store info for store id " + storeEntity.getId());
List<Pair<Long, StoreRef>> stores = nodeDAO.getStores();
for (Pair<Long, StoreRef> storeRefPair : stores)
{
if (storeEntity.getId() == storeRefPair.getFirst())
{
StoreRef storeRef = storeRefPair.getSecond();
storeEntity.setIdentifier(storeRef.getIdentifier());
storeEntity.setProtocol(storeRef.getProtocol());
logger.debug("Added store info" + storeEntity.toString());
break;
}
}
}
} }

View File

@@ -37,15 +37,19 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.alfresco.repo.cache.lookup.EntityLookupCache; import org.alfresco.repo.cache.lookup.EntityLookupCache;
import org.alfresco.repo.domain.node.Node; import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.StoreEntity; import org.alfresco.repo.domain.node.StoreEntity;
import org.alfresco.repo.search.impl.querymodel.QueryOptions; import org.alfresco.repo.search.impl.querymodel.QueryOptions;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.util.Pair;
import org.apache.ibatis.executor.result.DefaultResultContext; import org.apache.ibatis.executor.result.DefaultResultContext;
import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.ResultHandler;
@@ -63,6 +67,7 @@ public class DBQueryEngineTest
private DBQuery dbQuery; private DBQuery dbQuery;
private ResultContext<Node> resultContext; private ResultContext<Node> resultContext;
private QueryOptions options; private QueryOptions options;
private NodeDAO nodeDAO;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Before @Before
@@ -78,6 +83,10 @@ public class DBQueryEngineTest
engine.setSqlSessionTemplate(template); engine.setSqlSessionTemplate(template);
engine.nodesCache = mock(EntityLookupCache.class); engine.nodesCache = mock(EntityLookupCache.class);
nodeDAO = mock(NodeDAO.class);
engine.setNodeDAO(nodeDAO);
mockStores();
} }
@Test @Test
@@ -260,4 +269,11 @@ public class DBQueryEngineTest
return node; return node;
} }
private void mockStores()
{
Pair<Long, StoreRef> spacesStore = new Pair<>(6L, new StoreRef("workspace://SpacesStore"));
List<Pair<Long, StoreRef>> stores = Arrays.asList(spacesStore);
when(nodeDAO.getStores()).thenReturn(stores);
}
} }