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;
}
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);
}
}
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");
}
}
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();
}
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);
}
}
Aggregations