FELIX-1192 - KARAF: Locking error in DefaultJDBCLock, also contains an eventual OutOfMemory error on locked processes.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@785865 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
index 305659d..551b59b 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
@@ -26,7 +26,7 @@
/**
* Represents an exclusive lock on a database,
- * used to avoid multiple SMX instances attempting
+ * used to avoid multiple Karaf instances attempting
* to become master.
*
* @version $Revision: $
@@ -70,45 +70,41 @@
}
if (user == null) { user = ""; }
if (password == null) { password = ""; }
- try {
- obtainLock();
- } catch (Exception e) {
- System.err.println("Error occured while attempting to obtain connection: " + e.getMessage());
- }
}
/**
- * obtainLock - obtain the lock connection.
+ * setUpdateCursor - Send Update directive to data base server.
*
* @throws Exception
*/
- private void obtainLock() throws Exception {
+ private boolean setUpdateCursor() throws Exception {
PreparedStatement statement = null;
- while (true) {
- try {
+ boolean result = false;
+ try {
+ if ((lockConnection == null) || (lockConnection.isClosed())) {
lockConnection = getConnection(driver, url, user, password);
lockConnection.setAutoCommit(false);
statements.init(lockConnection);
- String sql = statements.testLockTableStatus();
- statement = lockConnection.prepareStatement(sql);
- statement.execute();
- break;
- } catch (Exception e) {
- System.err.println("Could not obtain lock: " + e.getMessage());
- Thread.sleep(this.timeout);
- } finally {
- if (null != statement) {
- try {
- statement.close();
- } catch (SQLException e1) {
- System.err.println("Caught while closing statement: " + e1.getMessage());
- }
- statement = null;
- }
}
- Thread.sleep(this.timeout);
+ //statements.init(lockConnection);
+ String sql = statements.setUpdateCursor();
+ statement = lockConnection.prepareStatement(sql);
+ result = statement.execute();
+ } catch (Exception e) {
+ System.err.println("Could not obtain connection: " + e.getMessage());
+ } finally {
+ if (null != statement) {
+ try {
+ System.err.println("Cleaning up DB connection.");
+ statement.close();
+ } catch (SQLException e1) {
+ System.err.println("Caught while closing statement: " + e1.getMessage());
+ }
+ statement = null;
+ }
}
System.out.println("Connected to data source: " + url);
+ return result;
}
/**
@@ -120,7 +116,10 @@
PreparedStatement statement = null;
boolean result = false;
try {
- if (lockConnection.isClosed()) { obtainLock(); }
+ if (!setUpdateCursor()) {
+ System.err.println("Could not set DB update cursor");
+ return result;
+ }
long time = System.currentTimeMillis();
statement = lockConnection.prepareStatement(statements.getLockUpdateStatement(time));
int rows = statement.executeUpdate();
@@ -155,18 +154,32 @@
* isAlive - test if lock still exists.
*/
public boolean isAlive() throws Exception {
- if (lockConnection == null) { return false; }
- PreparedStatement statement = null;
- try {
- lockConnection.setAutoCommit(false);
- statements.init(lockConnection);
- String sql = statements.testLockTableStatus();
- statement = lockConnection.prepareStatement(sql);
- statement.execute();
- } catch (Exception ex) {
- return false;
+ if ((lockConnection == null) || (lockConnection.isClosed())) {
+ System.err.println("Lost lock!");
+ return false;
}
- return true;
+ PreparedStatement statement = null;
+ boolean result = true;
+ try {
+ long time = System.currentTimeMillis();
+ statement = lockConnection.prepareStatement(statements.getLockUpdateStatement(time));
+ int rows = statement.executeUpdate();
+ if (rows != 1) {
+ result = false;
+ }
+ } catch (Exception ex) {
+ System.err.println("Error occured while testing lock: " + ex + " " + ex.getMessage());
+ return false;
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (Exception ex1) {
+ System.err.println("Error occured after testing lock: " + ex1.getMessage());
+ }
+ }
+ }
+ return result;
}
/**
@@ -186,6 +199,7 @@
Class.forName(driver);
conn = DriverManager.getConnection(url + ";create=true", username, password);
} catch (Exception e) {
+ System.err.println("Error occured while setting up JDBC connection: " + e);
throw e;
}
return conn;
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
index 174e703..d417e2f 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
@@ -995,6 +995,7 @@
String clz = props.getProperty(PROPERTY_LOCK_CLASS, PROPERTY_LOCK_CLASS_DEFAULT);
lock = (Lock) Class.forName(clz).getConstructor(Properties.class).newInstance(props);
boolean lockLogged = false;
+ setStartLevel(lockStartLevel);
for (;;) {
if (lock.lock()) {
if (lockLogged) {
@@ -1017,7 +1018,9 @@
lockLogged = true;
}
Thread.sleep(lockDelay);
- }
+ }
+ } else {
+ setStartLevel(defaultStartLevel);
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
index d612f9a..3e675f4 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
@@ -38,7 +38,7 @@
this.lockPopulateStatement="insert into " + lockTableName + " (TIME, CLUSTER) values (1, '" + clusterName + "')";
}
- public String testLockTableStatus() {
+ public String setUpdateCursor() {
String test = "SELECT * FROM " + lockTableName + " FOR UPDATE";
return test;
}
@@ -92,7 +92,7 @@
System.err.println(ignore);
} finally {
try {
- s.close();
+ if (s != null) { s.close(); }
} catch (Throwable e) {
// ignore
}