All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.com.objectos.git.GitService Maven / Gradle / Ivy

/*
 * Copyright (C) 2020-2022 Objectos Software LTDA.
 *
 * 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 br.com.objectos.git;

import br.com.objectos.collections.set.ImmutableSet;
import br.com.objectos.concurrent.Computation;
import br.com.objectos.concurrent.CpuArray;
import br.com.objectos.concurrent.CpuWorker;
import br.com.objectos.concurrent.IoWorker;
import br.com.objectos.core.object.Checks;
import br.com.objectos.fs.Directory;
import br.com.objectos.logging.Logger;
import br.com.objectos.logging.NoopLogger;

/**
 * A class for supporting the execution of {@link GitCommand} instances.
 *
 * 

* A {@code GitService} allows for the execution of Git commands by offering the * required parameters of the * {@link GitCommand#submitAsync(GitCommandExecutor, CpuWorker)} method. * *

* Additionally, a {@code GitService} allows for configuring a number values * that influence, among others, its memory footprint and concurrency level. * *

* Applications will typically have one instance of this class per JVM. * *

Creation example

* * The following is a code example showing how to obtain a new instance of a * {@code GitService}. It creates a new instance using the default values for * all of the configuration options: * *
{@code
 * GitService service;
 * service = GitService.create(cpuArray, ioWorker);
 * }
* *

* The next example explicitly sets all configuration options with the default * values. Therefore, the previous and the next example are equivalent: * *

{@code
 * GitService service;
 * service = GitService.create(
 *     cpuArray,
 *
 *     ioWorker,
 *
 *     GitService.bufferSize(4096),
 *
 *     GitService.enginesPerWorker(1),
 *
 *     GitService.logger(NoopLogger.getInstance())
 * );
 * }
* * @since 3 */ public final class GitService implements GitExecutor { private final CpuArray cpuArray; private final GitCommandExecutor gitCommandExecutor = new ThisCommandExecutor(); private final GitWorker[] workers; GitService(CpuArray cpuArray, GitWorker[] workers) { this.cpuArray = cpuArray; this.workers = workers; } /** * The size in bytes of the internal buffers of each {@link GitEngine} in * this service. * * @param size * the size in bytes * * @return a new option that sets the buffer size to the specified value * * @throws IllegalArgumentException * if {@code size < 64} * * @see GitService#create(CpuArray, IoWorker, Option...) * @see GitEngine#bufferSize(int) */ public static Option bufferSize(final int size) { Git.checkBufferSize(size); return new Option() { @Override final void acceptBuilder(GitServiceBuilder builder) { builder.setBufferSize(size); } }; } /** * Creates a new {@code GitService} instance configured with the provided * values. * *

* Options are provided by {@code static} methods in this class. The available * options are: * *

* * * * * * * * * * * * * * * * * * * * * * * * * *
Options provided by the {@code GitService} class
Method nameDescriptionDefault value
{@link GitService#bufferSize(int) bufferSize}The size in bytes of the buffers used by each {@link GitEngine} in this * service{@code 4096}
{@link GitService#enginesPerWorker(int) * enginesPerWorker}The number of {@link GitEngine} instances per {@link CpuWorker}. It * defines the concurrency level per {@link CpuWorker}.{@code 1}
{@link GitService#logger(Logger) logger}The logger instance to use{@link NoopLogger#getInstance()}
* * @param cpuArray * the CPU worker array to be used by this Git service * @param ioWorker * the I/O worker * @param options * the additional configuration options * * @return a new {@code GitService} instance configured with the provided * values */ public static GitService create(CpuArray cpuArray, IoWorker ioWorker, Option... options) { Checks.checkNotNull(cpuArray, "cpuArray == null"); Checks.checkNotNull(ioWorker, "ioWorker == null"); Checks.checkNotNull(options, "options == null"); GitServiceBuilder builder; builder = new GitServiceBuilder(cpuArray, ioWorker); for (int i = 0; i < options.length; i++) { Option option; option = options[i]; Checks.checkNotNull(option, "options[", i, "] == null"); option.acceptBuilder(builder); } return builder.build(); } /** * The number of {@link GitEngine} instances per {@link CpuWorker}. * *

* For each {@link CpuWorker} in the {@link CpuArray} used to create this * service, the specified value of {@link GitEngine}s are created. For * example, if a {@code GitService} is created with: * *

    *
  • a cpu array containing {@code 4} cpu workers; and
  • *
  • a value of {@code 3} engines per worker.
  • *
* *

* The service will contain a total of {@code 12} {@link GitEngine} instances, * three for each thread (cpu worker). Therefore, in this example, each thread * will be able to run, at most, three concurrent Git tasks. * * @param value * the number of engines per worker to set * * @return a new option that sets the engines per worker to the * specified value * * @throws IllegalArgumentException * if {@code value <= 0} * * @see GitService#create(CpuArray, IoWorker, Option...) */ public static Option enginesPerWorker(final int value) { Checks.checkArgument(value > 0, "engines/worker minimum value is 1 engine/worker"); return new Option() { @Override final void acceptBuilder(GitServiceBuilder builder) { builder.setEnginesPerWorker(value); } }; } /** * The logger instance to be used by this service (and by all of the * {@link GitEngine} instances). * * @param logger * the logger instance * * @return a new option that sets the logger instance to the specified value */ public static Option logger(final Logger logger) { Checks.checkNotNull(logger, "logger == null"); return new Option() { @Override final void acceptBuilder(GitServiceBuilder builder) { builder.setLogger(logger); } }; } /** * {@inheritDoc} */ @Override public final Computation submit(GitCommand command) { Checks.checkNotNull(command, "command == null"); int index; index = Git.randomIndex(cpuArray); CpuWorker cpuWorker; cpuWorker = cpuArray.get(index); return command.submitAsync(gitCommandExecutor, cpuWorker); } final Computation updateRef( Repository repository, RefName ref, ObjectId newValue) { GitWorker w; w = randomWorker(); return w.updateRef(repository, ref, newValue); } final Computation writeCommit(Repository repository, MutableCommit commit) { GitWorker w; w = randomWorker(); return w.writeCommit(repository, commit); } final Computation writeTree( GitCommand command, Repository repository, MutableTree tree) { GitWorker w; w = randomWorker(); return w.writeTree(command, repository, tree); } private GitWorker randomWorker() { int index; index = Git.randomIndex(workers); return workers[index]; } /** * A {@code GitService} configuration option. */ public abstract static class Option { Option() {} abstract void acceptBuilder(GitServiceBuilder builder); } private class ThisCommandExecutor implements GitCommandExecutor { @Override public final Computation> copyObjects( Repository source, ImmutableSet objectsToCopy, Repository destination) { GitWorker w; w = randomWorker(); return w.copyObjects(source, objectsToCopy, destination); } @Override public final Computation materializeEntry( Repository repository, Entry entry, Directory directory) { GitWorker w; w = randomWorker(); return w.materializeEntry(repository, entry, directory); } @Override public final Computation openRepository(Directory directory) { GitWorker w; w = randomWorker(); return w.openRepository(directory); } @Override public final Computation readBlob(Repository repository, ObjectId id) { GitWorker w; w = randomWorker(); return w.readBlob(repository, id); } @Override public final Computation readCommit(Repository repository, ObjectId id) { GitWorker w; w = randomWorker(); return w.readCommit(repository, id); } @Override public final Computation readTree(Repository repository, ObjectId id) { GitWorker w; w = randomWorker(); return w.readTree(repository, id); } @Override public final Computation resolve(Repository repository, RefName ref) { GitWorker w; w = randomWorker(); return w.resolve(repository, ref); } @Override public final Computation submit(GitCommand command) { return GitService.this.submit(command); } @Override public final Computation updateRef( Repository repository, RefName ref, ObjectId newValue) { GitWorker w; w = randomWorker(); return w.updateRef(repository, ref, newValue); } @Override public final Computation writeCommit(Repository repository, MutableCommit commit) { GitWorker w; w = randomWorker(); return w.writeCommit(repository, commit); } @Override public final Computation writeTree( GitCommand command, Repository repository, MutableTree tree) { GitWorker w; w = randomWorker(); return w.writeTree(command, repository, tree); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy