Search in sources :

Example 1 with DataReader

use of org.h2.store.DataReader in project h2database by h2database.

the class PageLog method readRow.

/**
 * Read a row from an input stream.
 *
 * @param rowFactory the row factory
 * @param in the input stream
 * @param data a temporary buffer
 * @return the row
 */
public static Row readRow(RowFactory rowFactory, DataReader in, Data data) throws IOException {
    long key = in.readVarLong();
    int len = in.readVarInt();
    data.reset();
    data.checkCapacity(len);
    in.readFully(data.getBytes(), len);
    int columnCount = data.readVarInt();
    Value[] values = new Value[columnCount];
    for (int i = 0; i < columnCount; i++) {
        values[i] = data.readValue();
    }
    Row row = rowFactory.createRow(values, Row.MEMORY_CALCULATE);
    row.setKey(key);
    return row;
}
Also used : Value(org.h2.value.Value) Row(org.h2.result.Row)

Example 2 with DataReader

use of org.h2.store.DataReader in project h2database by h2database.

the class Recover method dumpPageLogStream.

private void dumpPageLogStream(PrintWriter writer, int logKey, int logFirstTrunkPage, int logFirstDataPage, long pageCount) throws IOException {
    Data s = Data.create(this, pageSize);
    DataReader in = new DataReader(new PageInputStream(writer, this, store, logKey, logFirstTrunkPage, logFirstDataPage, pageSize));
    writer.println("---- Transaction log ----");
    CompressLZF compress = new CompressLZF();
    while (true) {
        int x = in.readByte();
        if (x < 0) {
            break;
        }
        if (x == PageLog.NOOP) {
        // ignore
        } else if (x == PageLog.UNDO) {
            int pageId = in.readVarInt();
            int size = in.readVarInt();
            byte[] data = new byte[pageSize];
            if (size == 0) {
                in.readFully(data, pageSize);
            } else if (size == 1) {
            // empty
            } else {
                byte[] compressBuffer = new byte[size];
                in.readFully(compressBuffer, size);
                try {
                    compress.expand(compressBuffer, 0, size, data, 0, pageSize);
                } catch (ArrayIndexOutOfBoundsException e) {
                    throw DbException.convertToIOException(e);
                }
            }
            String typeName = "";
            int type = data[0];
            boolean last = (type & Page.FLAG_LAST) != 0;
            type &= ~Page.FLAG_LAST;
            switch(type) {
                case Page.TYPE_EMPTY:
                    typeName = "empty";
                    break;
                case Page.TYPE_DATA_LEAF:
                    typeName = "data leaf " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_DATA_NODE:
                    typeName = "data node " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_DATA_OVERFLOW:
                    typeName = "data overflow " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_BTREE_LEAF:
                    typeName = "b-tree leaf " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_BTREE_NODE:
                    typeName = "b-tree node " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_FREE_LIST:
                    typeName = "free list " + (last ? "(last)" : "");
                    break;
                case Page.TYPE_STREAM_TRUNK:
                    typeName = "log trunk";
                    break;
                case Page.TYPE_STREAM_DATA:
                    typeName = "log data";
                    break;
                default:
                    typeName = "ERROR: unknown type " + type;
                    break;
            }
            writer.println("-- undo page " + pageId + " " + typeName);
            if (trace) {
                Data d = Data.create(null, data);
                dumpPage(writer, d, pageId, pageCount);
            }
        } else if (x == PageLog.ADD) {
            int sessionId = in.readVarInt();
            setStorage(in.readVarInt());
            Row row = PageLog.readRow(RowFactory.DEFAULT, in, s);
            writer.println("-- session " + sessionId + " table " + storageId + " + " + row.toString());
            if (transactionLog) {
                if (storageId == 0 && row.getColumnCount() >= 4) {
                    int tableId = (int) row.getKey();
                    String sql = row.getValue(3).getString();
                    String name = extractTableOrViewName(sql);
                    if (row.getValue(2).getInt() == DbObject.TABLE_OR_VIEW) {
                        tableMap.put(tableId, name);
                    }
                    writer.println(sql + ";");
                } else {
                    String tableName = tableMap.get(storageId);
                    if (tableName != null) {
                        StatementBuilder buff = new StatementBuilder();
                        buff.append("INSERT INTO ").append(tableName).append(" VALUES(");
                        for (int i = 0; i < row.getColumnCount(); i++) {
                            buff.appendExceptFirst(", ");
                            buff.append(row.getValue(i).getSQL());
                        }
                        buff.append(");");
                        writer.println(buff.toString());
                    }
                }
            }
        } else if (x == PageLog.REMOVE) {
            int sessionId = in.readVarInt();
            setStorage(in.readVarInt());
            long key = in.readVarLong();
            writer.println("-- session " + sessionId + " table " + storageId + " - " + key);
            if (transactionLog) {
                if (storageId == 0) {
                    int tableId = (int) key;
                    String tableName = tableMap.get(tableId);
                    if (tableName != null) {
                        writer.println("DROP TABLE IF EXISTS " + tableName + ";");
                    }
                } else {
                    String tableName = tableMap.get(storageId);
                    if (tableName != null) {
                        String sql = "DELETE FROM " + tableName + " WHERE _ROWID_ = " + key + ";";
                        writer.println(sql);
                    }
                }
            }
        } else if (x == PageLog.TRUNCATE) {
            int sessionId = in.readVarInt();
            setStorage(in.readVarInt());
            writer.println("-- session " + sessionId + " table " + storageId + " truncate");
            if (transactionLog) {
                writer.println("TRUNCATE TABLE " + storageId);
            }
        } else if (x == PageLog.COMMIT) {
            int sessionId = in.readVarInt();
            writer.println("-- commit " + sessionId);
        } else if (x == PageLog.ROLLBACK) {
            int sessionId = in.readVarInt();
            writer.println("-- rollback " + sessionId);
        } else if (x == PageLog.PREPARE_COMMIT) {
            int sessionId = in.readVarInt();
            String transaction = in.readString();
            writer.println("-- prepare commit " + sessionId + " " + transaction);
        } else if (x == PageLog.NOOP) {
        // nothing to do
        } else if (x == PageLog.CHECKPOINT) {
            writer.println("-- checkpoint");
        } else if (x == PageLog.FREE_LOG) {
            int size = in.readVarInt();
            StringBuilder buff = new StringBuilder("-- free");
            for (int i = 0; i < size; i++) {
                buff.append(' ').append(in.readVarInt());
            }
            writer.println(buff);
        } else {
            writer.println("-- ERROR: unknown operation " + x);
            break;
        }
    }
}
Also used : DataReader(org.h2.store.DataReader) CompressLZF(org.h2.compress.CompressLZF) StatementBuilder(org.h2.util.StatementBuilder) Data(org.h2.store.Data) Row(org.h2.result.Row) SimpleRow(org.h2.result.SimpleRow)

