Search in sources :

Example 1 with RestApiException

use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.

the class ReviewDbBatchUpdate method executeChangeOps.

private List<ChangeTask> executeChangeOps(boolean parallel, boolean dryrun) throws UpdateException, RestApiException {
    List<ChangeTask> tasks;
    boolean success = false;
    Stopwatch sw = Stopwatch.createStarted();
    try {
        logDebug("Executing change ops (parallel? {})", parallel);
        ListeningExecutorService executor = parallel ? changeUpdateExector : MoreExecutors.newDirectExecutorService();
        tasks = new ArrayList<>(ops.keySet().size());
        try {
            if (notesMigration.commitChangeWrites() && repoView != null) {
                // A NoteDb change may have been rebuilt since the repo was originally
                // opened, so make sure we see that.
                logDebug("Preemptively scanning for repo changes");
                repoView.getRepository().scanForRepoChanges();
            }
            if (!ops.isEmpty() && notesMigration.failChangeWrites()) {
                // Fail fast before attempting any writes if changes are read-only, as
                // this is a programmer error.
                logDebug("Failing early due to read-only Changes table");
                throw new OrmException(NoteDbUpdateManager.CHANGES_READ_ONLY);
            }
            List<ListenableFuture<?>> futures = new ArrayList<>(ops.keySet().size());
            for (Map.Entry<Change.Id, Collection<BatchUpdateOp>> e : ops.asMap().entrySet()) {
                ChangeTask task = new ChangeTask(e.getKey(), e.getValue(), Thread.currentThread(), dryrun);
                tasks.add(task);
                if (!parallel) {
                    logDebug("Direct execution of task for ops: {}", ops);
                }
                futures.add(executor.submit(task));
            }
            if (parallel) {
                logDebug("Waiting on futures for {} ops spanning {} changes", ops.size(), ops.keySet().size());
            }
            Futures.allAsList(futures).get();
            if (notesMigration.commitChangeWrites()) {
                if (!dryrun) {
                    executeNoteDbUpdates(tasks);
                }
            }
            success = true;
        } catch (ExecutionException | InterruptedException e) {
            Throwables.throwIfInstanceOf(e.getCause(), UpdateException.class);
            Throwables.throwIfInstanceOf(e.getCause(), RestApiException.class);
            throw new UpdateException(e);
        } catch (OrmException | IOException e) {
            throw new UpdateException(e);
        }
    } finally {
        metrics.executeChangeOpsLatency.record(success, sw.elapsed(NANOSECONDS), NANOSECONDS);
    }
    return tasks;
}
Also used : Stopwatch(com.google.common.base.Stopwatch) ArrayList(java.util.ArrayList) IOException(java.io.IOException) OrmException(com.google.gwtorm.server.OrmException) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Collection(java.util.Collection) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) RequestId(com.google.gerrit.server.util.RequestId) ExecutionException(java.util.concurrent.ExecutionException) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 2 with RestApiException

use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.

the class ReviewDbBatchUpdate method executeRefUpdates.

private void executeRefUpdates(boolean dryrun) throws IOException, RestApiException {
    if (getRefUpdates().isEmpty()) {
        logDebug("No ref updates to execute");
        return;
    }
    // May not be opened if the caller added ref updates but no new objects.
    // TODO(dborowitz): Really?
    initRepository();
    batchRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
    batchRefUpdate.setPushCertificate(pushCert);
    batchRefUpdate.setRefLogMessage(refLogMessage, true);
    batchRefUpdate.setAllowNonFastForwards(true);
    repoView.getCommands().addTo(batchRefUpdate);
    logDebug("Executing batch of {} ref updates", batchRefUpdate.getCommands().size());
    if (dryrun) {
        return;
    }
    // that might have access to unflushed objects.
    try (RevWalk updateRw = new RevWalk(repoView.getRepository())) {
        batchRefUpdate.execute(updateRw, NullProgressMonitor.INSTANCE);
    }
    boolean ok = true;
    for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
        if (cmd.getResult() != ReceiveCommand.Result.OK) {
            ok = false;
            break;
        }
    }
    if (!ok) {
        throw new RestApiException("BatchRefUpdate failed: " + batchRefUpdate);
    }
}
Also used : ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) RevWalk(org.eclipse.jgit.revwalk.RevWalk) RestApiException(com.google.gerrit.extensions.restapi.RestApiException)

