org.neo4j.dbms.database.AbstractVersionComponent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-kernel Show documentation
Show all versions of neo4j-kernel Show documentation
Neo4j kernel is a lightweight, embedded Java database designed to
store data structured as graphs rather than tables. For more
information, see http://neo4j.org.
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.dbms.database;
import java.util.function.Function;
import org.neo4j.configuration.Config;
import org.neo4j.configuration.GraphDatabaseSettings;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.util.Preconditions;
import static org.neo4j.configuration.GraphDatabaseSettings.SYSTEM_DATABASE_NAME;
/**
* These components only care about the version number
*/
public abstract class AbstractVersionComponent extends AbstractSystemGraphComponent
{
private final String componentName;
private final T latestVersion;
protected final Function convertToVersion;
protected volatile T currentVersion;
public AbstractVersionComponent( String componentName, T latestVersion, Config config, Function convertFunction )
{
super( config );
this.componentName = componentName;
this.latestVersion = latestVersion;
this.convertToVersion = convertFunction;
}
abstract T getFallbackVersion();
@Override
public String componentName()
{
return componentName;
}
@Override
public Status detect( Transaction tx )
{
try
{
Integer versionNumber = getVersion( tx, componentName );
if ( versionNumber == null )
{
return Status.UNINITIALIZED;
}
else
{
T version = convertToVersion.apply( getVersion( tx, componentName ) );
if ( latestVersion.isGreaterThan( version ) )
{
return Status.REQUIRES_UPGRADE;
}
else if ( latestVersion.equals( version ) )
{
return Status.CURRENT;
}
else
{
return Status.UNSUPPORTED_FUTURE;
}
}
}
catch ( IllegalArgumentException e )
{
return Status.UNSUPPORTED_FUTURE;
}
}
@Override
public void initializeSystemGraph( GraphDatabaseService system, boolean firstInitialization ) throws Exception
{
boolean mayUpgrade = config.get( GraphDatabaseSettings.allow_single_automatic_upgrade );
Preconditions.checkState( system.databaseName().equals( SYSTEM_DATABASE_NAME ),
"Cannot initialize system graph on database '" + system.databaseName() + "'" );
Status status;
try ( Transaction tx = system.beginTx() )
{
status = detect( tx );
tx.commit();
}
switch ( status )
{
case CURRENT:
break;
case UNINITIALIZED:
if ( mayUpgrade || firstInitialization )
{
initializeSystemGraphModel( system );
}
break;
case REQUIRES_UPGRADE:
if ( mayUpgrade )
{
upgradeToCurrent( system );
}
break;
default:
throw new IllegalStateException( String.format( "Unsupported component state for '%s': %s", componentName(), status.description() ) );
}
}
@Override
protected void initializeSystemGraphModel( GraphDatabaseService system ) throws Exception
{
SystemGraphComponent.executeWithFullAccess( system, this::setToLatestVersion );
}
void setToLatestVersion( Transaction tx )
{
try ( var nodes = tx.findNodes( VERSION_LABEL ) )
{
var node = nodes
.stream()
.findFirst()
.orElseGet( () -> tx.createNode( VERSION_LABEL ) );
node.setProperty( componentName, latestVersion.getVersion() );
}
}
@Override
public void upgradeToCurrent( GraphDatabaseService system ) throws Exception
{
initializeSystemGraphModel( system );
}
T fetchStateFromSystemDatabase( GraphDatabaseService system )
{
T result = getFallbackVersion();
try ( var tx = system.beginTx() )
{
Integer version = getVersion( tx, componentName );
if ( version != null )
{
result = convertToVersion.apply( version );
}
}
return result;
}
}