Example 3 with DataReader

use of org.h2.store.DataReader in project h2database by h2database.

the class PageLog method recover.

/**
 * Run one recovery stage. There are three recovery stages: 0: only the undo
 * steps are run (restoring the state before the last checkpoint). 1: the
 * pages that are used by the transaction log are allocated. 2: the
 * committed operations are re-applied.
 *
 * @param stage the recovery stage
 * @return whether the transaction log was empty
 */
boolean recover(int stage) {
    if (trace.isDebugEnabled()) {
        trace.debug("log recover stage: " + stage);
    }
    if (stage == RECOVERY_STAGE_ALLOCATE) {
        PageInputStream in = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
        usedLogPages = in.allocateAllPages();
        in.close();
        return true;
    }
    PageInputStream pageIn = new PageInputStream(store, logKey, firstTrunkPage, firstDataPage);
    DataReader in = new DataReader(pageIn);
    int logId = 0;
    Data data = store.createData();
    boolean isEmpty = true;
    try {
        int pos = 0;
        while (true) {
            int x = in.readByte();
            if (x < 0) {
                break;
            }
            pos++;
            isEmpty = false;
            if (x == UNDO) {
                int pageId = in.readVarInt();
                int size = in.readVarInt();
                if (size == 0) {
                    in.readFully(data.getBytes(), store.getPageSize());
                } else if (size == 1) {
                    // empty
                    Arrays.fill(data.getBytes(), 0, store.getPageSize(), (byte) 0);
                } else {
                    in.readFully(compressBuffer, size);
                    try {
                        compress.expand(compressBuffer, 0, size, data.getBytes(), 0, store.getPageSize());
                    } catch (ArrayIndexOutOfBoundsException e) {
                        DbException.convertToIOException(e);
                    }
                }
                if (stage == RECOVERY_STAGE_UNDO) {
                    if (!undo.get(pageId)) {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log undo {0}", pageId);
                        }
                        store.writePage(pageId, data);
                        undo.set(pageId);
                        undoAll.set(pageId);
                    } else {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log undo skip {0}", pageId);
                        }
                    }
                }
            } else if (x == ADD) {
                int sessionId = in.readVarInt();
                int tableId = in.readVarInt();
                Row row = readRow(store.getDatabase().getRowFactory(), in, data);
                if (stage == RECOVERY_STAGE_UNDO) {
                    store.allocateIfIndexRoot(pos, tableId, row);
                } else if (stage == RECOVERY_STAGE_REDO) {
                    if (isSessionCommitted(sessionId, logId, pos)) {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log redo + table: " + tableId + " s: " + sessionId + " " + row);
                        }
                        store.redo(tableId, row, true);
                    } else {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log ignore s: " + sessionId + " + table: " + tableId + " " + row);
                        }
                    }
                }
            } else if (x == REMOVE) {
                int sessionId = in.readVarInt();
                int tableId = in.readVarInt();
                long key = in.readVarLong();
                if (stage == RECOVERY_STAGE_REDO) {
                    if (isSessionCommitted(sessionId, logId, pos)) {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log redo - table: " + tableId + " s:" + sessionId + " key: " + key);
                        }
                        store.redoDelete(tableId, key);
                    } else {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log ignore s: " + sessionId + " - table: " + tableId + " " + key);
                        }
                    }
                }
            } else if (x == TRUNCATE) {
                int sessionId = in.readVarInt();
                int tableId = in.readVarInt();
                if (stage == RECOVERY_STAGE_REDO) {
                    if (isSessionCommitted(sessionId, logId, pos)) {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log redo truncate table: " + tableId);
                        }
                        store.redoTruncate(tableId);
                    } else {
                        if (trace.isDebugEnabled()) {
                            trace.debug("log ignore s: " + sessionId + " truncate table: " + tableId);
                        }
                    }
                }
            } else if (x == PREPARE_COMMIT) {
                int sessionId = in.readVarInt();
                String transaction = in.readString();
                if (trace.isDebugEnabled()) {
                    trace.debug("log prepare commit " + sessionId + " " + transaction + " pos: " + pos);
                }
                if (stage == RECOVERY_STAGE_UNDO) {
                    int page = pageIn.getDataPage();
                    setPrepareCommit(sessionId, page, transaction);
                }
            } else if (x == ROLLBACK) {
                int sessionId = in.readVarInt();
                if (trace.isDebugEnabled()) {
                    trace.debug("log rollback " + sessionId + " pos: " + pos);
                }
            // ignore - this entry is just informational
            } else if (x == COMMIT) {
                int sessionId = in.readVarInt();
                if (trace.isDebugEnabled()) {
                    trace.debug("log commit " + sessionId + " pos: " + pos);
                }
                if (stage == RECOVERY_STAGE_UNDO) {
                    setLastCommitForSession(sessionId, logId, pos);
                }
            } else if (x == NOOP) {
            // nothing to do
            } else if (x == CHECKPOINT) {
                logId++;
            } else if (x == FREE_LOG) {
                int count = in.readVarInt();
                for (int i = 0; i < count; i++) {
                    int pageId = in.readVarInt();
                    if (stage == RECOVERY_STAGE_REDO) {
                        if (!usedLogPages.get(pageId)) {
                            store.free(pageId, false);
                        }
                    }
                }
            } else {
                if (trace.isDebugEnabled()) {
                    trace.debug("log end");
                    break;
                }
            }
        }
    } catch (DbException e) {
        if (e.getErrorCode() == ErrorCode.FILE_CORRUPTED_1) {
            trace.debug("log recovery stopped");
        } else {
            throw e;
        }
    } catch (IOException e) {
        trace.debug("log recovery completed");
    }
    undo = new BitSet();
    if (stage == RECOVERY_STAGE_REDO) {
        usedLogPages = null;
    }
    return isEmpty;
}
Also used : BitSet(java.util.BitSet) Row(org.h2.result.Row) IOException(java.io.IOException) DbException(org.h2.message.DbException)

Aggregations

Row (org.h2.result.Row)3 IOException (java.io.IOException)1 BitSet (java.util.BitSet)1 CompressLZF (org.h2.compress.CompressLZF)1 DbException (org.h2.message.DbException)1 SimpleRow (org.h2.result.SimpleRow)1 Data (org.h2.store.Data)1 DataReader (org.h2.store.DataReader)1 StatementBuilder (org.h2.util.StatementBuilder)1 Value (org.h2.value.Value)1