⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 database.java

📁 非常棒的java数据库
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
        dummy = DataPage.create(this, 0);
        if (persistent) {
            if (readOnly) {
                traceSystem = new TraceSystem(null, false);
            } else {
                traceSystem = new TraceSystem(databaseName + Constants.SUFFIX_TRACE_FILE, true);
            }
            if (cipher != null) {
                traceSystem.setManualEnabling(false);
            }
            traceSystem.setLevelFile(traceLevelFile);
            traceSystem.setLevelSystemOut(traceLevelSystemOut);
            traceSystem.getTrace(Trace.DATABASE)
                    .info("opening " + databaseName + " (build " + Constants.BUILD_ID + ")");
            if (!readOnly && fileLockMethod != FileLock.LOCK_NO) {
                lock = new FileLock(traceSystem, Constants.LOCK_SLEEP);
                lock.lock(databaseName + Constants.SUFFIX_LOCK_FILE, fileLockMethod == FileLock.LOCK_SOCKET);
            }
            deleteOldTempFiles();
            log = new LogSystem(this, databaseName, readOnly, accessModeLog);
            openFileData();
            log.open();
            openFileIndex();
            log.recover();
            fileData.init();
            try {
                fileIndex.init();
            } catch (Throwable e) {
                if (recovery) {
                    traceSystem.getTrace(Trace.DATABASE).error("opening index", e);
                    fileIndex.close();
                    fileIndex.delete();
                    openFileIndex();
                } else {
                    throw Message.convert(e);
                }
            }
            reserveLobFileObjectIds();
            writer = WriterThread.create(this, writeDelay);
        } else {
            traceSystem = new TraceSystem(null, false);
            log = new LogSystem(null, null, false, null);
        }
        systemUser = new User(this, 0, Constants.DBA_NAME, true);
        mainSchema = new Schema(this, 0, Constants.SCHEMA_MAIN, systemUser, true);
        infoSchema = new Schema(this, -1, Constants.SCHEMA_INFORMATION, 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);
        ObjectArray cols = new ObjectArray();
        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));
        meta = mainSchema.createTable("SYS", 0, cols, persistent, false);
        IndexColumn[] pkCols = IndexColumn.wrap(new Column[] { columnId });
        metaIdIndex = meta.addIndex(systemSession, "SYS_ID", 0, pkCols, IndexType.createPrimaryKey(
                false, false), Index.EMPTY_HEAD, null);
        objectIds.set(0);
        // there could be views on system tables, so they must be added first
        addMetaData(MetaTable.TABLES);
        addMetaData(MetaTable.COLUMNS);
        addMetaData(MetaTable.INDEXES);
        addMetaData(MetaTable.TABLE_TYPES);
        addMetaData(MetaTable.TYPE_INFO);
        addMetaData(MetaTable.CATALOGS);
        addMetaData(MetaTable.SETTINGS);
        addMetaData(MetaTable.HELP);
        addMetaData(MetaTable.SEQUENCES);
        addMetaData(MetaTable.USERS);
        addMetaData(MetaTable.ROLES);
        addMetaData(MetaTable.RIGHTS);
        addMetaData(MetaTable.FUNCTION_ALIASES);
        addMetaData(MetaTable.SCHEMATA);
        addMetaData(MetaTable.TABLE_PRIVILEGES);
        addMetaData(MetaTable.COLUMN_PRIVILEGES);
        addMetaData(MetaTable.COLLATIONS);
        addMetaData(MetaTable.VIEWS);
        addMetaData(MetaTable.IN_DOUBT);
        addMetaData(MetaTable.CROSS_REFERENCES);
        addMetaData(MetaTable.CONSTRAINTS);
        addMetaData(MetaTable.FUNCTION_COLUMNS);
        addMetaData(MetaTable.CONSTANTS);
        addMetaData(MetaTable.DOMAINS);
        addMetaData(MetaTable.TRIGGERS);
        addMetaData(MetaTable.SESSIONS);
        addMetaData(MetaTable.LOCKS);
        starting = true;
        Cursor cursor = metaIdIndex.find(systemSession, null, null);
        // first, create all function aliases and sequences because
        // they might be used in create table / view / constraints and so on
        ObjectArray records = new ObjectArray();
        while (cursor.next()) {
            MetaRecord rec = new MetaRecord(cursor.get());
            objectIds.set(rec.getId());
            records.add(rec);
        }
        MetaRecord.sort(records);
        for (int i = 0; i < records.size(); i++) {
            MetaRecord rec = (MetaRecord) records.get(i);
            rec.execute(this, systemSession, eventListener);
        }
        // try to recompile the views that are invalid
        recompileInvalidViews(systemSession);
        starting = false;
        addDefaultSetting(systemSession, SetTypes.DEFAULT_LOCK_TIMEOUT, null, Constants.INITIAL_LOCK_TIMEOUT);
        addDefaultSetting(systemSession, SetTypes.DEFAULT_TABLE_TYPE, null, Constants.DEFAULT_TABLE_TYPE);
        addDefaultSetting(systemSession, SetTypes.TRACE_LEVEL_FILE, null, traceSystem.getLevelFile());
        addDefaultSetting(systemSession, SetTypes.TRACE_LEVEL_SYSTEM_OUT, null, traceSystem.getLevelSystemOut());
        addDefaultSetting(systemSession, SetTypes.CACHE_SIZE, null, SysProperties.CACHE_SIZE_DEFAULT);
        addDefaultSetting(systemSession, SetTypes.CLUSTER, Constants.CLUSTERING_DISABLED, 0);
        addDefaultSetting(systemSession, SetTypes.WRITE_DELAY, null, Constants.DEFAULT_WRITE_DELAY);
        addDefaultSetting(systemSession, SetTypes.CREATE_BUILD, null, Constants.BUILD_ID);
        if (!readOnly) {
            removeUnusedStorages(systemSession);
        }
        systemSession.commit(true);
        if (!readOnly && persistent) {
            emergencyReserve = openFile(createTempFile(), "rw", false);
            emergencyReserve.autoDelete();
            emergencyReserve.setLength(SysProperties.EMERGENCY_SPACE_INITIAL);
        }
        traceSystem.getTrace(Trace.DATABASE).info("opened " + databaseName);
    }

    private void recompileInvalidViews(Session session) {
        boolean recompileSuccessful;
        do {
            recompileSuccessful = false;
            ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
            for (int i = 0; i < list.size(); i++) {
                DbObject obj = (DbObject) list.get(i);
                if (obj instanceof TableView) {
                    TableView view = (TableView) obj;
                    if (view.getInvalid()) {
                        try {
                            view.recompile(session);
                        } catch (Throwable e) {
                            // ignore
                        }
                        if (!view.getInvalid()) {
                            recompileSuccessful = true;
                        }
                    }
                }
            }
        } while (recompileSuccessful);
        // when opening a database, views are initialized before indexes, 
        // so they may not have the optimal plan yet
        // this is not a problem, it is just nice to see the newest plan
        ObjectArray list = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
        for (int i = 0; i < list.size(); i++) {
            DbObject obj = (DbObject) list.get(i);
            if (obj instanceof TableView) {
                TableView view = (TableView) obj;
                if (!view.getInvalid()) {
                    try {
                        view.recompile(systemSession);
                    } catch (SQLException e) {
                        // ignore
                    }
                }
            }
        }
    }

    private void removeUnusedStorages(Session session) throws SQLException {
        if (persistent) {
            ObjectArray storages = getAllStorages();
            for (int i = 0; i < storages.size(); i++) {
                Storage storage = (Storage) storages.get(i);
                if (storage != null && storage.getRecordReader() == null) {
                    storage.delete(session);
                }
            }
        }
    }

    private void addDefaultSetting(Session session, int type, String stringValue, int intValue) throws SQLException {
        if (readOnly) {
            return;
        }
        String name = SetTypes.getTypeName(type);
        if (settings.get(name) == null) {
            Setting setting = new Setting(this, allocateObjectId(false, true), name);
            if (stringValue == null) {
                setting.setIntValue(intValue);
            } else {
                setting.setStringValue(stringValue);
            }
            addDatabaseObject(session, setting);
        }
    }

    public void removeStorage(int id, DiskFile file) {
        if (SysProperties.CHECK) {
            Storage s = (Storage) storageMap.get(id);
            if (s == null || s.getDiskFile() != file) {
                throw Message.getInternalError();
            }
        }
        storageMap.remove(id);
    }

    public Storage getStorage(int id, DiskFile file) {
        Storage storage = (Storage) storageMap.get(id);
        if (storage != null) {
            if (SysProperties.CHECK && storage.getDiskFile() != file) {
                throw Message.getInternalError();
            }
        } else {
            storage = new Storage(this, file, null, id);
            storageMap.put(id, storage);
        }
        return storage;
    }

    private void addMetaData(int type) throws SQLException {
        MetaTable m = new MetaTable(infoSchema, -1 - type, type);
        infoSchema.add(m);
    }

    private synchronized void addMeta(Session session, DbObject obj) throws SQLException {
        if (obj.getTemporary()) {
            return;
        }
        Row r = meta.getTemplateRow();
        MetaRecord rec = new MetaRecord(obj);
        rec.setRecord(r);
        objectIds.set(obj.getId());
        meta.lock(session, true, true);
        meta.addRow(session, r);
        if (isMultiVersion()) {
            // TODO this should work without MVCC, but avoid risks at the moment
            session.log(meta, UndoLogRecord.INSERT, r);
        }
    }

    public synchronized void removeMeta(Session session, int id) throws SQLException {
        SearchRow r = meta.getTemplateSimpleRow(false);
        r.setValue(0, ValueInt.get(id));
        Cursor cursor = metaIdIndex.find(session, r, r);
        if (cursor.next()) {
            Row found = cursor.get();
            meta.lock(session, true, true);
            meta.removeRow(session, found);
            if (isMultiVersion()) {
                // TODO this should work without MVCC, but avoid risks at the
                // moment
                session.log(meta, UndoLogRecord.DELETE, found);
            }
            objectIds.clear(id);
            if (SysProperties.CHECK) {
                checkMetaFree(session, id);
            }
        }
    }

    private HashMap getMap(int type) {
        switch (type) {
        case DbObject.USER:
            return users;
        case DbObject.SETTING:
            return settings;
        case DbObject.ROLE:
            return roles;
        case DbObject.RIGHT:
            return rights;
        case DbObject.FUNCTION_ALIAS:
            return functionAliases;
        case DbObject.SCHEMA:
            return schemas;
        case DbObject.USER_DATATYPE:
            return userDataTypes;
        case DbObject.COMMENT:
            return comments;
        case DbObject.AGGREGATE:
            return aggregates;
        default:
            throw Message.getInternalError("type=" + type);
        }
    }

    public synchronized void addSchemaObject(Session session, SchemaObject obj) throws SQLException {
        obj.getSchema().add(obj);
        int id = obj.getId();
        if (id > 0 && !starting) {
            addMeta(session, obj);
        }
    }

    public synchronized void addDatabaseObject(Session session, DbObject obj) throws SQLException {
        HashMap map = getMap(obj.getType());
        if (obj.getType() == DbObject.USER) {
            User user = (User) obj;
            if (user.getAdmin() && systemUser.getName().equals(Constants.DBA_NAME)) {
                systemUser.rename(user.getName());
            }
        }
        String name = obj.getName();
        if (SysProperties.CHECK && map.get(name) != null) {
            throw Message.getInternalError("object already exists");
        }
        int id = obj.getId();
        if (id > 0 && !starting) {
            addMeta(session, obj);
        }
        map.put(name, obj);
    }

    public Setting findSetting(String name) {
        return (Setting) settings.get(name);
    }

    public Comment findComment(DbObject object) {
        if (object.getType() == DbObject.COMMENT) {
            return null;
        }
        String key = Comment.getKey(object);
        return (Comment) comments.get(key);
    }

    public User findUser(String name) {
        return (User) users.get(name);
    }

    public FunctionAlias findFunctionAlias(String name) {
        return (FunctionAlias) functionAliases.get(name);
    }

    public UserAggregate findAggregate(String name) {
        return (UserAggregate) aggregates.get(name);
    }

    public UserDataType findUserDataType(String name) {
        return (UserDataType) userDataTypes.get(name);
    }

    public User getUser(String name, SQLException notFound) throws SQLException {
        User user = (User) users.get(name);
        if (user == null) {
            try {
                Thread.sleep(Constants.DELAY_WRONG_PASSWORD);
            } catch (InterruptedException e) {
                // ignore
            }
            throw notFound;
        }
        return user;
    }

    public User getUser(String name) throws SQLException {
        return getUser(name, Message.getSQLException(ErrorCode.USER_NOT_FOUND_1, name));
    }

    public synchronized Session createSession(User user) throws SQLException {
        if (exclusiveSession != null) {
            throw Message.getSQLException(ErrorCode.DATABASE_IS_IN_EXCLUSIVE_MODE);
        }
        Session session = new Session(this, user, ++nextSessionId);
        sessions.add(session);
        traceSystem.getTrace(Trace.SESSION).info("connecting #" + session.getId() + " to " + databaseName);
        if (delayedCloser != null) {
            delayedCloser.reset();
            delayedCloser = null;
        }
        return session;
    }

    public synchronized void removeSession(Session session) throws SQLException {
        if (session != null) {
            if (exclusiveSession == session) {
                exclusiveSession = null;
            }
            sessions.remove(session);
            if (session != systemSession) {
                traceSystem.getTrace(Trace.SESSION).info("disconnecting #" + session.getId());
            }
        }
        if (sessions.size() == 0 && session != systemSession) {
            if (closeDelay == 0) {
                close(false);
            } else if (closeDelay < 0) {
                return;
            } else {
                delayedCloser = new DatabaseCloser(this, closeDelay * 1000, false);
                delayedCloser.setName("H2 Close Delay " + getShortName());
                delayedCloser.setDaemon(true);
                delayedCloser.start();
            }
        }
        if (session != systemSession && session != null) {
            traceSystem.getTrace(Trace.SESSION).info("disconnected #" + session.getId());
        }
    }

    synchronized void close(boolean fromShutdownHook) {
        closing = true;
        if (sessions.size() > 0) {
            if (!fromShutdownHook) {
                return;
            }
            traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName + " from shutdown hook");
            Session[] all = new Session[sessions.size()];
            sessions.toArray(all);
            for (int i = 0; i < all.length; i++) {
                Session s = all[i];
                try {
                    s.close();
                } catch (SQLException e) {
                    traceSystem.getTrace(Trace.SESSION).error("disconnecting #" + s.getId(), e);
                }
            }
        }
        if (log != null) {
            log.setDisabled(false);
        }
        traceSystem.getTrace(Trace.DATABASE).info("closing " + databaseName);
        if (eventListener != null) {
            // allow the event listener to connect to the database
            closing = false;
            DatabaseEventListener e = eventListener;
            // set it to null, to make sure it's called only once
            eventListener = null;
            e.closingDatabase();
            if (sessions.size() > 0) {
                // if a connection was opened, we can't close the database
                return;
            }
            closing = true;
        }
        try {
            if (systemSession != null) {
                ObjectArray tablesAndViews = getAllSchemaObjects(DbObject.TABLE_OR_VIEW);
                for (int i = 0; i < tablesAndViews.size(); i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -