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; } } }