Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/auth-caching' into featu…
Browse files Browse the repository at this point in the history
…re/performance-stable
  • Loading branch information
1azyman committed Apr 12, 2018
2 parents a3db033 + e8488d4 commit bf9db50
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 157 deletions.
Expand Up @@ -13804,8 +13804,80 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="caching" type="tns:CachingConfigurationType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
TODO

TEMPORARY/EXPERIMENTAL.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="CachingConfigurationType">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="global" type="tns:GlobalCacheConfigurationType" minOccurs="0"/>
<xsd:element name="authentication" type="xsd:int" minOccurs="0" default="0">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="GlobalCacheConfigurationType">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="enabled" type="xsd:boolean" minOccurs="0" default="false">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="objectType" type="xsd:QName" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="maxObjectsPerType" type="xsd:int" minOccurs="0" default="5000">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="expirationInterval" type="xsd:int" minOccurs="0" default="900">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="defaultVersionCheckInterval" type="xsd:int" minOccurs="0" default="60">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="AdminGuiConfigurationType">
<xsd:annotation>
Expand Down
4 changes: 4 additions & 0 deletions model/model-impl/pom.xml
Expand Up @@ -164,6 +164,10 @@
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
Expand Down
Expand Up @@ -48,6 +48,9 @@
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.PointInTimeType;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
Expand Down Expand Up @@ -102,6 +105,8 @@ public class AssignmentEvaluator<F extends FocusType> {
private final boolean loginMode; // restricted mode, evaluating only authorizations and gui config (TODO name)
private final PrismObject<SystemConfigurationType> systemConfiguration;
private final MappingEvaluator mappingEvaluator;
private final boolean allowCached;
private final Long staleness;
private final EvaluatedAssignmentTargetCache evaluatedAssignmentTargetCache;

private AssignmentEvaluator(Builder<F> builder) {
Expand All @@ -118,6 +123,8 @@ private AssignmentEvaluator(Builder<F> builder) {
loginMode = builder.loginMode;
systemConfiguration = builder.systemConfiguration;
mappingEvaluator = builder.mappingEvaluator;
allowCached = builder.allowCached;
staleness = builder.staleness;
evaluatedAssignmentTargetCache = new EvaluatedAssignmentTargetCache();
}

Expand Down Expand Up @@ -623,7 +630,15 @@ private <O extends ObjectType> List<PrismObject<O>> resolveTargets(AssignmentPat
LOGGER.trace("Resolving target {}:{} from repository", targetClass.getSimpleName(), oid);
PrismObject<O> target;
try {
target = repository.getObject(targetClass, oid, null, ctx.result);
Collection<SelectorOptions<GetOperationOptions>> options = null;
if (allowCached) {
GetOperationOptions opts = GetOperationOptions.createPointInTimeType(PointInTimeType.CACHED);
opts.setStaleness(staleness);

options = SelectorOptions.createCollection(opts);
}

target = repository.getObject(targetClass, oid, options, ctx.result);
} catch (SchemaException e) {
throw new SchemaException(e.getMessage() + " in " + segment.sourceDescription, e);
}
Expand Down Expand Up @@ -1231,10 +1246,22 @@ public static final class Builder<F extends FocusType> {
private boolean loginMode = false;
private PrismObject<SystemConfigurationType> systemConfiguration;
private MappingEvaluator mappingEvaluator;
private boolean allowCached = false;
private Long staleness;

public Builder() {
}

public Builder<F> allowCached(boolean val) {
allowCached = val;
return this;
}

public Builder<F> staleness(Long val) {
staleness = val;
return this;
}

public Builder<F> repository(RepositoryService val) {
repository = val;
return this;
Expand Down
Expand Up @@ -42,7 +42,10 @@
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.PointInTimeType;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.AdminGuiConfigTypeUtil;
Expand All @@ -55,19 +58,13 @@
import com.evolveum.midpoint.security.api.UserProfileService;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.PolicyViolationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
Expand All @@ -82,9 +79,9 @@
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
* @author lazyman
Expand Down Expand Up @@ -112,6 +109,22 @@ public class UserProfileServiceImpl implements UserProfileService, UserDetailsSe

private MessageSourceAccessor messages;

private static final long ASSIGNMENT_TARGET_STALENESS = 60 * 1000; // 60 seconds

// todo move oid cache to repository cache
private static final long MAX_CACHE_SIZE = 5000;
private static final long MAX_CACHE_TTL = 60 * 1000; // 60 seconds
// caches <user.name, oid>
private Cache<String, String> oidCache;

{
oidCache = CacheBuilder.newBuilder()
.expireAfterAccess(MAX_CACHE_TTL, TimeUnit.MILLISECONDS)
.concurrencyLevel(20)
.maximumSize(MAX_CACHE_SIZE)
.build();
}

@Override
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
Expand Down Expand Up @@ -181,6 +194,22 @@ public void updateUser(MidPointPrincipal principal) {
}

private PrismObject<UserType> findByUsername(String username, OperationResult result) throws SchemaException, ObjectNotFoundException {
String oid = null;
try {
oid = oidCache.getIfPresent(username);
} catch (Exception ex) {
}
if (oid != null) {
GetOperationOptions opts = GetOperationOptions.createPointInTimeType(PointInTimeType.CACHED);
opts.setStaleness(MAX_CACHE_TTL);

PrismObject user = repositoryService.getObject(UserType.class, oid, SelectorOptions.createCollection(opts), result);
String userName = user.getName() != null ? user.getName().getOrig() : null;
if (Objects.equals(username, userName)) {
return user;
}
}

PolyString usernamePoly = new PolyString(username);
ObjectQuery query = ObjectQueryUtil.createNormNameQuery(usernamePoly, prismContext);
LOGGER.trace("Looking for user, query:\n" + query.debugDump());
Expand All @@ -190,7 +219,10 @@ private PrismObject<UserType> findByUsername(String username, OperationResult re
if (list.size() != 1) {
return null;
}
return list.get(0);
PrismObject<UserType> user = list.get(0);
oidCache.put(username, user.getOid());

return user;
}

private void initializePrincipalFromAssignments(MidPointPrincipal principal, PrismObject<SystemConfigurationType> systemConfiguration, AuthorizationTransformer authorizationTransformer) throws SchemaException {
Expand Down Expand Up @@ -225,7 +257,10 @@ private void initializePrincipalFromAssignments(MidPointPrincipal principal, Pri
.loginMode(true)
// We do not have real lens context here. But the push methods in ModelExpressionThreadLocalHolder
// will need something to push on the stack. So give them context placeholder.
.lensContext(lensContext);
.lensContext(lensContext)
// this will allow to read cached assignment target references
.allowCached(true)
.staleness(ASSIGNMENT_TARGET_STALENESS);

AssignmentEvaluator<UserType> assignmentEvaluator = builder.build();

Expand Down Expand Up @@ -389,6 +424,4 @@ public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
// TODO Auto-generated method stub

}


}
6 changes: 6 additions & 0 deletions repo/repo-cache/pom.xml
Expand Up @@ -79,6 +79,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>

<!-- Eh cache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>

<!-- Testing dependecies -->
<dependency>
Expand Down

This file was deleted.

0 comments on commit bf9db50

Please sign in to comment.