Merge branch 'AbrahamKiggundu/briar-master': better lock encapsulation

This commit is contained in:
akwizgran
2015-01-29 11:27:30 +00:00
23 changed files with 944 additions and 517 deletions

View File

@@ -27,6 +27,9 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import org.briarproject.api.Author;
@@ -313,16 +316,19 @@ abstract class JdbcDatabase implements Database<Connection> {
private final Clock clock;
private final LinkedList<Connection> connections =
new LinkedList<Connection>(); // Locking: self
new LinkedList<Connection>(); // Locking: connectionsLock
private final AtomicInteger transactionCount = new AtomicInteger(0);
private int openConnections = 0; // Locking: connections
private boolean closed = false; // Locking: connections
private int openConnections = 0; // Locking: connectionsLock
private boolean closed = false; // Locking: connectionsLock
protected abstract Connection createConnection() throws SQLException;
protected abstract void flushBuffersToDisk(Statement s) throws SQLException;
private final Lock connectionsLock = new ReentrantLock();
private final Condition connectionsChanged = connectionsLock.newCondition();
JdbcDatabase(String hashType, String binaryType, String counterType,
String secretType, Clock clock) {
this.hashType = hashType;
@@ -431,9 +437,12 @@ abstract class JdbcDatabase implements Database<Connection> {
public Connection startTransaction() throws DbException {
Connection txn = null;
synchronized(connections) {
connectionsLock.lock();
try {
if(closed) throw new DbClosedException();
txn = connections.poll();
} finally {
connectionsLock.unlock();
}
try {
if(txn == null) {
@@ -441,8 +450,11 @@ abstract class JdbcDatabase implements Database<Connection> {
txn = createConnection();
if(txn == null) throw new DbException();
txn.setAutoCommit(false);
synchronized(connections) {
connectionsLock.lock();
try {
openConnections++;
} finally {
connectionsLock.unlock();
}
}
} catch(SQLException e) {
@@ -455,9 +467,12 @@ abstract class JdbcDatabase implements Database<Connection> {
public void abortTransaction(Connection txn) {
try {
txn.rollback();
synchronized(connections) {
connectionsLock.lock();
try {
connections.add(txn);
connections.notifyAll();
connectionsChanged.signalAll();
} finally {
connectionsLock.unlock();
}
} catch(SQLException e) {
// Try to close the connection
@@ -468,9 +483,12 @@ abstract class JdbcDatabase implements Database<Connection> {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e1.toString(), e1);
}
// Whatever happens, allow the database to close
synchronized(connections) {
connectionsLock.lock();
try {
openConnections--;
connections.notifyAll();
connectionsChanged.signalAll();
} finally {
connectionsLock.unlock();
}
}
}
@@ -486,9 +504,12 @@ abstract class JdbcDatabase implements Database<Connection> {
tryToClose(s);
throw new DbException(e);
}
synchronized(connections) {
connectionsLock.lock();
try {
connections.add(txn);
connections.notifyAll();
connectionsChanged.signalAll();
} finally {
connectionsLock.unlock();
}
}
@@ -502,14 +523,15 @@ abstract class JdbcDatabase implements Database<Connection> {
protected void closeAllConnections() throws SQLException {
boolean interrupted = false;
synchronized(connections) {
connectionsLock.lock();
try {
closed = true;
for(Connection c : connections) c.close();
openConnections -= connections.size();
connections.clear();
while(openConnections > 0) {
try {
connections.wait();
connectionsChanged.await();
} catch(InterruptedException e) {
LOG.warning("Interrupted while closing connections");
interrupted = true;
@@ -518,7 +540,10 @@ abstract class JdbcDatabase implements Database<Connection> {
openConnections -= connections.size();
connections.clear();
}
} finally {
connectionsLock.unlock();
}
if(interrupted) Thread.currentThread().interrupt();
}