Source Code Cross Referenced for LogSystem.java in  » Database-DBMS » h2database » org » h2 » log » 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 » h2database » org.h2.log 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003:         * (http://h2database.com/html/license.html).
004:         * Initial Developer: H2 Group
005:         */
006:        package org.h2.log;
007:
008:        import java.sql.SQLException;
009:        import java.util.Comparator;
010:        import java.util.HashMap;
011:
012:        import org.h2.api.DatabaseEventListener;
013:        import org.h2.engine.Constants;
014:        import org.h2.engine.Database;
015:        import org.h2.engine.Session;
016:        import org.h2.message.Trace;
017:        import org.h2.store.DataPage;
018:        import org.h2.store.DiskFile;
019:        import org.h2.store.Record;
020:        import org.h2.store.Storage;
021:        import org.h2.util.FileUtils;
022:        import org.h2.util.ObjectArray;
023:        import org.h2.util.ObjectUtils;
024:
025:        /**
026:         * The transaction log system is responsible for the write ahead log mechanism
027:         * used in this database. A number of {@link LogFile} objects are used (one for
028:         * each file).
029:         */
030:        public class LogSystem {
031:
032:            public static final int LOG_WRITTEN = -1;
033:
034:            private Database database;
035:            private ObjectArray activeLogs;
036:            private LogFile currentLog;
037:            private String fileNamePrefix;
038:            private HashMap storages = new HashMap();
039:            private HashMap sessions = new HashMap();
040:            private DataPage rowBuff;
041:            private ObjectArray undo;
042:            // TODO log file / deleteOldLogFilesAutomatically: 
043:            // make this a setting, so they can be backed up
044:            private boolean deleteOldLogFilesAutomatically = true;
045:            private long maxLogSize = Constants.DEFAULT_MAX_LOG_SIZE;
046:            private boolean readOnly;
047:            private boolean flushOnEachCommit;
048:            private ObjectArray inDoubtTransactions;
049:            private boolean disabled;
050:            private int keepFiles;
051:            private boolean closed;
052:            private String accessMode;
053:
054:            public LogSystem(Database database, String fileNamePrefix,
055:                    boolean readOnly, String accessMode) throws SQLException {
056:                this .database = database;
057:                this .readOnly = readOnly;
058:                this .accessMode = accessMode;
059:                closed = true;
060:                if (database == null) {
061:                    return;
062:                }
063:                this .fileNamePrefix = fileNamePrefix;
064:                rowBuff = DataPage.create(database,
065:                        Constants.DEFAULT_DATA_PAGE_SIZE);
066:            }
067:
068:            public void setMaxLogSize(long maxSize) {
069:                this .maxLogSize = maxSize;
070:            }
071:
072:            public long getMaxLogSize() {
073:                return maxLogSize;
074:            }
075:
076:            public boolean containsInDoubtTransactions() {
077:                return inDoubtTransactions != null
078:                        && inDoubtTransactions.size() > 0;
079:            }
080:
081:            private void flushAndCloseUnused() throws SQLException {
082:                currentLog.flush();
083:                DiskFile file = database.getDataFile();
084:                if (file == null) {
085:                    return;
086:                }
087:                file.flush();
088:                if (containsInDoubtTransactions()) {
089:                    // if there are any in-doubt transactions 
090:                    // (even if they are resolved), can't update or delete the log files
091:                    return;
092:                }
093:                Session[] sessions = database.getSessions();
094:                int firstUncommittedLog = currentLog.getId();
095:                int firstUncommittedPos = currentLog.getPos();
096:                for (int i = 0; i < sessions.length; i++) {
097:                    Session session = sessions[i];
098:                    int log = session.getFirstUncommittedLog();
099:                    int pos = session.getFirstUncommittedPos();
100:                    if (pos != LOG_WRITTEN) {
101:                        if (log < firstUncommittedLog
102:                                || (log == firstUncommittedLog && pos < firstUncommittedPos)) {
103:                            firstUncommittedLog = log;
104:                            firstUncommittedPos = pos;
105:                        }
106:                    }
107:                }
108:                for (int i = activeLogs.size() - 1; i >= 0; i--) {
109:                    LogFile l = (LogFile) activeLogs.get(i);
110:                    if (l.getId() < firstUncommittedLog) {
111:                        l.setFirstUncommittedPos(LOG_WRITTEN);
112:                    } else if (l.getId() == firstUncommittedLog) {
113:                        if (firstUncommittedPos == l.getPos()) {
114:                            l.setFirstUncommittedPos(LOG_WRITTEN);
115:                        } else {
116:                            l.setFirstUncommittedPos(firstUncommittedPos);
117:                        }
118:                    }
119:                }
120:                for (int i = 0; i < activeLogs.size(); i++) {
121:                    LogFile l = (LogFile) activeLogs.get(i);
122:                    if (l.getFirstUncommittedPos() == LOG_WRITTEN) {
123:                        // must remove the log file first
124:                        // if we don't do that, the file is closed but still in the list
125:                        activeLogs.remove(i);
126:                        i--;
127:                        closeOldFile(l);
128:                    }
129:                }
130:            }
131:
132:            public void close() throws SQLException {
133:                if (database == null) {
134:                    return;
135:                }
136:                synchronized (database) {
137:                    if (closed) {
138:                        return;
139:                    }
140:                    if (readOnly) {
141:                        for (int i = 0; i < activeLogs.size(); i++) {
142:                            LogFile l = (LogFile) activeLogs.get(i);
143:                            l.close(false);
144:                        }
145:                        closed = true;
146:                        return;
147:                    }
148:                    // TODO refactor flushing and closing files when we know what to do exactly
149:                    SQLException closeException = null;
150:                    try {
151:                        flushAndCloseUnused();
152:                        if (!containsInDoubtTransactions()) {
153:                            checkpoint();
154:                        }
155:                    } catch (SQLException e) {
156:                        closeException = e;
157:                    }
158:                    for (int i = 0; i < activeLogs.size(); i++) {
159:                        LogFile l = (LogFile) activeLogs.get(i);
160:                        try {
161:                            // if there are any in-doubt transactions 
162:                            // (even if they are resolved), can't delete the log files
163:                            if (l.getFirstUncommittedPos() == LOG_WRITTEN
164:                                    && !containsInDoubtTransactions()) {
165:                                closeOldFile(l);
166:                            } else {
167:                                l.close(false);
168:                            }
169:                        } catch (SQLException e) {
170:                            // TODO log exception
171:                            if (closeException == null) {
172:                                closeException = e;
173:                            }
174:                        }
175:                    }
176:                    closed = true;
177:                    if (closeException != null) {
178:                        throw closeException;
179:                    }
180:                }
181:            }
182:
183:            void addUndoLogRecord(LogFile log, int logRecordId, int sessionId) {
184:                getOrAddSessionState(sessionId);
185:                LogRecord record = new LogRecord(log, logRecordId, sessionId);
186:                undo.add(record);
187:            }
188:
189:            public boolean recover() throws SQLException {
190:                if (database == null) {
191:                    return false;
192:                }
193:                synchronized (database) {
194:                    if (closed) {
195:                        return false;
196:                    }
197:                    undo = new ObjectArray();
198:                    for (int i = 0; i < activeLogs.size(); i++) {
199:                        LogFile log = (LogFile) activeLogs.get(i);
200:                        log.redoAllGoEnd();
201:                    }
202:                    database.getDataFile().flushRedoLog();
203:                    database.getIndexFile().flushRedoLog();
204:                    int end = currentLog.getPos();
205:                    Object[] states = sessions.values().toArray();
206:                    inDoubtTransactions = new ObjectArray();
207:                    for (int i = 0; i < states.length; i++) {
208:                        SessionState state = (SessionState) states[i];
209:                        if (state.inDoubtTransaction != null) {
210:                            inDoubtTransactions.add(state.inDoubtTransaction);
211:                        }
212:                    }
213:                    for (int i = undo.size() - 1; i >= 0 && sessions.size() > 0; i--) {
214:                        database.setProgress(
215:                                DatabaseEventListener.STATE_RECOVER, null, undo
216:                                        .size()
217:                                        - 1 - i, undo.size());
218:                        LogRecord record = (LogRecord) undo.get(i);
219:                        if (sessions.get(ObjectUtils
220:                                .getInteger(record.sessionId)) != null) {
221:                            // undo only if the session is not yet committed
222:                            record.log.undo(record.logRecordId);
223:                            database.getDataFile().flushRedoLog();
224:                            database.getIndexFile().flushRedoLog();
225:                        }
226:                    }
227:                    currentLog.go(end);
228:                    boolean fileChanged = undo.size() > 0;
229:                    undo = null;
230:                    storages.clear();
231:                    if (!readOnly && fileChanged
232:                            && !containsInDoubtTransactions()) {
233:                        checkpoint();
234:                    }
235:                    return fileChanged;
236:                }
237:            }
238:
239:            private void closeOldFile(LogFile l) throws SQLException {
240:                l.close(deleteOldLogFilesAutomatically && keepFiles == 0);
241:            }
242:
243:            public void open() throws SQLException {
244:                String path = FileUtils.getParent(fileNamePrefix);
245:                String[] list = FileUtils.listFiles(path);
246:                activeLogs = new ObjectArray();
247:                for (int i = 0; i < list.length; i++) {
248:                    String s = list[i];
249:                    LogFile l = null;
250:                    try {
251:                        l = LogFile.openIfLogFile(this , fileNamePrefix, s);
252:                    } catch (SQLException e) {
253:                        database.getTrace(Trace.LOG).debug(
254:                                "Error opening log file, header corrupt: " + s,
255:                                e);
256:                        // this can happen if the system crashes just 
257:                        // after creating a new file (before writing the header)
258:                        // rename it, so that it doesn't get in the way the next time
259:                        FileUtils.delete(s + ".corrupt");
260:                        FileUtils.rename(s, s + ".corrupt");
261:                    }
262:                    if (l != null) {
263:                        if (l.getPos() == LOG_WRITTEN) {
264:                            closeOldFile(l);
265:                        } else {
266:                            activeLogs.add(l);
267:                        }
268:                    }
269:                }
270:                activeLogs.sort(new Comparator() {
271:                    public int compare(Object a, Object b) {
272:                        return ((LogFile) a).getId() - ((LogFile) b).getId();
273:                    }
274:                });
275:                if (activeLogs.size() == 0) {
276:                    LogFile l = new LogFile(this , 0, fileNamePrefix);
277:                    activeLogs.add(l);
278:                }
279:                currentLog = (LogFile) activeLogs.get(activeLogs.size() - 1);
280:                closed = false;
281:            }
282:
283:            Storage getStorageForRecovery(int id) throws SQLException {
284:                boolean dataFile;
285:                if (id < 0) {
286:                    dataFile = false;
287:                    id = -id;
288:                } else {
289:                    dataFile = true;
290:                }
291:                Integer i = ObjectUtils.getInteger(id);
292:                Storage storage = (Storage) storages.get(i);
293:                if (storage == null) {
294:                    storage = database.getStorage(null, id, dataFile);
295:                    storages.put(i, storage);
296:                }
297:                return storage;
298:            }
299:
300:            boolean isSessionCommitted(int sessionId, int logId, int pos) {
301:                Integer key = ObjectUtils.getInteger(sessionId);
302:                SessionState state = (SessionState) sessions.get(key);
303:                if (state == null) {
304:                    return true;
305:                }
306:                return state.isCommitted(logId, pos);
307:            }
308:
309:            void setLastCommitForSession(int sessionId, int logId, int pos) {
310:                SessionState state = getOrAddSessionState(sessionId);
311:                state.lastCommitLog = logId;
312:                state.lastCommitPos = pos;
313:                state.inDoubtTransaction = null;
314:            }
315:
316:            SessionState getOrAddSessionState(int sessionId) {
317:                Integer key = ObjectUtils.getInteger(sessionId);
318:                SessionState state = (SessionState) sessions.get(key);
319:                if (state == null) {
320:                    state = new SessionState();
321:                    sessions.put(key, state);
322:                    state.sessionId = sessionId;
323:                }
324:                return state;
325:            }
326:
327:            void setPreparedCommitForSession(LogFile log, int sessionId,
328:                    int pos, String transaction, int blocks) {
329:                SessionState state = getOrAddSessionState(sessionId);
330:                // this is potentially a commit, so 
331:                // don't roll back the action before it (currently)
332:                setLastCommitForSession(sessionId, log.getId(), pos);
333:                state.inDoubtTransaction = new InDoubtTransaction(log,
334:                        sessionId, pos, transaction, blocks);
335:            }
336:
337:            public ObjectArray getInDoubtTransactions() {
338:                return inDoubtTransactions;
339:            }
340:
341:            void removeSession(int sessionId) {
342:                sessions.remove(ObjectUtils.getInteger(sessionId));
343:            }
344:
345:            public void prepareCommit(Session session, String transaction)
346:                    throws SQLException {
347:                if (database == null || readOnly) {
348:                    return;
349:                }
350:                synchronized (database) {
351:                    if (closed) {
352:                        return;
353:                    }
354:                    currentLog.prepareCommit(session, transaction);
355:                }
356:            }
357:
358:            public void commit(Session session) throws SQLException {
359:                if (database == null || readOnly) {
360:                    return;
361:                }
362:                synchronized (database) {
363:                    if (closed) {
364:                        return;
365:                    }
366:                    currentLog.commit(session);
367:                    session.setAllCommitted();
368:                }
369:            }
370:
371:            public void flush() throws SQLException {
372:                if (database == null || readOnly) {
373:                    return;
374:                }
375:                synchronized (database) {
376:                    if (closed) {
377:                        return;
378:                    }
379:                    currentLog.flush();
380:                }
381:            }
382:
383:            /**
384:             * Add a truncate entry.
385:             * 
386:             * @param session the session
387:             * @param file the disk file
388:             * @param storageId the storage id
389:             * @param recordId the id of the first record
390:             * @param blockCount the number of blocks
391:             */
392:            public void addTruncate(Session session, DiskFile file,
393:                    int storageId, int recordId, int blockCount)
394:                    throws SQLException {
395:                if (database == null) {
396:                    return;
397:                }
398:                synchronized (database) {
399:                    if (disabled || closed) {
400:                        return;
401:                    }
402:                    database.checkWritingAllowed();
403:                    if (!file.isDataFile()) {
404:                        storageId = -storageId;
405:                    }
406:                    currentLog.addTruncate(session, storageId, recordId,
407:                            blockCount);
408:                    if (currentLog.getFileSize() > maxLogSize) {
409:                        checkpoint();
410:                    }
411:                }
412:            }
413:
414:            public void add(Session session, DiskFile file, Record record)
415:                    throws SQLException {
416:                if (database == null) {
417:                    return;
418:                }
419:                synchronized (database) {
420:                    if (disabled || closed) {
421:                        return;
422:                    }
423:                    database.checkWritingAllowed();
424:                    int storageId = record.getStorageId();
425:                    if (!file.isDataFile()) {
426:                        storageId = -storageId;
427:                    }
428:                    int log = currentLog.getId();
429:                    int pos = currentLog.getPos();
430:                    session.addLogPos(log, pos);
431:                    record.setLastLog(log, pos);
432:                    currentLog.add(session, storageId, record);
433:                    if (currentLog.getFileSize() > maxLogSize) {
434:                        checkpoint();
435:                    }
436:                }
437:            }
438:
439:            public void checkpoint() throws SQLException {
440:                if (readOnly || database == null) {
441:                    return;
442:                }
443:                synchronized (database) {
444:                    if (closed || disabled) {
445:                        return;
446:                    }
447:                    flushAndCloseUnused();
448:                    currentLog = new LogFile(this , currentLog.getId() + 1,
449:                            fileNamePrefix);
450:                    activeLogs.add(currentLog);
451:                    writeSummary();
452:                    currentLog.flush();
453:                }
454:            }
455:
456:            public ObjectArray getActiveLogFiles() {
457:                synchronized (database) {
458:                    ObjectArray list = new ObjectArray();
459:                    list.addAll(activeLogs);
460:                    return list;
461:                }
462:            }
463:
464:            private void writeSummary() throws SQLException {
465:                byte[] summary;
466:                DiskFile file;
467:                file = database.getDataFile();
468:                if (file == null) {
469:                    return;
470:                }
471:                summary = file.getSummary();
472:                if (summary != null) {
473:                    currentLog.addSummary(true, summary);
474:                }
475:                if (database.getLogIndexChanges()
476:                        || database.getIndexSummaryValid()) {
477:                    file = database.getIndexFile();
478:                    summary = file.getSummary();
479:                    if (summary != null) {
480:                        currentLog.addSummary(false, summary);
481:                    }
482:                } else {
483:                    // invalidate the index summary
484:                    currentLog.addSummary(false, null);
485:                }
486:            }
487:
488:            Database getDatabase() {
489:                return database;
490:            }
491:
492:            DataPage getRowBuffer() {
493:                return rowBuff;
494:            }
495:
496:            public void setFlushOnEachCommit(boolean b) {
497:                flushOnEachCommit = b;
498:            }
499:
500:            boolean getFlushOnEachCommit() {
501:                return flushOnEachCommit;
502:            }
503:
504:            public void sync() throws SQLException {
505:                if (database == null || readOnly) {
506:                    return;
507:                }
508:                synchronized (database) {
509:                    if (currentLog != null) {
510:                        currentLog.flush();
511:                        currentLog.sync();
512:                    }
513:                }
514:            }
515:
516:            public void setDisabled(boolean disabled) {
517:                this .disabled = disabled;
518:            }
519:
520:            void addRedoLog(Storage storage, int recordId, int blockCount,
521:                    DataPage rec) throws SQLException {
522:                DiskFile file = storage.getDiskFile();
523:                file.addRedoLog(storage, recordId, blockCount, rec);
524:            }
525:
526:            public void invalidateIndexSummary() throws SQLException {
527:                currentLog.addSummary(false, null);
528:            }
529:
530:            public synchronized void updateKeepFiles(int incrementDecrement) {
531:                keepFiles += incrementDecrement;
532:            }
533:
534:            String getAccessMode() {
535:                return accessMode;
536:            }
537:
538:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.