Parse draft notes from staged results if auto-rebuilding fails

It's possible for ChangeNotes to think the change is up to date with
respect to the NoteDbChangeState, but drafts for one or more users
might be out of date, so DraftCommentNotes may actually be responsible
for rebuilding the change. Do the same thing as in I2797d4fb but for
drafts.

I attempted to write a test for this in I2797d4fb, but missed the fact
that setting the NoteDbChangeState to an invalid value would cause
rebuilding to happen in the ChangeNotes rather than the
DraftCommentNotes, so we weren't exercising that code.

Fix the bug and add another test method. The first method was actually
testing something useful, that ChangeNotes was properly passing the
rebuildResult field to its child DraftCommentNotes. It just wasn't
testing DraftCommentNotes#rebuildAndOpen.

Change-Id: I1eadba8e9ccd18c39a18535d9d737c4178dc1626
This commit is contained in:
Dave Borowitz
2016-06-20 11:29:14 -04:00
parent b554602b62
commit 954a8cf963
3 changed files with 92 additions and 11 deletions

View File

@@ -15,17 +15,20 @@
package com.google.gerrit.server.notedb;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimap;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.RepoRefCache;
import com.google.gerrit.server.notedb.NoteDbUpdateManager.StagedResult;
import com.google.gerrit.server.project.NoSuchChangeException;
@@ -181,22 +184,42 @@ public class DraftCommentNotes extends AbstractChangeNotes<DraftCommentNotes> {
}
private LoadHandle rebuildAndOpen(Repository repo) throws IOException {
try {
NoteDbUpdateManager.Result r =
args.rebuilder.get().rebuild(args.db.get(), getChangeId());
if (r == null) {
try (Timer1.Context timer =
args.metrics.autoRebuildLatency.start(CHANGES)) {
Change.Id cid = getChangeId();
ReviewDb db = args.db.get();
ChangeRebuilder rebuilder = args.rebuilder.get();
NoteDbUpdateManager manager = rebuilder.stage(db, cid);
if (manager == null) {
return super.openHandle(repo); // May be null in tests.
}
ObjectId draftsId = r.newState().getDraftIds().get(author);
repo.scanForRepoChanges();
return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), draftsId);
NoteDbUpdateManager.Result r = manager.stageAndApplyDelta(change);
try {
rebuilder.execute(db, cid, manager);
repo.scanForRepoChanges();
} catch (OrmException | IOException e) {
// See ChangeNotes#rebuildAndOpen.
args.metrics.autoRebuildFailureCount.increment(CHANGES);
checkNotNull(r.staged());
return LoadHandle.create(
ChangeNotesCommit.newStagedRevWalk(
repo, r.staged().allUsersObjects()),
draftsId(r));
}
return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), draftsId(r));
} catch (NoSuchChangeException e) {
return super.openHandle(repo);
} catch (OrmException | ConfigInvalidException e) {
} catch (OrmException e) {
throw new IOException(e);
}
}
private ObjectId draftsId(NoteDbUpdateManager.Result r) {
checkNotNull(r);
checkNotNull(r.newState());
return r.newState().getDraftIds().get(author);
}
@VisibleForTesting
NoteMap getNoteMap() {
return revisionNoteMap != null ? revisionNoteMap.noteMap : null;