Search in sources :

Example 1 with FileLockMethod

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

the class Engine method createSessionAndValidate.

private Session createSessionAndValidate(ConnectionInfo ci) {
    try {
        ConnectionInfo backup = null;
        String lockMethodName = ci.getProperty("FILE_LOCK", null);
        FileLockMethod fileLockMethod = FileLock.getFileLockMethod(lockMethodName);
        if (fileLockMethod == FileLockMethod.SERIALIZED) {
            // In serialized mode, database instance sharing is not possible
            ci.setProperty("OPEN_NEW", "TRUE");
            try {
                backup = ci.clone();
            } catch (CloneNotSupportedException e) {
                throw DbException.convert(e);
            }
        }
        Session session = openSession(ci);
        validateUserAndPassword(true);
        if (backup != null) {
            session.setConnectionInfo(backup);
        }
        return session;
    } catch (DbException e) {
        if (e.getErrorCode() == ErrorCode.WRONG_USER_OR_PASSWORD) {
            validateUserAndPassword(false);
        }
        throw e;
    }
}
Also used : FileLockMethod(org.h2.store.FileLockMethod) DbException(org.h2.message.DbException)

Example 2 with FileLockMethod

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

the class Database method reconnectModified.

/**
 * Set or reset the pending change flag in the .lock.db file.
 *
 * @param pending the new value of the flag
 * @return true if the call was successful,
 *          false if another connection was faster
 */
private synchronized boolean reconnectModified(boolean pending) {
    if (readOnly || lock == null || fileLockMethod != FileLockMethod.SERIALIZED) {
        return true;
    }
    try {
        if (pending == reconnectChangePending) {
            long now = System.nanoTime();
            if (now > reconnectCheckNext) {
                if (pending) {
                    String pos = pageStore == null ? null : "" + pageStore.getWriteCountTotal();
                    lock.setProperty("logPos", pos);
                    lock.save();
                }
                reconnectCheckNext = now + reconnectCheckDelayNs;
            }
            return true;
        }
        Properties old = lock.load();
        if (pending) {
            if (old.getProperty("changePending") != null) {
                return false;
            }
            trace.debug("wait before writing");
            Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (reconnectCheckDelayNs * 1.1)));
            Properties now = lock.load();
            if (!now.equals(old)) {
                // somebody else was faster
                return false;
            }
        }
        String pos = pageStore == null ? null : "" + pageStore.getWriteCountTotal();
        lock.setProperty("logPos", pos);
        if (pending) {
            lock.setProperty("changePending", "true-" + Math.random());
        } else {
            lock.setProperty("changePending", null);
        }
        // ensure that the writer thread will
        // not reset the flag before we are done
        reconnectCheckNext = System.nanoTime() + 2 * reconnectCheckDelayNs;
        old = lock.save();
        if (pending) {
            trace.debug("wait before writing again");
            Thread.sleep(TimeUnit.NANOSECONDS.toMillis((long) (reconnectCheckDelayNs * 1.1)));
            Properties now = lock.load();
            if (!now.equals(old)) {
                // somebody else was faster
                return false;
            }
        } else {
            Thread.sleep(1);
        }
        reconnectLastLock = old;
        reconnectChangePending = pending;
        reconnectCheckNext = System.nanoTime() + reconnectCheckDelayNs;
        return true;
    } catch (Exception e) {
        trace.error(e, "pending {0}", pending);
        return false;
    }
}
Also used : Properties(java.util.Properties) DbException(org.h2.message.DbException) SQLException(java.sql.SQLException) IOException(java.io.IOException)

Example 3 with FileLockMethod

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

the class Database method isReconnectNeeded.

/**
 * Check if the contents of the database was changed and therefore it is
 * required to re-connect. This method waits until pending changes are
 * completed. If a pending change takes too long (more than 2 seconds), the
 * pending change is broken (removed from the properties file).
 *
 * @return true if reconnecting is required
 */
