提交 c7400dc2 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 87e8a128
...@@ -35,6 +35,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -35,6 +35,8 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>Version 1.0 (Current)</h3> <h3>Version 1.0 (Current)</h3>
<h3>Version 1.0 / 2007-TODO</h3><ul> <h3>Version 1.0 / 2007-TODO</h3><ul>
<li>In some situations the log file got corrupt if the process was terminated while the database was opening.
<li>Using ;RECOVER=1 in the database URL threw a syntax exception. Fixed.
<li>If a CLOB or BLOB was deleted in a transaction and the database crashed before the transaction was committed or rolled back, <li>If a CLOB or BLOB was deleted in a transaction and the database crashed before the transaction was committed or rolled back,
the object was lost if it was large. Fixed. the object was lost if it was large. Fixed.
<li>Now using ant-build.properties. The jdk is automatically updated when using ant codeswitch_... <li>Now using ant-build.properties. The jdk is automatically updated when using ant codeswitch_...
......
...@@ -3364,6 +3364,9 @@ public class Parser { ...@@ -3364,6 +3364,9 @@ public class Parser {
} else if(readIf("DB_CLOSE_ON_EXIT")) { } else if(readIf("DB_CLOSE_ON_EXIT")) {
read(); read();
return new NoOperation(session); return new NoOperation(session);
} else if(readIf("RECOVER")) {
read();
return new NoOperation(session);
} else if(readIf("SCHEMA")) { } else if(readIf("SCHEMA")) {
Set command = new Set(session, SetTypes.SCHEMA); Set command = new Set(session, SetTypes.SCHEMA);
command.setString(readAliasIdentifier()); command.setString(readAliasIdentifier());
......
...@@ -523,7 +523,7 @@ public class Database implements DataHandler { ...@@ -523,7 +523,7 @@ public class Database implements DataHandler {
removeUnusedStorages(); removeUnusedStorages();
systemSession.commit(); systemSession.commit();
if(!readOnly) { if(!readOnly) {
emergencyReserve = openFile(createTempFile(), true); emergencyReserve = openFile(createTempFile(), false);
emergencyReserve.autoDelete(); emergencyReserve.autoDelete();
emergencyReserve.setLength(Constants.EMERGENCY_SPACE_INITIAL); emergencyReserve.setLength(Constants.EMERGENCY_SPACE_INITIAL);
} }
......
...@@ -194,7 +194,9 @@ public class DiskFile implements CacheWriter { ...@@ -194,7 +194,9 @@ public class DiskFile implements CacheWriter {
ObjectArray list = database.getAllStorages(); ObjectArray list = database.getAllStorages();
for(int i=0; i<list.size(); i++) { for(int i=0; i<list.size(); i++) {
Storage s = (Storage)list.get(i); Storage s = (Storage)list.get(i);
database.removeStorage(s.getId(), this); if(s.getDiskFile() == this) {
database.removeStorage(s.getId(), this);
}
} }
reset(); reset();
initAlreadyTried = false; initAlreadyTried = false;
...@@ -304,6 +306,7 @@ public class DiskFile implements CacheWriter { ...@@ -304,6 +306,7 @@ public class DiskFile implements CacheWriter {
} }
synchronized void flush() throws SQLException { synchronized void flush() throws SQLException {
database.checkPowerOff();
ObjectArray list = cache.getAllChanged(); ObjectArray list = cache.getAllChanged();
CacheObject.sort(list); CacheObject.sort(list);
for(int i=0; i<list.size(); i++) { for(int i=0; i<list.size(); i++) {
......
...@@ -281,15 +281,6 @@ public class LogFile { ...@@ -281,15 +281,6 @@ public class LogFile {
default: default:
throw Message.getInternalError("type="+type); throw Message.getInternalError("type="+type);
} }
if(undo) {
int posNow = getBlock();
in.setInt(0, -blocks);
in.fill(blocks * BLOCK_SIZE);
in.updateChecksum();
go(pos);
file.write(in.getBytes(), 0, BLOCK_SIZE * blocks);
go(posNow);
}
return true; return true;
} }
...@@ -341,7 +332,7 @@ public class LogFile { ...@@ -341,7 +332,7 @@ public class LogFile {
if(bufferPos > 0) { if(bufferPos > 0) {
if(file == null) { if(file == null) {
throw Message.getSQLException(Message.SIMULATED_POWER_OFF); throw Message.getSQLException(Message.SIMULATED_POWER_OFF);
} }
file.write(buffer, 0, bufferPos); file.write(buffer, 0, bufferPos);
for(int i=0; i<unwritten.size(); i++) { for(int i=0; i<unwritten.size(); i++) {
Record r = (Record) unwritten.get(i); Record r = (Record) unwritten.get(i);
......
...@@ -41,7 +41,7 @@ public class LogSystem { ...@@ -41,7 +41,7 @@ public class LogSystem {
public LogSystem(Database database, String fileNamePrefix, boolean readOnly) throws SQLException { public LogSystem(Database database, String fileNamePrefix, boolean readOnly) throws SQLException {
this.database = database; this.database = database;
this.readOnly = readOnly; this.readOnly = readOnly;
if(database==null || readOnly) { if (database == null || readOnly) {
return; return;
} }
this.fileNamePrefix = fileNamePrefix; this.fileNamePrefix = fileNamePrefix;
...@@ -64,43 +64,43 @@ public class LogSystem { ...@@ -64,43 +64,43 @@ public class LogSystem {
private void flushAndCloseUnused() throws SQLException { private void flushAndCloseUnused() throws SQLException {
currentLog.flush(); currentLog.flush();
DiskFile file = database.getDataFile(); DiskFile file = database.getDataFile();
if(file == null) { if (file == null) {
return; return;
} }
file.flush(); file.flush();
if(containsInDoubtTransactions()) { if (containsInDoubtTransactions()) {
// if there are any in-doubt transactions (even if they are resolved), can't update or delete the log files // if there are any in-doubt transactions (even if they are resolved), can't update or delete the log files
return; return;
} }
Session[] sessions = database.getSessions(); Session[] sessions = database.getSessions();
int firstUncommittedLog = currentLog.getId(); int firstUncommittedLog = currentLog.getId();
int firstUncommittedPos = currentLog.getPos(); int firstUncommittedPos = currentLog.getPos();
for(int i=0; i<sessions.length; i++) { for (int i = 0; i < sessions.length; i++) {
Session session = sessions[i]; Session session = sessions[i];
int log = session.getFirstUncommittedLog(); int log = session.getFirstUncommittedLog();
int pos = session.getFirstUncommittedPos(); int pos = session.getFirstUncommittedPos();
if(pos != LOG_WRITTEN) { if (pos != LOG_WRITTEN) {
if(log < firstUncommittedLog || (log==firstUncommittedLog && pos < firstUncommittedPos)) { if (log < firstUncommittedLog || (log == firstUncommittedLog && pos < firstUncommittedPos)) {
firstUncommittedLog = log; firstUncommittedLog = log;
firstUncommittedPos = pos; firstUncommittedPos = pos;
} }
} }
} }
for(int i = activeLogs.size()-1; i>=0; i--) { for (int i = activeLogs.size() - 1; i >= 0; i--) {
LogFile l = (LogFile) activeLogs.get(i); LogFile l = (LogFile) activeLogs.get(i);
if(l.getId() < firstUncommittedLog) { if (l.getId() < firstUncommittedLog) {
l.setFirstUncommittedPos(LOG_WRITTEN); l.setFirstUncommittedPos(LOG_WRITTEN);
} else if(l.getId() == firstUncommittedLog) { } else if (l.getId() == firstUncommittedLog) {
if(firstUncommittedPos == l.getPos()) { if (firstUncommittedPos == l.getPos()) {
l.setFirstUncommittedPos(LOG_WRITTEN); l.setFirstUncommittedPos(LOG_WRITTEN);
} else { } else {
l.setFirstUncommittedPos(firstUncommittedPos); l.setFirstUncommittedPos(firstUncommittedPos);
} }
} }
} }
for(int i = 0; i < activeLogs.size(); i++) { for (int i = 0; i < activeLogs.size(); i++) {
LogFile l = (LogFile) activeLogs.get(i); LogFile l = (LogFile) activeLogs.get(i);
if(l.getFirstUncommittedPos() == LOG_WRITTEN) { if (l.getFirstUncommittedPos() == LOG_WRITTEN) {
l.close(deleteOldLogFilesAutomatically); l.close(deleteOldLogFilesAutomatically);
activeLogs.remove(i); activeLogs.remove(i);
i--; i--;
...@@ -109,45 +109,45 @@ public class LogSystem { ...@@ -109,45 +109,45 @@ public class LogSystem {
} }
public void close() throws SQLException { public void close() throws SQLException {
if(database==null || readOnly) { if (database == null || readOnly) {
return; return;
} }
synchronized(database) { synchronized (database) {
// TODO refactor flushing and closing files when we know what to do exactly // TODO refactor flushing and closing files when we know what to do exactly
SQLException closeException = null; SQLException closeException = null;
try { try {
flushAndCloseUnused(); flushAndCloseUnused();
if(!containsInDoubtTransactions()) { if (!containsInDoubtTransactions()) {
checkpoint(); checkpoint();
} }
} catch (SQLException e) { } catch (SQLException e) {
closeException = e; closeException = e;
} }
for(int i=0; i<activeLogs.size(); i++) { for (int i = 0; i < activeLogs.size(); i++) {
LogFile l = (LogFile) activeLogs.get(i); LogFile l = (LogFile) activeLogs.get(i);
try { try {
// if there are any in-doubt transactions (even if they are resolved), can't delete the log files // if there are any in-doubt transactions (even if they are resolved), can't delete the log files
if(l.getFirstUncommittedPos() == LOG_WRITTEN && !containsInDoubtTransactions()) { if (l.getFirstUncommittedPos() == LOG_WRITTEN && !containsInDoubtTransactions()) {
l.close(deleteOldLogFilesAutomatically); l.close(deleteOldLogFilesAutomatically);
} else { } else {
l.close(false); l.close(false);
} }
} catch(SQLException e) { } catch (SQLException e) {
// TODO log exception // TODO log exception
if(closeException == null) { if (closeException == null) {
closeException = e; closeException = e;
} }
} }
} }
database = null; database = null;
if(closeException != null) { if (closeException != null) {
throw closeException; throw closeException;
} }
} }
} }
boolean needMoreUndo() { boolean needMoreUndo() {
return sessions.size()>0; return sessions.size() > 0;
} }
void addUndoLogRecord(LogFile log, int logRecordId, int sessionId) { void addUndoLogRecord(LogFile log, int logRecordId, int sessionId) {
...@@ -156,12 +156,12 @@ public class LogSystem { ...@@ -156,12 +156,12 @@ public class LogSystem {
} }
public boolean recover() throws SQLException { public boolean recover() throws SQLException {
if(database==null) { if (database == null) {
return false; return false;
} }
synchronized(database) { synchronized (database) {
undo = new ObjectArray(); undo = new ObjectArray();
for(int i=0; i<activeLogs.size(); i++) { for (int i = 0; i < activeLogs.size(); i++) {
LogFile log = (LogFile) activeLogs.get(i); LogFile log = (LogFile) activeLogs.get(i);
log.redoAllGoEnd(); log.redoAllGoEnd();
} }
...@@ -170,16 +170,16 @@ public class LogSystem { ...@@ -170,16 +170,16 @@ public class LogSystem {
int end = currentLog.getPos(); int end = currentLog.getPos();
Object[] states = sessions.values().toArray(); Object[] states = sessions.values().toArray();
inDoubtTransactions = new ObjectArray(); inDoubtTransactions = new ObjectArray();
for(int i=0; i<states.length; i++) { for (int i = 0; i < states.length; i++) {
SessionState state = (SessionState)states[i]; SessionState state = (SessionState) states[i];
if(state.inDoubtTransaction != null) { if (state.inDoubtTransaction != null) {
inDoubtTransactions.add(state.inDoubtTransaction); inDoubtTransactions.add(state.inDoubtTransaction);
} }
} }
for(int i=undo.size()-1; i>=0 && sessions.size()>0; i--) { for (int i = undo.size() - 1; i >= 0 && sessions.size() > 0; i--) {
database.setProgress(DatabaseEventListener.STATE_RECOVER, null, undo.size()-1-i, undo.size()); database.setProgress(DatabaseEventListener.STATE_RECOVER, null, undo.size() - 1 - i, undo.size());
LogRecord record = (LogRecord)undo.get(i); LogRecord record = (LogRecord) undo.get(i);
if(sessions.get(new Integer(record.sessionId)) != null) { if (sessions.get(new Integer(record.sessionId)) != null) {
// undo only if the session is not yet committed // undo only if the session is not yet committed
record.log.undo(record.logRecordId); record.log.undo(record.logRecordId);
database.getDataFile().flushRedoLog(); database.getDataFile().flushRedoLog();
...@@ -190,6 +190,9 @@ public class LogSystem { ...@@ -190,6 +190,9 @@ public class LogSystem {
boolean fileChanged = undo.size() > 0; boolean fileChanged = undo.size() > 0;
undo = null; undo = null;
storages.clear(); storages.clear();
if (fileChanged && !containsInDoubtTransactions()) {
checkpoint();
}
return fileChanged; return fileChanged;
} }
} }
...@@ -198,11 +201,11 @@ public class LogSystem { ...@@ -198,11 +201,11 @@ public class LogSystem {
String path = FileUtils.getParent(fileNamePrefix); String path = FileUtils.getParent(fileNamePrefix);
String[] list = FileUtils.listFiles(path); String[] list = FileUtils.listFiles(path);
activeLogs = new ObjectArray(); activeLogs = new ObjectArray();
for(int i=0; i<list.length; i++) { for (int i = 0; i < list.length; i++) {
String s = list[i]; String s = list[i];
LogFile l = LogFile.openIfLogFile(this, fileNamePrefix, s); LogFile l = LogFile.openIfLogFile(this, fileNamePrefix, s);
if(l != null) { if (l != null) {
if(l.getPos() == LOG_WRITTEN) { if (l.getPos() == LOG_WRITTEN) {
l.close(deleteOldLogFilesAutomatically); l.close(deleteOldLogFilesAutomatically);
} else { } else {
activeLogs.add(l); activeLogs.add(l);
...@@ -211,19 +214,19 @@ public class LogSystem { ...@@ -211,19 +214,19 @@ public class LogSystem {
} }
activeLogs.sort(new Comparator() { activeLogs.sort(new Comparator() {
public int compare(Object a, Object b) { public int compare(Object a, Object b) {
return ((LogFile)a).getId() - ((LogFile)b).getId(); return ((LogFile) a).getId() - ((LogFile) b).getId();
} }
}); });
if(activeLogs.size()==0) { if (activeLogs.size() == 0) {
LogFile l = new LogFile(this, 0, fileNamePrefix); LogFile l = new LogFile(this, 0, fileNamePrefix);
activeLogs.add(l); activeLogs.add(l);
} }
currentLog = (LogFile) activeLogs.get(activeLogs.size()-1); currentLog = (LogFile) activeLogs.get(activeLogs.size() - 1);
} }
Storage getStorageForRecovery(int id) throws SQLException { Storage getStorageForRecovery(int id) throws SQLException {
boolean dataFile; boolean dataFile;
if(id < 0) { if (id < 0) {
dataFile = false; dataFile = false;
id = -id; id = -id;
} else { } else {
...@@ -231,7 +234,7 @@ public class LogSystem { ...@@ -231,7 +234,7 @@ public class LogSystem {
} }
Integer i = new Integer(id); Integer i = new Integer(id);
Storage storage = (Storage) storages.get(i); Storage storage = (Storage) storages.get(i);
if(storage == null) { if (storage == null) {
storage = database.getStorage(null, id, dataFile); storage = database.getStorage(null, id, dataFile);
storages.put(i, storage); storages.put(i, storage);
} }
...@@ -240,8 +243,8 @@ public class LogSystem { ...@@ -240,8 +243,8 @@ public class LogSystem {
boolean isSessionCommitted(int sessionId, int logId, int pos) { boolean isSessionCommitted(int sessionId, int logId, int pos) {
Integer key = new Integer(sessionId); Integer key = new Integer(sessionId);
SessionState state = (SessionState)sessions.get(key); SessionState state = (SessionState) sessions.get(key);
if(state == null) { if (state == null) {
return true; return true;
} }
return state.isCommitted(logId, pos); return state.isCommitted(logId, pos);
...@@ -249,8 +252,8 @@ public class LogSystem { ...@@ -249,8 +252,8 @@ public class LogSystem {
void setLastCommitForSession(int sessionId, int logId, int pos) { void setLastCommitForSession(int sessionId, int logId, int pos) {
Integer key = new Integer(sessionId); Integer key = new Integer(sessionId);
SessionState state = (SessionState)sessions.get(key); SessionState state = (SessionState) sessions.get(key);
if(state == null) { if (state == null) {
state = new SessionState(); state = new SessionState();
sessions.put(key, state); sessions.put(key, state);
state.sessionId = sessionId; state.sessionId = sessionId;
...@@ -262,8 +265,8 @@ public class LogSystem { ...@@ -262,8 +265,8 @@ public class LogSystem {
void setPreparedCommitForSession(LogFile log, int sessionId, int pos, String transaction, int blocks) { void setPreparedCommitForSession(LogFile log, int sessionId, int pos, String transaction, int blocks) {
Integer key = new Integer(sessionId); Integer key = new Integer(sessionId);
SessionState state = (SessionState)sessions.get(key); SessionState state = (SessionState) sessions.get(key);
if(state == null) { if (state == null) {
state = new SessionState(); state = new SessionState();
sessions.put(key, state); sessions.put(key, state);
state.sessionId = sessionId; state.sessionId = sessionId;
...@@ -282,57 +285,57 @@ public class LogSystem { ...@@ -282,57 +285,57 @@ public class LogSystem {
} }
public void prepareCommit(Session session, String transaction) throws SQLException { public void prepareCommit(Session session, String transaction) throws SQLException {
if(database==null || readOnly) { if (database == null || readOnly) {
return; return;
} }
synchronized(database) { synchronized (database) {
currentLog.prepareCommit(session, transaction); currentLog.prepareCommit(session, transaction);
} }
} }
public void commit(Session session) throws SQLException { public void commit(Session session) throws SQLException {
if(database==null || readOnly) { if (database == null || readOnly) {
return; return;
} }
synchronized(database) { synchronized (database) {
currentLog.commit(session); currentLog.commit(session);
session.setAllCommitted(); session.setAllCommitted();
} }
} }
public void flush() throws SQLException { public void flush() throws SQLException {
if(database==null || readOnly) { if (database == null || readOnly) {
return; return;
} }
synchronized(database) { synchronized (database) {
currentLog.flush(); currentLog.flush();
} }
} }
public void addTruncate(Session session, DiskFile file, int storageId, int recordId, int blockCount) throws SQLException { public void addTruncate(Session session, DiskFile file, int storageId, int recordId, int blockCount) throws SQLException {
if(database==null || disabled) { if (database == null || disabled) {
return; return;
} }
synchronized(database) { synchronized (database) {
database.checkWritingAllowed(); database.checkWritingAllowed();
if(!file.isDataFile()) { if (!file.isDataFile()) {
storageId = -storageId; storageId = -storageId;
} }
currentLog.addTruncate(session, storageId, recordId, blockCount); currentLog.addTruncate(session, storageId, recordId, blockCount);
if(currentLog.getFileSize() > maxLogSize) { if (currentLog.getFileSize() > maxLogSize) {
checkpoint(); checkpoint();
} }
} }
} }
public void add(Session session, DiskFile file, Record record) throws SQLException { public void add(Session session, DiskFile file, Record record) throws SQLException {
if(database==null || disabled) { if (database == null || disabled) {
return; return;
} }
synchronized(database) { synchronized (database) {
database.checkWritingAllowed(); database.checkWritingAllowed();
int storageId = record.getStorageId(); int storageId = record.getStorageId();
if(!file.isDataFile()) { if (!file.isDataFile()) {
storageId = -storageId; storageId = -storageId;
} }
int log = currentLog.getId(); int log = currentLog.getId();
...@@ -340,39 +343,40 @@ public class LogSystem { ...@@ -340,39 +343,40 @@ public class LogSystem {
session.addLogPos(log, pos); session.addLogPos(log, pos);
record.setLastLog(log, pos); record.setLastLog(log, pos);
currentLog.add(session, storageId, record); currentLog.add(session, storageId, record);
if(currentLog.getFileSize() > maxLogSize) { if (currentLog.getFileSize() > maxLogSize) {
checkpoint(); checkpoint();
} }
} }
} }
public void checkpoint() throws SQLException { public void checkpoint() throws SQLException {
if(database==null || readOnly || disabled) { if (database == null || readOnly || disabled) {
return; return;
} }
synchronized(database) { synchronized (database) {
flushAndCloseUnused(); flushAndCloseUnused();
currentLog = new LogFile(this, currentLog.getId()+1, fileNamePrefix); currentLog = new LogFile(this, currentLog.getId() + 1, fileNamePrefix);
activeLogs.add(currentLog); activeLogs.add(currentLog);
writeSummary(); writeSummary();
currentLog.flush();
} }
} }
private void writeSummary() throws SQLException { private void writeSummary() throws SQLException {
if(database==null || readOnly || disabled) { if (database == null || readOnly || disabled) {
return; return;
} }
byte[] summary; byte[] summary;
DiskFile file; DiskFile file;
file = database.getDataFile(); file = database.getDataFile();
summary = file.getSummary(); summary = file.getSummary();
if(summary != null) { if (summary != null) {
currentLog.addSummary(true, summary); currentLog.addSummary(true, summary);
} }
if(database.getLogIndexChanges() || database.getIndexSummaryValid()) { if (database.getLogIndexChanges() || database.getIndexSummaryValid()) {
file = database.getIndexFile(); file = database.getIndexFile();
summary = file.getSummary(); summary = file.getSummary();
if(summary != null) { if (summary != null) {
currentLog.addSummary(false, summary); currentLog.addSummary(false, summary);
} }
} else { } else {
...@@ -398,8 +402,8 @@ public class LogSystem { ...@@ -398,8 +402,8 @@ public class LogSystem {
} }
public void sync() throws SQLException { public void sync() throws SQLException {
synchronized(database) { synchronized (database) {
if(currentLog != null) { if (currentLog != null) {
currentLog.flush(); currentLog.flush();
currentLog.sync(); currentLog.sync();
} }
......
...@@ -34,6 +34,7 @@ import org.h2.store.FileStore; ...@@ -34,6 +34,7 @@ import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream; import org.h2.store.FileStoreInputStream;
import org.h2.store.LogFile; import org.h2.store.LogFile;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.RandomUtils; import org.h2.util.RandomUtils;
...@@ -300,8 +301,9 @@ public class Recover implements DataHandler { ...@@ -300,8 +301,9 @@ public class Recover implements DataHandler {
private void dumpLob(String fileName, boolean lobCompression) { private void dumpLob(String fileName, boolean lobCompression) {
FileOutputStream out = null; FileOutputStream out = null;
FileStore store = null; FileStore store = null;
int size = 0;
String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
try { try {
String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
out = new FileOutputStream(n); out = new FileOutputStream(n);
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
...@@ -315,13 +317,24 @@ public class Recover implements DataHandler { ...@@ -315,13 +317,24 @@ public class Recover implements DataHandler {
break; break;
} }
out.write(buffer, 0, l); out.write(buffer, 0, l);
size += l;
} }
} catch(Throwable e) { } catch(Throwable e) {
logError(fileName, e); // this is usually not a problem, because we try both compressed and uncompressed
if(log) {
logError(fileName, e);
}
} finally { } finally {
IOUtils.closeSilently(out); IOUtils.closeSilently(out);
closeSilently(store); closeSilently(store);
} }
if(size == 0) {
try {
FileUtils.delete(n);
} catch (SQLException e) {
logError(n, e);
}
}
} }
private void dumpLog(String fileName) throws SQLException { private void dumpLog(String fileName) throws SQLException {
...@@ -371,14 +384,17 @@ public class Recover implements DataHandler { ...@@ -371,14 +384,17 @@ public class Recover implements DataHandler {
byte[] b2 = new byte[blocks * blockSize]; byte[] b2 = new byte[blocks * blockSize];
System.arraycopy(buff, 0, b2, 0, blockSize); System.arraycopy(buff, 0, b2, 0, blockSize);
buff = b2; buff = b2;
store.readFully(buff, blockSize, blocks * blockSize - blockSize); try {
store.readFully(buff, blockSize, blocks * blockSize - blockSize);
} catch(SQLException e) {
break;
}
s = DataPage.create(this, buff); s = DataPage.create(this, buff);
s.check(blocks * blockSize); s.check(blocks * blockSize);
} else {
s.reset();
} }
blocks = s.readInt(); s.reset();
if(blocks<=0) { blocks = Math.abs(s.readInt());
if(blocks==0) {
writer.println("// [" + pos+"] blocks: "+blocks+" (end)"); writer.println("// [" + pos+"] blocks: "+blocks+" (end)");
break; break;
} else { } else {
...@@ -386,12 +402,12 @@ public class Recover implements DataHandler { ...@@ -386,12 +402,12 @@ public class Recover implements DataHandler {
int sessionId = s.readInt(); int sessionId = s.readInt();
if(type == 'P') { if(type == 'P') {
String transaction = s.readString(); String transaction = s.readString();
writer.println("// prepared session:"+sessionId+" tx: " + transaction); writer.println("// prepared session:"+sessionId+" tx:" + transaction);
} else if(type == 'C') { } else if(type == 'C') {
writer.println("// commit session:" + sessionId); writer.println("// commit session:" + sessionId);
} else { } else {
int storageId = s.readInt(); int storageId = s.readInt();
int recordId = s.readInt(); int recId = s.readInt();
int blockCount = s.readInt(); int blockCount = s.readInt();
if(type != 'T') { if(type != 'T') {
s.readDataPageNoSize(); s.readDataPageNoSize();
...@@ -404,21 +420,21 @@ public class Recover implements DataHandler { ...@@ -404,21 +420,21 @@ public class Recover implements DataHandler {
if(sumLength > 0) { if(sumLength > 0) {
s.read(summary, 0, sumLength); s.read(summary, 0, sumLength);
} }
writer.println("// summary session:"+sessionId+" fileType: " + fileType + " sumLength: " + sumLength); writer.println("// summary session:"+sessionId+" fileType:" + fileType + " sumLength:" + sumLength);
dumpSummary(writer, summary); dumpSummary(writer, summary);
break; break;
} }
case 'T': case 'T':
writer.println("// truncate session:"+sessionId+" storage: " + storageId + " recordId: " + recordId + " blockCount: "+blockCount); writer.println("// truncate session:"+sessionId+" storage:" + storageId + " pos:" + recId + " blockCount:"+blockCount);
break; break;
case 'I': case 'I':
writer.println("// insert session:"+sessionId+" storage: " + storageId + " recordId: " + recordId + " blockCount: "+blockCount); writer.println("// insert session:"+sessionId+" storage:" + storageId + " pos:" + recId + " blockCount:"+blockCount);
break; break;
case 'D': case 'D':
writer.println("// delete session:"+sessionId+" storage: " + storageId + " recordId: " + recordId + " blockCount: "+blockCount); writer.println("// delete session:"+sessionId+" storage:" + storageId + " pos:" + recId + " blockCount:"+blockCount);
break; break;
default: default:
writer.println("// type?:"+type+" session:"+sessionId+" storage: " + storageId + " recordId: " + recordId + " blockCount: "+blockCount); writer.println("// type?:"+type+" session:"+sessionId+" storage:" + storageId + " pos:" + recId + " blockCount:"+blockCount);
break; break;
} }
} }
...@@ -441,8 +457,20 @@ public class Recover implements DataHandler { ...@@ -441,8 +457,20 @@ public class Recover implements DataHandler {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(summary)); DataInputStream in = new DataInputStream(new ByteArrayInputStream(summary));
int b2 = in.readInt(); int b2 = in.readInt();
for(int i=0; i<b2 / 8; i++) { for(int i=0; i<b2 / 8; i++) {
in.read(); int x = in.read();
if((i % 8) == 0) {
writer.print("// ");
}
writer.print(" " + Long.toString(i * 8) + ":");
for(int j=0; j<8; j++) {
writer.print(((x & 1) == 1) ? "1" : "0");
x >>>= 1;
}
if((i % 8) == 7) {
writer.println("");
}
} }
writer.println("//");
int len = in.readInt(); int len = in.readInt();
for(int i=0; i<len; i++) { for(int i=0; i<len; i++) {
int storageId = in.readInt(); int storageId = in.readInt();
...@@ -542,7 +570,7 @@ public class Recover implements DataHandler { ...@@ -542,7 +570,7 @@ public class Recover implements DataHandler {
PrintWriter writer = null; PrintWriter writer = null;
FileStore store = null; FileStore store = null;
try { try {
databaseName = fileName.substring(fileName.length() - Constants.SUFFIX_DATA_FILE.length()); databaseName = fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length());
writer = getWriter(fileName, ".sql"); writer = getWriter(fileName, ".sql");
ObjectArray schema = new ObjectArray(); ObjectArray schema = new ObjectArray();
HashSet objectIdSet = new HashSet(); HashSet objectIdSet = new HashSet();
...@@ -578,6 +606,7 @@ public class Recover implements DataHandler { ...@@ -578,6 +606,7 @@ public class Recover implements DataHandler {
blockCount = 1; blockCount = 1;
continue; continue;
} }
writer.println("-- block " + block + " - " + (block + blockCount-1));
try { try {
s.checkCapacity(blockCount * blockSize); s.checkCapacity(blockCount * blockSize);
} catch(OutOfMemoryError e) { } catch(OutOfMemoryError e) {
...@@ -643,11 +672,12 @@ public class Recover implements DataHandler { ...@@ -643,11 +672,12 @@ public class Recover implements DataHandler {
sb.append("INSERT INTO O_" + storageId + " VALUES("); sb.append("INSERT INTO O_" + storageId + " VALUES(");
for(valueId=0; valueId<recordLength; valueId++) { for(valueId=0; valueId<recordLength; valueId++) {
try { try {
data[valueId] = s.readValue(); Value v = s.readValue();
data[valueId] = v;
if(valueId>0) { if(valueId>0) {
sb.append(", "); sb.append(", ");
} }
sb.append(data[valueId].getSQL()); sb.append(v.getSQL());
} catch(Exception e) { } catch(Exception e) {
writeDataError(writer, "exception " + e, s.getBytes(), blockCount); writeDataError(writer, "exception " + e, s.getBytes(), blockCount);
continue; continue;
......
...@@ -117,14 +117,18 @@ public class FileUtils { ...@@ -117,14 +117,18 @@ public class FileUtils {
if(oldFile.getName().equals(newFile.getName())) { if(oldFile.getName().equals(newFile.getName())) {
throw Message.getInternalError("rename file old=new"); throw Message.getInternalError("rename file old=new");
} }
if(oldFile.exists() && !newFile.exists()) { if(!oldFile.exists()) {
for(int i=0; i<16; i++) { throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
boolean ok = oldFile.renameTo(newFile); }
if(ok) { if(newFile.exists()) {
return; throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
} }
wait(i); for(int i=0; i<16; i++) {
boolean ok = oldFile.renameTo(newFile);
if(ok) {
return;
} }
wait(i);
} }
throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null); throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论