// 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.google.gerrit.server.notedb.rebuild;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_HASHTAGS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_PATCH_SET;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.toList;

import com.google.common.base.Splitter;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.notedb.ChangeBundle;
import com.google.gerrit.server.notedb.ChangeBundleReader;
import com.google.gerrit.server.notedb.ChangeDraftUpdate;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NoteDbChangeState;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.notedb.NoteDbUpdateManager;
import com.google.gerrit.server.notedb.NoteDbUpdateManager.OpenRepo;
import com.google.gerrit.server.notedb.NoteDbUpdateManager.Result;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.update.ChainedReceiveCommands;
import com.google.gwtorm.client.Key;
import com.google.gwtorm.server.Access;
import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

public class ChangeRebuilderImpl extends ChangeRebuilder {
  /**
   * The maximum amount of time between the ReviewDb timestamp of the first and last events batched
   * together into a single NoteDb update.
   *
   * <p>Used to account for the fact that different records with their own timestamps (e.g. {@link
   * PatchSetApproval} and {@link ChangeMessage}) historically didn't necessarily use the same
   * timestamp, and tended to call {@code System.currentTimeMillis()} independently.
   */
  public static final long MAX_WINDOW_MS = SECONDS.toMillis(3);

  /**
   * The maximum amount of time between two consecutive events to consider them to be in the same
   * batch.
   */
  static final long MAX_DELTA_MS = SECONDS.toMillis(1);

  private final AccountCache accountCache;
  private final ChangeBundleReader bundleReader;
  private final ChangeDraftUpdate.Factory draftUpdateFactory;
  private final ChangeNoteUtil changeNoteUtil;
  private final ChangeNotes.Factory notesFactory;
  private final ChangeUpdate.Factory updateFactory;
  private final CommentsUtil commentsUtil;
  private final NoteDbUpdateManager.Factory updateManagerFactory;
  private final NotesMigration migration;
  private final PatchListCache patchListCache;
  private final PersonIdent serverIdent;
  private final ProjectCache projectCache;
  private final String anonymousCowardName;
  private final String serverId;
  private final long skewMs;

  @Inject
  ChangeRebuilderImpl(
      @GerritServerConfig Config cfg,
      SchemaFactory<ReviewDb> schemaFactory,
      AccountCache accountCache,
      ChangeBundleReader bundleReader,
      ChangeDraftUpdate.Factory draftUpdateFactory,
      ChangeNoteUtil changeNoteUtil,
      ChangeNotes.Factory notesFactory,
      ChangeUpdate.Factory updateFactory,
      CommentsUtil commentsUtil,
      NoteDbUpdateManager.Factory updateManagerFactory,
      NotesMigration migration,
      PatchListCache patchListCache,
      @GerritPersonIdent PersonIdent serverIdent,
      @Nullable ProjectCache projectCache,
      @AnonymousCowardName String anonymousCowardName,
      @GerritServerId String serverId) {
    super(schemaFactory);
    this.accountCache = accountCache;
    this.bundleReader = bundleReader;
    this.draftUpdateFactory = draftUpdateFactory;
    this.changeNoteUtil = changeNoteUtil;
    this.notesFactory = notesFactory;
    this.updateFactory = updateFactory;
    this.commentsUtil = commentsUtil;
    this.updateManagerFactory = updateManagerFactory;
    this.migration = migration;
    this.patchListCache = patchListCache;
    this.serverIdent = serverIdent;
    this.projectCache = projectCache;
    this.anonymousCowardName = anonymousCowardName;
    this.serverId = serverId;
    this.skewMs = NoteDbChangeState.getReadOnlySkew(cfg);
  }

  @Override
  public Result rebuild(ReviewDb db, Change.Id changeId) throws IOException, OrmException {
    return rebuild(db, changeId, true);
  }

  @Override
  public Result rebuildEvenIfReadOnly(ReviewDb db, Change.Id changeId)
      throws IOException, OrmException {
    return rebuild(db, changeId, false);
  }

