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
             }