LCOV - code coverage report
Current view: top level - server/rules - PrologEnvironment.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 58 68 85.3 %
Date: 2022-11-19 15:00:39 Functions: 17 23 73.9 %

          Line data    Source code
       1             : // Copyright (C) 2011 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.rules;
      16             : 
      17             : import com.google.common.flogger.FluentLogger;
      18             : import com.google.gerrit.server.AnonymousUser;
      19             : import com.google.gerrit.server.IdentifiedUser;
      20             : import com.google.gerrit.server.PatchSetUtil;
      21             : import com.google.gerrit.server.account.Emails;
      22             : import com.google.gerrit.server.config.GerritServerConfig;
      23             : import com.google.gerrit.server.config.PluginConfigFactory;
      24             : import com.google.gerrit.server.git.GitRepositoryManager;
      25             : import com.google.gerrit.server.patch.DiffOperations;
      26             : import com.google.gerrit.server.patch.PatchSetInfoFactory;
      27             : import com.google.gerrit.server.permissions.PermissionBackend;
      28             : import com.google.gerrit.server.project.ProjectCache;
      29             : import com.google.inject.Inject;
      30             : import com.google.inject.Provider;
      31             : import com.google.inject.Singleton;
      32             : import com.google.inject.assistedinject.Assisted;
      33             : import com.googlecode.prolog_cafe.lang.BufferingPrologControl;
      34             : import com.googlecode.prolog_cafe.lang.Predicate;
      35             : import com.googlecode.prolog_cafe.lang.PredicateEncoder;
      36             : import com.googlecode.prolog_cafe.lang.Prolog;
      37             : import com.googlecode.prolog_cafe.lang.PrologMachineCopy;
      38             : import java.util.ArrayList;
      39             : import java.util.EnumSet;
      40             : import java.util.HashMap;
      41             : import java.util.Iterator;
      42             : import java.util.List;
      43             : import java.util.Map;
      44             : import org.eclipse.jgit.lib.Config;
      45             : 
      46             : /**
      47             :  * Per-thread Prolog interpreter.
      48             :  *
      49             :  * <p>This class is not thread safe.
      50             :  *
      51             :  * <p>A single copy of the Prolog interpreter, for the current thread.
      52             :  */
      53             : public class PrologEnvironment extends BufferingPrologControl {
      54         147 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      55             : 
      56             :   public interface Factory {
      57             :     /**
      58             :      * Construct a new Prolog interpreter.
      59             :      *
      60             :      * @param src the machine to template the new environment from.
      61             :      * @return the new interpreter.
      62             :      */
      63             :     PrologEnvironment create(PrologMachineCopy src);
      64             :   }
      65             : 
      66             :   private final Args args;
      67             :   private final Map<StoredValue<Object>, Object> storedValues;
      68             :   private List<Runnable> cleanup;
      69             : 
      70             :   @Inject
      71             :   PrologEnvironment(Args a, @Assisted PrologMachineCopy src) {
      72         104 :     super(src);
      73         104 :     setEnabled(EnumSet.allOf(Prolog.Feature.class), false);
      74         104 :     args = a;
      75         104 :     storedValues = new HashMap<>();
      76         104 :     cleanup = new ArrayList<>();
      77         104 :   }
      78             : 
      79             :   public Args getArgs() {
      80           4 :     return args;
      81             :   }
      82             : 
      83             :   @Override
      84             :   public void setPredicate(Predicate goal) {
      85         104 :     super.setPredicate(goal);
      86         104 :     int reductionLimit = args.reductionLimit(goal);
      87         104 :     setReductionLimit(reductionLimit);
      88         104 :   }
      89             : 
      90             :   /**
      91             :    * Lookup a stored value in the interpreter's hash manager.
      92             :    *
      93             :    * @param <T> type of stored Java object.
      94             :    * @param sv unique key.
      95             :    * @return the value; null if not stored.
      96             :    */
      97             :   @SuppressWarnings("unchecked")
      98             :   public <T> T get(StoredValue<T> sv) {
      99         104 :     return (T) storedValues.get(sv);
     100             :   }
     101             : 
     102             :   /**
     103             :    * Set a stored value on the interpreter's hash manager.
     104             :    *
     105             :    * @param <T> type of stored Java object.
     106             :    * @param sv unique key.
     107             :    * @param obj the value to store under {@code sv}.
     108             :    */
     109             :   @SuppressWarnings("unchecked")
     110             :   public <T> void set(StoredValue<T> sv, T obj) {
     111         104 :     storedValues.put((StoredValue<Object>) sv, obj);
     112         104 :   }
     113             : 
     114             :   /**
     115             :    * Copy the stored values from another interpreter to this one. Also gets the cleanup from the
     116             :    * child interpreter
     117             :    */
     118             :   public void copyStoredValues(PrologEnvironment child) {
     119         102 :     storedValues.putAll(child.storedValues);
     120         102 :     setCleanup(child.cleanup);
     121         102 :   }
     122             : 
     123             :   /**
     124             :    * Assign the environment a cleanup list (in order to use a centralized list) If this
     125             :    * enivronment's list is non-empty, append its cleanup tasks to the assigning list.
     126             :    */
     127             :   public void setCleanup(List<Runnable> newCleanupList) {
     128         102 :     newCleanupList.addAll(cleanup);
     129         102 :     cleanup = newCleanupList;
     130         102 :   }
     131             : 
     132             :   /**
     133             :    * Adds cleanup task to run when close() is called
     134             :    *
     135             :    * @param task is run when close() is called
     136             :    */
     137             :   public void addToCleanup(Runnable task) {
     138           2 :     cleanup.add(task);
     139           2 :   }
     140             : 
     141             :   /** Release resources stored in interpreter's hash manager. */
     142             :   public void close() {
     143         103 :     for (Iterator<Runnable> i = cleanup.iterator(); i.hasNext(); ) {
     144             :       try {
     145           2 :         i.next().run();
     146           0 :       } catch (Exception err) {
     147           0 :         logger.atSevere().withCause(err).log("Failed to execute cleanup for PrologEnvironment");
     148           2 :       }
     149           2 :       i.remove();
     150             :     }
     151         103 :   }
     152             : 
     153             :   @Singleton
     154             :   public static class Args {
     155             :     private static final Class<Predicate> CONSULT_STREAM_2;
     156             : 
     157             :     static {
     158             :       try {
     159             :         @SuppressWarnings("unchecked")
     160         147 :         Class<Predicate> c =
     161             :             (Class<Predicate>)
     162         147 :                 Class.forName(
     163         147 :                     PredicateEncoder.encode(Prolog.BUILTIN, "consult_stream", 2),
     164             :                     false,
     165         147 :                     RulesCache.class.getClassLoader());
     166         147 :         CONSULT_STREAM_2 = c;
     167           0 :       } catch (ClassNotFoundException e) {
     168           0 :         throw new LinkageError("cannot find predicate consult_stream", e);
     169         147 :       }
     170         147 :     }
     171             : 
     172             :     private final ProjectCache projectCache;
     173             :     private final PermissionBackend permissionBackend;
     174             :     private final GitRepositoryManager repositoryManager;
     175             :     private final PluginConfigFactory pluginConfigFactory;
     176             :     private final DiffOperations diffOperations;
     177             :     private final PatchSetInfoFactory patchSetInfoFactory;
     178             :     private final IdentifiedUser.GenericFactory userFactory;
     179             :     private final Provider<AnonymousUser> anonymousUser;
     180             :     private final int reductionLimit;
     181             :     private final int compileLimit;
     182             :     private final PatchSetUtil patchsetUtil;
     183             :     private Emails emails;
     184             : 
     185             :     @Inject
     186             :     Args(
     187             :         ProjectCache projectCache,
     188             :         PermissionBackend permissionBackend,
     189             :         GitRepositoryManager repositoryManager,
     190             :         PluginConfigFactory pluginConfigFactory,
     191             :         DiffOperations diffOperations,
     192             :         PatchSetInfoFactory patchSetInfoFactory,
     193             :         IdentifiedUser.GenericFactory userFactory,
     194             :         Provider<AnonymousUser> anonymousUser,
     195             :         @GerritServerConfig Config config,
     196             :         PatchSetUtil patchsetUtil,
     197         147 :         Emails emails) {
     198         147 :       this.projectCache = projectCache;
     199         147 :       this.permissionBackend = permissionBackend;
     200         147 :       this.repositoryManager = repositoryManager;
     201         147 :       this.pluginConfigFactory = pluginConfigFactory;
     202         147 :       this.diffOperations = diffOperations;
     203         147 :       this.patchSetInfoFactory = patchSetInfoFactory;
     204         147 :       this.userFactory = userFactory;
     205         147 :       this.anonymousUser = anonymousUser;
     206         147 :       this.patchsetUtil = patchsetUtil;
     207         147 :       this.emails = emails;
     208         147 :       this.reductionLimit = RuleUtil.reductionLimit(config);
     209         147 :       this.compileLimit = RuleUtil.compileReductionLimit(config);
     210             : 
     211         147 :       logger.atInfo().log("reductionLimit: %d, compileLimit: %d", reductionLimit, compileLimit);
     212         147 :     }
     213             : 
     214             :     private int reductionLimit(Predicate goal) {
     215         104 :       if (goal.getClass() == CONSULT_STREAM_2) {
     216           1 :         logger.atFine().log(
     217             :             "predicate class is CONSULT_STREAM_2: override reductionLimit with compileLimit (%d)",
     218             :             compileLimit);
     219           1 :         return compileLimit;
     220             :       }
     221         104 :       return reductionLimit;
     222             :     }
     223             : 
     224             :     public ProjectCache getProjectCache() {
     225           0 :       return projectCache;
     226             :     }
     227             : 
     228             :     public PermissionBackend getPermissionBackend() {
     229           0 :       return permissionBackend;
     230             :     }
     231             : 
     232             :     public GitRepositoryManager getGitRepositoryManager() {
     233           2 :       return repositoryManager;
     234             :     }
     235             : 
     236             :     public PluginConfigFactory getPluginConfigFactory() {
     237           0 :       return pluginConfigFactory;
     238             :     }
     239             : 
     240             :     public DiffOperations getDiffOperations() {
     241           2 :       return diffOperations;
     242             :     }
     243             : 
     244             :     public PatchSetInfoFactory getPatchSetInfoFactory() {
     245           0 :       return patchSetInfoFactory;
     246             :     }
     247             : 
     248             :     public IdentifiedUser.GenericFactory getUserFactory() {
     249           0 :       return userFactory;
     250             :     }
     251             : 
     252             :     public AnonymousUser getAnonymousUser() {
     253           0 :       return anonymousUser.get();
     254             :     }
     255             : 
     256             :     public PatchSetUtil getPatchsetUtil() {
     257           4 :       return patchsetUtil;
     258             :     }
     259             : 
     260             :     public Emails getEmails() {
     261           3 :       return emails;
     262             :     }
     263             :   }
     264             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750