KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > TransactionManager


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import org.hsqldb.lib.DoubleIntIndex;
35 import org.hsqldb.lib.HashMappedList;
36 import org.hsqldb.lib.HsqlArrayList;
37 import org.hsqldb.lib.LongKeyIntValueHashMap;
38
39 /**
40  * Manages rows involved in transactions
41  *
42  * @author fredt@users
43  * @version 1.8.0
44  * @since 1.8.0
45  */

46 public class TransactionManager {
47
48     LongKeyIntValueHashMap rowSessionMap;
49     boolean reWriteProtect;
50     Database database;
51
52     TransactionManager(Database db) {
53         database = db;
54         rowSessionMap = new LongKeyIntValueHashMap(true);
55     }
56
57     public void setReWriteProtection(boolean value) {
58         reWriteProtect = value;
59     }
60
61     void checkDelete(Session session, Row row) throws HsqlException {}
62
63     void checkDelete(Session session,
64                      HashMappedList rowSet) throws HsqlException {
65
66         if (!reWriteProtect) {
67             return;
68         }
69
70         int sessionid = session.getId();
71
72         for (int i = 0, size = rowSet.size(); i < size; i++) {
73             Row row = (Row) rowSet.getKey(i);
74             long rowid = row.getId();
75
76             if (rowSessionMap.get(rowid, sessionid) != sessionid) {
77                 throw Trace.error(Trace.INVALID_TRANSACTION_STATE_NO_SUBCLASS,
78                                   Trace.ITSNS_OVERWRITE);
79             }
80         }
81     }
82
83     void checkDelete(Session session,
84                      HsqlArrayList rowSet) throws HsqlException {
85
86         if (!reWriteProtect) {
87             return;
88         }
89
90         int sessionid = session.getId();
91
92         for (int i = 0, size = rowSet.size(); i < size; i++) {
93             Row row = (Row) rowSet.get(i);
94             long rowid = row.getId();
95
96             if (rowSessionMap.get(rowid, sessionid) != sessionid) {
97                 throw Trace.error(Trace.INVALID_TRANSACTION_STATE_NO_SUBCLASS,
98                                   Trace.ITSNS_OVERWRITE);
99             }
100         }
101     }
102
103     void commit(Session session) {
104
105         Object JavaDoc[] list = session.rowActionList.getArray();
106         int size = session.rowActionList.size();
107
108         for (int i = 0; i < size; i++) {
109             Transaction tx = (Transaction) list[i];
110             long rowid = tx.row.getId();
111
112             tx.commit(session);
113             rowSessionMap.remove(rowid);
114         }
115
116         session.rowActionList.clear();
117         session.savepoints.clear();
118     }
119
120     synchronized void rollback(Session session) {
121         rollbackTransactions(session, 0, false);
122         session.savepoints.clear();
123     }
124
125     void rollbackSavepoint(Session session,
126                            String JavaDoc name) throws HsqlException {
127
128         int index = session.savepoints.getIndex(name);
129
130         if (index < 0) {
131             throw Trace.error(Trace.SAVEPOINT_NOT_FOUND, name);
132         }
133
134         Integer JavaDoc oi = (Integer JavaDoc) session.savepoints.get(index);
135         int limit = oi.intValue();
136
137         rollbackTransactions(session, limit, false);
138
139         while (session.savepoints.size() > index) {
140             session.savepoints.remove(session.savepoints.size() - 1);
141         }
142     }
143
144     void rollbackTransactions(Session session, int limit, boolean log) {
145
146         Object JavaDoc[] list = session.rowActionList.getArray();
147         int size = session.rowActionList.size();
148
149         for (int i = size - 1; i >= limit; i--) {
150             Transaction tx = (Transaction) list[i];
151
152             tx.rollback(session, log);
153         }
154
155         for (int i = limit; i < size; i++) {
156             Transaction tx = (Transaction) list[i];
157             long rowid = tx.row.getId();
158
159             rowSessionMap.remove(rowid);
160         }
161
162         session.rowActionList.setSize(limit);
163     }
164
165     void addTransaction(Session session, Transaction transaction) {
166
167         if (reWriteProtect) {
168             rowSessionMap.put(transaction.row.getId(), session.getId());
169         }
170     }
171
172     private long globalActionTimestamp = 0;
173
174     /**
175      * gets the next timestamp for an action
176      */

177     long nextActionTimestamp() {
178
179         globalActionTimestamp++;
180
181         return globalActionTimestamp;
182     }
183
184     /**
185      * Return an array of all transactions sorted by System Change No.
186      */

187     Transaction[] getTransactionList() {
188
189         Session[] sessions = database.sessionManager.getAllSessions();
190         int[] tIndex = new int[sessions.length];
191         Transaction[] transactions;
192         int transactionCount = 0;
193
194         {
195             int actioncount = 0;
196
197             for (int i = 0; i < sessions.length; i++) {
198                 actioncount += sessions[i].getTransactionSize();
199             }
200
201             transactions = new Transaction[actioncount];
202         }
203
204         while (true) {
205             boolean found = false;
206             long minChangeNo = Long.MAX_VALUE;
207             int sessionIndex = 0;
208
209             // find the lowest available SCN across all sessions
210
for (int i = 0; i < sessions.length; i++) {
211                 int tSize = sessions[i].getTransactionSize();
212
213                 if (tIndex[i] < tSize) {
214                     Transaction current =
215                         (Transaction) sessions[i].rowActionList.get(
216                             tIndex[i]);
217
218                     if (current.SCN < minChangeNo) {
219                         minChangeNo = current.SCN;
220                         sessionIndex = i;
221                     }
222
223                     found = true;
224                 }
225             }
226
227             if (!found) {
228                 break;
229             }
230
231             HsqlArrayList currentList = sessions[sessionIndex].rowActionList;
232
233             for (; tIndex[sessionIndex] < currentList.size(); ) {
234                 Transaction current =
235                     (Transaction) currentList.get(tIndex[sessionIndex]);
236
237                 // if the next change no is in this session, continue adding
238
if (current.SCN == minChangeNo + 1) {
239                     minChangeNo++;
240                 }
241
242                 if (current.SCN == minChangeNo) {
243                     transactions[transactionCount++] = current;
244
245                     tIndex[sessionIndex]++;
246                 } else {
247                     break;
248                 }
249             }
250         }
251
252         return transactions;
253     }
254
255     /**
256      * Return a lookup of all transactions ids for cached tables.
257      */

258     public DoubleIntIndex getTransactionIDList() {
259
260         Session[] sessions = database.sessionManager.getAllSessions();
261         DoubleIntIndex lookup = new DoubleIntIndex(10, false);
262
263         lookup.setKeysSearchTarget();
264
265         for (int i = 0; i < sessions.length; i++) {
266             HsqlArrayList tlist = sessions[i].rowActionList;
267
268             for (int j = 0, size = tlist.size(); j < size; j++) {
269                 Transaction tx = (Transaction) tlist.get(j);
270
271                 if (tx.tTable.getTableType() == Table.CACHED_TABLE) {
272                     lookup.addUnique(tx.row.getPos(), 0);
273                 }
274             }
275         }
276
277         return lookup;
278     }
279
280     /**
281      * Convert row ID's for cached table rows in transactions
282      */

283     public void convertTransactionIDs(DoubleIntIndex lookup) {
284
285         Session[] sessions = database.sessionManager.getAllSessions();
286
287         for (int i = 0; i < sessions.length; i++) {
288             HsqlArrayList tlist = sessions[i].rowActionList;
289
290             for (int j = 0, size = tlist.size(); j < size; j++) {
291                 Transaction tx = (Transaction) tlist.get(j);
292
293                 if (tx.tTable.getTableType() == Table.CACHED_TABLE) {
294                     int pos = lookup.lookupFirstEqual(tx.row.getPos());
295
296                     tx.row.setPos(pos);
297                 }
298             }
299         }
300     }
301 }
302
Popular Tags