org.neo4j.kernel.availability.DatabaseAvailability 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.kernel.availability;
import java.time.Clock;
import org.neo4j.kernel.impl.transaction.stats.TransactionCounters;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.locks.LockSupport.parkNanos;
/**
* This class handles whether the database as a whole is available to use at all.
* As it runs as the last service in the lifecycle list, the stop() is called first
* on stop, shutdown or restart, and thus blocks access to everything else for outsiders.
*/
public class DatabaseAvailability extends LifecycleAdapter
{
private static final AvailabilityRequirement UNAVAILABILITY_REQUIREMENT = new DescriptiveAvailabilityRequirement( "Database unavailable" );
private final AvailabilityGuard databaseAvailabilityGuard;
private final TransactionCounters transactionCounters;
private final Clock clock;
private final long awaitActiveTransactionDeadlineMillis;
public DatabaseAvailability( AvailabilityGuard databaseAvailabilityGuard, TransactionCounters transactionCounters, Clock clock,
long awaitActiveTransactionDeadlineMillis )
{
this.databaseAvailabilityGuard = databaseAvailabilityGuard;
this.transactionCounters = transactionCounters;
this.awaitActiveTransactionDeadlineMillis = awaitActiveTransactionDeadlineMillis;
this.clock = clock;
}
@Override
public void init() throws Exception
{
databaseAvailabilityGuard.require( UNAVAILABILITY_REQUIREMENT );
}
@Override
public void start()
{
databaseAvailabilityGuard.fulfill( UNAVAILABILITY_REQUIREMENT );
}
@Override
public void stop()
{
// Database is no longer available for use
// Deny beginning new transactions
databaseAvailabilityGuard.require( UNAVAILABILITY_REQUIREMENT );
// Await transactions stopped
awaitTransactionsClosedWithinTimeout();
}
private void awaitTransactionsClosedWithinTimeout()
{
long deadline = clock.millis() + awaitActiveTransactionDeadlineMillis;
while ( transactionCounters.getNumberOfActiveTransactions() > 0 && clock.millis() < deadline )
{
parkNanos( MILLISECONDS.toNanos( 10 ) );
}
}
}