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

io.atomix.copycat.server.storage.compaction.Compactor Maven / Gradle / Ivy

There is a newer version: 1.2.8
Show newest version
/*
 * Copyright 2015 the original author or authors.
 *
 * 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 io.atomix.copycat.server.storage.compaction;

import io.atomix.catalyst.util.Assert;
import io.atomix.catalyst.util.concurrent.ThreadContext;
import io.atomix.catalyst.util.concurrent.ThreadPoolContext;
import io.atomix.copycat.server.storage.SegmentManager;
import io.atomix.copycat.server.storage.Storage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Manages compaction of log {@link io.atomix.copycat.server.storage.Segment}s in a pool of background
 * threads.
 * 

* The compactor is responsible for managing log compaction processes. Log {@link Compaction} processes * are run in a pool of background threads of the configured number of {@link Storage#compactionThreads()}. * {@link Compaction#MINOR} and {@link Compaction#MAJOR} executions are scheduled according to the configured * {@link Storage#minorCompactionInterval()} and {@link Storage#majorCompactionInterval()} respectively. * Compaction can also be run synchronously via {@link Compactor#compact()} or {@link Compactor#compact(Compaction)}. *

* When a {@link Compaction} is executed either synchronously or asynchronously, the compaction's associated * {@link CompactionManager} is called to build a list of {@link CompactionTask}s to run. Compaction tasks * are run in parallel in the compaction thread pool. However, the compactor will not allow multiple compaction * executions to run in parallel. If a compaction is attempted while another compaction is already running, * it will be ignored. * * @author compact(Compaction.MINOR), storage.minorCompactionInterval().toMillis(), storage.minorCompactionInterval().toMillis(), TimeUnit.MILLISECONDS); major = executor.scheduleAtFixedRate(() -> compact(Compaction.MAJOR), storage.majorCompactionInterval().toMillis(), storage.majorCompactionInterval().toMillis(), TimeUnit.MILLISECONDS); } /** * Compacts the log using the default {@link Compaction#MINOR} compaction strategy. * * @return A completable future to be completed once the log has been compacted. */ public CompletableFuture compact() { return compact(Compaction.MINOR); } /** * Compacts the log using the given {@link CompactionManager}. *

* The provided {@link CompactionManager} will be queried for a list of {@link CompactionTask}s to run. * Tasks will be run in parallel in a pool of background threads, and the returned {@link CompletableFuture} * will be completed once those tasks have completed. * * @param compaction The compaction strategy. * @return A completable future to be completed once the log has been compacted. */ public synchronized CompletableFuture compact(Compaction compaction) { if (future != null) return future; LOGGER.info("Compacting log with compaction: {}", compaction); future = new CompletableFuture<>(); ThreadContext compactorThread = ThreadContext.currentContext(); CompactionManager manager = compaction.manager(); AtomicInteger counter = new AtomicInteger(); Collection tasks = manager.buildTasks(storage, segments); if (!tasks.isEmpty()) { LOGGER.debug("Executing {} compaction task(s)", tasks.size()); for (CompactionTask task : tasks) { LOGGER.debug("Executing {}", task); ThreadContext taskThread = new ThreadPoolContext(executor, segments.serializer()); taskThread.execute(task).whenComplete((result, error) -> { LOGGER.debug("{} complete", task); if (counter.incrementAndGet() == tasks.size()) { if (compactorThread != null) { compactorThread.executor().execute(() -> future.complete(null)); } else { future.complete(null); } } }); } } else { future.complete(null); } return future.whenComplete((result, error) -> future = null); } /** * Closes the log compactor. *

* When the compactor is closed, existing compaction tasks will be allowed to complete, future scheduled * compactions will be cancelled, and the underlying {@link ScheduledExecutorService} will be shut down. */ @Override public void close() { if (minor != null) minor.cancel(false); if (major != null) major.cancel(false); executor.shutdown(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy