Skip to content

Commit

Permalink
Introduce and inject CoreAPIAvailabilityGuard
Browse files Browse the repository at this point in the history
  • Loading branch information
boggle committed Feb 18, 2016
1 parent d07acc4 commit 4c1e995
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 42 deletions.
@@ -0,0 +1,61 @@
package org.neo4j.kernel.impl.coreapi;

/*
* 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 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 <http://www.gnu.org/licenses/>.
*/

import org.neo4j.graphdb.DatabaseShutdownException;
import org.neo4j.kernel.AvailabilityGuard;

/**
* This is a simple wrapper around {@link AvailabilityGuard} that augments its behavior to match how
* availability errors and timeouts are handled in the Core API.
*/
public class CoreAPIAvailabilityGuard
{
private final AvailabilityGuard guard;
private final long timeout;

public CoreAPIAvailabilityGuard( AvailabilityGuard guard, long timeout )
{
this.guard = guard;
this.timeout = timeout;
}

public boolean isAvailable( long timeoutMillis )
{
return guard.isAvailable( timeoutMillis );
}

public void assertDatabaseAvailable()
{
try
{
guard.await( timeout );
}
catch ( AvailabilityGuard.UnavailableException e )
{
if( guard.isShutdown())
{
throw new DatabaseShutdownException();
}
throw new org.neo4j.graphdb.TransactionFailureException( e.getMessage() );
}
}
}
Expand Up @@ -19,27 +19,26 @@
*/
package org.neo4j.kernel.impl.factory;

import java.net.URL;
import java.util.Map;

import org.neo4j.graphdb.DatabaseShutdownException;
import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.graphdb.NotInTransactionException;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.event.KernelEventHandler;
import org.neo4j.graphdb.event.TransactionEventHandler;
import org.neo4j.graphdb.security.URLAccessValidationError;
import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.exceptions.TransactionFailureException;
import org.neo4j.kernel.impl.api.AutoIndexing;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.query.QueryExecutionKernelException;
import org.neo4j.kernel.impl.query.QuerySession;
import org.neo4j.kernel.impl.store.StoreId;
import org.neo4j.kernel.lifecycle.LifecycleException;
import org.neo4j.logging.Logger;

import java.net.URL;
import java.util.Map;

