/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.karaf.main.lock;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* <p>This class is used to create the sql statements for the Karaf lock tables that are used
* for clustering of Karaf instances.</p>
*
* <p>It will generate sql statement to create two separate tables, a lock table and a lock id table:</p>
*
* <code>
* CREATE TABLE LOCK ( ID INTEGER DEFAULT 0, STATE INTEGER DEFAULT 0, LOCK_DELAY INTEGER DEFAULT 0 )
*
* CREATE TABLE LOCK_ID ( ID INTEGER DEFAULT 0 )
* </code>
*
*/
public class GenericStatements {
private final String lockTableName;
private final String lockIdTableName;
private final String clusterName;
/**
* This constructor is used to determine the name of the Karaf lock table, the Karaf lock id
* table and the name of the clustered instances.
*
* @param lockTableName The name of the karaf lock table.
* @param lockIdTableName The name of the karaf lock id table.
* @param clusterName the name of the cluster being used.
*/
public GenericStatements(String lockTableName, String lockIdTableName, String clusterName) {
this.lockTableName = lockTableName;
this.lockIdTableName = lockIdTableName;
this.clusterName = clusterName;
}
/**
* This method will return the name of the cluster that the instances are using to compete for the
* master lock.
*
* @return The cluster node name.
*/
public final String getNodeName() {
return this.clusterName;
}
/**
* This method will return the name of the Karaf lock table.
*
* @return The name of the Karaf lock table.
*/
public final String getLockTableName() {
return lockTableName;
}
/**
* This method will return the insert statement used to create a row in the Lock table and will
* generate the following sql statement.
*
* <code>
* INSERT INTO KARAF_LOCK (ID, STATE, LOCK_DELAY) VALUES (0, 0, 0)
* </code>
*
* @return The SQL insert statement.
*/
private String getLockTableInitialInsertStatement() {
return "INSERT INTO " + this.getLockTableName() + "(ID, STATE, LOCK_DELAY) VALUES (0, 0, 0)";
}
/**
* This will be called when trying to acquire the lock and will generate the following sql statement.
*
* <code>
* UPDATE KARAF_LOCK SET ID = ?, STATE = ?, LOCK_DELAY = ? WHERE ID = 0 OR ID = ?
* </code>
*
* You are then expected to assign the values associated with the sql statement.
*
* @param id The new ID.
* @param state The new lock state.
* @param lock_delay The new lock delay.
* @param curId The current ID.
* @return The SQL update statement.
*/
public String getLockUpdateIdStatement(int id, int state, int lock_delay, int curId) {
return String.format("UPDATE %s SET ID = %d, STATE = %d, LOCK_DELAY = %d WHERE ID = 0 OR ID = %d",
this.getLockTableName(), id, state, lock_delay, curId);
}
/**
* This will be called when trying to steal the lock and will generate the following sql statement.
*
* <code>
* UPDATE KARAF_LOCK SET ID = ?, STATE = ?, LOCK_DELAY = ? WHERE ( ID = 0 OR ID = ? ) AND STATE = ?
* </code>
*
* You are then responsible to assign the values of the different fields using standard JDBC statement
* calls.
*
* @param id The new ID.
* @param state The new lock state.
* @param lock_delay The new lock delay.
* @param curId The current ID.
* @param curState The current state.
* @return The SQL update statement.
*/
public String getLockUpdateIdStatementToStealLock(int id, int state, int lock_delay, int curId, int curState) {
return String.format("UPDATE %s SET ID = %d, STATE = %d, LOCK_DELAY = %d WHERE ( ID = 0 OR ID = %d ) AND STATE = %d",
this.getLockTableName(), id, state, lock_delay, curId, curState) ;
}
/**
* This method is called only when we are releasing the lock and will generate the following sql
* statement.
*
* UPDATE KARAF_LOCK SET ID = 0 WHERE ID = ?
*
* @param id The current ID.
* @return sql update statement
*/
public String getLockResetIdStatement(int id) {
return String.format("UPDATE %s SET ID = 0 WHERE ID = %d", this.getLockTableName(), id);
}
/**
* This will be called to determine the current master instance for the lock table and will
* generate the following sql statement.
*
* <code>
* SELECT ID, STATE, LOCK_DELAY FROM KARAF_LOCK
* </code>
*
* @return sql select statement
*/
public String getLockSelectStatement() {
return "SELECT ID, STATE, LOCK_DELAY FROM " + this.getLockTableName();
}
public int getIdFromLockSelectStatement(ResultSet rs) throws SQLException {
return rs.getInt(1);
}
public int getStateFromLockSelectStatement(ResultSet rs) throws SQLException {
return rs.getInt(2);
}
public int getLockDelayFromLockSelectStatement(ResultSet rs) throws SQLException {
return rs.getInt(3);
}
/**
* This method should only be called during the creation of the KARAF_LOCK table and will
* generate the following sql statement.
*
* <code>
* CREATE TABLE KARAF_LOCK (ID INTEGER DEFAULT 0, STATE INTEGER DEFAULT 0, LOCK_DELAY INTEGER DEFAULT 0)
* </code>
*
* @return The SQL create table statement.
*/
private String getLockTableCreateStatement() {
return "CREATE TABLE " + this.getLockTableName()
+ " ( ID INTEGER DEFAULT 0, STATE INTEGER DEFAULT 0 , LOCK_DELAY INTEGER DEFAULT 0 )";
}
/**
* This method will generate the create table sql statement to create the karaf id table and will
* generate the following sql statement.
*
* <code>
* CREATE TABLE KARAF_ID ( ID INTEGER DEFAULT 0 )
* </code>
*
* @return The SQL create table statement.
*/
private String getLockIdTableCreateStatement() {
return "CREATE TABLE " + this.getLockIdTableName()
+ " ( ID INTEGER DEFAULT 0 )";
}
/**
* This method will return the sql statement to retreive the id of the lock id table and will
* generate the following sql statement.
*
* <code>
* SELECT ID FROM KARAF_ID
* </code>
*
* @return The SQL select statement.
*/
public String getLockIdSelectStatement() {
return "SELECT ID FROM " + this.getLockIdTableName();
}
public int getIdFromLockIdSelectStatement(ResultSet rs) throws SQLException {
return rs.getInt(1);
}
/**
* This method will return the update statement for the lock id table and will generate the
* following sql statement.
*
* <code>
* UPDATE KARAF_ID SET ID = ? WHERE ID = ?
* </code>
*
* @param id The new ID.
* @param curId The current ID.
* @return The SQL update statement.
*/
public String getLockIdUpdateIdStatement(int id, int curId) {
return String.format("UPDATE %s SET ID = %d WHERE ID = %d", this.getLockIdTableName(), id, curId);
}
/**
* This method will return the name of the Karaf lock id table.
*
* @return The name of the Karaf lock id table.
*/
public final String getLockIdTableName() {
return lockIdTableName;
}
/**
* This method will return the required sql statements to initialize the lock database.
*
* @param moment The moment.
* @return The array of SQL statements.
*/
public String[] getLockCreateSchemaStatements(long moment) {
return new String[] {
getLockTableCreateStatement(),
getLockIdTableCreateStatement(),
getLockTableInitialInsertStatement(),
getLockIdTableInitialInsertStatement(),
};
}
/**
* This method will return the insert statement to insert a row in the lock id table and will
* generate the following sql statement.
*
* <code>
* INSERT INTO KARAF_ID (ID) VALUES (0)
* </code>
*
* @return The SQL insert statement.
*/
private String getLockIdTableInitialInsertStatement() {
return "INSERT INTO " + this.getLockIdTableName() + "(ID) VALUES (0)";
}
}