/** * * Copyright 2005 The Apache Software Foundation or its licensors, as applicable * * Licensed 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.geronimo.samples.daytrader.direct; 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.geronimo.samples.daytrader.util.*; import org.apache.geronimo.samples.daytrader.*; public class KeySequenceDirect { private static HashMap keyMap = new HashMap(); public static synchronized Integer getNextID(Connection conn, String keyName, 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, inGlobalTxn); Collection block = (Collection) keyMap.get(keyName); Iterator ids = block.iterator(); if ( ids.hasNext() == false ) ids = allocNewBlock(conn, keyName, inGlobalTxn).iterator(); //get and return a new unique key nextID = (Integer) ids.next(); if (Log.doTrace()) Log.trace("KeySequenceDirect:getNextID - return new PK ID for Entity type: " + keyName + " ID=" + nextID); return nextID; } private static Collection allocNewBlock(Connection conn, String keyName, boolean inGlobalTxn) throws Exception { try { if (inGlobalTxn == false) 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); int rowCount = 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); int rowCount = stmt.executeUpdate(); stmt.close(); Collection block = new KeyBlock(keyVal, keyVal+TradeConfig.KEYBLOCKSIZE-1); keyMap.put(keyName, block); if (inGlobalTxn == false) 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 = ?"; }