Search in sources :

Example 51 with Store

use of org.h2.mvstore.db.MVTableEngine.Store 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 52 with Store

use of org.h2.mvstore.db.MVTableEngine.Store 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)

Example 53 with Store

use of org.h2.mvstore.db.MVTableEngine.Store in project h2database by h2database.

the class PageDataLeaf method moveTo.

@Override
public void moveTo(Session session, int newPos) {
    PageStore store = index.getPageStore();
    // are written
    if (parentPageId != ROOT) {
        store.getPage(parentPageId);
    }
    store.logUndo(this, data);
    PageDataLeaf p2 = PageDataLeaf.create(index, newPos, parentPageId);
    readAllRows();
    p2.keys = keys;
    p2.overflowRowSize = overflowRowSize;
    p2.firstOverflowPageId = firstOverflowPageId;
    p2.rowRef = rowRef;
    p2.rows = rows;
    if (firstOverflowPageId != 0) {
        p2.rows[0] = getRowAt(0);
    }
    p2.entryCount = entryCount;
    p2.offsets = offsets;
    p2.start = start;
    p2.remapChildren(getPos());
    p2.writeData();
    p2.data.truncate(index.getPageStore().getPageSize());
    store.update(p2);
    if (parentPageId == ROOT) {
        index.setRootPageId(session, newPos);
    } else {
        PageDataNode p = (PageDataNode) store.getPage(parentPageId);
        p.moveChild(getPos(), newPos);
    }
    store.free(getPos());
}
Also used : PageStore(org.h2.store.PageStore)

Example 54 with Store

use of org.h2.mvstore.db.MVTableEngine.Store in project h2database by h2database.

the class PageDataLeaf method getRowAt.

/**
 * Get the row at the given index.
 *
 * @param at the index
 * @return the row
 */
Row getRowAt(int at) {
    Row r = rows[at];
    if (r == null) {
        if (firstOverflowPageId == 0) {
            r = readRow(data, offsets[at], columnCount);
        } else {
            if (rowRef != null) {
                r = rowRef.get();
                if (r != null) {
                    return r;
                }
            }
            PageStore store = index.getPageStore();
            Data buff = store.createData();
            int pageSize = store.getPageSize();
            int offset = offsets[at];
            buff.write(data.getBytes(), offset, pageSize - offset);
            int next = firstOverflowPageId;
            do {
                PageDataOverflow page = index.getPageOverflow(next);
                next = page.readInto(buff);
            } while (next != 0);
            overflowRowSize = pageSize + buff.length();
            r = readRow(buff, 0, columnCount);
        }
        r.setKey(keys[at]);
        if (firstOverflowPageId != 0) {
            rowRef = new SoftReference<>(r);
        } else {
            rows[at] = r;
            memoryChange(true, r);
        }
    }
    return r;
}
Also used : PageStore(org.h2.store.PageStore) Data(org.h2.store.Data) Row(org.h2.result.Row)

Example 55 with Store

use of org.h2.mvstore.db.MVTableEngine.Store in project h2database by h2database.

the class PageDataNode method moveTo.

@Override
public void moveTo(Session session, int newPos) {
    PageStore store = index.getPageStore();
    // are written
    for (int i = 0; i < entryCount + 1; i++) {
        int child = childPageIds[i];
        store.getPage(child);
    }
    if (parentPageId != ROOT) {
        store.getPage(parentPageId);
    }
    store.logUndo(this, data);
    PageDataNode p2 = PageDataNode.create(index, newPos, parentPageId);
    p2.rowCountStored = rowCountStored;
    p2.rowCount = rowCount;
    p2.childPageIds = childPageIds;
    p2.keys = keys;
    p2.entryCount = entryCount;
    p2.length = length;
    store.update(p2);
    if (parentPageId == ROOT) {
        index.setRootPageId(session, newPos);
    } else {
        PageDataNode p = (PageDataNode) store.getPage(parentPageId);
        p.moveChild(getPos(), newPos);
    }
    for (int i = 0; i < entryCount + 1; i++) {
        int child = childPageIds[i];
        PageData p = (PageData) store.getPage(child);
        p.setParentPageId(newPos);
        store.update(p);
    }
    store.free(getPos());
}
Also used : PageStore(org.h2.store.PageStore)

Aggregations

MVStore (org.h2.mvstore.MVStore)29 IOException (java.io.IOException)13 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)12 ByteArrayInputStream (java.io.ByteArrayInputStream)10 InputStream (java.io.InputStream)8 HashMap (java.util.HashMap)8 DbException (org.h2.message.DbException)8 StreamStore (org.h2.mvstore.StreamStore)8 PageStore (org.h2.store.PageStore)8 Random (java.util.Random)7 OutputStream (java.io.OutputStream)6 FileStore (org.h2.store.FileStore)6 BufferedInputStream (java.io.BufferedInputStream)5 ArrayList (java.util.ArrayList)5 FileStore (org.h2.mvstore.FileStore)5 Store (org.h2.mvstore.db.MVTableEngine.Store)5 Row (org.h2.result.Row)5 FileStoreInputStream (org.h2.store.FileStoreInputStream)5 PrintWriter (java.io.PrintWriter)4 Database (org.h2.engine.Database)4