From b695469bbc26940ed3ba9cb7a67dca5d6d9975c6 Mon Sep 17 00:00:00 2001 From: Zhen Date: Thu, 1 Dec 2016 15:48:56 +0100 Subject: [PATCH] lock free driver This PR ensure that after a driver is closed, no new session could be started. --- .../org/neo4j/driver/internal/BaseDriver.java | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/driver/src/main/java/org/neo4j/driver/internal/BaseDriver.java b/driver/src/main/java/org/neo4j/driver/internal/BaseDriver.java index ae7534ecee..e021aa6232 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/BaseDriver.java +++ b/driver/src/main/java/org/neo4j/driver/internal/BaseDriver.java @@ -18,7 +18,7 @@ */ package org.neo4j.driver.internal; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.atomic.AtomicBoolean; import org.neo4j.driver.internal.security.SecurityPlan; import org.neo4j.driver.v1.AccessMode; @@ -34,8 +34,7 @@ abstract class BaseDriver implements Driver private final SecurityPlan securityPlan; protected final Logger log; - private final ReentrantReadWriteLock closedLock = new ReentrantReadWriteLock(); - private boolean closed; + private AtomicBoolean closed = new AtomicBoolean( false ); BaseDriver( SecurityPlan securityPlan, Logging logging ) { @@ -46,16 +45,8 @@ abstract class BaseDriver implements Driver @Override public final boolean isEncrypted() { - closedLock.readLock().lock(); - try - { - assertOpen(); - return securityPlan.requiresEncryption(); - } - finally - { - closedLock.readLock().unlock(); - } + assertOpen(); + return securityPlan.requiresEncryption(); } @Override @@ -67,33 +58,26 @@ public final Session session() @Override public final Session session( AccessMode mode ) { - closedLock.readLock().lock(); - try - { - assertOpen(); - return newSessionWithMode( mode ); - } - finally + assertOpen(); + Session session = newSessionWithMode( mode ); + if( closed.get() ) { - closedLock.readLock().unlock(); + // the driver is already closed and we either 1. obtain this session from the old session pool + // or 2. we obtain this session from a new session pool + // For 1. this closeResources will take no effect as everything is already closed. + // For 2. this closeResources will close the new connection pool just created to ensure no resource leak. + closeResources(); + throw driverCloseException(); } + return session; } @Override public final void close() { - closedLock.writeLock().lock(); - try + if ( closed.compareAndSet(false, true) ) { - if ( !closed ) - { - closeResources(); - } - } - finally - { - closed = true; - closedLock.writeLock().unlock(); + closeResources(); } } @@ -103,9 +87,14 @@ public final void close() private void assertOpen() { - if ( closed ) + if ( closed.get() ) { - throw new IllegalStateException( "This driver instance has already been closed" ); + throw driverCloseException(); } } + + private IllegalStateException driverCloseException() + { + return new IllegalStateException( "This driver instance has already been closed" ); + } }