KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > persist > Logger


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.persist;
33
34 import org.hsqldb.Database;
35 import org.hsqldb.HsqlException;
36 import org.hsqldb.NumberSequence;
37 import org.hsqldb.Session;
38 import org.hsqldb.Table;
39 import org.hsqldb.Trace;
40 import org.hsqldb.lib.SimpleLog;
41
42 // boucherb@users 20030510 - patch 1.7.2 - added cooperative file locking
43

44 /**
45  * The public interface of logging and cache classes.<p>
46  *
47  * Implements a storage manager wrapper that provides a consistent,
48  * always available interface to storage management for the Database
49  * class, despite the fact not all Database objects actually use file
50  * storage.<p>
51  *
52  * The Logger class makes it possible to avoid testing for a
53  * null Log Database attribute again and again, in many different places,
54  * and generally avoids tight coupling between Database and Log, opening
55  * the doors for multiple logs/caches in the future. In this way, the
56  * Database class does not need to know the details of the Logging/Cache
57  * implementation, lowering its breakability factor and promoting
58  * long-term code flexibility.
59  *
60  * @author fredt@users
61  * @version 1.8.0
62  * @since 1.7.0
63  */

64 public class Logger {
65
66     public SimpleLog appLog;
67
68     /**
69      * The Log object this Logger object wraps
70      */

71     private Log log;
72
73     /**
74      * The LockFile object this Logger uses to cooperatively lock
75      * the database files
76      */

77     private LockFile lf;
78     boolean needsCheckpoint;
79     private boolean logStatements;
80     private boolean syncFile = false;
81
82     public Logger() {
83         appLog = new SimpleLog(null, SimpleLog.LOG_NONE, false);
84     }
85
86     /**
87      * Opens the specified Database object's database files and starts up
88      * the logging process. <p>
89      *
90      * If the specified Database object is a new database, its database
91      * files are first created.
92      *
93      * @param db the Database
94      * @throws HsqlException if there is a problem, such as the case when
95      * the specified files are in use by another process
96      */

97     public void openLog(Database db) throws HsqlException {
98
99         needsCheckpoint = false;
100
101         String JavaDoc path = db.getPath();
102         int loglevel = db.getProperties().getIntegerProperty(
103             HsqlDatabaseProperties.hsqldb_applog, 0);
104
105         if (loglevel != SimpleLog.LOG_NONE) {
106             appLog = new SimpleLog(path + ".app.log", loglevel,
107                                    !db.isFilesReadOnly());
108         }
109
110         appLog.sendLine(SimpleLog.LOG_ERROR, "Database (re)opened");
111
112         logStatements = false;
113
114         if (!db.isFilesReadOnly()) {
115             acquireLock(path);
116         }
117
118         log = new Log(db);
119
120         log.open();
121
122         logStatements = !db.isFilesReadOnly();
123     }
124
125 // fredt@users 20020130 - patch 495484 by boucherb@users
126

127     /**
128      * Shuts down the logging process using the specified mode. <p>
129      *
130      * @param closemode The mode in which to shut down the logging
131      * process
132      * <OL>
133      * <LI> closemode -1 performs SHUTDOWN IMMEDIATELY, equivalent
134      * to a poweroff or crash.
135      * <LI> closemode 0 performs a normal SHUTDOWN that
136      * checkpoints the database normally.
137      * <LI> closemode 1 performs a shutdown compact that scripts
138      * out the contents of any CACHED tables to the log then
139      * deletes the existing *.data file that contains the data
140      * for all CACHED table before the normal checkpoint process
141      * which in turn creates a new, compact *.data file.
142      * <LI> closemode 2 performs a SHUTDOWN SCRIPT.
143      * </OL>
144      *
145      * @return true if closed with no problems or false if a problem was
146      * encountered.
147      */

148     public boolean closeLog(int closemode) {
149
150         if (log == null) {
151             appLog.sendLine(SimpleLog.LOG_ERROR, "Database closed");
152             appLog.close();
153
154             return true;
155         }
156
157         try {
158             switch (closemode) {
159
160                 case Database.CLOSEMODE_IMMEDIATELY :
161                     log.shutdown();
162                     break;
163
164                 case Database.CLOSEMODE_NORMAL :
165                     log.close(false);
166                     break;
167
168                 case Database.CLOSEMODE_COMPACT :
169                 case Database.CLOSEMODE_SCRIPT :
170                     log.close(true);
171                     break;
172             }
173         } catch (Throwable JavaDoc e) {
174             appLog.logContext(e, "error closing log");
175             appLog.close();
176
177             log = null;
178
179             return false;
180         }
181
182         appLog.sendLine(SimpleLog.LOG_ERROR, "Database closed");
183         appLog.close();
184
185         log = null;
186
187         return true;
188     }
189
190     /**
191      * Determines if the logging process actually does anything. <p>
192      *
193      * In-memory Database objects do not need to log anything. This
194      * method is essentially equivalent to testing whether this logger's
195      * database is an in-memory mode database.
196      *
197      * @return true if this object encapsulates a non-null Log instance,
198      * else false
199      */

200     public boolean hasLog() {
201         return log != null;
202     }
203
204     /**
205      * Returns the Cache object or null if one doesn't exist.
206      */

207     public DataFileCache getCache() throws HsqlException {
208
209         if (log == null) {
210             return null;
211         } else {
212             return log.getCache();
213         }
214     }
215
216     /**
217      * Returns the Cache object or null if one doesn't exist.
218      */

219     public boolean hasCache() {
220
221         if (log == null) {
222             return false;
223         } else {
224             return log.hasCache();
225         }
226     }
227
228     /**
229      * Records a Log entry representing a new connection action on the
230      * specified Session object.
231      *
232      * @param session the Session object for which to record the log
233      * entry
234      * @throws HsqlException if there is a problem recording the Log
235      * entry
236      */

237     public synchronized void logConnectUser(Session session)
238     throws HsqlException {
239
240         if (logStatements) {
241             writeToLog(session, session.getUser().getConnectStatement());
242         }
243     }
244
245     /**
246      * Records a Log entry for the specified SQL statement, on behalf of
247      * the specified Session object.
248      *
249      * @param session the Session object for which to record the Log
250      * entry
251      * @param statement the SQL statement to Log
252      * @throws HsqlException if there is a problem recording the entry
253      */

254     public synchronized void writeToLog(Session session,
255                                         String JavaDoc statement)
256                                         throws HsqlException {
257
258         if (logStatements && log != null) {
259             log.writeStatement(session, statement);
260         }
261     }
262
263     public synchronized void writeInsertStatement(Session session,
264             Table table, Object JavaDoc[] row) throws HsqlException {
265
266         if (logStatements) {
267             log.writeInsertStatement(session, table, row);
268         }
269     }
270
271     public synchronized void writeDeleteStatement(Session session, Table t,
272             Object JavaDoc[] row) throws HsqlException {
273
274         if (logStatements) {
275             log.writeDeleteStatement(session, t, row);
276         }
277     }
278
279     public synchronized void writeSequenceStatement(Session session,
280             NumberSequence s) throws HsqlException {
281
282         if (logStatements) {
283             log.writeSequenceStatement(session, s);
284         }
285     }
286
287     public synchronized void writeCommitStatement(Session session)
288     throws HsqlException {
289
290         if (logStatements) {
291             log.writeCommitStatement(session);
292             synchLog();
293         }
294     }
295
296     /**
297      * Called after commits or after each statement when autocommit is on
298      */

299     public synchronized void synchLog() {
300
301         if (logStatements && syncFile) {
302             log.synchLog();
303         }
304     }
305
306     public synchronized void synchLogForce() {
307
308         if (logStatements) {
309             log.synchLog();
310         }
311     }
312
313     /**
314      * Checkpoints the database. <p>
315      *
316      * The most important effect of calling this method is to cause the
317      * log file to be rewritten in the most efficient form to
318      * reflect the current state of the database, i.e. only the DDL and
319      * insert DML required to recreate the database in its present state.
320      * Other house-keeping duties are performed w.r.t. other database
321      * files, in order to ensure as much as possible the ACID properites
322      * of the database.
323      *
324      * @throws HsqlException if there is a problem checkpointing the
325      * database
326      */

327     public synchronized void checkpoint(boolean mode) throws HsqlException {
328
329         if (logStatements) {
330             appLog.logContext(appLog.LOG_NORMAL, "start");
331
332             needsCheckpoint = false;
333
334             log.checkpoint(mode);
335             appLog.logContext(appLog.LOG_NORMAL, "end");
336         }
337     }
338
339     /**
340      * Sets the maximum size to which the log file can grow
341      * before being automatically checkpointed.
342      *
343      * @param megas size in MB
344      */

345     public synchronized void setLogSize(int megas) {
346
347         if (log != null) {
348             log.setLogSize(megas);
349         }
350     }
351
352     /**
353      * Sets the type of script file, currently 0 for text (default)
354      * 1 for binary and 3 for compressed
355      *
356      * @param i The type
357      */

358     public synchronized void setScriptType(int i) throws HsqlException {
359
360         if (log != null) {
361             log.setScriptType(i);
362         }
363     }
364
365     /**
366      * Sets the log write delay mode to number of seconds. By default
367      * executed commands written to the log are committed fully at most
368      * 60 second after they are executed. This improves performance for
369      * applications that execute a large number
370      * of short running statements in a short period of time, but risks
371      * failing to log some possibly large number of statements in the
372      * event of a crash. A small value improves recovery.
373      * A value of 0 will severly slow down logging when autocommit is on,
374      * or many short transactions are committed.
375      *
376      * @param delay in seconds
377      */

378     public synchronized void setWriteDelay(int delay) {
379
380         if (log != null) {
381             syncFile = (delay == 0);
382
383             log.setWriteDelay(delay);
384         }
385     }
386
387     public int getWriteDelay() {
388         return log != null ? log.getWriteDelay()
389                            : 0;
390     }
391
392     public int getLogSize() {
393         return log != null ? log.getLogSize()
394                            : 0;
395     }
396
397     public int getScriptType() {
398         return log != null ? log.getScriptType()
399                            : 0;
400     }
401
402     /**
403      * Opens the TextCache object.
404      */

405     public DataFileCache openTextCache(Table table, String JavaDoc source,
406                                        boolean readOnlyData,
407                                        boolean reversed)
408                                        throws HsqlException {
409         return log.openTextCache(table, source, readOnlyData, reversed);
410     }
411
412     /**
413      * Closes the TextCache object.
414      */

415     public void closeTextCache(Table table) throws HsqlException {
416         log.closeTextCache(table);
417     }
418
419     public boolean needsCheckpoint() {
420         return needsCheckpoint;
421     }
422
423     /**
424      * Attempts to aquire a cooperative lock condition on the database files
425      */

426     public void acquireLock(String JavaDoc path) throws HsqlException {
427
428         if (lf != null) {
429             return;
430         }
431
432         lf = LockFile.newLockFileLock(path);
433     }
434
435     public void releaseLock() {
436
437         try {
438             if (lf != null) {
439                 lf.tryRelease();
440             }
441         } catch (Exception JavaDoc e) {
442             if (Trace.TRACE) {
443                 Trace.printSystemOut(e.toString());
444             }
445         }
446
447         lf = null;
448     }
449 }
450
Popular Tags