  private Result rebuild(ReviewDb db, Change.Id changeId, boolean checkReadOnly)
      throws IOException, OrmException {
    db = ReviewDbUtil.unwrapDb(db);
    // Read change just to get project; this instance is then discarded so we can read a consistent
    // ChangeBundle inside a transaction.
    Change change = db.changes().get(changeId);
    if (change == null) {
      throw new NoSuchChangeException(changeId);
    }
    try (NoteDbUpdateManager manager = updateManagerFactory.create(change.getProject())) {
      buildUpdates(manager, bundleReader.fromReviewDb(db, changeId));
      return execute(db, changeId, manager, checkReadOnly, true);
    }
  }

  @Override
  public Result rebuild(NoteDbUpdateManager manager, ChangeBundle bundle)
      throws NoSuchChangeException, IOException, OrmException {
    Change change = new Change(bundle.getChange());
    buildUpdates(manager, bundle);
    return manager.stageAndApplyDelta(change);
  }

  @Override
  public NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId)
      throws IOException, OrmException {
    db = ReviewDbUtil.unwrapDb(db);
    Change change = checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
    if (change == null) {
      throw new NoSuchChangeException(changeId);
    }
    NoteDbUpdateManager manager = updateManagerFactory.create(change.getProject());
    buildUpdates(manager, bundleReader.fromReviewDb(db, changeId));
    manager.stage();
    return manager;
  }

  @Override
  public Result execute(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager)
      throws OrmException, IOException {
    return execute(db, changeId, manager, true, true);
  }

  public Result execute(
      ReviewDb db,
      Change.Id changeId,
      NoteDbUpdateManager manager,
      boolean checkReadOnly,
      boolean executeManager)
      throws OrmException, IOException {
    db = ReviewDbUtil.unwrapDb(db);
    Change change = checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
    if (change == null) {
      throw new NoSuchChangeException(changeId);
    }

    final String oldNoteDbState = change.getNoteDbState();
    Result r = manager.stageAndApplyDelta(change);
    final String newNoteDbState = change.getNoteDbState();
    try {
      db.changes()
          .atomicUpdate(
              changeId,
              new AtomicUpdate<Change>() {
                @Override
                public Change update(Change change) {
                  if (checkReadOnly) {
                    NoteDbChangeState.checkNotReadOnly(change, skewMs);
                  }
                  String currNoteDbState = change.getNoteDbState();
                  if (Objects.equals(currNoteDbState, newNoteDbState)) {
                    // Another thread completed the same rebuild we were about to.
                    throw new AbortUpdateException();
                  } else if (!Objects.equals(oldNoteDbState, currNoteDbState)) {
                    // Another thread updated the state to something else.
                    throw new ConflictingUpdateRuntimeException(change, oldNoteDbState);
                  }
                  change.setNoteDbState(newNoteDbState);
                  return change;
                }
              });
    } catch (ConflictingUpdateRuntimeException e) {
      // Rethrow as an OrmException so the caller knows to use staged results. Strictly speaking
      // they are not completely up to date, but result we send to the caller is the same as if this
      // rebuild had executed before the other thread.
      throw new ConflictingUpdateException(e);
    } catch (AbortUpdateException e) {
      if (NoteDbChangeState.parse(changeId, newNoteDbState)
          .isUpToDate(
              manager.getChangeRepo().cmds.getRepoRefCache(),
              manager.getAllUsersRepo().cmds.getRepoRefCache())) {
        // If the state in ReviewDb matches NoteDb at this point, it means another thread
        // successfully completed this rebuild. It's ok to not execute the update in this case,
        // since the object referenced in the Result was flushed to the repo by whatever thread won
        // the race.
        return r;
      }
      // If the state doesn't match, that means another thread attempted this rebuild, but
      // failed. Fall through and try to update the ref again.
    }
    if (migration.failChangeWrites()) {
      // Don't even attempt to execute if read-only, it would fail anyway. But do throw an exception
      // to the caller so they know to use the staged results instead of reading from the repo.
      throw new OrmException(NoteDbUpdateManager.CHANGES_READ_ONLY);
    }
    if (executeManager) {
      manager.execute();
    }
    return r;
  }

  static Change checkNoteDbState(Change c) throws OrmException {
    // Can only rebuild a change if its primary storage is ReviewDb.
    NoteDbChangeState s = NoteDbChangeState.parse(c);
    if (s != null && s.getPrimaryStorage() != PrimaryStorage.REVIEW_DB) {
      throw new OrmException(
          String.format("cannot rebuild change " + c.getId() + " with state " + s));
    }
    return c;
  }

  @Override
  public void buildUpdates(NoteDbUpdateManager manager, ChangeBundle bundle)
      throws IOException, OrmException {
    manager.setCheckExpectedState(false).setRefLogMessage("Rebuilding change");
    Change change = new Change(bundle.getChange());
    if (bundle.getPatchSets().isEmpty()) {
      throw new NoPatchSetsException(change.getId());
    }
    if (change.getLastUpdatedOn().compareTo(change.getCreatedOn()) < 0) {
      // A bug in data migration might set created_on to the time of the migration. The
      // correct timestamps were lost, but we can at least set it so created_on is not after
      // last_updated_on.
      // See https://bugs.chromium.org/p/gerrit/issues/detail?id=7397
      change.setCreatedOn(change.getLastUpdatedOn());
    }

    // We will rebuild all events, except for draft comments, in buckets based on author and
    // timestamp.
    List<Event> events = new ArrayList<>();
    ListMultimap<Account.Id, DraftCommentEvent> draftCommentEvents =
        MultimapBuilder.hashKeys().arrayListValues().build();

    events.addAll(getHashtagsEvents(change, manager));

    // Delete ref only after hashtags have been read.
    deleteChangeMetaRef(change, manager.getChangeRepo().cmds);
    deleteDraftRefs(change, manager.getAllUsersRepo());

    Integer minPsNum = getMinPatchSetNum(bundle);
    TreeMap<PatchSet.Id, PatchSetEvent> patchSetEvents =
        new TreeMap<>(ReviewDbUtil.intKeyOrdering());

    for (PatchSet ps : bundle.getPatchSets()) {
      PatchSetEvent pse = new PatchSetEvent(change, ps, manager.getChangeRepo().rw);
      patchSetEvents.put(ps.getId(), pse);
      events.add(pse);
      for (Comment c : getComments(bundle, serverId, Status.PUBLISHED, ps)) {
        CommentEvent e = new CommentEvent(c, change, ps, patchListCache);
        events.add(e.addDep(pse));
      }
      for (Comment c : getComments(bundle, serverId, Status.DRAFT, ps)) {
        DraftCommentEvent e = new DraftCommentEvent(c, change, ps, patchListCache);
        draftCommentEvents.put(c.author.getId(), e);
      }
    }
    ensurePatchSetOrder(patchSetEvents);

    for (PatchSetApproval psa : bundle.getPatchSetApprovals()) {
      PatchSetEvent pse = patchSetEvents.get(psa.getPatchSetId());
      if (pse != null) {
        events.add(new ApprovalEvent(psa, change.getCreatedOn()).addDep(pse));
      }
    }

    for (Table.Cell<ReviewerStateInternal, Account.Id, Timestamp> r :
        bundle.getReviewers().asTable().cellSet()) {
      events.add(new ReviewerEvent(r, change.getCreatedOn()));
    }

    Change noteDbChange = new Change(null, null, null, null, null);
    for (ChangeMessage msg : bundle.getChangeMessages()) {
      Event msgEvent = new ChangeMessageEvent(change, noteDbChange, msg, change.getCreatedOn());
      if (msg.getPatchSetId() != null) {
        PatchSetEvent pse = patchSetEvents.get(msg.getPatchSetId());
        if (pse == null) {
          continue; // Ignore events for missing patch sets.
        }
        msgEvent.addDep(pse);
      }
      events.add(msgEvent);
    }

    sortAndFillEvents(change, noteDbChange, bundle.getPatchSets(), events, minPsNum);

    EventList<Event> el = new EventList<>();
    for (Event e : events) {
      if (!el.canAdd(e)) {
        flushEventsToUpdate(manager, el, change);
        checkState(el.canAdd(e));
      }
      el.add(e);
    }
    flushEventsToUpdate(manager, el, change);

    EventList<DraftCommentEvent> plcel = new EventList<>();
    for (Account.Id author : draftCommentEvents.keys()) {
      for (DraftCommentEvent e : Ordering.natural().sortedCopy(draftCommentEvents.get(author))) {
        if (!plcel.canAdd(e)) {
          flushEventsToDraftUpdate(manager, plcel, change);
          checkState(plcel.canAdd(e));
        }
        plcel.add(e);
      }
      flushEventsToDraftUpdate(manager, plcel, change);
    }
  }

  private static Integer getMinPatchSetNum(ChangeBundle bundle) {
    Integer minPsNum = null;
    for (PatchSet ps : bundle.getPatchSets()) {
      int n = ps.getId().get();
      if (minPsNum == null || n < minPsNum) {
        minPsNum = n;
      }
    }
    return minPsNum;
  }

  private static void ensurePatchSetOrder(TreeMap<PatchSet.Id, PatchSetEvent> events) {
    if (events.isEmpty()) {
      return;
    }
    Iterator<PatchSetEvent> it = events.values().iterator();
    PatchSetEvent curr = it.next();
    while (it.hasNext()) {
      PatchSetEvent next = it.next();
      next.addDep(curr);
      curr = next;
    }
  }

  private static List<Comment> getComments(
      ChangeBundle bundle, String serverId, PatchLineComment.Status status, PatchSet ps) {
    return bundle
        .getPatchLineComments()
        .stream()
        .filter(c -> c.getPatchSetId().equals(ps.getId()) && c.getStatus() == status)
        .map(plc -> plc.asComment(serverId))
        .sorted(CommentsUtil.COMMENT_ORDER)
        .collect(toList());
  }

  private void sortAndFillEvents(
      Change change,
      Change noteDbChange,
      ImmutableCollection<PatchSet> patchSets,
      List<Event> events,
      Integer minPsNum) {
    Event finalUpdates = new FinalUpdatesEvent(change, noteDbChange, patchSets);
    events.add(finalUpdates);
    setPostSubmitDeps(events);
    new EventSorter(events).sort();

    // Ensure the first event in the list creates the change, setting the author and any required
    // footers. Also force the creation time of the first patch set to match the creation time of
    // the change.
    Event first = events.get(0);
    if (first instanceof PatchSetEvent && change.getOwner().equals(first.user)) {
      first.when = change.getCreatedOn();
      ((PatchSetEvent) first).createChange = true;
    } else {
      events.add(0, new CreateChangeEvent(change, minPsNum));
    }

    // Final pass to correct some inconsistencies.
    //
    // First, fill in any missing patch set IDs using the latest patch set of the change at the time
    // of the event, because NoteDb can't represent actions with no associated patch set ID. This
    // workaround is as if a user added a ChangeMessage on the change by replying from the latest
    // patch set.
    //
    // Start with the first patch set that actually exists. If there are no patch sets at all,
    // minPsNum will be null, so just bail and use 1 as the patch set ID.
    //
    // Second, ensure timestamps are nondecreasing, by copying the previous timestamp if this
    // happens. This assumes that the only way this can happen is due to dependency constraints, and
    // it is ok to give an event the same timestamp as one of its dependencies.
    int ps = firstNonNull(minPsNum, 1);
    for (int i = 0; i < events.size(); i++) {
      Event e = events.get(i);
      if (e.psId == null) {
        e.psId = new PatchSet.Id(change.getId(), ps);
      } else {
        ps = Math.max(ps, e.psId.get());
      }

      if (i > 0) {
        Event p = events.get(i - 1);
        if (e.when.before(p.when)) {
          e.when = p.when;
        }
      }
    }
  }

  private void setPostSubmitDeps(List<Event> events) {
    Optional<Event> submitEvent =
        Lists.reverse(events).stream().filter(Event::isSubmit).findFirst();
    if (submitEvent.isPresent()) {
      events.stream().filter(Event::isPostSubmitApproval).forEach(e -> e.addDep(submitEvent.get()));
    }
  }

  private void flushEventsToUpdate(
      NoteDbUpdateManager manager, EventList<Event> events, Change change)
      throws OrmException, IOException {
    if (events.isEmpty()) {
      return;
    }
    Comparator<String> labelNameComparator;
    if (projectCache != null) {
      labelNameComparator = projectCache.get(change.getProject()).getLabelTypes().nameComparator();
    } else {
      // No project cache available, bail and use natural ordering; there's no semantic difference
      // anyway difference.
      labelNameComparator = Ordering.natural();
    }
    ChangeUpdate update =
        updateFactory.create(
            change,
            events.getAccountId(),
            events.getRealAccountId(),
            newAuthorIdent(events),
            events.getWhen(),
            labelNameComparator);
    update.setAllowWriteToNewRef(true);
    update.setPatchSetId(events.getPatchSetId());
    update.setTag(events.getTag());
    for (Event e : events) {
      e.apply(update);
    }
    manager.add(update);
    events.clear();
  }

  private void flushEventsToDraftUpdate(
      NoteDbUpdateManager manager, EventList<DraftCommentEvent> events, Change change)
      throws OrmException {
    if (events.isEmpty()) {
      return;
    }
    ChangeDraftUpdate update =
        draftUpdateFactory.create(
            change,
            events.getAccountId(),
            events.getRealAccountId(),
            newAuthorIdent(events),
            events.getWhen());
    update.setPatchSetId(events.getPatchSetId());
    for (DraftCommentEvent e : events) {
      e.applyDraft(update);
    }
    manager.add(update);
    events.clear();
  }

  private PersonIdent newAuthorIdent(EventList<?> events) {
    Account.Id id = events.getAccountId();
    if (id == null) {
      return new PersonIdent(serverIdent, events.getWhen());
    }
    return changeNoteUtil.newIdent(
        accountCache.get(id).getAccount(), events.getWhen(), serverIdent, anonymousCowardName);
  }

  private List<HashtagsEvent> getHashtagsEvents(Change change, NoteDbUpdateManager manager)
      throws IOException {
    String refName = changeMetaRef(change.getId());
    Optional<ObjectId> old = manager.getChangeRepo().getObjectId(refName);
    if (!old.isPresent()) {
      return Collections.emptyList();
    }

    RevWalk rw = manager.getChangeRepo().rw;
    List<HashtagsEvent> events = new ArrayList<>();
    rw.reset();
    rw.markStart(rw.parseCommit(old.get()));
    for (RevCommit commit : rw) {
      Account.Id authorId;
      try {
        authorId = changeNoteUtil.parseIdent(commit.getAuthorIdent(), change.getId());
      } catch (ConfigInvalidException e) {
        continue; // Corrupt data, no valid hashtags in this commit.
      }
      PatchSet.Id psId = parsePatchSetId(change, commit);
      Set<String> hashtags = parseHashtags(commit);
      if (authorId == null || psId == null || hashtags == null) {
        continue;
      }

      Timestamp commitTime = new Timestamp(commit.getCommitterIdent().getWhen().getTime());
      events.add(new HashtagsEvent(psId, authorId, commitTime, hashtags, change.getCreatedOn()));
    }
    return events;
  }

  private Set<String> parseHashtags(RevCommit commit) {
    List<String> hashtagsLines = commit.getFooterLines(FOOTER_HASHTAGS);
    if (hashtagsLines.isEmpty() || hashtagsLines.size() > 1) {
      return null;
    }

    if (hashtagsLines.get(0).isEmpty()) {
      return ImmutableSet.of();
    }
    return Sets.newHashSet(Splitter.on(',').split(hashtagsLines.get(0)));
  }

  private PatchSet.Id parsePatchSetId(Change change, RevCommit commit) {
    List<String> psIdLines = commit.getFooterLines(FOOTER_PATCH_SET);
    if (psIdLines.size() != 1) {
      return null;
    }
    Integer psId = Ints.tryParse(psIdLines.get(0));
    if (psId == null) {
      return null;
    }
    return new PatchSet.Id(change.getId(), psId);
  }

  private void deleteChangeMetaRef(Change change, ChainedReceiveCommands cmds) throws IOException {
    String refName = changeMetaRef(change.getId());
    Optional<ObjectId> old = cmds.get(refName);
    if (old.isPresent()) {
      cmds.add(new ReceiveCommand(old.get(), ObjectId.zeroId(), refName));
    }
  }

  private void deleteDraftRefs(Change change, OpenRepo allUsersRepo) throws IOException {
    for (Ref r :
        allUsersRepo
            .repo
            .getRefDatabase()
            .getRefs(RefNames.refsDraftCommentsPrefix(change.getId()))
            .values()) {
      allUsersRepo.cmds.add(new ReceiveCommand(r.getObjectId(), ObjectId.zeroId(), r.getName()));
    }
  }

  static void createChange(ChangeUpdate update, Change change) {
    update.setSubjectForCommit("Create change");
    update.setChangeId(change.getKey().get());
    update.setBranch(change.getDest().get());
    update.setSubject(change.getOriginalSubject());
    if (change.getRevertOf() != null) {
      update.setRevertOf(change.getRevertOf().get());
    }
  }

  @Override
  public void rebuildReviewDb(ReviewDb db, Project.NameKey project, Change.Id changeId)
      throws OrmException {
    // TODO(dborowitz): Fail fast if changes tables are disabled in ReviewDb.
    ChangeNotes notes = notesFactory.create(db, project, changeId);
    ChangeBundle bundle = ChangeBundle.fromNotes(commentsUtil, notes);

    db = ReviewDbUtil.unwrapDb(db);
    db.changes().beginTransaction(changeId);
    try {
      Change c = db.changes().get(changeId);
      if (c != null) {
        PrimaryStorage ps = PrimaryStorage.of(c);
        switch (ps) {
          case REVIEW_DB:
            return; // Nothing to do.
          case NOTE_DB:
            break; // Continue and rebuild.
          default:
            throw new OrmException("primary storage of " + changeId + " is " + ps);
        }
      } else {
        c = notes.getChange();
      }
      db.changes().upsert(Collections.singleton(c));
      putExactlyEntities(
          db.changeMessages(), db.changeMessages().byChange(c.getId()), bundle.getChangeMessages());
      putExactlyEntities(db.patchSets(), db.patchSets().byChange(c.getId()), bundle.getPatchSets());
      putExactlyEntities(
          db.patchSetApprovals(),
          db.patchSetApprovals().byChange(c.getId()),
          bundle.getPatchSetApprovals());
      putExactlyEntities(
          db.patchComments(),
          db.patchComments().byChange(c.getId()),
          bundle.getPatchLineComments());
      db.commit();
    } finally {
      db.rollback();
    }
  }

  private static <T, K extends Key<?>> void putExactlyEntities(
      Access<T, K> access, Iterable<T> existing, Collection<T> ents) throws OrmException {
    Set<K> toKeep = access.toMap(ents).keySet();
    access.delete(
        FluentIterable.from(existing).filter(e -> !toKeep.contains(access.primaryKey(e))));
    access.upsert(ents);
  }
}
