Search in sources :

Example 41 with Page

use of org.h2.mvstore.Page in project h2database by h2database.

the class WebApp method query.

private String query() {
    String sql = attributes.getProperty("sql").trim();
    try {
        ScriptReader r = new ScriptReader(new StringReader(sql));
        final ArrayList<String> list = New.arrayList();
        while (true) {
            String s = r.readStatement();
            if (s == null) {
                break;
            }
            list.add(s);
        }
        final Connection conn = session.getConnection();
        if (SysProperties.CONSOLE_STREAM && server.getAllowChunked()) {
            String page = new String(server.getFile("result.jsp"), StandardCharsets.UTF_8);
            int idx = page.indexOf("${result}");
            // the first element of the list is the header, the last the
            // footer
            list.add(0, page.substring(0, idx));
            list.add(page.substring(idx + "${result}".length()));
            session.put("chunks", new Iterator<String>() {

                private int i;

                @Override
                public boolean hasNext() {
                    return i < list.size();
                }

                @Override
                public String next() {
                    String s = list.get(i++);
                    if (i == 1 || i == list.size()) {
                        return s;
                    }
                    StringBuilder b = new StringBuilder();
                    query(conn, s, i - 1, list.size() - 2, b);
                    return b.toString();
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            });
            return "result.jsp";
        }
        String result;
        StringBuilder buff = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            query(conn, s, i, list.size(), buff);
        }
        result = buff.toString();
        session.put("result", result);
    } catch (Throwable e) {
        session.put("result", getStackTrace(0, e, session.getContents().isH2()));
    }
    return "result.jsp";
}
Also used : StringReader(java.io.StringReader) Connection(java.sql.Connection) ScriptReader(org.h2.util.ScriptReader)

Example 42 with Page

use of org.h2.mvstore.Page 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 43 with Page

use of org.h2.mvstore.Page 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 44 with Page

use of org.h2.mvstore.Page in project h2database by h2database.

the class PageStore method compact.

/**
 * Shrink the file so there are no empty pages at the end.
 *
 * @param compactMode 0 if no compacting should happen, otherwise
 * TransactionCommand.SHUTDOWN_COMPACT or TransactionCommand.SHUTDOWN_DEFRAG
 */
