Search in sources :

Example 51 with ReviewDb

use of com.google.gerrit.reviewdb.server.ReviewDb in project gerrit by GerritCodeReview.

the class ReviewDbBatchUpdate method executeNoteDbUpdates.

private void executeNoteDbUpdates(List<ChangeTask> tasks) throws ResourceConflictException, IOException {
    // Aggregate together all NoteDb ref updates from the ops we executed,
    // possibly in parallel. Each task had its own NoteDbUpdateManager instance
    // with its own thread-local copy of the repo(s), but each of those was just
    // used for staging updates and was never executed.
    //
    // Use a new BatchRefUpdate as the original batchRefUpdate field is intended
    // for use only by the updateRepo phase.
    //
    // See the comments in NoteDbUpdateManager#execute() for why we execute the
    // updates on the change repo first.
    logDebug("Executing NoteDb updates for {} changes", tasks.size());
    try {
        initRepository();
        BatchRefUpdate changeRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
        boolean hasAllUsersCommands = false;
        try (ObjectInserter ins = repoView.getRepository().newObjectInserter()) {
            int objs = 0;
            for (ChangeTask task : tasks) {
                if (task.noteDbResult == null) {
                    logDebug("No-op update to {}", task.id);
                    continue;
                }
                for (ReceiveCommand cmd : task.noteDbResult.changeCommands()) {
                    changeRefUpdate.addCommand(cmd);
                }
                for (InsertedObject obj : task.noteDbResult.changeObjects()) {
                    objs++;
                    ins.insert(obj.type(), obj.data().toByteArray());
                }
                hasAllUsersCommands |= !task.noteDbResult.allUsersCommands().isEmpty();
            }
            logDebug("Collected {} objects and {} ref updates to change repo", objs, changeRefUpdate.getCommands().size());
            executeNoteDbUpdate(getRevWalk(), ins, changeRefUpdate);
        }
        if (hasAllUsersCommands) {
            try (Repository allUsersRepo = repoManager.openRepository(allUsers);
                RevWalk allUsersRw = new RevWalk(allUsersRepo);
                ObjectInserter allUsersIns = allUsersRepo.newObjectInserter()) {
                int objs = 0;
                BatchRefUpdate allUsersRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
                for (ChangeTask task : tasks) {
                    for (ReceiveCommand cmd : task.noteDbResult.allUsersCommands()) {
                        allUsersRefUpdate.addCommand(cmd);
                    }
                    for (InsertedObject obj : task.noteDbResult.allUsersObjects()) {
                        allUsersIns.insert(obj.type(), obj.data().toByteArray());
                    }
                }
                logDebug("Collected {} objects and {} ref updates to All-Users", objs, allUsersRefUpdate.getCommands().size());
                executeNoteDbUpdate(allUsersRw, allUsersIns, allUsersRefUpdate);
            }
        } else {
            logDebug("No All-Users updates");
        }
    } catch (IOException e) {
        if (tasks.stream().allMatch(t -> t.storage == PrimaryStorage.REVIEW_DB)) {
            // Ignore all errors trying to update NoteDb at this point. We've already written the
            // NoteDbChangeStates to ReviewDb, which means if any state is out of date it will be
            // rebuilt the next time it is needed.
            //
            // Always log even without RequestId.
            log.debug("Ignoring NoteDb update error after ReviewDb write", e);
        // Otherwise, we can't prove it's safe to ignore the error, either because some change had
        // NOTE_DB primary, or a task failed before determining the primary storage.
        } else if (e instanceof LockFailureException) {
            // although it happened too late for us to produce anything but a generic error message.
            throw new ResourceConflictException("Updating change failed due to conflicting write", e);
        }
        throw e;
    }
}
Also used : AllUsersName(com.google.gerrit.server.config.AllUsersName) ChangeControl(com.google.gerrit.server.project.ChangeControl) RequestId(com.google.gerrit.server.util.RequestId) OrmException(com.google.gwtorm.server.OrmException) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) Inject(com.google.inject.Inject) ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) LoggerFactory(org.slf4j.LoggerFactory) CheckedFuture(com.google.common.util.concurrent.CheckedFuture) PrimaryStorage(com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage) Assisted(com.google.inject.assistedinject.Assisted) RevWalk(org.eclipse.jgit.revwalk.RevWalk) Config(org.eclipse.jgit.lib.Config) InsertedObject(com.google.gerrit.server.git.InsertedObject) ChangeIndexer(com.google.gerrit.server.index.change.ChangeIndexer) Map(java.util.Map) NoteDbUpdateManager(com.google.gerrit.server.notedb.NoteDbUpdateManager) Timer1(com.google.gerrit.metrics.Timer1) GerritServerConfig(com.google.gerrit.server.config.GerritServerConfig) TimeZone(java.util.TimeZone) Timestamp(java.sql.Timestamp) Collection(java.util.Collection) NullProgressMonitor(org.eclipse.jgit.lib.NullProgressMonitor) Preconditions.checkState(com.google.common.base.Preconditions.checkState) PersonIdent(org.eclipse.jgit.lib.PersonIdent) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) ReviewDbWrapper(com.google.gerrit.reviewdb.server.ReviewDbWrapper) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate) MetricMaker(com.google.gerrit.metrics.MetricMaker) NotesMigration(com.google.gerrit.server.notedb.NotesMigration) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) Singleton(com.google.inject.Singleton) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) ReviewDb(com.google.gerrit.reviewdb.server.ReviewDb) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Change(com.google.gerrit.reviewdb.client.Change) NANOSECONDS(java.util.concurrent.TimeUnit.NANOSECONDS) Stopwatch(com.google.common.base.Stopwatch) MismatchedStateException(com.google.gerrit.server.notedb.NoteDbUpdateManager.MismatchedStateException) Callable(java.util.concurrent.Callable) LockFailureException(com.google.gerrit.server.git.LockFailureException) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) Description(com.google.gerrit.metrics.Description) Field(com.google.gerrit.metrics.Field) Comparator.comparing(java.util.Comparator.comparing) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) Project(com.google.gerrit.reviewdb.client.Project) CurrentUser(com.google.gerrit.server.CurrentUser) Logger(org.slf4j.Logger) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Units(com.google.gerrit.metrics.Description.Units) Throwables(com.google.common.base.Throwables) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) SchemaFactory(com.google.gwtorm.server.SchemaFactory) NoteDbChangeState(com.google.gerrit.server.notedb.NoteDbChangeState) ExecutionException(java.util.concurrent.ExecutionException) Collectors.toList(java.util.stream.Collectors.toList) Futures(com.google.common.util.concurrent.Futures) ChangeUpdate(com.google.gerrit.server.notedb.ChangeUpdate) GitRepositoryManager(com.google.gerrit.server.git.GitRepositoryManager) TreeMap(java.util.TreeMap) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) PatchSet(com.google.gerrit.reviewdb.client.PatchSet) Collections(java.util.Collections) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) GitReferenceUpdated(com.google.gerrit.server.extensions.events.GitReferenceUpdated) Repository(org.eclipse.jgit.lib.Repository) ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) InsertedObject(com.google.gerrit.server.git.InsertedObject) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) LockFailureException(com.google.gerrit.server.git.LockFailureException) Repository(org.eclipse.jgit.lib.Repository) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate)

