/**
* 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.aries.samples.ariestrader.persist.jdbc;
import java.util.Collection;
import java.util.Iterator;
import java.util.HashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.apache.aries.samples.ariestrader.util.*;
public class KeySequenceDirect {
private static HashMap keyMap = new HashMap();
public static synchronized Integer getNextID(Connection conn, String keyName, boolean inSession, boolean inGlobalTxn)
throws Exception {
Integer nextID = null;
// First verify we have allocated a block of keys
// for this key name
// Then verify the allocated block has not been depleted
// allocate a new block if necessary
if (keyMap.containsKey(keyName) == false)
allocNewBlock(conn, keyName, inSession, inGlobalTxn);
Collection block = (Collection) keyMap.get(keyName);
Iterator ids = block.iterator();
if (ids.hasNext() == false)
ids = allocNewBlock(conn, keyName, inSession, inGlobalTxn).iterator();
// get and return a new unique key
nextID = (Integer) ids.next();
if (Log.doTrace())
Log.trace("KeySequenceDirect:getNextID inSession(" + inSession + ") - return new PK ID for Entity type: "
+ keyName + " ID=" + nextID);
return nextID;
}
private static Collection allocNewBlock(Connection conn, String keyName, boolean inSession, boolean inGlobalTxn)
throws Exception {
try {
if (inGlobalTxn == false && !inSession)
conn.commit(); // commit any pending txns
PreparedStatement stmt = conn.prepareStatement(getKeyForUpdateSQL);
stmt.setString(1, keyName);
ResultSet rs = stmt.executeQuery();
if (!rs.next()) {
// No keys found for this name - create a new one
PreparedStatement stmt2 = conn.prepareStatement(createKeySQL);
int keyVal = 0;
stmt2.setString(1, keyName);
stmt2.setInt(2, keyVal);
stmt2.executeUpdate();
stmt2.close();
stmt.close();
stmt = conn.prepareStatement(getKeyForUpdateSQL);
stmt.setString(1, keyName);
rs = stmt.executeQuery();
rs.next();
}
int keyVal = rs.getInt("keyval");
stmt.close();
stmt = conn.prepareStatement(updateKeyValueSQL);
stmt.setInt(1, keyVal + TradeConfig.KEYBLOCKSIZE);
stmt.setString(2, keyName);
stmt.executeUpdate();
stmt.close();
Collection block = new KeyBlock(keyVal, keyVal + TradeConfig.KEYBLOCKSIZE - 1);
keyMap.put(keyName, block);
if (inGlobalTxn == false && !inSession)
conn.commit();
return block;
} catch (Exception e) {
String error =
"KeySequenceDirect:allocNewBlock - failure to allocate new block of keys for Entity type: " + keyName;
Log.error(e, error);
throw new Exception(error + e.toString());
}
}
private static final String getKeyForUpdateSQL = "select * from keygenejb kg where kg.keyname = ? for update";
private static final String createKeySQL =
"insert into keygenejb " + "( keyname, keyval ) " + "VALUES ( ? , ? )";
private static final String updateKeyValueSQL = "update keygenejb set keyval = ? " + "where keyname = ?";
}