001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.persist;
032:
033: import java.io.EOFException;
034:
035: import org.hsqldb.Database;
036: import org.hsqldb.HsqlException;
037: import org.hsqldb.Result;
038: import org.hsqldb.Session;
039: import org.hsqldb.Trace;
040: import org.hsqldb.lib.IntKeyHashMap;
041: import org.hsqldb.lib.SimpleLog;
042: import org.hsqldb.lib.StopWatch;
043: import org.hsqldb.scriptio.ScriptReaderBase;
044:
045: /**
046: * Restores the state of a Database instance from an SQL log file. <p>
047: *
048: * If there is an error, processing stops at that line and the message is
049: * logged to the application log. If memory runs out, an exception is thrown.
050: *
051: * @author fredt@users
052: * @version 1.8.0
053: * @since 1.7.2
054: */
055: public class ScriptRunner {
056:
057: /**
058: * This is used to read the *.log file and manage any necessary
059: * transaction rollback.
060: *
061: * @throws HsqlException
062: */
063: public static void runScript(Database database, String logFilename,
064: int logType) throws HsqlException {
065:
066: IntKeyHashMap sessionMap = new IntKeyHashMap();
067: Session sysSession = database.getSessionManager()
068: .getSysSession();
069: Session current = sysSession;
070: int currentId = 0;
071:
072: database.setReferentialIntegrity(false);
073:
074: ScriptReaderBase scr = null;
075:
076: try {
077: StopWatch sw = new StopWatch();
078:
079: scr = ScriptReaderBase.newScriptReader(database,
080: logFilename, logType);
081:
082: while (scr.readLoggedStatement(current)) {
083: int sessionId = scr.getSessionNumber();
084:
085: if (currentId != sessionId) {
086: currentId = sessionId;
087: current = (Session) sessionMap.get(currentId);
088:
089: if (current == null) {
090: current = database.getSessionManager()
091: .newSession(database,
092: sysSession.getUser(), false,
093: true);
094:
095: sessionMap.put(currentId, current);
096: }
097: }
098:
099: if (current.isClosed()) {
100: sessionMap.remove(currentId);
101:
102: continue;
103: }
104:
105: Result result = null;
106:
107: switch (scr.getStatementType()) {
108:
109: case ScriptReaderBase.ANY_STATEMENT:
110: result = current.sqlExecuteDirectNoPreChecks(scr
111: .getLoggedStatement());
112:
113: if (result != null && result.isError()) {
114: if (result.getException() != null) {
115: throw result.getException();
116: }
117:
118: throw Trace.error(result);
119: }
120: break;
121:
122: case ScriptReaderBase.SEQUENCE_STATEMENT:
123: scr.getCurrentSequence().reset(
124: scr.getSequenceValue());
125: break;
126:
127: case ScriptReaderBase.COMMIT_STATEMENT:
128: current.commit();
129: break;
130:
131: case ScriptReaderBase.INSERT_STATEMENT: {
132: Object[] data = scr.getData();
133:
134: scr.getCurrentTable().insertNoCheckFromLog(current,
135: data);
136:
137: break;
138: }
139: case ScriptReaderBase.DELETE_STATEMENT: {
140: Object[] data = scr.getData();
141:
142: scr.getCurrentTable().deleteNoCheckFromLog(current,
143: data);
144:
145: break;
146: }
147: case ScriptReaderBase.SCHEMA_STATEMENT: {
148: current.setSchema(scr.getCurrentSchema());
149: }
150: }
151:
152: if (current.isClosed()) {
153: sessionMap.remove(currentId);
154: }
155: }
156: } catch (Throwable e) {
157: String message;
158:
159: // catch out-of-memory errors and terminate
160: if (e instanceof EOFException) {
161:
162: // end of file - normal end
163: } else if (e instanceof OutOfMemoryError) {
164: message = "out of memory processing " + logFilename
165: + " line: " + scr.getLineNumber();
166:
167: database.logger.appLog.logContext(SimpleLog.LOG_ERROR,
168: message);
169:
170: throw Trace.error(Trace.OUT_OF_MEMORY);
171: } else {
172:
173: // stop processing on bad log line
174: message = logFilename + " line: " + scr.getLineNumber()
175: + " " + e.toString();
176:
177: database.logger.appLog.logContext(SimpleLog.LOG_ERROR,
178: message);
179: }
180: } finally {
181: if (scr != null) {
182: scr.close();
183: }
184:
185: database.getSessionManager().closeAllSessions();
186: database.setReferentialIntegrity(true);
187: }
188: }
189: }
|