KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > keygenerator > hilo > HiLoKeyGenerator


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.keygenerator.hilo;
23 import org.jboss.ejb.plugins.keygenerator.KeyGenerator;
24 import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
25 import org.jboss.logging.Logger;
26
27 import javax.sql.DataSource JavaDoc;
28 import javax.transaction.TransactionManager JavaDoc;
29 import javax.transaction.Transaction JavaDoc;
30 import javax.transaction.SystemException JavaDoc;
31 import java.sql.PreparedStatement JavaDoc;
32 import java.sql.Connection JavaDoc;
33 import java.sql.SQLException JavaDoc;
34 import java.sql.ResultSet JavaDoc;
35 /**
36  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
37  * @version <tt>$Revision: 45723 $</tt>
38  */

39 public class HiLoKeyGenerator
40    implements KeyGenerator
41 {
42    private static long highestHi = 0;
43
44    public static synchronized long getHighestHi()
45    {
46       return highestHi;
47    }
48
49    public static synchronized void setHighestHi(long highestHi)
50    {
51       HiLoKeyGenerator.highestHi = highestHi;
52    }
53
54    private final Logger log;
55    private final DataSource JavaDoc ds;
56    private final long blockSize;
57
58    private long hi;
59    private long lo;
60
61    private TransactionManager JavaDoc tm;
62    private String JavaDoc updateHiSql;
63    private String JavaDoc selectHiSql;
64
65    public HiLoKeyGenerator(
66       DataSource JavaDoc ds,
67       String JavaDoc tableName,
68       String JavaDoc sequenceColumn,
69       String JavaDoc sequenceName,
70       String JavaDoc idColumnName,
71       String JavaDoc selectHiSql,
72       long blockSize,
73       TransactionManager JavaDoc tm
74       )
75    {
76       this.ds = ds;
77       this.blockSize = blockSize;
78       this.tm = tm;
79       this.log = Logger.getLogger(getClass().getName() + "#" + tableName + "_" + sequenceName);
80
81       updateHiSql = "update " +
82          tableName +
83          " set " +
84          idColumnName +
85          "=?" +
86          " where " + sequenceColumn + "='" + sequenceName + "' and " +
87          idColumnName + "=?";
88
89       this.selectHiSql = selectHiSql;
90    }
91
92    public synchronized Object JavaDoc generateKey()
93    {
94       if(lo < hi)
95       {
96          ++lo;
97       }
98       else
99       {
100          Transaction JavaDoc curTx = null;
101          try
102          {
103             curTx = tm.suspend();
104          }
105          catch(SystemException JavaDoc e)
106          {
107             throw new IllegalStateException JavaDoc("Failed to suspend current transaction.");
108          }
109
110          try
111          {
112             tm.begin();
113          }
114          catch(Exception JavaDoc e)
115          {
116             throw new IllegalStateException JavaDoc("Failed to begin a new transaction.");
117          }
118
119          try
120          {
121             doGenerate();
122             tm.commit();
123          }
124          catch(SQLException JavaDoc e)
125          {
126             log.error("Failed to update table: " + e.getMessage(), e);
127
128             try
129             {
130                tm.rollback();
131             }
132             catch(SystemException JavaDoc e1)
133             {
134                log.error("Failed to rollback.", e1);
135             }
136
137             throw new IllegalStateException JavaDoc(e.getMessage());
138          }
139          catch(Exception JavaDoc e)
140          {
141             log.error("Failed to commit.", e);
142          }
143          finally
144          {
145             if(curTx != null)
146             {
147                try
148                {
149                   tm.resume(curTx);
150                }
151                catch(Exception JavaDoc e)
152                {
153                   throw new IllegalStateException JavaDoc("Failed to resume transaction: " + e.getMessage());
154                }
155             }
156          }
157       }
158
159       return new Long JavaDoc(lo);
160    }
161
162    private void doGenerate() throws SQLException JavaDoc
163    {
164       long curHi;
165       do
166       {
167          curHi = getCurrentHi();
168          lo = curHi + 1;
169          hi = curHi + blockSize;
170       }
171       while(!updateHi(curHi, hi));
172    }
173
174    private long getCurrentHi() throws SQLException JavaDoc
175    {
176       return selectHiSql != null ? selectHi() : getHighestHi();
177    }
178
179    private boolean updateHi(long curHi, long newHi) throws SQLException JavaDoc
180    {
181       if(selectHiSql == null)
182       {
183          setHighestHi(newHi);
184       }
185       return updateTable(curHi, newHi);
186    }
187
188    private long selectHi() throws SQLException JavaDoc
189    {
190       Connection JavaDoc con = null;
191       PreparedStatement JavaDoc selectHiSt = null;
192       ResultSet JavaDoc rs = null;
193
194       if(log.isTraceEnabled())
195       {
196          log.trace("Executing SQL: " + selectHiSql);
197       }
198
199       try
200       {
201          con = ds.getConnection();
202          selectHiSt = con.prepareStatement(selectHiSql);
203          rs = selectHiSt.executeQuery();
204          if(!rs.next())
205          {
206             throw new IllegalStateException JavaDoc("The sequence has not been initialized in the service start phase!");
207          }
208          return rs.getLong(1);
209       }
210       finally
211       {
212          JDBCUtil.safeClose(rs);
213          JDBCUtil.safeClose(selectHiSt);
214          JDBCUtil.safeClose(con);
215       }
216    }
217
218    private boolean updateTable(long curHi, long newHi) throws SQLException JavaDoc
219    {
220       Connection JavaDoc con = null;
221       PreparedStatement JavaDoc updateHi = null;
222
223       if(log.isTraceEnabled())
224       {
225          log.trace("Executing SQL: " + updateHiSql + ", [" + newHi + "," + curHi + "]");
226       }
227
228       try
229       {
230          con = ds.getConnection();
231          updateHi = con.prepareStatement(updateHiSql);
232          updateHi.setLong(1, newHi);
233          updateHi.setLong(2, curHi);
234          return updateHi.executeUpdate() == 1;
235       }
236       finally
237       {
238          JDBCUtil.safeClose(updateHi);
239          JDBCUtil.safeClose(con);
240       }
241    }
242 }
Popular Tags