/**
* This implements the backend for the "classic" Core API - meaning the surface-layer-of-the-database, thread bound API. It's a thin veneer to wire the
* various components the kernel and related utilities expose in a way that {@link GraphDatabaseFacade} likes.
Expand All @@ -50,14 +49,14 @@ class ClassicCoreSPI implements GraphDatabaseFacade.SPI
private final PlatformModule platform;
private final DataSourceModule dataSource;
private final Logger msgLog;
private final EditionModule edition;
private final CoreAPIAvailabilityGuard availability;

public ClassicCoreSPI( PlatformModule platform, DataSourceModule dataSource, Logger msgLog, EditionModule edition )
public ClassicCoreSPI(PlatformModule platform, DataSourceModule dataSource, Logger msgLog, CoreAPIAvailabilityGuard availability )
{
this.platform = platform;
this.dataSource = dataSource;
this.msgLog = msgLog;
this.edition = edition;
this.availability = availability;
}

@Override
Expand All @@ -71,7 +70,7 @@ public Result executeQuery( String query, Map<String,Object> parameters, QuerySe
{
try
{
assertDatabaseAvailable();
availability.assertDatabaseAvailable();
return dataSource.queryExecutor.get().executeQuery( query, parameters, querySession );
}
catch ( QueryExecutionKernelException e )
Expand Down Expand Up @@ -161,7 +160,7 @@ public KernelTransaction beginTransaction()
{
try
{
assertDatabaseAvailable();
availability.assertDatabaseAvailable();
KernelTransaction kernelTx = dataSource.kernelAPI.get().newTransaction();
kernelTx.registerCloseListener( (s) -> dataSource.threadToTransactionBridge.unbindTransactionFromCurrentThread() );
dataSource.threadToTransactionBridge.bindTransactionToCurrentThread( kernelTx );
Expand All @@ -176,7 +175,7 @@ public KernelTransaction beginTransaction()
@Override
public KernelTransaction currentTransaction()
{
assertDatabaseAvailable();
availability.assertDatabaseAvailable();
KernelTransaction tx = dataSource.threadToTransactionBridge.getKernelTransactionBoundToThisThread( false );
if( tx == null )
{
Expand All @@ -196,20 +195,4 @@ public Statement currentStatement()
{
return dataSource.threadToTransactionBridge.get();
}

private void assertDatabaseAvailable()
{
try
{
platform.availabilityGuard.await( edition.transactionStartTimeout );
}
catch ( AvailabilityGuard.UnavailableException e )
{
if( platform.availabilityGuard.isShutdown())
{
throw new DatabaseShutdownException();
}
throw new org.neo4j.graphdb.TransactionFailureException( e.getMessage() );
}
}
}
Expand Up @@ -45,6 +45,7 @@
import org.neo4j.kernel.impl.core.DelegatingRelationshipTypeTokenHolder;
import org.neo4j.kernel.impl.core.ReadOnlyTokenCreator;
import org.neo4j.kernel.impl.core.TokenCreator;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.locking.ResourceTypes;
import org.neo4j.kernel.impl.locking.community.CommunityLockManger;
Expand Down Expand Up @@ -105,6 +106,8 @@ public CommunityEditionModule( PlatformModule platformModule )

constraintSemantics = createSchemaRuleVerifier();

coreAPIAvailabilityGuard = new CoreAPIAvailabilityGuard( platformModule.availabilityGuard, transactionStartTimeout );

registerRecovery( platformModule.databaseInfo, life, dependencies );

publishEditionInfo( dependencies.resolveDependency( UsageData.class ), platformModule.databaseInfo, config );
Expand Down
Expand Up @@ -29,6 +29,7 @@
import org.neo4j.kernel.impl.core.LabelTokenHolder;
import org.neo4j.kernel.impl.core.PropertyKeyTokenHolder;
import org.neo4j.kernel.impl.core.RelationshipTypeTokenHolder;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.Configuration;
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.store.id.IdGeneratorFactory;
Expand Down Expand Up @@ -65,6 +66,8 @@ public abstract class EditionModule

public ConstraintSemantics constraintSemantics;

public CoreAPIAvailabilityGuard coreAPIAvailabilityGuard;

protected void doAfterRecoveryAndStartup( DatabaseInfo databaseInfo, DependencyResolver dependencyResolver)
{
DiagnosticsManager diagnosticsManager = dependencyResolver.resolveDependency( DiagnosticsManager.class );
Expand Down
Expand Up @@ -29,6 +29,7 @@
import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.configuration.Settings;
import org.neo4j.kernel.extension.KernelExtensionFactory;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.query.QueryEngineProvider;
import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.logging.LogProvider;
Expand Down Expand Up @@ -126,9 +127,10 @@ public GraphDatabaseFacade newFacade( File storeDir, Map<String, String> params,
EditionModule edition = createEdition( platform );
final DataSourceModule dataSource = createDataSource( dependencies, platform, edition );
Logger msgLog = platform.logging.getInternalLog( getClass() ).infoLogger();
CoreAPIAvailabilityGuard coreAPIAvailabilityGuard = edition.coreAPIAvailabilityGuard;

// Start it
graphDatabaseFacade.init( platform.config, new ClassicCoreSPI( platform, dataSource, msgLog, edition ) );
graphDatabaseFacade.init( platform.config, new ClassicCoreSPI( platform, dataSource, msgLog, coreAPIAvailabilityGuard ) );

Throwable error = null;
try
Expand Down
Expand Up @@ -22,6 +22,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

Expand Down Expand Up @@ -143,7 +144,7 @@ public LifeSupport createLife()
@Override
protected EditionModule createEdition( PlatformModule platformModule )
{
return null;
return Mockito.mock( EditionModule.class, Mockito.RETURNS_DEEP_STUBS );
}

@Override
Expand Down
Expand Up @@ -60,6 +60,7 @@
import org.neo4j.kernel.impl.core.DelegatingPropertyKeyTokenHolder;
import org.neo4j.kernel.impl.core.DelegatingRelationshipTypeTokenHolder;
import org.neo4j.kernel.impl.core.ReadOnlyTokenCreator;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.factory.DatabaseInfo;
import org.neo4j.kernel.impl.factory.EditionModule;
import org.neo4j.kernel.impl.factory.GraphDatabaseFacade;
Expand Down Expand Up @@ -129,6 +130,8 @@ public void assertSchemaWritesAllowed() throws InvalidTransactionTypeKernelExcep

constraintSemantics = new StandardConstraintSemantics();

coreAPIAvailabilityGuard = new CoreAPIAvailabilityGuard( platformModule.availabilityGuard, transactionStartTimeout );

registerRecovery( platformModule.databaseInfo, life, dependencies );

publishEditionInfo( dependencies.resolveDependency( UsageData.class ), platformModule.databaseInfo, config );
Expand Down
Expand Up @@ -126,6 +126,7 @@
import org.neo4j.kernel.impl.core.LastTxIdGetter;
import org.neo4j.kernel.impl.core.ReadOnlyTokenCreator;
import org.neo4j.kernel.impl.core.TokenCreator;
import org.neo4j.kernel.impl.coreapi.CoreAPIAvailabilityGuard;
import org.neo4j.kernel.impl.enterprise.EnterpriseConstraintSemantics;
import org.neo4j.kernel.impl.enterprise.EnterpriseEditionModule;
import org.neo4j.kernel.impl.factory.CommunityEditionModule;
Expand Down Expand Up @@ -492,6 +493,8 @@ public void elected( String role, InstanceId instanceId, URI electedMember )

constraintSemantics = new EnterpriseConstraintSemantics();

coreAPIAvailabilityGuard = new CoreAPIAvailabilityGuard( platformModule.availabilityGuard, transactionStartTimeout );

registerRecovery( platformModule.databaseInfo, dependencies, logging );

UsageData usageData = dependencies.resolveDependency( UsageData.class );
Expand Down
Expand Up @@ -19,28 +19,18 @@
*/
package org.neo4j.kernel.api;

import java.io.File;

import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

import java.io.File;

import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.QueryExecutionException;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.schema.ConstraintDefinition;
import org.neo4j.graphdb.schema.ConstraintType;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.helpers.Exceptions;
import org.neo4j.kernel.impl.coreapi.TopLevelTransaction;
import org.neo4j.kernel.api.ConstraintHaIT.NodePropertyExistenceConstraintHaIT;
import org.neo4j.kernel.api.ConstraintHaIT.RelationshipPropertyExistenceConstraintHaIT;
import org.neo4j.kernel.api.ConstraintHaIT.UniquenessConstraintHaIT;
Expand Down

0 comments on commit 4c1e995

Please sign in to comment.