public boolean isReconnectNeeded() {
    if (fileLockMethod != FileLockMethod.SERIALIZED) {
        return false;
    }
    if (reconnectChangePending) {
        return false;
    }
    long now = System.nanoTime();
    if (now < reconnectCheckNext) {
        return false;
    }
    reconnectCheckNext = now + reconnectCheckDelayNs;
    if (lock == null) {
        lock = new FileLock(traceSystem, databaseName + Constants.SUFFIX_LOCK_FILE, Constants.LOCK_SLEEP);
    }
    try {
        Properties prop = lock.load(), first = prop;
        while (true) {
            if (prop.equals(reconnectLastLock)) {
                return false;
            }
            if (prop.getProperty("changePending", null) == null) {
                break;
            }
            if (System.nanoTime() > now + reconnectCheckDelayNs * 10) {
                if (first.equals(prop)) {
                    // the writing process didn't update the file -
                    // it may have terminated
                    lock.setProperty("changePending", null);
                    lock.save();
                    break;
                }
            }
            trace.debug("delay (change pending)");
            Thread.sleep(TimeUnit.NANOSECONDS.toMillis(reconnectCheckDelayNs));
            prop = lock.load();
        }
        reconnectLastLock = prop;
    } catch (Exception e) {
        // DbException, InterruptedException
        trace.error(e, "readOnly {0}", readOnly);
    // ignore
    }
    return true;
}
Also used : FileLock(org.h2.store.FileLock) Properties(java.util.Properties) DbException(org.h2.message.DbException) SQLException(java.sql.SQLException) IOException(java.io.IOException)

Example 4 with FileLockMethod

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

the class Database method getPageStore.

public PageStore getPageStore() {
    if (dbSettings.mvStore) {
        if (mvStore == null) {
            mvStore = MVTableEngine.init(this);
        }
        return null;
    }
    if (pageStore == null) {
        pageStore = new PageStore(this, databaseName + Constants.SUFFIX_PAGE_FILE, accessModeData, cacheSize);
        if (pageSize != Constants.DEFAULT_PAGE_SIZE) {
            pageStore.setPageSize(pageSize);
        }
        if (!readOnly && fileLockMethod == FileLockMethod.FS) {
            pageStore.setLockFile(true);
        }
        pageStore.setLogMode(logMode);
        pageStore.open();
    }
    return pageStore;
}
Also used : PageStore(org.h2.store.PageStore)

Example 5 with FileLockMethod

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

the class Database method open.

