Log the reason why a ref object wasn't loaded by RevisionReader
It may happen that one ref cannot be read in memory for being used
in an ApplyObject REST-API. Add more logging on the reason behind
the failure to read all the objects pointed to a ref, so that the
Gerrit admin can take the appropriate actions to allow the replication
shortcut and avoid a full git fetch.
Change-Id: I7dbaa7b6ed35c389c7e2477467829d85dfc542e8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/RevisionReader.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/RevisionReader.java
index 92cbd95..eedd9eb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/RevisionReader.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/RevisionReader.java
@@ -81,7 +81,7 @@
ObjectLoader commitLoader = git.open(objectId);
totalRefSize += commitLoader.getSize();
- verifySize(totalRefSize, commitLoader);
+ verifySize(project, refName, objectId, totalRefSize, commitLoader);
if (commitLoader.getType() == Constants.OBJ_BLOB) {
return Optional.of(
@@ -108,7 +108,7 @@
RevTree tree = commit.getTree();
ObjectLoader treeLoader = git.open(commit.getTree().toObjectId());
totalRefSize += treeLoader.getSize();
- verifySize(totalRefSize, treeLoader);
+ verifySize(project, refName, commit.getTree().toObjectId(), totalRefSize, treeLoader);
RevisionObjectData treeRev =
new RevisionObjectData(tree.getType(), treeLoader.getCachedBytes());
@@ -117,11 +117,11 @@
try (TreeWalk walk = new TreeWalk(git)) {
if (commit.getParentCount() > 0) {
List<DiffEntry> diffEntries = readDiffs(git, commit, tree, walk);
- blobs = readBlobs(git, totalRefSize, diffEntries);
+ blobs = readBlobs(project, refName, git, totalRefSize, diffEntries);
} else {
walk.setRecursive(true);
walk.addTree(tree);
- blobs = readBlobs(git, totalRefSize, walk);
+ blobs = readBlobs(project, refName, git, totalRefSize, walk);
}
}
return Optional.of(new RevisionData(commitRev, treeRev, blobs));
@@ -143,7 +143,8 @@
return DiffEntry.scan(walk, true);
}
- private List<RevisionObjectData> readBlobs(Repository git, Long totalRefSize, TreeWalk walk)
+ private List<RevisionObjectData> readBlobs(
+ Project.NameKey projectName, String refName, Repository git, Long totalRefSize, TreeWalk walk)
throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException,
IOException {
List<RevisionObjectData> blobs = Lists.newLinkedList();
@@ -151,7 +152,7 @@
ObjectId objectId = walk.getObjectId(0);
ObjectLoader objectLoader = git.open(objectId);
totalRefSize += objectLoader.getSize();
- verifySize(totalRefSize, objectLoader);
+ verifySize(projectName, refName, objectId, totalRefSize, objectLoader);
RevisionObjectData rev =
new RevisionObjectData(objectLoader.getType(), objectLoader.getCachedBytes());
@@ -161,14 +162,19 @@
}
private List<RevisionObjectData> readBlobs(
- Repository git, Long totalRefSize, List<DiffEntry> diffEntries)
+ Project.NameKey projectName,
+ String refName,
+ Repository git,
+ Long totalRefSize,
+ List<DiffEntry> diffEntries)
throws MissingObjectException, IOException {
List<RevisionObjectData> blobs = Lists.newLinkedList();
for (DiffEntry diffEntry : diffEntries) {
if (!ChangeType.DELETE.equals(diffEntry.getChangeType())) {
ObjectLoader objectLoader = git.open(diffEntry.getNewId().toObjectId());
totalRefSize += objectLoader.getSize();
- verifySize(totalRefSize, objectLoader);
+ verifySize(
+ projectName, refName, diffEntry.getNewId().toObjectId(), totalRefSize, objectLoader);
RevisionObjectData rev =
new RevisionObjectData(objectLoader.getType(), objectLoader.getCachedBytes());
blobs.add(rev);
@@ -185,9 +191,44 @@
return parentCommit.getTree();
}
- private void verifySize(Long totalRefSize, ObjectLoader loader) throws LargeObjectException {
- if (loader.isLarge() || totalRefSize > maxRefSize) {
- throw new LargeObjectException();
+ private void verifySize(
+ Project.NameKey projectName,
+ String refName,
+ ObjectId objectId,
+ Long totalRefSize,
+ ObjectLoader loader)
+ throws LargeObjectException {
+ if (loader.isLarge()) {
+ repLog.warn(
+ "Objects associated with {}:{} ({}) are too big to fit into the object loader's memory",
+ projectName,
+ refName,
+ objectTypeToString(loader.getType()));
+ throw new LargeObjectException(objectId);
+ }
+
+ if (totalRefSize > maxRefSize) {
+ repLog.warn(
+ "Objects associated with {}:{} ({}) use {} bytes, over the maximum limit of {} bytes",
+ projectName,
+ refName,
+ objectTypeToString(loader.getType()),
+ totalRefSize,
+ maxRefSize);
+ throw new LargeObjectException(objectId);
+ }
+ }
+
+ private static String objectTypeToString(int type) {
+ switch (type) {
+ case Constants.OBJ_BLOB:
+ return "BLOB";
+ case Constants.OBJ_COMMIT:
+ return "COMMIT";
+ case Constants.OBJ_TREE:
+ return "TREE";
+ default:
+ return "type:" + type;
}
}
}