Search in sources :

Example 1 with FileLock

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

the class FileLister method tryUnlockDatabase.

/**
 * Try to lock the database, and then unlock it. If this worked, the
 * .lock.db file will be removed.
 *
 * @param files the database files to check
 * @param message the text to include in the error message
 * @throws SQLException if it failed
 */
public static void tryUnlockDatabase(List<String> files, String message) throws SQLException {
    for (String fileName : files) {
        if (fileName.endsWith(Constants.SUFFIX_LOCK_FILE)) {
            FileLock lock = new FileLock(new TraceSystem(null), fileName, Constants.LOCK_SLEEP);
            try {
                lock.lock(FileLockMethod.FILE);
                lock.unlock();
            } catch (DbException e) {
                throw DbException.get(ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, message).getSQLException();
            }
        } else if (fileName.endsWith(Constants.SUFFIX_MV_FILE)) {
            try (FileChannel f = FilePath.get(fileName).open("r")) {
                java.nio.channels.FileLock lock = f.tryLock(0, Long.MAX_VALUE, true);
                lock.release();
            } catch (Exception e) {
                throw DbException.get(ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, e, message).getSQLException();
            }
        }
    }
}
Also used : FileChannel(java.nio.channels.FileChannel) TraceSystem(org.h2.message.TraceSystem) SQLException(java.sql.SQLException) DbException(org.h2.message.DbException) DbException(org.h2.message.DbException)

Example 2 with FileLock

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

the class TestFileLock method testFutureModificationDate.

private void testFutureModificationDate() throws Exception {
    File f = new File(getFile());
    f.delete();
    f.createNewFile();
    f.setLastModified(System.currentTimeMillis() + 10000);
    FileLock lock = new FileLock(new TraceSystem(null), getFile(), Constants.LOCK_SLEEP);
    lock.lock(FileLockMethod.FILE);
    lock.unlock();
}
Also used : FileLock(org.h2.store.FileLock) TraceSystem(org.h2.message.TraceSystem) File(java.io.File)

Example 3 with FileLock

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

the class FileStore method open.

/**
 * Try to open the file.
 *
 * @param fileName the file name
 * @param readOnly whether the file should only be opened in read-only mode,
 *            even if the file is writable
 * @param encryptionKey the encryption key, or null if encryption is not
 *            used
 */
public void open(String fileName, boolean readOnly, char[] encryptionKey) {
    if (file != null) {
        return;
    }
    if (fileName != null) {
        // ensure the Cache file system is registered
        FilePathCache.INSTANCE.getScheme();
        FilePath p = FilePath.get(fileName);
        // if no explicit scheme was specified, NIO is used
        if (p instanceof FilePathDisk && !fileName.startsWith(p.getScheme() + ":")) {
            // ensure the NIO file system is registered
            FilePathNio.class.getName();
            fileName = "nio:" + fileName;
        }
    }
    this.fileName = fileName;
    FilePath f = FilePath.get(fileName);
    FilePath parent = f.getParent();
    if (parent != null && !parent.exists()) {
        throw DataUtils.newIllegalArgumentException("Directory does not exist: {0}", parent);
    }
    if (f.exists() && !f.canWrite()) {
        readOnly = true;
    }
    this.readOnly = readOnly;
    try {
        file = f.open(readOnly ? "r" : "rw");
        if (encryptionKey != null) {
            byte[] key = FilePathEncrypt.getPasswordBytes(encryptionKey);
            encryptedFile = file;
            file = new FilePathEncrypt.FileEncrypt(fileName, key, file);
        }
        try {
            if (readOnly) {
                fileLock = file.tryLock(0, Long.MAX_VALUE, true);
            } else {
                fileLock = file.tryLock();
            }
        } catch (OverlappingFileLockException e) {
            throw DataUtils.newIllegalStateException(DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName, e);
        }
        if (fileLock == null) {
            throw DataUtils.newIllegalStateException(DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName);
        }
        fileSize = file.size();
    } catch (IOException e) {
        throw DataUtils.newIllegalStateException(DataUtils.ERROR_READING_FAILED, "Could not open file {0}", fileName, e);
    }
}
Also used : FilePath(org.h2.store.fs.FilePath) FilePathEncrypt(org.h2.store.fs.FilePathEncrypt) IOException(java.io.IOException) FilePathDisk(org.h2.store.fs.FilePathDisk) OverlappingFileLockException(java.nio.channels.OverlappingFileLockException)

Example 4 with FileLock

use of org.h2.store.FileLock 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 5 with FileLock

use of org.h2.store.FileLock 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

TraceSystem (org.h2.message.TraceSystem)5 FileLock (org.h2.store.FileLock)5 DbException (org.h2.message.DbException)3 IOException (java.io.IOException)2 FileChannel (java.nio.channels.FileChannel)2 SQLException (java.sql.SQLException)2 FilePath (org.h2.store.fs.FilePath)2 File (java.io.File)1 InputStream (java.io.InputStream)1 FileLock (java.nio.channels.FileLock)1 OverlappingFileLockException (java.nio.channels.OverlappingFileLockException)1 BitSet (java.util.BitSet)1 Properties (java.util.Properties)1 Random (java.util.Random)1 CreateTableData (org.h2.command.ddl.CreateTableData)1 Constraint (org.h2.constraint.Constraint)1 Cursor (org.h2.index.Cursor)1 Schema (org.h2.schema.Schema)1 FilePathDisk (org.h2.store.fs.FilePathDisk)1 FilePathEncrypt (org.h2.store.fs.FilePathEncrypt)1