提交 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,8 +194,10 @@ public class DiskFile implements CacheWriter { ...@@ -194,8 +194,10 @@ 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);
if(s.getDiskFile() == this) {
database.removeStorage(s.getId(), this); database.removeStorage(s.getId(), this);
} }
}
reset(); reset();
initAlreadyTried = false; initAlreadyTried = false;
init = false; init = 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;
} }
......
...@@ -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;
try { int size = 0;
String n = fileName + (lobCompression ? ".comp" : "") + ".txt"; String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
try {
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) {
// this is usually not a problem, because we try both compressed and uncompressed
if(log) {
logError(fileName, e); 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;
try {
store.readFully(buff, blockSize, blocks * blockSize - blockSize); 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,7 +117,12 @@ public class FileUtils { ...@@ -117,7 +117,12 @@ 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()) {
throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
}
if(newFile.exists()) {
throw Message.getSQLException(Message.FILE_RENAME_FAILED_2, new String[]{oldName, newName}, null);
}
for(int i=0; i<16; i++) { for(int i=0; i<16; i++) {
boolean ok = oldFile.renameTo(newFile); boolean ok = oldFile.renameTo(newFile);
if(ok) { if(ok) {
...@@ -125,7 +130,6 @@ public class FileUtils { ...@@ -125,7 +130,6 @@ public class FileUtils {
} }
wait(i); 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论