diff -urb openfire_src.orig/src/database/openfire_mysql.sql openfire_src/src/database/openfire_mysql.sql
--- openfire_src.orig/src/database/openfire_mysql.sql	2008-11-21 13:53:51.000000000 -0500
+++ openfire_src/src/database/openfire_mysql.sql	2009-01-08 15:01:32.000000000 -0500
@@ -354,6 +354,10 @@
   PRIMARY KEY (serviceID, leaf)
 );
 
+CREATE TABLE ofFailover (
+  node                CHAR(100)      NULL
+);
+
 # Finally, insert default table values.
 
 INSERT INTO ofID (idType, id) VALUES (18, 1);
diff -urb openfire_src.orig/src/java/org/jivesoftware/openfire/XMPPServer.java openfire_src/src/java/org/jivesoftware/openfire/XMPPServer.java
--- openfire_src.orig/src/java/org/jivesoftware/openfire/XMPPServer.java	2008-11-21 13:53:55.000000000 -0500
+++ openfire_src/src/java/org/jivesoftware/openfire/XMPPServer.java	2009-01-09 14:03:45.000000000 -0500
@@ -57,11 +57,13 @@
 import java.io.InputStream;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.security.KeyStore;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.*;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -384,6 +386,7 @@
                         }
 
                         verifyDataSource();
+                        verifySingleServer();
                         // First load all the modules so that modules may access other modules while
                         // being initialized
                         loadModules();
@@ -425,6 +428,7 @@
             // If the server has already been setup then we can start all the server's modules
             if (!setupMode) {
                 verifyDataSource();
+                verifySingleServer();
                 // First load all the modules so that modules may access other modules while
                 // being initialized
                 loadModules();
@@ -722,6 +726,79 @@
     }
 
     /**
+     * Verify that only one server is running (for failover purposes)
+     * 
+     * @author Randall Norviel
+     */
+    private void verifySingleServer() throws UnknownHostException {
+//      String localID = InetAddress.getLocalHost().getHostAddress();
+      String localID = InetAddress.getLocalHost().getCanonicalHostName();
+      java.sql.Connection conn = null;
+
+      try {
+        conn = DbConnectionManager.getConnection();
+        conn.setAutoCommit(false);
+        conn.setTransactionIsolation(java.sql.Connection.TRANSACTION_SERIALIZABLE);
+        java.sql.Statement stmt = conn.createStatement();
+        ResultSet rs = stmt.executeQuery("SELECT * FROM ofFailover");
+
+        if (rs.next()) {
+          String nodeID = rs.getString("node");
+          Socket client = null;
+          
+          if (!nodeID.equals(localID)) {
+            try {
+              client = new Socket(nodeID, 5222);
+              Log.error("Server already running: " + nodeID);
+              throw new IllegalArgumentException("Server already running: " + nodeID);
+            } catch (IOException e) {
+              // the other node is unreachable on port 5222, so delete its lock
+              Statement crudStmt = conn.createStatement();
+              crudStmt.executeUpdate("DELETE FROM ofFailover");
+              crudStmt.executeUpdate("INSERT INTO ofFailover VALUES ('" + localID + "')");
+              Log.info("Server " + nodeID + " is down, registering this server: " + localID);
+            } finally {
+              if (client != null) {
+                try {
+                  client.close();
+                } catch (IOException e) {
+                  Log.error(e);
+                }
+              }
+            }
+          } else {
+            Log.info("This server already registered: " + nodeID);
+          }
+        } else {
+          Statement crudStmt = conn.createStatement();
+          crudStmt.executeUpdate("INSERT INTO ofFailover VALUES ('" + localID + "')");
+          Log.info("Registering this server: " + localID);
+        }
+
+        rs.close();
+        stmt.close();
+        conn.commit();
+        conn.setAutoCommit(false);
+      } catch (SQLException e) {
+        System.err.println("Database setup or configuration error: " +
+            "Please verify your database settings and check the " +
+          "logs/error.log file for detailed error messages.");
+        Log.error("Database could not be accessed", e);
+        throw new IllegalArgumentException(e);
+      }
+      finally {
+        if (conn != null) {
+          try {
+            conn.close();
+          }
+          catch (SQLException e) {
+            Log.error(e);
+          }
+        }
+      }
+    }
+
+    /**
      * Verifies that the given home guess is a real Openfire home directory.
      * We do the verification by checking for the Openfire config file in
      * the config dir of jiveHome.