Example 3 with RestApiException

use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.

the class NoteDbOnlyIT method noRetryOnLockFailureWithoutAtomicUpdates.

@Test
public void noRetryOnLockFailureWithoutAtomicUpdates() throws Exception {
    assume().that(notesMigration.fuseUpdates()).isFalse();
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getChange().getId();
    String master = "refs/heads/master";
    ObjectId initial;
    try (Repository repo = repoManager.openRepository(project)) {
        initial = repo.exactRef(master).getObjectId();
    }
    AtomicInteger updateRepoCalledCount = new AtomicInteger();
    AtomicInteger updateChangeCalledCount = new AtomicInteger();
    AtomicInteger afterUpdateReposCalledCount = new AtomicInteger();
    try {
        retryHelper.execute(batchUpdateFactory -> {
            try (BatchUpdate bu = newBatchUpdate(batchUpdateFactory)) {
                bu.addOp(id, new UpdateRefAndAddMessageOp(updateRepoCalledCount, updateChangeCalledCount));
                bu.execute(new ConcurrentWritingListener(afterUpdateReposCalledCount));
            }
            return null;
        });
        assert_().fail("expected RestApiException");
    } catch (RestApiException e) {
    // Expected.
    }
    assertThat(updateRepoCalledCount.get()).isEqualTo(1);
    assertThat(afterUpdateReposCalledCount.get()).isEqualTo(1);
    assertThat(updateChangeCalledCount.get()).isEqualTo(0);
    // updateChange was never called, so no message was ever added.
    assertThat(getMessages(id)).doesNotContain(UpdateRefAndAddMessageOp.CHANGE_MESSAGE);
    try (Repository repo = repoManager.openRepository(project)) {
        // Op lost the race, so the other writer's commit happened first. Op didn't retry, because the
        // ref updates weren't atomic, so it didn't throw LockFailureException on failure.
        assertThat(commitMessages(repo, initial, repo.exactRef(master).getObjectId())).containsExactly(ConcurrentWritingListener.MSG_PREFIX + "1");
    }
}
Also used : InMemoryRepository(org.eclipse.jgit.internal.storage.dfs.InMemoryRepository) Repository(org.eclipse.jgit.lib.Repository) ObjectId(org.eclipse.jgit.lib.ObjectId) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Change(com.google.gerrit.reviewdb.client.Change) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) PushOneCommit(com.google.gerrit.acceptance.PushOneCommit) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Test(org.junit.Test) AbstractDaemonTest(com.google.gerrit.acceptance.AbstractDaemonTest)

Example 4 with RestApiException

use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.

the class DeleteExternalIds method apply.