Example 52 with ReviewDb

use of com.google.gerrit.reviewdb.server.ReviewDb in project gerrit by GerritCodeReview.

the class Schema_131 method migrateData.

@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
    SortedSet<Project.NameKey> repoList = repoManager.list();
    SortedSet<Project.NameKey> repoUpgraded = new TreeSet<>();
    ui.message("\tMigrating " + repoList.size() + " repositories ...");
    for (Project.NameKey projectName : repoList) {
        try (Repository git = repoManager.openRepository(projectName);
            MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
            ProjectConfig config = ProjectConfig.read(md);
            if (config.hasLegacyPermissions()) {
                md.getCommitBuilder().setAuthor(serverUser);
                md.getCommitBuilder().setCommitter(serverUser);
                md.setMessage(COMMIT_MSG);
                config.commit(md);
                repoUpgraded.add(projectName);
            }
        } catch (ConfigInvalidException | IOException ex) {
            throw new OrmException("Cannot migrate project " + projectName, ex);
        }
    }
    ui.message("\tMigration completed:  " + repoUpgraded.size() + " repositories updated:");
    ui.message("\t" + repoUpgraded.stream().map(n -> n.get()).collect(joining(" ")));
}
Also used : Project(com.google.gerrit.reviewdb.client.Project) ReviewDb(com.google.gerrit.reviewdb.server.ReviewDb) OrmException(com.google.gwtorm.server.OrmException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) SortedSet(java.util.SortedSet) MetaDataUpdate(com.google.gerrit.server.git.MetaDataUpdate) Inject(com.google.inject.Inject) IOException(java.io.IOException) Collectors.joining(java.util.stream.Collectors.joining) TreeSet(java.util.TreeSet) PersonIdent(org.eclipse.jgit.lib.PersonIdent) Provider(com.google.inject.Provider) GitRepositoryManager(com.google.gerrit.server.git.GitRepositoryManager) ProjectConfig(com.google.gerrit.server.git.ProjectConfig) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) GitReferenceUpdated(com.google.gerrit.server.extensions.events.GitReferenceUpdated) Repository(org.eclipse.jgit.lib.Repository) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) IOException(java.io.IOException) ProjectConfig(com.google.gerrit.server.git.ProjectConfig) Project(com.google.gerrit.reviewdb.client.Project) Repository(org.eclipse.jgit.lib.Repository) OrmException(com.google.gwtorm.server.OrmException) TreeSet(java.util.TreeSet) MetaDataUpdate(com.google.gerrit.server.git.MetaDataUpdate)