public synchronized void compact(int compactMode) {
    if (!database.getSettings().pageStoreTrim) {
        return;
    }
    if (SysProperties.MODIFY_ON_WRITE && readMode && compactMode == 0) {
        return;
    }
    openForWriting();
    // find the last used page
    int lastUsed = -1;
    for (int i = getFreeListId(pageCount); i >= 0; i--) {
        lastUsed = getFreeList(i).getLastUsed();
        if (lastUsed != -1) {
            break;
        }
    }
    // open a new log at the very end
    // (to be truncated later)
    writeBack();
    log.free();
    recoveryRunning = true;
    try {
        logFirstTrunkPage = lastUsed + 1;
        allocatePage(logFirstTrunkPage);
        log.openForWriting(logFirstTrunkPage, true);
        // ensure the free list is backed up again
        log.checkpoint();
    } finally {
        recoveryRunning = false;
    }
    long start = System.nanoTime();
    boolean isCompactFully = compactMode == CommandInterface.SHUTDOWN_COMPACT;
    boolean isDefrag = compactMode == CommandInterface.SHUTDOWN_DEFRAG;
    if (database.getSettings().defragAlways) {
        isCompactFully = isDefrag = true;
    }
    int maxCompactTime = database.getSettings().maxCompactTime;
    int maxMove = database.getSettings().maxCompactCount;
    if (isCompactFully || isDefrag) {
        maxCompactTime = Integer.MAX_VALUE;
        maxMove = Integer.MAX_VALUE;
    }
    int blockSize = isCompactFully ? COMPACT_BLOCK_SIZE : 1;
    int firstFree = MIN_PAGE_COUNT;
    for (int x = lastUsed, j = 0; x > MIN_PAGE_COUNT && j < maxMove; x -= blockSize) {
        for (int full = x - blockSize + 1; full <= x; full++) {
            if (full > MIN_PAGE_COUNT && isUsed(full)) {
                synchronized (this) {
                    firstFree = getFirstFree(firstFree);
                    if (firstFree == -1 || firstFree >= full) {
                        j = maxMove;
                        break;
                    }
                    if (compact(full, firstFree)) {
                        j++;
                        long now = System.nanoTime();
                        if (now > start + TimeUnit.MILLISECONDS.toNanos(maxCompactTime)) {
                            j = maxMove;
                            break;
                        }
                    }
                }
            }
        }
    }
    if (isDefrag) {
        log.checkpoint();
        writeBack();
        cache.clear();
        ArrayList<Table> tables = database.getAllTablesAndViews(false);
        recordedPagesList = New.arrayList();
        recordedPagesIndex = new IntIntHashMap();
        recordPageReads = true;
        Session sysSession = database.getSystemSession();
        for (Table table : tables) {
            if (!table.isTemporary() && TableType.TABLE == table.getTableType()) {
                Index scanIndex = table.getScanIndex(sysSession);
                Cursor cursor = scanIndex.find(sysSession, null, null);
                while (cursor.next()) {
                    cursor.get();
                }
                for (Index index : table.getIndexes()) {
                    if (index != scanIndex && index.canScan()) {
                        cursor = index.find(sysSession, null, null);
                        while (cursor.next()) {
                        // the data is already read
                        }
                    }
                }
            }
        }
        recordPageReads = false;
        int target = MIN_PAGE_COUNT - 1;
        int temp = 0;
        for (int i = 0, size = recordedPagesList.size(); i < size; i++) {
            log.checkpoint();
            writeBack();
            int source = recordedPagesList.get(i);
            Page pageSource = getPage(source);
            if (!pageSource.canMove()) {
                continue;
            }
            while (true) {
                Page pageTarget = getPage(++target);
                if (pageTarget == null || pageTarget.canMove()) {
                    break;
                }
            }
            if (target == source) {
                continue;
            }
            temp = getFirstFree(temp);
            if (temp == -1) {
                DbException.throwInternalError("no free page for defrag");
            }
            cache.clear();
            swap(source, target, temp);
            int index = recordedPagesIndex.get(target);
            if (index != IntIntHashMap.NOT_FOUND) {
                recordedPagesList.set(index, source);
                recordedPagesIndex.put(source, index);
            }
            recordedPagesList.set(i, target);
            recordedPagesIndex.put(target, i);
        }
        recordedPagesList = null;
        recordedPagesIndex = null;
    }
    // TODO can most likely be simplified
    checkpoint();
    log.checkpoint();
    writeIndexRowCounts();
    log.checkpoint();
    writeBack();
    commit(pageStoreSession);
    writeBack();
    log.checkpoint();
    log.free();
    // truncate the log
    recoveryRunning = true;
    try {
        setLogFirstPage(++logKey, 0, 0);
    } finally {
        recoveryRunning = false;
    }
    writeBack();
    for (int i = getFreeListId(pageCount); i >= 0; i--) {
        lastUsed = getFreeList(i).getLastUsed();
        if (lastUsed != -1) {
            break;
        }
    }
    int newPageCount = lastUsed + 1;
    if (newPageCount < pageCount) {
        freed.set(newPageCount, pageCount, false);
    }
    pageCount = newPageCount;
    // the easiest way to remove superfluous entries
    freeLists.clear();
    trace.debug("pageCount: " + pageCount);
    long newLength = (long) pageCount << pageSizeShift;
    if (file.length() != newLength) {
        file.setLength(newLength);
        writeCount++;
    }
}
Also used : IntIntHashMap(org.h2.util.IntIntHashMap) RegularTable(org.h2.table.RegularTable) Table(org.h2.table.Table) Index(org.h2.index.Index) PageIndex(org.h2.index.PageIndex) PageDelegateIndex(org.h2.index.PageDelegateIndex) MultiVersionIndex(org.h2.index.MultiVersionIndex) PageBtreeIndex(org.h2.index.PageBtreeIndex) PageDataIndex(org.h2.index.PageDataIndex) Cursor(org.h2.index.Cursor) Session(org.h2.engine.Session)

Example 45 with Page

use of org.h2.mvstore.Page in project h2database by h2database.

the class PageStore method readStaticHeader.

private void readStaticHeader() {
    file.seek(FileStore.HEADER_LENGTH);
    Data page = Data.create(database, new byte[PAGE_SIZE_MIN - FileStore.HEADER_LENGTH]);
    file.readFully(page.getBytes(), 0, PAGE_SIZE_MIN - FileStore.HEADER_LENGTH);
    readCount++;
    setPageSize(page.readInt());
    int writeVersion = page.readByte();
    int readVersion = page.readByte();
    if (readVersion > READ_VERSION) {
        throw DbException.get(ErrorCode.FILE_VERSION_ERROR_1, fileName);
    }
    if (writeVersion > WRITE_VERSION) {
        close();
        database.setReadOnly(true);
        accessMode = "r";
        file = database.openFile(fileName, accessMode, true);
    }
}
Also used : CreateTableData(org.h2.command.ddl.CreateTableData)

Aggregations

CreateTableData (org.h2.command.ddl.CreateTableData)9 Value (org.h2.value.Value)8 Data (org.h2.store.Data)7 Column (org.h2.table.Column)6 Page (org.h2.mvstore.Page)5 IndexColumn (org.h2.table.IndexColumn)5 ResultSet (java.sql.ResultSet)4 SQLException (java.sql.SQLException)4 QueryCancelledException (org.apache.ignite.cache.query.QueryCancelledException)4 DataRegionConfiguration (org.apache.ignite.configuration.DataRegionConfiguration)4 UnsafeMemoryProvider (org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider)4 PageMemory (org.apache.ignite.internal.pagemem.PageMemory)4 PageMemoryNoStoreImpl (org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl)4 DataRegionMetricsImpl (org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl)4 GridCacheSqlQuery (org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery)4 Row (org.h2.result.Row)4 Connection (java.sql.Connection)3 ArrayList (java.util.ArrayList)3 CRC32 (java.util.zip.CRC32)3 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)3