Source Code Cross Referenced for TransactionManager.java in  » Database-DBMS » JDBM » jdbm » recman » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » JDBM » jdbm.recman 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * JDBM LICENSE v1.00
003:         *
004:         * Redistribution and use of this software and associated documentation
005:         * ("Software"), with or without modification, are permitted provided
006:         * that the following conditions are met:
007:         *
008:         * 1. Redistributions of source code must retain copyright
009:         *    statements and notices.  Redistributions must also contain a
010:         *    copy of this document.
011:         *
012:         * 2. Redistributions in binary form must reproduce the
013:         *    above copyright notice, this list of conditions and the
014:         *    following disclaimer in the documentation and/or other
015:         *    materials provided with the distribution.
016:         *
017:         * 3. The name "JDBM" must not be used to endorse or promote
018:         *    products derived from this Software without prior written
019:         *    permission of Cees de Groot.  For written permission,
020:         *    please contact cg@cdegroot.com.
021:         *
022:         * 4. Products derived from this Software may not be called "JDBM"
023:         *    nor may "JDBM" appear in their names without prior written
024:         *    permission of Cees de Groot.
025:         *
026:         * 5. Due credit should be given to the JDBM Project
027:         *    (http://jdbm.sourceforge.net/).
028:         *
029:         * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS
030:         * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
031:         * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
032:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
033:         * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
034:         * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
035:         * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
036:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
037:         * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
038:         * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
039:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
040:         * OF THE POSSIBILITY OF SUCH DAMAGE.
041:         *
042:         * Copyright 2000 (C) Cees de Groot. All Rights Reserved.
043:         * Contributions are Copyright (C) 2000 by their associated contributors.
044:         *
045:         * $Id: TransactionManager.java,v 1.7 2005/06/25 23:12:32 doomdark Exp $
046:         */package jdbm.recman;
047:
048:        import java.io.*;
049:        import java.util.*;
050:
051:        /**
052:         *  This class manages the transaction log that belongs to every
053:         *  {@link RecordFile}. The transaction log is either clean, or
054:         *  in progress. In the latter case, the transaction manager
055:         *  takes care of a roll forward.
056:         *<p>
057:         *  Implementation note: this is a proof-of-concept implementation
058:         *  which hasn't been optimized for speed. For instance, all sorts
059:         *  of streams are created for every transaction.
060:         */
061:        // TODO: Handle the case where we are recovering lg9 and lg0, were we
062:        // should start with lg9 instead of lg0!
063:        public final class TransactionManager {
064:            private RecordFile owner;
065:
066:            // streams for transaction log.
067:            private FileOutputStream fos;
068:            private ObjectOutputStream oos;
069:
070:            /** 
071:             * By default, we keep 10 transactions in the log file before
072:             * synchronizing it with the main database file.
073:             */
074:            static final int DEFAULT_TXNS_IN_LOG = 10;
075:
076:            /** 
077:             * Maximum number of transactions before the log file is
078:             * synchronized with the main database file.
079:             */
080:            private int _maxTxns = DEFAULT_TXNS_IN_LOG;
081:
082:            /**
083:             * In-core copy of transactions. We could read everything back from
084:             * the log file, but the RecordFile needs to keep the dirty blocks in
085:             * core anyway, so we might as well point to them and spare us a lot
086:             * of hassle.
087:             */
088:            private ArrayList[] txns = new ArrayList[DEFAULT_TXNS_IN_LOG];
089:            private int curTxn = -1;
090:
091:            /** Extension of a log file. */
092:            static final String extension = ".lg";
093:
094:            /**
095:             *  Instantiates a transaction manager instance. If recovery
096:             *  needs to be performed, it is done.
097:             *
098:             *  @param owner the RecordFile instance that owns this transaction mgr.
099:             */
100:            TransactionManager(RecordFile owner) throws IOException {
101:                this .owner = owner;
102:                recover();
103:                open();
104:            }
105:
106:            /**
107:             * Synchronize log file data with the main database file.
108:             * <p>
109:             * After this call, the main database file is guaranteed to be 
110:             * consistent and guaranteed to be the only file needed for 
111:             * backup purposes.
112:             */
113:            public void synchronizeLog() throws IOException {
114:                synchronizeLogFromMemory();
115:            }
116:
117:            /**
118:             * Set the maximum number of transactions to record in
119:             * the log (and keep in memory) before the log is
120:             * synchronized with the main database file.
121:             * <p>
122:             * This method must be called while there are no
123:             * pending transactions in the log.
124:             */
125:            public void setMaximumTransactionsInLog(int maxTxns)
126:                    throws IOException {
127:                if (maxTxns <= 0) {
128:                    throw new IllegalArgumentException(
129:                            "Argument 'maxTxns' must be greater than 0.");
130:                }
131:                if (curTxn != -1) {
132:                    throw new IllegalStateException(
133:                            "Cannot change setting while transactions are pending in the log");
134:                }
135:                _maxTxns = maxTxns;
136:                txns = new ArrayList[maxTxns];
137:            }
138:
139:            /** Builds logfile name  */
140:            private String makeLogName() {
141:                return owner.getFileName() + extension;
142:            }
143:
144:            /** Synchs in-core transactions to data file and opens a fresh log */
145:            private void synchronizeLogFromMemory() throws IOException {
146:                close();
147:
148:                TreeSet blockList = new TreeSet(new BlockIoComparator());
149:
150:                int numBlocks = 0;
151:                int writtenBlocks = 0;
152:                for (int i = 0; i < _maxTxns; i++) {
153:                    if (txns[i] == null)
154:                        continue;
155:                    // Add each block to the blockList, replacing the old copy of this
156:                    // block if necessary, thus avoiding writing the same block twice
157:                    for (Iterator k = txns[i].iterator(); k.hasNext();) {
158:                        BlockIo block = (BlockIo) k.next();
159:                        if (blockList.contains(block)) {
160:                            block.decrementTransactionCount();
161:                        } else {
162:                            writtenBlocks++;
163:                            boolean result = blockList.add(block);
164:                        }
165:                        numBlocks++;
166:                    }
167:
168:                    txns[i] = null;
169:                }
170:                // Write the blocks from the blockList to disk
171:                synchronizeBlocks(blockList.iterator(), true);
172:
173:                owner.sync();
174:                open();
175:            }
176:
177:            /** Opens the log file */
178:            private void open() throws IOException {
179:                fos = new FileOutputStream(makeLogName());
180:                oos = new ObjectOutputStream(fos);
181:                oos.writeShort(Magic.LOGFILE_HEADER);
182:                oos.flush();
183:                curTxn = -1;
184:            }
185:
186:            /** Startup recovery on all files */
187:            private void recover() throws IOException {
188:                String logName = makeLogName();
189:                File logFile = new File(logName);
190:                if (!logFile.exists())
191:                    return;
192:                if (logFile.length() == 0) {
193:                    logFile.delete();
194:                    return;
195:                }
196:
197:                FileInputStream fis = new FileInputStream(logFile);
198:                ObjectInputStream ois = new ObjectInputStream(fis);
199:
200:                try {
201:                    if (ois.readShort() != Magic.LOGFILE_HEADER)
202:                        throw new Error("Bad magic on log file");
203:                } catch (IOException e) {
204:                    // corrupted/empty logfile
205:                    logFile.delete();
206:                    return;
207:                }
208:
209:                while (true) {
210:                    ArrayList blocks = null;
211:                    try {
212:                        blocks = (ArrayList) ois.readObject();
213:                    } catch (ClassNotFoundException e) {
214:                        throw new Error("Unexcepted exception: " + e);
215:                    } catch (IOException e) {
216:                        // corrupted logfile, ignore rest of transactions
217:                        break;
218:                    }
219:                    synchronizeBlocks(blocks.iterator(), false);
220:
221:                    // ObjectInputStream must match exactly each
222:                    // ObjectOutputStream created during writes
223:                    try {
224:                        ois = new ObjectInputStream(fis);
225:                    } catch (IOException e) {
226:                        // corrupted logfile, ignore rest of transactions
227:                        break;
228:                    }
229:                }
230:                owner.sync();
231:                logFile.delete();
232:            }
233:
234:            /** Synchronizes the indicated blocks with the owner. */
235:            private void synchronizeBlocks(Iterator blockIterator,
236:                    boolean fromCore) throws IOException {
237:                // write block vector elements to the data file.
238:                while (blockIterator.hasNext()) {
239:                    BlockIo cur = (BlockIo) blockIterator.next();
240:                    owner.synch(cur);
241:                    if (fromCore) {
242:                        cur.decrementTransactionCount();
243:                        if (!cur.isInTransaction()) {
244:                            owner.releaseFromTransaction(cur, true);
245:                        }
246:                    }
247:                }
248:            }
249:
250:            /** Set clean flag on the blocks. */
251:            private void setClean(ArrayList blocks) throws IOException {
252:                for (Iterator k = blocks.iterator(); k.hasNext();) {
253:                    BlockIo cur = (BlockIo) k.next();
254:                    cur.setClean();
255:                }
256:            }
257:
258:            /** Discards the indicated blocks and notify the owner. */
259:            private void discardBlocks(ArrayList blocks) throws IOException {
260:                for (Iterator k = blocks.iterator(); k.hasNext();) {
261:                    BlockIo cur = (BlockIo) k.next();
262:                    cur.decrementTransactionCount();
263:                    if (!cur.isInTransaction()) {
264:                        owner.releaseFromTransaction(cur, false);
265:                    }
266:                }
267:            }
268:
269:            /**
270:             *  Starts a transaction. This can block if all slots have been filled
271:             *  with full transactions, waiting for the synchronization thread to
272:             *  clean out slots.
273:             */
274:            void start() throws IOException {
275:                curTxn++;
276:                if (curTxn == _maxTxns) {
277:                    synchronizeLogFromMemory();
278:                    curTxn = 0;
279:                }
280:                txns[curTxn] = new ArrayList();
281:            }
282:
283:            /**
284:             *  Indicates the block is part of the transaction.
285:             */
286:            void add(BlockIo block) throws IOException {
287:                block.incrementTransactionCount();
288:                txns[curTxn].add(block);
289:            }
290:
291:            /**
292:             *  Commits the transaction to the log file.
293:             */
294:            void commit() throws IOException {
295:                oos.writeObject(txns[curTxn]);
296:                sync();
297:
298:                // set clean flag to indicate blocks have been written to log
299:                setClean(txns[curTxn]);
300:
301:                // open a new ObjectOutputStream in order to store
302:                // newer states of BlockIo
303:                oos = new ObjectOutputStream(fos);
304:            }
305:
306:            /** Flushes and syncs */
307:            private void sync() throws IOException {
308:                oos.flush();
309:                fos.flush();
310:                fos.getFD().sync();
311:            }
312:
313:            /**
314:             *  Shutdowns the transaction manager. Resynchronizes outstanding
315:             *  logs.
316:             */
317:            void shutdown() throws IOException {
318:                synchronizeLogFromMemory();
319:                close();
320:            }
321:
322:            /**
323:             *  Closes open files.
324:             */
325:            private void close() throws IOException {
326:                sync();
327:                oos.close();
328:                fos.close();
329:                oos = null;
330:                fos = null;
331:            }
332:
333:            /**
334:             * Force closing the file without synchronizing pending transaction data.
335:             * Used for testing purposes only.
336:             */
337:            void forceClose() throws IOException {
338:                oos.close();
339:                fos.close();
340:                oos = null;
341:                fos = null;
342:            }
343:
344:            /**
345:             * Use the disk-based transaction log to synchronize the data file.
346:             * Outstanding memory logs are discarded because they are believed
347:             * to be inconsistent.
348:             */
349:            void synchronizeLogFromDisk() throws IOException {
350:                close();
351:
352:                for (int i = 0; i < _maxTxns; i++) {
353:                    if (txns[i] == null)
354:                        continue;
355:                    discardBlocks(txns[i]);
356:                    txns[i] = null;
357:                }
358:
359:                recover();
360:                open();
361:            }
362:
363:            /** INNER CLASS.
364:             *  Comparator class for use by the tree set used to store the blocks
365:             *  to write for this transaction.  The BlockIo objects are ordered by
366:             *  their blockIds.
367:             */
368:            public static class BlockIoComparator implements  Comparator {
369:
370:                public int compare(Object o1, Object o2) {
371:                    BlockIo block1 = (BlockIo) o1;
372:                    BlockIo block2 = (BlockIo) o2;
373:                    int result = 0;
374:                    if (block1.getBlockId() == block2.getBlockId()) {
375:                        result = 0;
376:                    } else if (block1.getBlockId() < block2.getBlockId()) {
377:                        result = -1;
378:                    } else {
379:                        result = 1;
380:                    }
381:                    return result;
382:                }
383:
384:                public boolean equals(Object obj) {
385:                    return super .equals(obj);
386:                }
387:            } // class BlockIOComparator
388:
389:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.