From a2b985276ce88152fb8e66ca0b018f189fdb095b Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Sat, 21 Nov 2015 09:47:32 -0800 Subject: [PATCH] Enable larger rules.pl files Allow administrators to boost the internal limits on rules.pl files. Change-Id: I667d18d032cc51b6dabfe7c45268e995f728a2dd --- Documentation/config-gerrit.txt | 20 +++++++++++++++ .../com/google/gerrit/rules/RulesCache.java | 25 ++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 359f281983..c9bea0aa2e 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -3134,6 +3134,26 @@ compiling source code to internal Prolog machine code. + Default is 10x reductionLimit (1,000,000). +[[rules.maxSourceBytes]]rules.maxSourceBytes:: ++ +Maximum input size (in bytes) of a Prolog rules.pl file. Larger +source files may need a larger rules.compileReductionLimit. Consider +using link:pgm-rulec.html[rulec] to precompile larger rule files. ++ +A size of 0 bytes disables rules, same as rules.enable = false. ++ +Default is 128 KiB. + +[[rules.maxPrologDatabaseSize]]rules.maxPrologDatabaseSize:: ++ +Number of predicate clauses allowed to be defined in the Prolog +database by project rules. Very complex rules may need more than the +default 256 limit, but cost more memory and may need more time to +evaluate. Consider using link:pgm-rulec.html[rulec] to precompile +larger rule files. ++ +Default is 256. + [[execution]] === Section execution diff --git a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java index 5dd26f9881..f6df335ab8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java +++ b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java @@ -75,20 +75,9 @@ import java.util.Map; */ @Singleton public class RulesCache { - /** Maximum size of a dynamic Prolog script, in bytes. */ - private static final int SRC_LIMIT = 128 * 1024; - - /** Default size of the internal Prolog database within each interpreter. */ - private static final int DB_MAX = 256; - private static final List PACKAGE_LIST = ImmutableList.of( Prolog.BUILTIN, "gerrit"); - private final Map machineCache = new HashMap<>(); - - private final ReferenceQueue dead = - new ReferenceQueue<>(); - private static final class MachineRef extends WeakReference { final ObjectId key; @@ -100,17 +89,25 @@ public class RulesCache { } private final boolean enableProjectRules; + private final int maxDbSize; + private final int maxSrcBytes; private final Path cacheDir; private final Path rulesDir; private final GitRepositoryManager gitMgr; private final DynamicSet predicateProviders; private final ClassLoader systemLoader; private final PrologMachineCopy defaultMachine; + private final Map machineCache = new HashMap<>(); + private final ReferenceQueue dead = + new ReferenceQueue<>(); @Inject protected RulesCache(@GerritServerConfig Config config, SitePaths site, GitRepositoryManager gm, DynamicSet predicateProviders) { - enableProjectRules = config.getBoolean("rules", null, "enable", true); + maxDbSize = config.getInt("rules", null, "maxPrologDatabaseSize", 256); + maxSrcBytes = config.getInt("rules", null, "maxSourceBytes", 128 << 10); + enableProjectRules = config.getBoolean("rules", null, "enable", true) + && maxSrcBytes > 0; cacheDir = site.resolve(config.getString("cache", null, "directory")); rulesDir = cacheDir != null ? cacheDir.resolve("rules") : null; gitMgr = gm; @@ -267,7 +264,7 @@ public class RulesCache { try (Repository git = gitMgr.openRepository(project)) { try { ObjectLoader ldr = git.open(rulesId, Constants.OBJ_BLOB); - byte[] raw = ldr.getCachedBytes(SRC_LIMIT); + byte[] raw = ldr.getCachedBytes(maxSrcBytes); return RawParseUtils.decode(raw); } catch (LargeObjectException e) { throw new CompileException("rules of " + project + " are too large", e); @@ -281,7 +278,7 @@ public class RulesCache { private BufferingPrologControl newEmptyMachine(ClassLoader cl) { BufferingPrologControl ctl = new BufferingPrologControl(); - ctl.setMaxDatabaseSize(DB_MAX); + ctl.setMaxDatabaseSize(maxDbSize); ctl.setPrologClassLoader(new PrologClassLoader(new PredicateClassLoader( predicateProviders, cl))); ctl.setEnabled(EnumSet.allOf(Prolog.Feature.class), false);