Cleanup CommentsInNotesUtil to read larger notes
The default read limit inside of JGit is usually around 1-5 MiB,
after which the reader will fail to supply content unless the
caller is streaming.
Callers should supply their own maximum sane read limit. Cap it here
at 25 MiB worth of formatted comments per commit on a change. Notes
larger than this will fail to read into a server, stopping unexpected
memory explosion.
Callers that won't modify the data are encouraged to use the faster
getCachedBytes() method, which does not copy before returning.
Insert is overloaded to handle the entire byte array, allowing
the note to be written in one line of code.
Change-Id: Id3b197edb9fddb15d00d62dbe9b6c2b2c08ad9d1
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
index bb8fe4d..217d42d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
@@ -18,6 +18,7 @@
import static com.google.gerrit.server.notedb.ChangeNoteUtil.GERRIT_PLACEHOLDER_HOST;
import static com.google.gerrit.server.notedb.ChangeNotes.parseException;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
@@ -37,9 +38,9 @@
import com.google.inject.Inject;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -48,11 +49,11 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.GitDateFormatter;
+import org.eclipse.jgit.util.GitDateFormatter.Format;
import org.eclipse.jgit.util.GitDateParser;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.QuotedString;
import org.eclipse.jgit.util.RawParseUtils;
-import org.eclipse.jgit.util.GitDateFormatter.Format;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -79,6 +80,7 @@
private static final String PATCH_SET = "Patch-set";
private static final String REVISION = "Revision";
private static final String UUID = "UUID";
+ private static final int MAX_NOTE_SZ = 25 << 20;
public static NoteMap parseCommentsFromNotes(Repository repo, String refName,
RevWalk walk, Change.Id changeId,
@@ -90,12 +92,14 @@
if (ref == null) {
return null;
}
+
+ ObjectReader reader = walk.getObjectReader();
RevCommit commit = walk.parseCommit(ref.getObjectId());
- NoteMap noteMap = NoteMap.read(walk.getObjectReader(), commit);
+ NoteMap noteMap = NoteMap.read(reader, commit);
for (Note note: noteMap) {
- byte[] bytes = walk.getObjectReader().open(
- note.getData(), Constants.OBJ_BLOB).getBytes();
+ byte[] bytes =
+ reader.open(note.getData(), OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ);
List<PatchLineComment> result = parseNote(bytes, changeId, status);
if (result == null || result.isEmpty()) {
continue;
@@ -520,12 +524,10 @@
throws OrmException, IOException {
checkArgument(!allComments.isEmpty(),
"No comments to write; to delete, use removeNoteFromNoteMap().");
- ObjectId commitOID =
+ ObjectId commit =
ObjectId.fromString(allComments.get(0).getRevId().get());
Collections.sort(allComments, ChangeNotes.PatchLineCommentComparator);
- byte[] note = buildNote(allComments);
- ObjectId noteId = inserter.insert(Constants.OBJ_BLOB, note, 0, note.length);
- noteMap.set(commitOID, noteId);
+ noteMap.set(commit, inserter.insert(OBJ_BLOB, buildNote(allComments)));
}
public void removeNote(NoteMap noteMap, RevId commitId)