Merge branch 'stable-3.0'
* stable-3.0:
Bazel: Add fixes for --incompatible_load_java_rules_from_bzl
Upgrade bazlets to latest stable-3.0 to build with 3.0.2 API
Upgrade bazlets to latest stable-2.16 to build with 2.16.11.1 API
Upgrade bazlets to latest stable-2.15 to build with 2.15.16 API
Upgrade bazlets to latest stable-2.15 to build with 2.15.15 API
Enforce repository size quota with QuotaEnforcer
Switch to Gerrit core snapshot version
Upgrade bazlets to latest stable-3.0
Upgrade bazlets to latest stable-2.16 to build with 2.16.10 API
Upgrade bazlets to latest stable-2.16
Upgrade bazlets to latest stable-2.15
Upgrade bazlets to latest stable-2.14
Upgrade bazlets to latest stable-2.15
Upgrade bazlets to latest stable-2.14
Upgrade bazlets to latest stable-2.16 to build with 2.16.9 API
Upgrade bazlets to latest stable-2.15
Upgrade bazlets to latest stable-2.14
Upgrade bazlets to latest stable-2.15 to build with 2.15.14 API
Change-Id: I00f1c82d59d9b7bd1a78469ba633c58b0c4cd740
diff --git a/BUILD b/BUILD
index 77d7922..147b37f 100644
--- a/BUILD
+++ b/BUILD
@@ -1,3 +1,4 @@
+load("@rules_java//java:defs.bzl", "java_library")
load("//tools/bzl:junit.bzl", "junit_tests")
load(
"//tools/bzl:plugin.bzl",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java b/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
index d6b8d87..a20ebed 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/MaxRepositorySizeQuota.java
@@ -14,6 +14,11 @@
package com.googlesource.gerrit.plugins.quota;
+import static com.google.gerrit.server.quota.QuotaGroupDefinitions.REPOSITORY_SIZE_GROUP;
+import static com.google.gerrit.server.quota.QuotaResponse.error;
+import static com.google.gerrit.server.quota.QuotaResponse.noOp;
+import static com.google.gerrit.server.quota.QuotaResponse.ok;
+
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Ordering;
@@ -22,8 +27,10 @@
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.ReceivePackInitializer;
import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.quota.QuotaEnforcer;
+import com.google.gerrit.server.quota.QuotaRequestContext;
+import com.google.gerrit.server.quota.QuotaResponse;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
@@ -36,7 +43,6 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Duration;
-import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
@@ -45,15 +51,11 @@
import org.eclipse.jgit.internal.storage.file.GC;
import org.eclipse.jgit.internal.storage.file.GC.RepoStatistics;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.transport.PostReceiveHook;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.transport.ReceivePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
-public class MaxRepositorySizeQuota
- implements ReceivePackInitializer, PostReceiveHook, RepoSizeCache {
+public class MaxRepositorySizeQuota implements QuotaEnforcer, RepoSizeCache {
private static final Logger log = LoggerFactory.getLogger(MaxRepositorySizeQuota.class);
static final String REPO_SIZE_CACHE = "repo_size";
@@ -73,26 +75,15 @@
protected final LoadingCache<Project.NameKey, AtomicLong> cache;
private final QuotaFinder quotaFinder;
private final ProjectCache projectCache;
- private final ProjectNameResolver projectNameResolver;
@Inject
protected MaxRepositorySizeQuota(
QuotaFinder quotaFinder,
@Named(REPO_SIZE_CACHE) LoadingCache<Project.NameKey, AtomicLong> cache,
- ProjectCache projectCache,
- ProjectNameResolver projectNameResolver) {
+ ProjectCache projectCache) {
this.quotaFinder = quotaFinder;
this.cache = cache;
this.projectCache = projectCache;
- this.projectNameResolver = projectNameResolver;
- }
-
- @Override
- public void init(Project.NameKey project, ReceivePack rp) {
- Optional<Long> maxPackSize = getMaxPackSize(project);
- if (maxPackSize.isPresent()) {
- rp.setMaxPackSizeLimit(maxPackSize.get());
- }
}
protected Optional<Long> getMaxPackSize(Project.NameKey project) {
@@ -132,27 +123,6 @@
}
}
- @Override
- public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
- Project.NameKey project = projectNameResolver.projectName(rp.getRepository());
- if (needPack(commands)) {
- try {
- cache.get(project).getAndAdd(rp.getPackSize());
- } catch (ExecutionException e) {
- log.warn("Couldn't process onPostReceive for {}", project, e);
- }
- }
- }
-
- private boolean needPack(Collection<ReceiveCommand> commands) {
- for (ReceiveCommand cmd : commands) {
- if (cmd.getType() != ReceiveCommand.Type.DELETE) {
- return true;
- }
- }
- return false;
- }
-
@Singleton
static class Loader extends CacheLoader<Project.NameKey, AtomicLong> {
@@ -223,4 +193,75 @@
log.warn("Error setting the size of project {}", p, e);
}
}
+
+ @Override
+ public QuotaResponse dryRun(String quotaGroup, QuotaRequestContext ctx, long numTokens) {
+ if (!REPOSITORY_SIZE_GROUP.equals(quotaGroup)) {
+ return noOp();
+ }
+
+ return ctx.project()
+ .flatMap(p -> getMaxPackSize(p))
+ .map(v -> requestQuota(ctx, numTokens, v, false))
+ .orElse(noOp());
+ }
+
+ @Override
+ public void refill(String quotaGroup, QuotaRequestContext ctx, long numTokens) {
+ if (!REPOSITORY_SIZE_GROUP.equals(quotaGroup)) {
+ return;
+ }
+
+ ctx.project()
+ .ifPresent(
+ p -> {
+ try {
+ cache.get(p).getAndUpdate(current -> current > numTokens ? current - numTokens : 0);
+ } catch (ExecutionException e) {
+ log.warn("Refilling [{}] bytes for repository {} failed", numTokens, p, e);
+ }
+ });
+ }
+
+ @Override
+ public QuotaResponse requestTokens(String quotaGroup, QuotaRequestContext ctx, long numTokens) {
+ if (!REPOSITORY_SIZE_GROUP.equals(quotaGroup)) {
+ return noOp();
+ }
+
+ return ctx.project()
+ .flatMap(p -> getMaxPackSize(p))
+ .map(v -> requestQuota(ctx, numTokens, v, true))
+ .orElse(noOp());
+ }
+
+ @Override
+ public QuotaResponse availableTokens(String quotaGroup, QuotaRequestContext ctx) {
+ if (!REPOSITORY_SIZE_GROUP.equals(quotaGroup)) {
+ return noOp();
+ }
+ return ctx.project().flatMap(p -> getMaxPackSize(p)).map(v -> ok(v)).orElse(noOp());
+ }
+
+ private QuotaResponse requestQuota(
+ QuotaRequestContext ctx, long requested, Long availableSpace, boolean deduct) {
+ Project.NameKey r = ctx.project().get();
+ if (availableSpace >= requested) {
+ if (deduct) {
+ try {
+ cache.get(r).getAndAdd(requested);
+ } catch (ExecutionException e) {
+ String msg = String.format("Quota request [%d] failed for repository %s", requested, r);
+ log.warn(msg, e);
+ return error(msg);
+ }
+ return ok();
+ }
+ }
+
+ return error(
+ String.format(
+ "Requested space [%d] is bigger then available [%d] for repository %s",
+ requested, availableSpace, r));
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/Module.java b/src/main/java/com/googlesource/gerrit/plugins/quota/Module.java
index e514334..37b7b06 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/quota/Module.java
@@ -35,9 +35,9 @@
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
-import com.google.gerrit.server.git.ReceivePackInitializer;
import com.google.gerrit.server.git.validators.UploadValidationListener;
import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.quota.QuotaEnforcer;
import com.google.gerrit.server.validators.ProjectCreationValidationListener;
import com.google.inject.Inject;
import com.google.inject.Provides;
@@ -50,7 +50,6 @@
import com.googlesource.gerrit.plugins.quota.AccountLimitsConfig.Type;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
-import org.eclipse.jgit.transport.PostReceiveHook;
class Module extends CacheModule {
static final String CACHE_NAME_ACCOUNTID = "rate_limits_by_account";
@@ -71,8 +70,7 @@
protected void configure() {
DynamicSet.bind(binder(), ProjectCreationValidationListener.class)
.to(MaxRepositoriesQuotaValidator.class);
- DynamicSet.bind(binder(), ReceivePackInitializer.class).to(MaxRepositorySizeQuota.class);
- DynamicSet.bind(binder(), PostReceiveHook.class).to(MaxRepositorySizeQuota.class);
+ DynamicSet.bind(binder(), QuotaEnforcer.class).to(MaxRepositorySizeQuota.class);
DynamicSet.bind(binder(), ProjectDeletedListener.class).to(DeletionListener.class);
DynamicSet.bind(binder(), GarbageCollectorListener.class).to(GCListener.class);
DynamicSet.setOf(binder(), UsageDataEventCreator.class);
@@ -89,7 +87,6 @@
});
bind(Publisher.class).in(Scopes.SINGLETON);
bind(PublisherScheduler.class).in(Scopes.SINGLETON);
- bind(ProjectNameResolver.class).in(Scopes.SINGLETON);
bind(LifecycleListener.class)
.annotatedWith(UniqueAnnotations.create())
.to(PublisherScheduler.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/quota/ProjectNameResolver.java b/src/main/java/com/googlesource/gerrit/plugins/quota/ProjectNameResolver.java
deleted file mode 100644
index 81980d4..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/quota/ProjectNameResolver.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2014 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.googlesource.gerrit.plugins.quota;
-
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.nio.file.Path;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Repository;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-class ProjectNameResolver {
-
- private static final Logger log = LoggerFactory.getLogger(ProjectNameResolver.class);
- private final Path basePath;
-
- @Inject
- ProjectNameResolver(SitePaths site, @GerritServerConfig final Config cfg) {
- this.basePath = site.resolve(cfg.getString("gerrit", null, "basePath"));
- }
-
- Project.NameKey projectName(Repository repo) {
- Path gitDir = repo.getDirectory().toPath();
- if (gitDir.startsWith(basePath)) {
- String p = basePath.relativize(gitDir).toString();
- String n = p.substring(0, p.length() - ".git".length());
- return Project.nameKey(n);
- }
- log.warn("Couldn't determine the project name from {}", gitDir);
- return null;
- }
-}