private synchronized void open(int traceLevelFile, int traceLevelSystemOut) {
    if (persistent) {
        String dataFileName = databaseName + Constants.SUFFIX_OLD_DATABASE_FILE;
        boolean existsData = FileUtils.exists(dataFileName);
        String pageFileName = databaseName + Constants.SUFFIX_PAGE_FILE;
        String mvFileName = databaseName + Constants.SUFFIX_MV_FILE;
        boolean existsPage = FileUtils.exists(pageFileName);
        boolean existsMv = FileUtils.exists(mvFileName);
        if (existsData && (!existsPage && !existsMv)) {
            throw DbException.get(ErrorCode.FILE_VERSION_ERROR_1, "Old database: " + dataFileName + " - please convert the database " + "to a SQL script and re-create it.");
        }
        if (existsPage && !FileUtils.canWrite(pageFileName)) {
            readOnly = true;
        }
        if (existsMv && !FileUtils.canWrite(mvFileName)) {
            readOnly = true;
        }
        if (existsPage && !existsMv) {
            dbSettings.mvStore = false;
        }
        if (readOnly) {
            if (traceLevelFile >= TraceSystem.DEBUG) {
                String traceFile = Utils.getProperty("java.io.tmpdir", ".") + "/" + "h2_" + System.currentTimeMillis();
                traceSystem = new TraceSystem(traceFile + Constants.SUFFIX_TRACE_FILE);
            } else {
                traceSystem = new TraceSystem(null);
            }
        } else {
            traceSystem = new TraceSystem(databaseName + Constants.SUFFIX_TRACE_FILE);
        }
        traceSystem.setLevelFile(traceLevelFile);
        traceSystem.setLevelSystemOut(traceLevelSystemOut);
        trace = traceSystem.getTrace(Trace.DATABASE);
        trace.info("opening {0} (build {1})", databaseName, Constants.BUILD_ID);
        if (autoServerMode) {
            if (readOnly || fileLockMethod == FileLockMethod.NO || fileLockMethod == FileLockMethod.SERIALIZED || fileLockMethod == FileLockMethod.FS || !persistent) {
                throw DbException.getUnsupportedException("autoServerMode && (readOnly || " + "fileLockMethod == NO || " + "fileLockMethod == SERIALIZED || " + "fileLockMethod == FS || " + "inMemory)");
            }
        }
        String lockFileName = databaseName + Constants.SUFFIX_LOCK_FILE;
        if (readOnly) {
            if (FileUtils.exists(lockFileName)) {
                throw DbException.get(ErrorCode.DATABASE_ALREADY_OPEN_1, "Lock file exists: " + lockFileName);
            }
        }
        if (!readOnly && fileLockMethod != FileLockMethod.NO) {
            if (fileLockMethod != FileLockMethod.FS) {
                lock = new FileLock(traceSystem, lockFileName, Constants.LOCK_SLEEP);
                lock.lock(fileLockMethod);
                if (autoServerMode) {
                    startServer(lock.getUniqueId());
                }
            }
        }
        if (SysProperties.MODIFY_ON_WRITE) {
            while (isReconnectNeeded()) {
            // wait until others stopped writing
            }
        } else {
            while (isReconnectNeeded() && !beforeWriting()) {
            // wait until others stopped writing and
            // until we can write (the file is not yet open -
            // no need to re-connect)
            }
        }
        deleteOldTempFiles();
        starting = true;
        if (SysProperties.MODIFY_ON_WRITE) {
            try {
                getPageStore();
            } catch (DbException e) {
                if (e.getErrorCode() != ErrorCode.DATABASE_IS_READ_ONLY) {
                    throw e;
                }
                pageStore = null;
                while (!beforeWriting()) {
                // wait until others stopped writing and
                // until we can write (the file is not yet open -
                // no need to re-connect)
                }
                getPageStore();
            }
        } else {
            getPageStore();
        }
        starting = false;
        if (mvStore == null) {
            writer = WriterThread.create(this, writeDelay);
        } else {
            setWriteDelay(writeDelay);
        }
    } else {
        if (autoServerMode) {
            throw DbException.getUnsupportedException("autoServerMode && inMemory");
        }
        traceSystem = new TraceSystem(null);
        trace = traceSystem.getTrace(Trace.DATABASE);
        if (dbSettings.mvStore) {
            getPageStore();
        }
    }
    systemUser = new User(this, 0, SYSTEM_USER_NAME, true);
    mainSchema = new Schema(this, 0, Constants.SCHEMA_MAIN, systemUser, true);
    infoSchema = new Schema(this, -1, "INFORMATION_SCHEMA", systemUser, true);
    schemas.put(mainSchema.getName(), mainSchema);
    schemas.put(infoSchema.getName(), infoSchema);
    publicRole = new Role(this, 0, Constants.PUBLIC_ROLE_NAME, true);
    roles.put(Constants.PUBLIC_ROLE_NAME, publicRole);
    systemUser.setAdmin(true);
    systemSession = new Session(this, systemUser, ++nextSessionId);
    lobSession = new Session(this, systemUser, ++nextSessionId);
    CreateTableData data = new CreateTableData();
    ArrayList<Column> cols = data.columns;
    Column columnId = new Column("ID", Value.INT);
    columnId.setNullable(false);
    cols.add(columnId);
    cols.add(new Column("HEAD", Value.INT));
    cols.add(new Column("TYPE", Value.INT));
    cols.add(new Column("SQL", Value.STRING));
    boolean create = true;
    if (pageStore != null) {
        create = pageStore.isNew();
    }
    data.tableName = "SYS";
    data.id = 0;
    data.temporary = false;
    data.persistData = persistent;
    data.persistIndexes = persistent;
    data.create = create;
    data.isHidden = true;
    data.session = systemSession;
    meta = mainSchema.createTable(data);
    IndexColumn[] pkCols = IndexColumn.wrap(new Column[] { columnId });
    metaIdIndex = meta.addIndex(systemSession, "SYS_ID", 0, pkCols, IndexType.createPrimaryKey(false, false), true, null);
    objectIds.set(0);
    starting = true;
    Cursor cursor = metaIdIndex.find(systemSession, null, null);
    ArrayList<MetaRecord> records = New.arrayList();
    while (cursor.next()) {
        MetaRecord rec = new MetaRecord(cursor.get());
        objectIds.set(rec.getId());
        records.add(rec);
    }
    Collections.sort(records);
    synchronized (systemSession) {
        for (MetaRecord rec : records) {
            rec.execute(this, systemSession, eventListener);
        }
    }
    if (mvStore != null) {
        mvStore.initTransactions();
        mvStore.removeTemporaryMaps(objectIds);
    }
    recompileInvalidViews(systemSession);
    starting = false;
    if (!readOnly) {
        // set CREATE_BUILD in a new database
        String name = SetTypes.getTypeName(SetTypes.CREATE_BUILD);
        if (settings.get(name) == null) {
            Setting setting = new Setting(this, allocateObjectId(), name);
            setting.setIntValue(Constants.BUILD_ID);
            lockMeta(systemSession);
            addDatabaseObject(systemSession, setting);
        }
        // mark all ids used in the page store
        if (pageStore != null) {
            BitSet f = pageStore.getObjectIds();
            for (int i = 0, len = f.length(); i < len; i++) {
                if (f.get(i) && !objectIds.get(i)) {
                    trace.info("unused object id: " + i);
                    objectIds.set(i);
                }
            }
        }
    }
    getLobStorage().init();
    systemSession.commit(true);
    trace.info("opened {0}", databaseName);
    if (checkpointAllowed > 0) {
        afterWriting();
    }
}
Also used : Schema(org.h2.schema.Schema) BitSet(java.util.BitSet) TraceSystem(org.h2.message.TraceSystem) CreateTableData(org.h2.command.ddl.CreateTableData) Cursor(org.h2.index.Cursor) Constraint(org.h2.constraint.Constraint) DbException(org.h2.message.DbException) IndexColumn(org.h2.table.IndexColumn) IndexColumn(org.h2.table.IndexColumn) Column(org.h2.table.Column) FileLock(org.h2.store.FileLock)

Aggregations

DbException (org.h2.message.DbException)5 IOException (java.io.IOException)3 SQLException (java.sql.SQLException)3 Properties (java.util.Properties)2 FileLock (org.h2.store.FileLock)2 BitSet (java.util.BitSet)1 DatabaseEventListener (org.h2.api.DatabaseEventListener)1 CreateTableData (org.h2.command.ddl.CreateTableData)1 Constraint (org.h2.constraint.Constraint)1 Cursor (org.h2.index.Cursor)1 TraceSystem (org.h2.message.TraceSystem)1 Schema (org.h2.schema.Schema)1 SchemaObject (org.h2.schema.SchemaObject)1 Sequence (org.h2.schema.Sequence)1 TriggerObject (org.h2.schema.TriggerObject)1 FileLockMethod (org.h2.store.FileLockMethod)1 PageStore (org.h2.store.PageStore)1 Column (org.h2.table.Column)1 IndexColumn (org.h2.table.IndexColumn)1 MetaTable (org.h2.table.MetaTable)1