提交 0ec9128a authored 作者: Thomas Mueller's avatar Thomas Mueller

Remove unused code.

上级 e2893192
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.log;
import java.sql.SQLException;
import org.h2.message.Message;
import org.h2.store.PageStore;
/**
* Represents an in-doubt transaction (a transaction in the prepare phase).
*/
public class InDoubtTransaction {
/**
* The transaction state meaning this transaction is not committed yet, but
* also not rolled back (in-doubt).
*/
public static final int IN_DOUBT = 0;
/**
* The transaction state meaning this transaction is committed.
*/
public static final int COMMIT = 1;
/**
* The transaction state meaning this transaction is rolled back.
*/
public static final int ROLLBACK = 2;
// TODO 2-phase-commit: document sql statements and metadata table
private final PageStore store;
private final int sessionId;
private final int pos;
private final String transaction;
private int state;
/**
* Create a new in-doubt transaction info object.
*
* @param store the page store
* @param sessionId the session id
* @param pos the position
* @param transaction the transaction name
*/
public InDoubtTransaction(PageStore store, int sessionId, int pos, String transaction) {
this.store = store;
this.sessionId = sessionId;
this.pos = pos;
this.transaction = transaction;
this.state = IN_DOUBT;
}
/**
* Change the state of this transaction.
* This will also update the log file.
*
* @param state the new state
*/
public void setState(int state) throws SQLException {
switch(state) {
case COMMIT:
store.setInDoubtTransactionState(sessionId, pos, true);
break;
case ROLLBACK:
store.setInDoubtTransactionState(sessionId, pos, false);
break;
default:
Message.throwInternalError("state="+state);
}
this.state = state;
}
/**
* Get the state of this transaction as a text.
*
* @return the transaction state text
*/
public String getState() {
switch(state) {
case IN_DOUBT:
return "IN_DOUBT";
case COMMIT:
return "COMMIT";
case ROLLBACK:
return "ROLLBACK";
default:
throw Message.throwInternalError("state="+state);
}
}
/**
* Get the name of the transaction.
*
* @return the transaction name
*/
public String getTransaction() {
return transaction;
}
}
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.log;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.store.PageStore;
import org.h2.util.ObjectArray;
/**
* The transaction log system is responsible for the write ahead log mechanism
* used in this database.
*/
public class LogSystem {
/**
* This special log position means that the log entry has been written.
*/
public static final int LOG_WRITTEN = -1;
private Database database;
// TODO log file / deleteOldLogFilesAutomatically:
// make this a setting, so they can be backed up
private boolean readOnly;
private boolean flushOnEachCommit;
private boolean closed;
private PageStore pageStore;
private ObjectArray<InDoubtTransaction> inDoubtTransactions;
/**
* Create new transaction log object. This will not open or create files
* yet.
*
* @param database the database
* @param readOnly if the log should be opened in read-only mode
* @param pageStore the page store
*/
public LogSystem(Database database, boolean readOnly, PageStore pageStore) {
this.database = database;
this.pageStore = pageStore;
this.readOnly = readOnly;
closed = true;
}
/**
* Get the list of in-doubt transactions.
*
* @return the list
*/
public ObjectArray<InDoubtTransaction> getInDoubtTransactions() {
if (pageStore != null) {
return pageStore.getInDoubtTransactions();
}
return inDoubtTransactions;
}
/**
* Prepare a transaction.
*
* @param session the session
* @param transaction the name of the transaction
*/
public void prepareCommit(Session session, String transaction) throws SQLException {
if (database == null || readOnly) {
return;
}
synchronized (database) {
pageStore.prepareCommit(session, transaction);
if (closed) {
return;
}
}
}
/**
* Commit the current transaction of the given session.
*
* @param session the session
*/
public void commit(Session session) throws SQLException {
if (database == null || readOnly) {
return;
}
synchronized (database) {
pageStore.commit(session);
session.setAllCommitted();
if (closed) {
return;
}
session.setAllCommitted();
}
}
/**
* Flush all pending changes to the transaction log files.
*/
public void flush() throws SQLException {
if (database == null || readOnly) {
return;
}
synchronized (database) {
pageStore.flushLog();
if (closed) {
return;
}
}
}
/**
* Enable or disable-flush-on-each-commit.
*
* @param b the new value
*/
public void setFlushOnEachCommit(boolean b) {
flushOnEachCommit = b;
}
/**
* Check if flush-on-each-commit is enabled.
*
* @return true if it is
*/
public boolean getFlushOnEachCommit() {
return flushOnEachCommit;
}
/**
* Get the write position.
*
* @return the write position
*/
public String getWritePos() {
return "" + pageStore.getWriteCountTotal();
}
}
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.log;
/**
* The session state contains information about when was the last commit of a
* session. It is only used during recovery.
*/
public class SessionState {
/**
* The session id
*/
public int sessionId;
/**
* The last log file id where a commit for this session is found.
*/
public int lastCommitLog;
/**
* The position where a commit for this session is found.
*/
public int lastCommitPos;
/**
* The in-doubt transaction if there is one.
*/
public InDoubtTransaction inDoubtTransaction;
/**
* Check if this session state is already committed at this point.
*
* @param logId the log file id
* @param pos the position in the log file
* @return true if it is committed
*/
public boolean isCommitted(int logId, int pos) {
if (logId != lastCommitLog) {
return lastCommitLog > logId;
}
return lastCommitPos >= pos;
}
public String toString() {
return "sessionId:" + sessionId + " log:" + lastCommitLog + " pos:" + lastCommitPos + " inDoubt:" + inDoubtTransaction;
}
}
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.log;
import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.store.Data;
import org.h2.store.FileStore;
import org.h2.util.ObjectArray;
/**
* Each session keeps a undo log if rollback is required.
*/
public class UndoLog {
private Database database;
// TODO undo log entry: a chain would probably be faster
// and use less memory than an array
private ObjectArray<UndoLogRecord> records = ObjectArray.newInstance();
private FileStore file;
private Data rowBuff;
private int memoryUndo;
/**
* Create a new undo log for the given session.
*
* @param session the session
*/
public UndoLog(Session session) {
this.database = session.getDatabase();
}
/**
* Get the number of active rows in this undo log.
*
* @return the number of rows
*/
public int size() {
if (SysProperties.CHECK && memoryUndo > records.size()) {
Message.throwInternalError();
}
return records.size();
}
/**
* Clear the undo log. This method is called after the transaction is
* committed.
*/
public void clear() {
records.clear();
memoryUndo = 0;
if (file != null) {
file.closeAndDeleteSilently();
file = null;
rowBuff = null;
}
}
/**
* Get the last record and remove it from the list of operations.
*
* @return the last record
*/
public UndoLogRecord getLast() throws SQLException {
int i = records.size() - 1;
UndoLogRecord entry = records.get(i);
if (entry.isStored()) {
int start = Math.max(0, i - database.getMaxMemoryUndo() / 2);
UndoLogRecord first = null;
for (int j = start; j <= i; j++) {
UndoLogRecord e = records.get(j);
if (e.isStored()) {
e.load(rowBuff, file);
memoryUndo++;
if (first == null) {
first = e;
}
}
}
for (int k = 0; k < i; k++) {
UndoLogRecord e = records.get(k);
e.invalidatePos();
}
first.seek(file);
}
return entry;
}
/**
* Remove the last record from the list of operations.
*
* @param trimToSize if the undo array should shrink to conserve memory
*/
public void removeLast(boolean trimToSize) {
int i = records.size() - 1;
UndoLogRecord r = (UndoLogRecord) records.remove(i);
if (!r.isStored()) {
memoryUndo--;
}
if (trimToSize && i > 1024 && (i & 1023) == 0) {
records.trimToSize();
}
}
/**
* Append an undo log entry to the log.
*
* @param entry the entry
*/
public void add(UndoLogRecord entry) throws SQLException {
records.add(entry);
if (!entry.isStored()) {
memoryUndo++;
}
if (memoryUndo > database.getMaxMemoryUndo() && database.isPersistent() && !database.isMultiVersion()) {
if (file == null) {
String fileName = database.createTempFile();
file = database.openFile(fileName, "rw", false);
file.seek(FileStore.HEADER_LENGTH);
rowBuff = Data.create(database, SysProperties.PAGE_SIZE);
Data buff = rowBuff;
for (int i = 0; i < records.size(); i++) {
UndoLogRecord r = records.get(i);
saveIfPossible(r, buff);
}
} else {
saveIfPossible(entry, rowBuff);
}
file.autoDelete();
}
}
private void saveIfPossible(UndoLogRecord r, Data buff) throws SQLException {
if (!r.isStored() && r.canStore()) {
r.save(buff, file);
memoryUndo--;
}
}
}
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.log;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.Index;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.store.Data;
import org.h2.store.FileStore;
import org.h2.table.Table;
import org.h2.value.Value;
/**
* An entry in a undo log.
*/
public class UndoLogRecord {
/**
* Operation type meaning the row was inserted.
*/
public static final short INSERT = 0;
/**
* Operation type meaning the row was deleted.
*/
public static final short DELETE = 1;
private static final int IN_MEMORY = 0, STORED = 1, IN_MEMORY_INVALID = 2;
private Table table;
private Row row;
private short operation;
private short state;
private int filePos;
/**
* Create a new undo log record
*
* @param table the table
* @param op the operation type
* @param row the row that was deleted or inserted
*/
public UndoLogRecord(Table table, short op, Row row) {
this.table = table;
this.row = row;
this.operation = op;
this.state = IN_MEMORY;
}
/**
* Check if the log record is stored in the file.
*
* @return true if it is
*/
boolean isStored() {
return state == STORED;
}
/**
* Check if this undo log record can be store. Only record can be stored if
* the table has a unique index.
*
* @return if it can be stored
*/
boolean canStore() {
return table.getUniqueIndex() != null;
}
/**
* Un-do the operation. If the row was inserted before, it is deleted now,
* and vice versa.
*
* @param session the session
*/
public void undo(Session session) throws SQLException {
Database db = session.getDatabase();
switch (operation) {
case INSERT:
if (state == IN_MEMORY_INVALID) {
state = IN_MEMORY;
}
if (db.getLockMode() == Constants.LOCK_MODE_OFF) {
if (row.isDeleted()) {
// it might have been deleted by another thread
return;
}
}
try {
row.setDeleted(false);
table.removeRow(session, row);
table.fireAfterRow(session, row, null, true);
} catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
&& e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) {
// it might have been deleted by another thread
// ignore
} else {
throw e;
}
}
break;
case DELETE:
try {
table.addRow(session, row);
table.fireAfterRow(session, null, row, true);
// reset session id, otherwise other session think
// that this row was inserted by this session
row.commit();
} catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
&& e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
// it might have been added by another thread
// ignore
} else {
throw e;
}
}
break;
default:
Message.throwInternalError("op=" + operation);
}
}
/**
* Go to the right position in the file.
*
* @param file the file
*/
void seek(FileStore file) throws SQLException {
file.seek(((long) filePos) * Constants.FILE_BLOCK_SIZE);
}
/**
* Save the row in the file using the data page as a buffer.
*
* @param buff the buffer
* @param file the file
*/
void save(Data buff, FileStore file) throws SQLException {
buff.reset();
buff.writeInt(0);
buff.writeInt(operation);
buff.writeByte(row.isDeleted() ? (byte) 1 : (byte) 0);
buff.writeLong(row.getKey());
buff.writeInt(row.getSessionId());
buff.writeInt(row.getColumnCount());
for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i);
buff.checkCapacity(buff.getValueLen(v));
buff.writeValue(v);
}
buff.fillAligned();
buff.setInt(0, buff.length() / Constants.FILE_BLOCK_SIZE);
filePos = (int) (file.getFilePointer() / Constants.FILE_BLOCK_SIZE);
file.write(buff.getBytes(), 0, buff.length());
row = null;
state = STORED;
}
/**
* Load an undo log record row using the data page as a buffer.
*
* @param buff the buffer
* @param file the source file
*/
void load(Data buff, FileStore file) throws SQLException {
int min = Constants.FILE_BLOCK_SIZE;
seek(file);
buff.reset();
file.readFully(buff.getBytes(), 0, min);
int len = buff.readInt() * Constants.FILE_BLOCK_SIZE;
buff.checkCapacity(len);
if (len - min > 0) {
file.readFully(buff.getBytes(), min, len - min);
}
int op = buff.readInt();
if (SysProperties.CHECK) {
if (operation != op) {
Message.throwInternalError("operation=" + operation + " op=" + op);
}
}
boolean deleted = buff.readByte() == 1;
long key = buff.readLong();
int sessionId = buff.readInt();
int columnCount = buff.readInt();
Value[] values = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
values[i] = buff.readValue();
}
row = new Row(values, 0);
row.setKey(key);
row.setDeleted(deleted);
row.setSessionId(sessionId);
state = IN_MEMORY_INVALID;
}
/**
* Get the table.
*
* @return the table
*/
public Table getTable() {
return table;
}
/**
* This method is called after the operation was committed.
* It commits the change to the indexes.
*/
public void commit() throws SQLException {
for (Index index : table.getIndexes()) {
index.commit(operation, row);
}
}
/**
* Get the row that was deleted or inserted.
*
* @return the row
*/
public Row getRow() {
return row;
}
/**
* Change the state from IN_MEMORY to IN_MEMORY_INVALID. This method is
* called if a later record was read from the temporary file, and therefore
* the position could have changed.
*/
void invalidatePos() {
if (this.state == IN_MEMORY) {
state = IN_MEMORY_INVALID;
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License, Version 1.0,
and under the Eclipse Public License, Version 1.0
(http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;">
Undo and redo log implementation.
</body></html>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论