/**
* 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.ext.udc.impl;
import org.neo4j.ext.udc.UdcProperties;
import org.neo4j.helpers.Service;
import org.neo4j.kernel.Config;
import org.neo4j.kernel.KernelExtension;
import org.neo4j.kernel.Version;
import org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource;
import java.util.Properties;
import java.util.Timer;
/**
* Kernel extension for UDC, the Usage Data Collector. The UDC runs as a background
* daemon, waking up once a day to collect basic usage information about a long
* running graph database.
* <p/>
* The first update is delayed to avoid needless activity during integration
* testing and short-run applications. Subsequent updates are made at regular
* intervals. Both times are specified in milliseconds.
*/
@Service.Implementation( KernelExtension.class )
public class UdcExtensionImpl extends KernelExtension implements UdcProperties
{
public static final String UDC_SOURCE_DISTRIBUTION_KEY = "neo4j.ext.udc.host";
/**
* Delay, in milliseconds, before the first UDC update is sent.
* <p/>
* Defaults to 10 minutes.
*/
private int firstDelay = 10 * 1000 * 60;
/**
* Millisecond interval for subsequent updates.
* <p/>
* Defaults to 24 hours.
*/
private int interval = 1000 * 60 * 60 * 24;
/**
* Host address to which UDC updates will be sent.
*/
private String hostAddress = "udc.neo4j.org";
/**
* Disable the extension.
* <p/>
* Defaults to false.
*/
private boolean disabled = false;
private Timer timer;
private String source;
/**
* No-arg constructor, sets the extension key to "kernel udc".
*/
public UdcExtensionImpl()
{
super( "kernel udc" );
}
/**
* Lifecycle load event, which occurs during the startup of
* a new GraphDbInstance.
* <p/>
* Configuration information is retrieved from the KernelData,
* then a daemon thread is started to periodically collect
* and submit usage data.
*
* @param kernel reference to the loading graph database kernel.
*/
@Override
protected void load( KernelData kernel )
{
configure( kernel.getConfig() );
// ABK: a hack to register this extension with the kernel, which
// only knows about extensions that have a saved state
kernel.setState( this, new Object() );
if ( !disabled )
{
timer = new Timer();
NeoStoreXaDataSource ds = (NeoStoreXaDataSource)kernel.getConfig().getTxModule().getXaDataSourceManager().getXaDataSource( "nioneodb" );
boolean crashPing = ds.getXaContainer().getLogicalLog().wasNonClean();
String storeId = Long.toHexString( ds.getRandomIdentifier() );
UdcTimerTask task = new UdcTimerTask( hostAddress, Version.VERSION.getRevision(), storeId, source, crashPing );
timer.scheduleAtFixedRate( task, firstDelay, interval );
}
}
@Override
protected void unload( KernelData kernel )
{
if ( timer != null )
{
timer.cancel();
}
}
/**
* Attempt to retrieve configuration provided by user.
* <p/>
* Configuration precedence is in this order:
* <p/>
* <ol>
* <li>value from config</li>
* <li>system property</li>
* <li>hard-coded default value</li>
* <ol>
*
* @param config user defined configuration parameters
*/
private void configure( Config config )
{
Properties props = loadSystemProperties();
MyConfig configuration = new MyConfig( config, props );
try
{
firstDelay = configuration.getInt( FIRST_DELAY_CONFIG_KEY, "600000" );
} catch ( Exception e )
{
;
}
try
{
interval = configuration.getInt( INTERVAL_CONFIG_KEY, "86400000" );
} catch ( Exception e )
{
;
}
try
{
hostAddress = configuration.getString( UDC_HOST_ADDRESS_KEY, hostAddress );
} catch ( Exception e )
{
;
}
try
{
disabled = configuration.getBool( UDC_DISABLE_KEY, "false" );
} catch ( Exception e )
{
;
}
try
{
source = configuration.getString( UDC_SOURCE_KEY, null );
} catch ( Exception e )
{
;
}
}
private class MyConfig
{
private final Config config;
private final Properties props;
private MyConfig( Config config, Properties props )
{
this.config = config;
this.props = props;
}
private String getString( String key, String defaultValue )
{
String result = (String)config.getParams().get( key );
if ( result == null )
{
result = props.getProperty( key, defaultValue );
}
return result;
}
private int getInt( String key, String defaultValue )
{
String result = getString( key, defaultValue );
return Integer.parseInt( result );
}
private boolean getBool( String key, String defaultValue )
{
String result = getString( key, defaultValue );
return Boolean.parseBoolean( result );
}
}
private Properties loadSystemProperties()
{
Properties sysProps = System.getProperties();
try
{
sysProps.load( getClass().getResourceAsStream( "/org/neo4j/ext/udc/udc.properties" ) );
} catch ( Exception e )
{
System.err.println( "failed to load udc.properties, because: " + e );
; // fail silently,
}
return sysProps;
}
}