Example 53 with ReviewDb

use of com.google.gerrit.reviewdb.server.ReviewDb in project gerrit by GerritCodeReview.

the class Submit method getDescription.

@Override
public UiAction.Description getDescription(RevisionResource resource) {
    Change change = resource.getChange();
    String topic = change.getTopic();
    ReviewDb db = dbProvider.get();
    ChangeData cd = changeDataFactory.create(db, resource.getControl());
    boolean visible;
    try {
        visible = change.getStatus().isOpen() && resource.isCurrent() && !resource.getPatchSet().isDraft() && resource.permissions().test(ChangePermission.SUBMIT);
        MergeOp.checkSubmitRule(cd);
    } catch (ResourceConflictException e) {
        visible = false;
    } catch (PermissionBackendException e) {
        log.error("Error checking if change is submittable", e);
        throw new OrmRuntimeException("Could not check submit permission", e);
    } catch (OrmException e) {
        log.error("Error checking if change is submittable", e);
        throw new OrmRuntimeException("Could not determine problems for the change", e);
    }
    if (!visible) {
        return new UiAction.Description().setLabel("").setTitle("").setVisible(false);
    }
    ChangeSet cs;
    try {
        cs = mergeSuperSet.get().completeChangeSet(db, cd.change(), resource.getControl().getUser());
    } catch (OrmException | IOException e) {
        throw new OrmRuntimeException("Could not determine complete set of changes to be submitted", e);
    }
    int topicSize = 0;
    if (!Strings.isNullOrEmpty(topic)) {
        topicSize = getChangesByTopic(topic).size();
    }
    boolean treatWithTopic = submitWholeTopic && !Strings.isNullOrEmpty(topic) && topicSize > 1;
    String submitProblems = problemsForSubmittingChangeset(cd, cs, resource.getUser());
    Boolean enabled;
    try {
        // Recheck mergeability rather than using value stored in the index,
        // which may be stale.
        // TODO(dborowitz): This is ugly; consider providing a way to not read
        // stored fields from the index in the first place.
        // cd.setMergeable(null);
        // That was done in unmergeableChanges which was called by
        // problemsForSubmittingChangeset, so now it is safe to read from
        // the cache, as it yields the same result.
        enabled = cd.isMergeable();
    } catch (OrmException e) {
        throw new OrmRuntimeException("Could not determine mergeability", e);
    }
    if (submitProblems != null) {
        return new UiAction.Description().setLabel(treatWithTopic ? submitTopicLabel : (cs.size() > 1) ? labelWithParents : label).setTitle(submitProblems).setVisible(true).setEnabled(false);
    }
    if (treatWithTopic) {
        Map<String, String> params = ImmutableMap.of("topicSize", String.valueOf(topicSize), "submitSize", String.valueOf(cs.size()));
        return new UiAction.Description().setLabel(submitTopicLabel).setTitle(Strings.emptyToNull(submitTopicTooltip.replace(params))).setVisible(true).setEnabled(Boolean.TRUE.equals(enabled));
    }
    RevId revId = resource.getPatchSet().getRevision();
    Map<String, String> params = ImmutableMap.of("patchSet", String.valueOf(resource.getPatchSet().getPatchSetId()), "branch", change.getDest().getShortName(), "commit", ObjectId.fromString(revId.get()).abbreviate(7).name(), "submitSize", String.valueOf(cs.size()));
    ParameterizedString tp = cs.size() > 1 ? titlePatternWithAncestors : titlePattern;
    return new UiAction.Description().setLabel(cs.size() > 1 ? labelWithParents : label).setTitle(Strings.emptyToNull(tp.replace(params))).setVisible(true).setEnabled(Boolean.TRUE.equals(enabled));
}
Also used : OrmRuntimeException(com.google.gwtorm.server.OrmRuntimeException) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) Change(com.google.gerrit.reviewdb.client.Change) ParameterizedString(com.google.gerrit.common.data.ParameterizedString) IOException(java.io.IOException) UiAction(com.google.gerrit.extensions.webui.UiAction) ChangeData(com.google.gerrit.server.query.change.ChangeData) RevId(com.google.gerrit.reviewdb.client.RevId) ParameterizedString(com.google.gerrit.common.data.ParameterizedString) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) OrmException(com.google.gwtorm.server.OrmException) ChangeSet(com.google.gerrit.server.git.ChangeSet) ReviewDb(com.google.gerrit.reviewdb.server.ReviewDb)