@Override
public Response<?> apply(AccountResource resource, List<String> extIds) throws RestApiException, IOException, OrmException, ConfigInvalidException {
    if (self.get() != resource.getUser() && !self.get().getCapabilities().canAccessDatabase()) {
        throw new AuthException("not allowed to delete external IDs");
    }
    if (extIds == null || extIds.size() == 0) {
        throw new BadRequestException("external IDs are required");
    }
    Map<ExternalId.Key, ExternalId> externalIdMap = externalIds.byAccount(resource.getUser().getAccountId()).stream().collect(toMap(i -> i.key(), i -> i));
    List<ExternalId> toDelete = new ArrayList<>();
    ExternalId.Key last = resource.getUser().getLastLoginExternalIdKey();
    for (String externalIdStr : extIds) {
        ExternalId id = externalIdMap.get(ExternalId.Key.parse(externalIdStr));
        if (id == null) {
            throw new UnprocessableEntityException(String.format("External id %s does not exist", externalIdStr));
        }
        if ((!id.isScheme(SCHEME_USERNAME)) && ((last == null) || (!last.get().equals(id.key().get())))) {
            toDelete.add(id);
        } else {
            throw new ResourceConflictException(String.format("External id %s cannot be deleted", externalIdStr));
        }
    }
    try {
        for (ExternalId extId : toDelete) {
            AuthRequest authRequest = new AuthRequest(extId.key());
            authRequest.setEmailAddress(extId.email());
            accountManager.unlink(extId.accountId(), authRequest);
        }
    } catch (AccountException e) {
        throw new ResourceConflictException(e.getMessage());
    }
    return Response.none();
}
Also used : CurrentUser(com.google.gerrit.server.CurrentUser) OrmException(com.google.gwtorm.server.OrmException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) Inject(com.google.inject.Inject) IOException(java.io.IOException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) Response(com.google.gerrit.extensions.restapi.Response) ExternalIds(com.google.gerrit.server.account.externalids.ExternalIds) ArrayList(java.util.ArrayList) RestModifyView(com.google.gerrit.extensions.restapi.RestModifyView) Provider(com.google.inject.Provider) List(java.util.List) Collectors.toMap(java.util.stream.Collectors.toMap) SCHEME_USERNAME(com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) Map(java.util.Map) AuthException(com.google.gerrit.extensions.restapi.AuthException) ExternalId(com.google.gerrit.server.account.externalids.ExternalId) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) ExternalId(com.google.gerrit.server.account.externalids.ExternalId) ArrayList(java.util.ArrayList) AuthException(com.google.gerrit.extensions.restapi.AuthException) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException)

Example 5 with RestApiException

use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.

the class SubmoduleOp method updateSuperProjects.

public void updateSuperProjects(BatchUpdate.Factory updateFactory) throws SubmoduleException {
    ImmutableSet<Project.NameKey> projects = getProjectsInOrder();
    if (projects == null) {
        return;
    }
    LinkedHashSet<Project.NameKey> superProjects = new LinkedHashSet<>();
    try {
        for (Project.NameKey project : projects) {
            // only need superprojects
            if (branchesByProject.containsKey(project)) {
                superProjects.add(project);
                // get a new BatchUpdate for the super project
                OpenRepo or = orm.getRepo(project);
                for (Branch.NameKey branch : branchesByProject.get(project)) {
                    addOp(or.getUpdate(updateFactory), branch);
                }
            }
        }
        batchUpdateFactory.execute(orm.batchUpdates(updateFactory, superProjects), BatchUpdateListener.NONE, orm.getSubmissionId(), false);
    } catch (RestApiException | UpdateException | IOException | NoSuchProjectException e) {
        throw new SubmoduleException("Cannot update gitlinks", e);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) IOException(java.io.IOException) Project(com.google.gerrit.reviewdb.client.Project) Branch(com.google.gerrit.reviewdb.client.Branch) OpenRepo(com.google.gerrit.server.git.MergeOpRepoManager.OpenRepo) UpdateException(com.google.gerrit.server.update.UpdateException) RestApiException(com.google.gerrit.extensions.restapi.RestApiException)

Aggregations

RestApiException (com.google.gerrit.extensions.restapi.RestApiException)93 ApiUtil.asRestApiException (com.google.gerrit.server.api.ApiUtil.asRestApiException)38 IOException (java.io.IOException)31 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)24 UpdateException (com.google.gerrit.server.update.UpdateException)23 BatchUpdate (com.google.gerrit.server.update.BatchUpdate)22 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)20 PermissionBackendException (com.google.gerrit.server.permissions.PermissionBackendException)19 AuthException (com.google.gerrit.extensions.restapi.AuthException)18 StorageException (com.google.gerrit.exceptions.StorageException)17 List (java.util.List)17 BatchUpdateOp (com.google.gerrit.server.update.BatchUpdateOp)16 Inject (com.google.inject.Inject)15 ArrayList (java.util.ArrayList)15 ResourceNotFoundException (com.google.gerrit.extensions.restapi.ResourceNotFoundException)14 ChangeNotes (com.google.gerrit.server.notedb.ChangeNotes)14 ChangeContext (com.google.gerrit.server.update.ChangeContext)14 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)14 Provider (com.google.inject.Provider)12 Change (com.google.gerrit.entities.Change)11