001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.samples.daytrader.direct; 018 019 import java.util.Collection; 020 import java.util.Iterator; 021 import java.util.HashMap; 022 023 import java.sql.Connection; 024 import java.sql.PreparedStatement; 025 import java.sql.ResultSet; 026 027 import org.apache.geronimo.samples.daytrader.util.*; 028 029 import org.apache.geronimo.samples.daytrader.*; 030 031 public class KeySequenceDirect { 032 033 private static HashMap keyMap = new HashMap(); 034 035 public static synchronized Integer getNextID(Connection conn, String keyName, boolean inSession, boolean inGlobalTxn) 036 throws Exception 037 { 038 Integer nextID = null; 039 // First verify we have allocated a block of keys 040 // for this key name 041 // Then verify the allocated block has not been depleted 042 // allocate a new block if necessary 043 if ( keyMap.containsKey(keyName) == false) 044 allocNewBlock(conn, keyName, inSession, inGlobalTxn); 045 Collection block = (Collection) keyMap.get(keyName); 046 047 Iterator ids = block.iterator(); 048 if ( ids.hasNext() == false ) 049 ids = allocNewBlock(conn, keyName, inSession, inGlobalTxn).iterator(); 050 //get and return a new unique key 051 nextID = (Integer) ids.next(); 052 053 if (Log.doTrace()) Log.trace("KeySequenceDirect:getNextID inSession(" + inSession + ") - return new PK ID for Entity type: " + keyName + " ID=" + nextID); 054 return nextID; 055 } 056 057 private static Collection allocNewBlock(Connection conn, String keyName, boolean inSession, boolean inGlobalTxn) 058 throws Exception 059 { 060 try 061 { 062 if (inGlobalTxn == false && !inSession) conn.commit(); // commit any pending txns 063 PreparedStatement stmt = conn.prepareStatement(getKeyForUpdateSQL); 064 stmt.setString(1, keyName); 065 ResultSet rs = stmt.executeQuery(); 066 if (!rs.next()) 067 { 068 // No keys found for this name - create a new one 069 PreparedStatement stmt2 = conn.prepareStatement(createKeySQL); 070 int keyVal = 0; 071 stmt2.setString(1, keyName); 072 stmt2.setInt(2, keyVal); 073 int rowCount = stmt2.executeUpdate(); 074 stmt2.close(); 075 stmt.close(); 076 stmt = conn.prepareStatement(getKeyForUpdateSQL); 077 stmt.setString(1, keyName); 078 rs = stmt.executeQuery(); 079 rs.next(); 080 } 081 082 int keyVal = rs.getInt("keyval"); 083 084 stmt.close(); 085 086 stmt = conn.prepareStatement(updateKeyValueSQL); 087 stmt.setInt(1, keyVal+TradeConfig.KEYBLOCKSIZE); 088 stmt.setString(2, keyName); 089 int rowCount = stmt.executeUpdate(); 090 stmt.close(); 091 092 Collection block = new KeyBlock(keyVal, keyVal+TradeConfig.KEYBLOCKSIZE-1); 093 keyMap.put(keyName, block); 094 if (inGlobalTxn == false && !inSession) conn.commit(); 095 return block; 096 } 097 catch (Exception e) 098 { 099 String error = "KeySequenceDirect:allocNewBlock - failure to allocate new block of keys for Entity type: "+ keyName; 100 Log.error(e, error); 101 throw new Exception(error + e.toString()); 102 } 103 } 104 105 private static final String getKeyForUpdateSQL = 106 "select * from keygenejb kg where kg.keyname = ? for update"; 107 108 private static final String createKeySQL = 109 "insert into keygenejb " + 110 "( keyname, keyval ) " + 111 "VALUES ( ? , ? )"; 112 113 private static final String updateKeyValueSQL = 114 "update keygenejb set keyval = ? " + 115 "where keyname = ?"; 116 117 } 118