Package org.neo4j.ha

Source Code of org.neo4j.ha.StandaloneDatabase$TimestampStream

/**
* Copyright (c) 2002-2011 "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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.ha;

import java.io.File;
import java.io.PrintStream;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.junit.Ignore;
import org.neo4j.com.Protocol;
import org.neo4j.kernel.HighlyAvailableGraphDatabase;
import org.neo4j.kernel.ha.Broker;
import org.neo4j.kernel.ha.FakeMasterBroker;
import org.neo4j.kernel.ha.FakeSlaveBroker;
import org.neo4j.kernel.ha.MasterClient;
import org.neo4j.kernel.ha.zookeeper.ZooKeeperException;
import org.neo4j.management.HighAvailability;
import org.neo4j.test.SubProcess;

import slavetest.AbstractHaTest;
import slavetest.Job;
import slavetest.PlaceHolderGraphDatabaseService;

@Ignore
public class StandaloneDatabase
{
    private final Controller process;

    public static StandaloneDatabase withDefaultBroker( String testMethodName, File path,
            int machineId, final LocalhostZooKeeperCluster zooKeeper, String haServer,
            String[] extraArgs )
    {
        return new StandaloneDatabase( testMethodName, new Bootstrap( path, machineId,//
                HighlyAvailableGraphDatabase.CONFIG_KEY_HA_SERVER, haServer,//
                HighlyAvailableGraphDatabase.CONFIG_KEY_HA_ZOO_KEEPER_SERVERS,
                zooKeeper.getConnectionString() )
        {
            @Override
            HighlyAvailableGraphDatabase start( String storeDir, Map<String, String> config )
            {
                HighlyAvailableGraphDatabase db = new HighlyAvailableGraphDatabase( storeDir,
                        config );
                System.out.println( "Started HA db (w/ zoo keeper)" );
                return db;
            }
        } )
        {
            @Override
            IllegalStateException format( StartupFailureException e )
            {
                return e.format( zooKeeper );
            }
        };
    }

    public static StandaloneDatabase withFakeBroker( String testMethodName, final File path,
            int machineId, final int masterId, String[] extraArgs )
    {
        StandaloneDatabase standalone = new StandaloneDatabase( testMethodName, new Bootstrap(
                path, machineId )
        {
            @Override
            HighlyAvailableGraphDatabase start( String storeDir, Map<String, String> config )
            {
                final PlaceHolderGraphDatabaseService placeHolderGraphDb = new PlaceHolderGraphDatabaseService( path.getAbsolutePath() );
                final Broker broker;
                if ( machineId == masterId )
                {
                    broker = new FakeMasterBroker( machineId, placeHolderGraphDb );
                }
                else
                {
                    broker = new FakeSlaveBroker( new MasterClient( "localhost",
                            Protocol.PORT, placeHolderGraphDb ), masterId, machineId, placeHolderGraphDb );
                }
                HighlyAvailableGraphDatabase db = new HighlyAvailableGraphDatabase( storeDir, config,
                        AbstractHaTest.wrapBrokerAndSetPlaceHolderDb( placeHolderGraphDb, broker ) );
                placeHolderGraphDb.setDb( db );
                System.out.println( "Started HA db (w/o zoo keeper)" );
                return db;
            }
        } );
        standalone.awaitStarted();
        return standalone;
    }

    private StandaloneDatabase( String testMethodName, Bootstrap bootstrap )
    {
        process = new HaDbProcess( testMethodName ).start( bootstrap );
    }

    @Override
    public String toString()
    {
        return getClass().getSimpleName() + process;
    }

    public void awaitStarted()
    {
        try
        {
            process.awaitStarted();
        }
        catch ( StartupFailureException e )
        {
            throw format( e );
        }
    }

    public <T> T executeJob( Job<T> job ) throws Exception
    {
        try
        {
            return process.executeJob( job );
        }
        catch ( StartupFailureException e )
        {
            throw format( e );
        }
    }

    public int getMachineId()
    {
        try
        {
            return process.getMachineId();
        }
        catch ( StartupFailureException e )
        {
            throw format( e );
        }
    }

    public void pullUpdates()
    {
        try
        {
            process.pullUpdates();
        }
        catch ( StartupFailureException e )
        {
            throw format( e );
        }
    }

    IllegalStateException format( StartupFailureException e )
    {
      return e.format();
    }

    public void shutdown()
    {
        SubProcess.stop( process );
    }

    // <IMPLEMENTATION>

    public interface Controller
    {
        void pullUpdates() throws StartupFailureException;

        void awaitStarted() throws StartupFailureException;

        int getMachineId() throws StartupFailureException;

        <T> T executeJob( Job<T> job ) throws Exception;
    }

    public static class StartupFailureException extends Exception
    {
        private final long timestamp;

    StartupFailureException( Throwable cause )
        {
            super( cause );
            timestamp = new Date().getTime();
        }

        public IllegalStateException format()
        {
      return new IllegalStateException( message() , getCause() );
    }

    private String message()
    {
      return "database failed to start @ " + TimestampStream.format( new Date( timestamp ) );
    }

    IllegalStateException format( LocalhostZooKeeperCluster zooKeeper )
        {
            Throwable cause = getCause();
            String message = message();
            if ( cause instanceof ZooKeeperException )
            {
                message += ". ZooKeeper status: " + zooKeeper.getStatus();
            }
            return new IllegalStateException( message, cause );
        }
    }

    public static abstract class Bootstrap implements Serializable
    {
        private final String[] config;
        private final File storeDir;
        final int machineId;

        private Bootstrap( File storeDir, int machineId, String... config )
        {
            this.storeDir = storeDir;
            this.machineId = machineId;
            this.config = config;
        }

        final HighlyAvailableGraphDatabase start()
        {
            Map<String, String> params = new HashMap<String, String>();
            params.put( HighlyAvailableGraphDatabase.CONFIG_KEY_HA_MACHINE_ID,
                    Integer.toString( machineId ) );
            for ( int i = 0; i < config.length; i += 2 )
            {
                params.put( config[i], config[i + 1] );
            }
            return start( storeDir.getAbsolutePath(), params );
        }

        abstract HighlyAvailableGraphDatabase start( String storeDir, Map<String, String> config );
    }

    private static abstract class DatabaseReference
    {
        abstract HighlyAvailableGraphDatabase graph() throws StartupFailureException;

        void shutdown()
        {
        }
    }

    private static class HaDbProcess extends SubProcess<Controller, Bootstrap> implements
            Controller
    {
        private transient volatile DatabaseReference db = null;
        private final String testMethodName;

        private HaDbProcess( String testMethodName )
        {
            this.testMethodName = testMethodName;
        }

        private HighlyAvailableGraphDatabase db() throws StartupFailureException
        {
            DatabaseReference ref = db;
            if ( ref == null ) throw new IllegalStateException( "database has not been started" );
            return ref.graph();
        }

        private synchronized void db( final HighlyAvailableGraphDatabase graph )
        {
            if ( db != null && graph != null )
            {
                graph.shutdown();
                throw new IllegalStateException( "database has already been started" );
            }
            db = new DatabaseReference()
            {
                @Override
                HighlyAvailableGraphDatabase graph()
                {
                    if ( graph == null )
                        throw new IllegalStateException( "database has been shut down" );
                    return graph;
                }

                @Override
                void shutdown()
                {
                    if ( graph == null )
                    {
                        System.out.println( "database has already been shut down" );
                    }
                    else
                    {
                        graph.shutdown();
                    }
                }
            };
        }

        private synchronized Throwable db( final Throwable cause )
        {
            db = new DatabaseReference()
            {
                @Override
                HighlyAvailableGraphDatabase graph() throws StartupFailureException
                {
                    throw new StartupFailureException( cause );
                }
            };
            return cause;
        }

        @Override
        public String toString()
        {
            return testMethodName;
        }

        @Override
        protected synchronized void startup( Bootstrap bootstrap ) throws Throwable
        {
            System.setOut( new TimestampStream( System.out ) );
            System.setErr( new TimestampStream( System.err ) );
            if ( db != null ) throw new IllegalStateException( "already started" );
            System.out.println( "About to start" );
            try
            {
                db( bootstrap.start() );
            }
            catch ( Throwable exception )
            {
                System.out.println( "Startup failed: " + exception );
                throw db( exception );
            }
        }

        @Override
        protected synchronized void shutdown()
        {
            DatabaseReference ref = db;
            if ( ref == null )
            {
                System.out.println( "Shutdown attempted before completion of startup" );
                throw new IllegalStateException( "database has not been started" );
            }
            System.out.println( "Shutdown started" );
            try
            {
                ref.shutdown();
            }
            finally
            {
                db( (HighlyAvailableGraphDatabase) null );
            }
            System.out.println( "Shutdown completed" );
            super.shutdown();
        }

        public void awaitStarted() throws StartupFailureException
        {
            boolean interrupted = false;
            while ( this.db == null )
            {
                try
                {
                    Thread.sleep( 100 );
                }
                catch ( InterruptedException e )
                {
                    interrupted = true;
                    Thread.interrupted();
                }
            }
            if ( interrupted ) Thread.currentThread().interrupt();
            db();
        }

        public <T> T executeJob( Job<T> job ) throws Exception
        {
            HighlyAvailableGraphDatabase database = db();
            System.out.println( "Executing job " + job );
            T result = job.execute( database );
            System.out.println( "Job " + job + " executed" );
            return result;
        }

        public int getMachineId() throws StartupFailureException
        {
            return Integer.parseInt( db().getManagementBean( HighAvailability.class ).getMachineId() );
        }

        public void pullUpdates() throws StartupFailureException
        {
            HighlyAvailableGraphDatabase database = db();
            System.out.println( "pullUpdates" );
            database.pullUpdates();
        }
    }

    private static class TimestampStream extends PrintStream
    {
        static ThreadLocal<DateFormat> timestamp = new ThreadLocal<DateFormat>()
        {
            @Override
            protected DateFormat initialValue()
            {
                return new SimpleDateFormat( "[HH:mm:ss:SS] " );
            }
        };

        static String format( Date date )
        {
            return timestamp.get().format( date );
        }

        TimestampStream( PrintStream out )
        {
            super( out );
        }

        @Override
        public void println( String string )
        {
            super.println( format( new Date() ) + string );
        }
    }
}
TOP

Related Classes of org.neo4j.ha.StandaloneDatabase$TimestampStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.