
info.archinnov.achilles.embedded.AchillesCassandraDaemon Maven / Gradle / Ivy
/*
* Copyright (C) 2012-2016 DuyHai DOAN
*
* 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 info.archinnov.achilles.embedded;
import java.io.IOException;
import java.util.List;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.cql3.functions.ThreadAwareSecurityManager;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.FSError;
import org.apache.cassandra.io.sstable.CorruptSSTableException;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.metrics.StorageMetrics;
import org.apache.cassandra.service.*;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.JVMStabilityInspector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
public class AchillesCassandraDaemon extends CassandraDaemon {
private static final Logger logger = LoggerFactory.getLogger(AchillesCassandraDaemon.class);
private NativeTransportService nativeTransportService;
/**
* Override the default setup process to speed up bootstrap
*
* - disable JMX
* - disable legacy schema migration
* - no pre-3.0 hints migration
* - no pre-3.0 batch entries migration
* - disable auto compaction on all keyspaces (your test data should fit in memory!!!)
* - disable metrics
* - disable GCInspector
* - disable mlock
* - disable Thrift server
* - disable startup checks (Jemalloc, validLaunchDate, JMXPorts, JvmOptions, JnaInitialization, initSigarLibrary, dataDirs, SSTablesFormat, SystemKeyspaceState, Datacenter, Rack)
* - disable materialized view rebuild (you should clean data folder between each test anyway)
* - disable the SizeEstimatesRecorder (estimate SSTable size, who cares for unit testing ?)
*/
@Override
protected void setup() {
// Delete any failed snapshot deletions on Windows - see CASSANDRA-9658
if (FBUtilities.isWindows())
WindowsFailedSnapshotTracker.deleteOldSnapshots();
ThreadAwareSecurityManager.install();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
StorageMetrics.exceptions.inc();
logger.error("Exception in thread {}", t, e);
Tracing.trace("Exception in thread {}", t, e);
for (Throwable e2 = e; e2 != null; e2 = e2.getCause())
{
JVMStabilityInspector.inspectThrowable(e2);
if (e2 instanceof FSError)
{
if (e2 != e) // make sure FSError gets logged exactly once.
logger.error("Exception in thread {}", t, e2);
FileUtils.handleFSError((FSError) e2);
}
if (e2 instanceof CorruptSSTableException)
{
if (e2 != e)
logger.error("Exception in thread " + t, e2);
FileUtils.handleCorruptSSTable((CorruptSSTableException) e2);
}
}
});
// load schema from disk
Schema.instance.loadFromDisk();
// clean up debris in the rest of the keyspaces
for (String keyspaceName : Schema.instance.getKeyspaces())
{
// Skip system as we've already cleaned it
if (keyspaceName.equals(SystemKeyspace.NAME))
continue;
for (CFMetaData cfm : Schema.instance.getTablesAndViews(keyspaceName))
ColumnFamilyStore.scrubDataDirectories(cfm);
}
Keyspace.setInitialized();
// initialize keyspaces
for (String keyspaceName : Schema.instance.getKeyspaces())
{
if (logger.isDebugEnabled())
logger.debug("opening keyspace {}", keyspaceName);
// disable auto compaction until commit log replay ends
for (ColumnFamilyStore cfs : Keyspace.open(keyspaceName).getColumnFamilyStores())
{
for (ColumnFamilyStore store : cfs.concatWithIndexes())
{
store.disableAutoCompaction();
}
}
}
try
{
loadRowAndKeyCacheAsync().get();
}
catch (Throwable t)
{
JVMStabilityInspector.inspectThrowable(t);
logger.warn("Error loading key or row cache", t);
}
// replay the log if necessary
try
{
CommitLog.instance.recover();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
// Re-populate token metadata after commit log recover (new peers might be loaded onto system keyspace #10293)
StorageService.instance.populateTokenMetadata();
SystemKeyspace.finishStartup();
// start server internals
StorageService.instance.registerDaemon(this);
try
{
StorageService.instance.initServer();
}
catch (ConfigurationException e)
{
System.err.println(e.getMessage() + "\nFatal configuration error; unable to start server. See log for stacktrace.");
exitOrFail(1, "Fatal configuration error", e);
}
// Native transport
nativeTransportService = new NativeTransportService();
completeSetup();
}
private void exitOrFail(int code, String message, Throwable cause)
{
logger.error(message, cause);
System.exit(code);
}
private ListenableFuture> loadRowAndKeyCacheAsync()
{
final ListenableFuture keyCacheLoad = CacheService.instance.keyCache.loadSavedAsync();
final ListenableFuture rowCacheLoad = CacheService.instance.rowCache.loadSavedAsync();
@SuppressWarnings("unchecked")
ListenableFuture> retval = Futures.successfulAsList(keyCacheLoad, rowCacheLoad);
return retval;
}
/**
* Start the Cassandra Daemon, assuming that it has already been
* initialized via {@link #init(String[])}
*
* Hook for JSVC
*/
@Override
public void start()
{
startNativeTransport();
StorageService.instance.setRpcReady(true);
}
/**
* Stop the daemon, ideally in an idempotent manner.
*
* Hook for JSVC / Procrun
*/
@Override
public void stop()
{
// On linux, this doesn't entirely shut down Cassandra, just the RPC server.
// jsvc takes care of taking the rest down
logger.info("Cassandra shutting down...");
if (nativeTransportService != null)
nativeTransportService.destroy();
StorageService.instance.setRpcReady(false);
// On windows, we need to stop the entire system as prunsrv doesn't have the jsvc hooks
// We rely on the shutdown hook to drain the node
if (FBUtilities.isWindows())
System.exit(0);
}
@Override
public void startNativeTransport()
{
if (nativeTransportService == null)
throw new IllegalStateException("setup() must be called first for CassandraDaemon");
else
nativeTransportService.start();
}
@Override
public void stopNativeTransport()
{
if (nativeTransportService != null)
nativeTransportService.stop();
}
@Override
public boolean isNativeTransportRunning()
{
return nativeTransportService != null ? nativeTransportService.isRunning() : false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy