Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.neo4j.coreedge.catchup;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.stream.ChunkedWriteHandler;
import java.net.BindException;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import org.neo4j.coreedge.VersionDecoder;
import org.neo4j.coreedge.VersionPrepender;
import org.neo4j.coreedge.catchup.CatchupServerProtocol.State;
import org.neo4j.coreedge.catchup.storecopy.FileHeaderEncoder;
import org.neo4j.coreedge.catchup.storecopy.GetStoreIdRequest;
import org.neo4j.coreedge.catchup.storecopy.GetStoreIdRequestHandler;
import org.neo4j.coreedge.catchup.storecopy.GetStoreRequestDecoder;
import org.neo4j.coreedge.catchup.storecopy.GetStoreRequestHandler;
import org.neo4j.coreedge.catchup.storecopy.StoreCopyFinishedResponseEncoder;
import org.neo4j.coreedge.catchup.tx.TxPullRequestDecoder;
import org.neo4j.coreedge.catchup.tx.TxPullRequestHandler;
import org.neo4j.coreedge.catchup.tx.TxPullResponseEncoder;
import org.neo4j.coreedge.catchup.tx.TxStreamFinishedResponseEncoder;
import org.neo4j.coreedge.core.CoreEdgeClusterSettings;
import org.neo4j.coreedge.core.state.CoreState;
import org.neo4j.coreedge.core.state.snapshot.CoreSnapshotEncoder;
import org.neo4j.coreedge.core.state.snapshot.CoreSnapshotRequest;
import org.neo4j.coreedge.core.state.snapshot.CoreSnapshotRequestHandler;
import org.neo4j.coreedge.handlers.ExceptionLoggingHandler;
import org.neo4j.coreedge.handlers.ExceptionMonitoringHandler;
import org.neo4j.coreedge.handlers.ExceptionSwallowingHandler;
import org.neo4j.coreedge.identity.StoreId;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.helpers.ListenSocketAddress;
import org.neo4j.helpers.NamedThreadFactory;
import org.neo4j.kernel.NeoStoreDataSource;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore;
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore;
import org.neo4j.kernel.impl.transaction.log.checkpoint.CheckPointer;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider;
public class CatchupServer extends LifecycleAdapter
{
private static final Setting setting = CoreEdgeClusterSettings.transaction_listen_address;
private final LogProvider logProvider;
private final Log log;
private final Log userLog;
private final Monitors monitors;
private final Supplier storeIdSupplier;
private final Supplier transactionIdStoreSupplier;
private final Supplier logicalTransactionStoreSupplier;
private final Supplier dataSourceSupplier;
private final BooleanSupplier dataSourceAvailabilitySupplier;
private final NamedThreadFactory threadFactory = new NamedThreadFactory( "catchup-server" );
private final CoreState coreState;
private final ListenSocketAddress listenAddress;
private EventLoopGroup workerGroup;
private Channel channel;
private Supplier checkPointerSupplier;
public CatchupServer( LogProvider logProvider, LogProvider userLogProvider, Supplier storeIdSupplier,
Supplier transactionIdStoreSupplier,
Supplier logicalTransactionStoreSupplier,
Supplier dataSourceSupplier, BooleanSupplier dataSourceAvailabilitySupplier,
CoreState coreState, Config config, Monitors monitors, Supplier checkPointerSupplier )
{
this.coreState = coreState;
this.listenAddress = config.get( setting );
this.transactionIdStoreSupplier = transactionIdStoreSupplier;
this.storeIdSupplier = storeIdSupplier;
this.dataSourceAvailabilitySupplier = dataSourceAvailabilitySupplier;
this.logicalTransactionStoreSupplier = logicalTransactionStoreSupplier;
this.logProvider = logProvider;
this.monitors = monitors;
this.log = logProvider.getLog( getClass() );
this.userLog = userLogProvider.getLog( getClass() );
this.dataSourceSupplier = dataSourceSupplier;
this.checkPointerSupplier = checkPointerSupplier;
}
@Override
public synchronized void start() throws Throwable
{
if ( channel != null )
{
return;
}
workerGroup = new NioEventLoopGroup( 0, threadFactory );
ServerBootstrap bootstrap = new ServerBootstrap()
.group( workerGroup )
.channel( NioServerSocketChannel.class )
.localAddress( listenAddress.socketAddress() )
.childHandler( new ChannelInitializer()
{
@Override
protected void initChannel( SocketChannel ch )
{
CatchupServerProtocol protocol = new CatchupServerProtocol();
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast( new LengthFieldBasedFrameDecoder( Integer.MAX_VALUE, 0, 4, 0, 4 ) );
pipeline.addLast( new LengthFieldPrepender( 4 ) );
pipeline.addLast( new VersionDecoder( logProvider ) );
pipeline.addLast( new VersionPrepender() );
pipeline.addLast( new ResponseMessageTypeEncoder() );
pipeline.addLast( new RequestMessageTypeEncoder() );
pipeline.addLast( new TxPullResponseEncoder() );
pipeline.addLast( new CoreSnapshotEncoder() );
pipeline.addLast( new StoreCopyFinishedResponseEncoder() );
pipeline.addLast( new TxStreamFinishedResponseEncoder() );
pipeline.addLast( new FileHeaderEncoder() );
pipeline.addLast( new ServerMessageTypeHandler( protocol, logProvider ) );
pipeline.addLast( decoders( protocol ) );
pipeline.addLast(
new TxPullRequestHandler( protocol, storeIdSupplier, dataSourceAvailabilitySupplier,
transactionIdStoreSupplier, logicalTransactionStoreSupplier, monitors,
logProvider ) ); pipeline.addLast( new ChunkedWriteHandler() );
pipeline.addLast( new GetStoreRequestHandler( protocol, dataSourceSupplier,
checkPointerSupplier ) );
pipeline.addLast( new GetStoreIdRequestHandler( protocol, storeIdSupplier ) );
pipeline.addLast( new CoreSnapshotRequestHandler( protocol, coreState ) );
pipeline.addLast( new ExceptionLoggingHandler( log ) );
pipeline.addLast( new ExceptionMonitoringHandler(
monitors.newMonitor( ExceptionMonitoringHandler.Monitor.class, CatchupServer.class ) ) );
pipeline.addLast( new ExceptionSwallowingHandler() );
}
} );
try
{
channel = bootstrap.bind().syncUninterruptibly().channel();
}
catch( Exception e )
{
// thanks to netty we need to catch everything and do an instanceof because it does not declare properly
// checked exception but it still throws them with some black magic at runtime.
//noinspection ConstantConditions
if ( e instanceof BindException )
{
userLog.error( "Address is already bound for setting: " + setting + " with value: " + listenAddress );
log.error( "Address is already bound for setting: " + setting + " with value: " + listenAddress, e );
throw e;
}
}
}
private ChannelInboundHandler decoders( CatchupServerProtocol protocol )
{
RequestDecoderDispatcher decoderDispatcher =
new RequestDecoderDispatcher<>( protocol, logProvider );
decoderDispatcher.register( State.TX_PULL, new TxPullRequestDecoder() );
decoderDispatcher.register( State.GET_STORE, new GetStoreRequestDecoder() );
decoderDispatcher.register( State.GET_STORE_ID, new SimpleRequestDecoder( GetStoreIdRequest::new ) );
decoderDispatcher.register( State.GET_CORE_SNAPSHOT, new SimpleRequestDecoder( CoreSnapshotRequest::new) );
return decoderDispatcher;
}
@Override
public synchronized void stop() throws Throwable
{
if ( channel == null )
{
return;
}
log.info( "CatchupServer stopping and unbinding from " + listenAddress );
try
{
channel.close().sync();
channel = null;
}
catch ( InterruptedException e )
{
Thread.currentThread().interrupt();
log.warn( "Interrupted while closing channel." );
}
if ( workerGroup != null &&
workerGroup.shutdownGracefully( 2, 5, TimeUnit.SECONDS ).awaitUninterruptibly( 10, TimeUnit.SECONDS ) )
{
log.warn( "Worker group not shutdown within 10 seconds." );
}
workerGroup = null;
}
}