Example 54 with ReviewDb

use of com.google.gerrit.reviewdb.server.ReviewDb in project gerrit by GerritCodeReview.

the class Submit method mergeChange.

public Change mergeChange(BatchUpdate.Factory updateFactory, RevisionResource rsrc, IdentifiedUser submitter, SubmitInput input) throws OrmException, RestApiException, IOException {
    Change change = rsrc.getChange();
    if (!change.getStatus().isOpen()) {
        throw new ResourceConflictException("change is " + ChangeUtil.status(change));
    } else if (!ProjectUtil.branchExists(repoManager, change.getDest())) {
        throw new ResourceConflictException(String.format("destination branch \"%s\" not found.", change.getDest().get()));
    } else if (!rsrc.getPatchSet().getId().equals(change.currentPatchSetId())) {
        // TODO Allow submitting non-current revision by changing the current.
        throw new ResourceConflictException(String.format("revision %s is not current revision", rsrc.getPatchSet().getRevision().get()));
    }
    try (MergeOp op = mergeOpFactory.create(updateFactory)) {
        ReviewDb db = dbProvider.get();
        op.merge(db, change, submitter, true, input, false);
        try {
            change = changeNotesFactory.createChecked(db, change.getProject(), change.getId()).getChange();
        } catch (NoSuchChangeException e) {
            throw new ResourceConflictException("change is deleted");
        }
    }
    switch(change.getStatus()) {
        case MERGED:
            return change;
        case NEW:
            ChangeMessage msg = getConflictMessage(rsrc);
            if (msg != null) {
                throw new ResourceConflictException(msg.getMessage());
            }
        //$FALL-THROUGH$
        case ABANDONED:
        case DRAFT:
        default:
            throw new ResourceConflictException("change is " + ChangeUtil.status(change));
    }
}
Also used : ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) NoSuchChangeException(com.google.gerrit.server.project.NoSuchChangeException) ChangeMessage(com.google.gerrit.reviewdb.client.ChangeMessage) MergeOp(com.google.gerrit.server.git.MergeOp) Change(com.google.gerrit.reviewdb.client.Change) ReviewDb(com.google.gerrit.reviewdb.server.ReviewDb)

Example 55 with ReviewDb

use of com.google.gerrit.reviewdb.server.ReviewDb in project gerrit by GerritCodeReview.

the class Rebase method findBaseRev.

private ObjectId findBaseRev(Repository repo, RevWalk rw, RevisionResource rsrc, RebaseInput input) throws RestApiException, OrmException, IOException, NoSuchChangeException {
    Branch.NameKey destRefKey = rsrc.getChange().getDest();
    if (input == null || input.base == null) {
        return rebaseUtil.findBaseRevision(rsrc.getPatchSet(), destRefKey, repo, rw);
    }
    Change change = rsrc.getChange();
    String str = input.base.trim();
    if (str.equals("")) {
        // Remove existing dependency to other patch set.
        Ref destRef = repo.exactRef(destRefKey.get());
        if (destRef == null) {
            throw new ResourceConflictException("can't rebase onto tip of branch " + destRefKey.get() + "; branch doesn't exist");
        }
        return destRef.getObjectId();
    }
    @SuppressWarnings("resource") ReviewDb db = dbProvider.get();
    Base base = rebaseUtil.parseBase(rsrc, str);
    if (base == null) {
        throw new ResourceConflictException("base revision is missing: " + str);
    }
    PatchSet.Id baseId = base.patchSet().getId();
    if (!base.control().isPatchVisible(base.patchSet(), db)) {
        throw new AuthException("base revision not accessible: " + str);
    } else if (change.getId().equals(baseId.getParentKey())) {
        throw new ResourceConflictException("cannot rebase change onto itself");
    }
    Change baseChange = base.control().getChange();
    if (!baseChange.getProject().equals(change.getProject())) {
        throw new ResourceConflictException("base change is in wrong project: " + baseChange.getProject());
    } else if (!baseChange.getDest().equals(change.getDest())) {
        throw new ResourceConflictException("base change is targeting wrong branch: " + baseChange.getDest());
    } else if (baseChange.getStatus() == Status.ABANDONED) {
        throw new ResourceConflictException("base change is abandoned: " + baseChange.getKey());
    } else if (isMergedInto(rw, rsrc.getPatchSet(), base.patchSet())) {
        throw new ResourceConflictException("base change " + baseChange.getKey() + " is a descendant of the current change - recursion not allowed");
    }
    return ObjectId.fromString(base.patchSet().getRevision().get());
}
Also used : Ref(org.eclipse.jgit.lib.Ref) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) Branch(com.google.gerrit.reviewdb.client.Branch) AuthException(com.google.gerrit.extensions.restapi.AuthException) PatchSet(com.google.gerrit.reviewdb.client.PatchSet) Change(com.google.gerrit.reviewdb.client.Change) ReviewDb(com.google.gerrit.reviewdb.server.ReviewDb) Base(com.google.gerrit.server.change.RebaseUtil.Base)

Aggregations

ReviewDb (com.google.gerrit.reviewdb.server.ReviewDb)63 OrmException (com.google.gwtorm.server.OrmException)25 Change (com.google.gerrit.reviewdb.client.Change)21 Account (com.google.gerrit.reviewdb.client.Account)17 ArrayList (java.util.ArrayList)14 IOException (java.io.IOException)12 GitRepositoryManager (com.google.gerrit.server.git.GitRepositoryManager)10 Repository (org.eclipse.jgit.lib.Repository)9 Project (com.google.gerrit.reviewdb.client.Project)8 GerritPersonIdent (com.google.gerrit.server.GerritPersonIdent)8 Provider (com.google.inject.Provider)8 PatchSet (com.google.gerrit.reviewdb.client.PatchSet)7 Inject (com.google.inject.Inject)7 AllUsersName (com.google.gerrit.server.config.AllUsersName)6 ChangeControl (com.google.gerrit.server.project.ChangeControl)6 PersonIdent (org.eclipse.jgit.lib.PersonIdent)6 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)5 AccountGroupMember (com.google.gerrit.reviewdb.client.AccountGroupMember)5 GerritServerConfig (com.google.gerrit.server.config.GerritServerConfig)5 GitReferenceUpdated (com.google.gerrit.server.extensions.events.GitReferenceUpdated)5