All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.rules.PrologEnvironment Maven / Gradle / Ivy

There is a newer version: 3.10.0-rc4
Show newest version
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.rules;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import com.googlecode.prolog_cafe.lang.BufferingPrologControl;
import com.googlecode.prolog_cafe.lang.Predicate;
import com.googlecode.prolog_cafe.lang.PredicateEncoder;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologMachineCopy;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.Config;

/**
 * Per-thread Prolog interpreter.
 *
 * 

This class is not thread safe. * *

A single copy of the Prolog interpreter, for the current thread. */ public class PrologEnvironment extends BufferingPrologControl { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); public interface Factory { /** * Construct a new Prolog interpreter. * * @param src the machine to template the new environment from. * @return the new interpreter. */ PrologEnvironment create(PrologMachineCopy src); } private final Args args; private final Map, Object> storedValues; private List cleanup; @Inject PrologEnvironment(Args a, @Assisted PrologMachineCopy src) { super(src); setEnabled(EnumSet.allOf(Prolog.Feature.class), false); args = a; storedValues = new HashMap<>(); cleanup = new LinkedList<>(); } public Args getArgs() { return args; } @Override public void setPredicate(Predicate goal) { super.setPredicate(goal); setReductionLimit(args.reductionLimit(goal)); } /** * Lookup a stored value in the interpreter's hash manager. * * @param type of stored Java object. * @param sv unique key. * @return the value; null if not stored. */ @SuppressWarnings("unchecked") public T get(StoredValue sv) { return (T) storedValues.get(sv); } /** * Set a stored value on the interpreter's hash manager. * * @param type of stored Java object. * @param sv unique key. * @param obj the value to store under {@code sv}. */ @SuppressWarnings("unchecked") public void set(StoredValue sv, T obj) { storedValues.put((StoredValue) sv, obj); } /** * Copy the stored values from another interpreter to this one. Also gets the cleanup from the * child interpreter */ public void copyStoredValues(PrologEnvironment child) { storedValues.putAll(child.storedValues); setCleanup(child.cleanup); } /** * Assign the environment a cleanup list (in order to use a centralized list) If this * enivronment's list is non-empty, append its cleanup tasks to the assigning list. */ public void setCleanup(List newCleanupList) { newCleanupList.addAll(cleanup); cleanup = newCleanupList; } /** * Adds cleanup task to run when close() is called * * @param task is run when close() is called */ public void addToCleanup(Runnable task) { cleanup.add(task); } /** Release resources stored in interpreter's hash manager. */ public void close() { for (Iterator i = cleanup.iterator(); i.hasNext(); ) { try { i.next().run(); } catch (Throwable err) { logger.atSevere().withCause(err).log("Failed to execute cleanup for PrologEnvironment"); } i.remove(); } } @Singleton public static class Args { private static final Class CONSULT_STREAM_2; static { try { @SuppressWarnings("unchecked") Class c = (Class) Class.forName( PredicateEncoder.encode(Prolog.BUILTIN, "consult_stream", 2), false, RulesCache.class.getClassLoader()); CONSULT_STREAM_2 = c; } catch (ClassNotFoundException e) { throw new LinkageError("cannot find predicate consult_stream", e); } } private final ProjectCache projectCache; private final PermissionBackend permissionBackend; private final GitRepositoryManager repositoryManager; private final PatchListCache patchListCache; private final PatchSetInfoFactory patchSetInfoFactory; private final IdentifiedUser.GenericFactory userFactory; private final Provider anonymousUser; private final int reductionLimit; private final int compileLimit; private final PatchSetUtil patchsetUtil; private Emails emails; @Inject Args( ProjectCache projectCache, PermissionBackend permissionBackend, GitRepositoryManager repositoryManager, PatchListCache patchListCache, PatchSetInfoFactory patchSetInfoFactory, IdentifiedUser.GenericFactory userFactory, Provider anonymousUser, @GerritServerConfig Config config, PatchSetUtil patchsetUtil, Emails emails) { this.projectCache = projectCache; this.permissionBackend = permissionBackend; this.repositoryManager = repositoryManager; this.patchListCache = patchListCache; this.patchSetInfoFactory = patchSetInfoFactory; this.userFactory = userFactory; this.anonymousUser = anonymousUser; this.patchsetUtil = patchsetUtil; this.emails = emails; int limit = config.getInt("rules", null, "reductionLimit", 100000); reductionLimit = limit <= 0 ? Integer.MAX_VALUE : limit; limit = config.getInt( "rules", null, "compileReductionLimit", (int) Math.min(10L * limit, Integer.MAX_VALUE)); compileLimit = limit <= 0 ? Integer.MAX_VALUE : limit; } private int reductionLimit(Predicate goal) { if (goal.getClass() == CONSULT_STREAM_2) { return compileLimit; } return reductionLimit; } public ProjectCache getProjectCache() { return projectCache; } public PermissionBackend getPermissionBackend() { return permissionBackend; } public GitRepositoryManager getGitRepositoryManager() { return repositoryManager; } public PatchListCache getPatchListCache() { return patchListCache; } public PatchSetInfoFactory getPatchSetInfoFactory() { return patchSetInfoFactory; } public IdentifiedUser.GenericFactory getUserFactory() { return userFactory; } public AnonymousUser getAnonymousUser() { return anonymousUser.get(); } public PatchSetUtil getPatchsetUtil() { return patchsetUtil; } public Emails getEmails() { return emails; } } }