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

📄 diskfile.java

📁 非常棒的java数据库
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
            try {
                cache.clear();
                file.close();
                FileUtils.delete(fileName);
            } catch (IOException e) {
                throw Message.convertIOException(e, fileName);
            } finally {
                file = null;
                fileName = null;
            }
        }
    }

    //    private int allocateBest(int start, int blocks) {
    //        while (true) {
    //            int p = getLastUsedPlusOne(start, blocks);
    //            if (p == start) {
    //                start = p;
    //                break;
    //            }
    //            start = p;
    //        }
    //        allocate(start, blocks);
    //        return start;
    //    }

    public void writeBack(CacheObject obj) throws SQLException {
        synchronized (database) {
            writeCount++;
            Record record = (Record) obj;
            int blockCount = record.getBlockCount();
            record.prepareWrite();
            go(record.getPos());
            DataPage buff = rowBuff;
            buff.reset();
            buff.checkCapacity(blockCount * BLOCK_SIZE);
            buff.writeInt(blockCount);
            buff.writeInt(record.getStorageId());
            record.write(buff);
            buff.fill(blockCount * BLOCK_SIZE);
            buff.updateChecksum();
            file.write(buff.getBytes(), 0, buff.length());
            record.setChanged(false);
        }
    }

    /*
     * Must be synchronized externally
     */
    BitField getUsed() {
        return used;
    }

    void updateRecord(Session session, Record record) throws SQLException {
        synchronized (database) {
            record.setChanged(true);
            int pos = record.getPos();
            Record old = (Record) cache.update(pos, record);
            if (SysProperties.CHECK) {
                if (old != null) {
                    if (old != record) {
                        database.checkPowerOff();
                        throw Message.getInternalError("old != record old=" + old + " new=" + record);
                    }
                    int blockCount = record.getBlockCount();
                    for (int i = 0; i < blockCount; i++) {
                        if (deleted.get(i + pos)) {
                            throw Message.getInternalError("update marked as deleted: " + (i + pos));
                        }
                    }
                }
            }
            if (logChanges) {
                log.add(session, this, record);
            }
        }
    }

    void writeDirectDeleted(int recordId, int blockCount) throws SQLException {
        synchronized (database) {
            go(recordId);
            for (int i = 0; i < blockCount; i++) {
                file.write(freeBlock.getBytes(), 0, freeBlock.length());
            }
            free(recordId, blockCount);
        }
    }

    void writeDirect(Storage storage, int pos, byte[] data, int offset) throws SQLException {
        synchronized (database) {
            go(pos);
            file.write(data, offset, BLOCK_SIZE);
            setBlockOwner(null, storage, pos, 1, true);
        }
    }

    public int copyDirect(int pos, OutputStream out) throws SQLException {
        synchronized (database) {
            try {
                if (pos < 0) {
                    // read the header
                    byte[] buffer = new byte[OFFSET];
                    file.seek(0);
                    file.readFullyDirect(buffer, 0, OFFSET);
                    out.write(buffer);
                    return 0;
                }
                if (pos >= fileBlockCount) {
                    return -1;
                }
                int blockSize = DiskFile.BLOCK_SIZE;
                byte[] buff = new byte[blockSize];
                DataPage s = DataPage.create(database, buff);
                database.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, this.fileName, pos, fileBlockCount);
                go(pos);
                file.readFully(buff, 0, blockSize);
                s.reset();
                int blockCount = s.readInt();
                if (SysProperties.CHECK && blockCount < 0) {
                    throw Message.getInternalError();
                }
                if (blockCount == 0) {
                    blockCount = 1;
                }
                int id = s.readInt();
                if (SysProperties.CHECK && id < 0) {
                    throw Message.getInternalError();
                }
                s.checkCapacity(blockCount * blockSize);
                if (blockCount > 1) {
                    file.readFully(s.getBytes(), blockSize, blockCount * blockSize - blockSize);
                }
                if (file.isEncrypted()) {
                    s.reset();
                    go(pos);
                    file.readFullyDirect(s.getBytes(), 0, blockCount * blockSize);
                }
                out.write(s.getBytes(), 0, blockCount * blockSize);
                return pos + blockCount;
            } catch (IOException e) {
                throw Message.convertIOException(e, fileName);
            }
        }
    }

    void removeRecord(Session session, int pos, Record record, int blockCount) throws SQLException {
        synchronized (database) {
            if (logChanges) {
                log.add(session, this, record);
            }
            cache.remove(pos);
            deleted.setRange(pos, blockCount, true);
            setUnused(session, pos, blockCount);
        }
    }

    void addRecord(Session session, Record record) throws SQLException {
        synchronized (database) {
            if (logChanges) {
                log.add(session, this, record);
            }
            cache.put(record);
        }
    }

    /*
     * Must be synchronized externally
     */
    public Cache getCache() {
        return cache;
    }

    void free(int pos, int blockCount) {
        synchronized (database) {
            used.setRange(pos, blockCount, false);
        }
    }

    public int getRecordOverhead() {
        return recordOverhead;
    }

    public void truncateStorage(Session session, Storage storage, IntArray pages) throws SQLException {
        synchronized (database) {
            int storageId = storage.getId();
            // make sure the cache records of this storage are not flushed to disk
            // afterwards
            ObjectArray list = cache.getAllChanged();
            for (int i = 0; i < list.size(); i++) {
                Record r = (Record) list.get(i);
                if (r.getStorageId() == storageId) {
                    r.setChanged(false);
                }
            }
            int[] pagesCopy = new int[pages.size()];
            // can not use pages directly, because setUnused removes rows from there
            pages.toArray(pagesCopy);
            for (int i = 0; i < pagesCopy.length; i++) {
                int page = pagesCopy[i];
                if (logChanges) {
                    log.addTruncate(session, this, storageId, page * BLOCKS_PER_PAGE, BLOCKS_PER_PAGE);
                }
                for (int j = 0; j < BLOCKS_PER_PAGE; j++) {
                    Record r = (Record) cache.find(page * BLOCKS_PER_PAGE + j);
                    if (r != null) {
                        cache.remove(r.getPos());
                    }
                }
                deleted.setRange(page * BLOCKS_PER_PAGE, BLOCKS_PER_PAGE, true);
                setUnused(session, page * BLOCKS_PER_PAGE, BLOCKS_PER_PAGE);
            }
        }
    }

    public void sync() {
        synchronized (database) {
            if (file != null) {
                file.sync();
            }
        }
    }

    public boolean isDataFile() {
        return dataFile;
    }

    public void setLogChanges(boolean b) {
        synchronized (database) {
            this.logChanges = b;
        }
    }

    /**
     * Add a redo-log entry to the redo buffer.
     * 
     * @param storage the storage
     * @param recordId the record id of the entry
     * @param blockCount the number of blocks
     * @param rec the record
     */
    public void addRedoLog(Storage storage, int recordId, int blockCount, DataPage rec) throws SQLException {
        synchronized (database) {
            byte[] data = null;
            if (rec != null) {
                DataPage all = rowBuff;
                all.reset();
                all.writeInt(blockCount);
                all.writeInt(storage.getId());
                all.writeDataPageNoSize(rec);
                // the buffer may have some additional fillers - just ignore them
                all.fill(blockCount * BLOCK_SIZE);
                all.updateChecksum();
                if (SysProperties.CHECK && all.length() != BLOCK_SIZE * blockCount) {
                    throw Message.getInternalError("blockCount:" + blockCount + " length: " + all.length() * BLOCK_SIZE);
                }
                data = new byte[all.length()];
                System.arraycopy(all.getBytes(), 0, data, 0, all.length());
            }
            for (int i = 0; i < blockCount; i++) {
                RedoLogRecord log = new RedoLogRecord();
                log.recordId = recordId + i;
                log.offset = i * BLOCK_SIZE;
                log.storage = storage;
                log.data = data;
                log.sequenceId = redoBuffer.size();
                redoBuffer.add(log);
                redoBufferSize += log.getSize();
            }
            if (redoBufferSize > SysProperties.REDO_BUFFER_SIZE) {
                flushRedoLog();
            }
        }
    }

    public void flushRedoLog() throws SQLException {
        synchronized (database) {
            if (redoBuffer.size() == 0) {
                return;
            }
            redoBuffer.sort(new Comparator() {
                public int compare(Object o1, Object o2) {
                    RedoLogRecord e1 = (RedoLogRecord) o1;
                    RedoLogRecord e2 = (RedoLogRecord) o2;
                    int comp = e1.recordId - e2.recordId;
                    if (comp == 0) {
                        comp = e1.sequenceId - e2.sequenceId;
                    }
                    return comp;
                }
            });
            // first write all deleted entries
            RedoLogRecord last = null;
            for (int i = 0; i < redoBuffer.size(); i++) {
                RedoLogRecord entry = (RedoLogRecord) redoBuffer.get(i);
                if (entry.data != null) {
                    continue;
                }
                if (last != null && entry.recordId != last.recordId) {
                    writeRedoLog(last);
                }
                last = entry;
            }
            if (last != null) {
                writeRedoLog(last);
            }
            // now write the last entry, skipping deleted entries
            last = null;
            for (int i = 0; i < redoBuffer.size(); i++) {
                RedoLogRecord entry = (RedoLogRecord) redoBuffer.get(i);
                if (last != null && entry.recordId != last.recordId) {
                    if (last.data != null) {
                        writeRedoLog(last);
                    }
                }
                last = entry;
            }
            if (last != null && last.data != null) {
                writeRedoLog(last);
            }
            redoBuffer.clear();
            redoBufferSize = 0;
        }
    }

    private void writeRedoLog(RedoLogRecord entry) throws SQLException {
        if (entry.data == null) {
            writeDirectDeleted(entry.recordId, 1);
        } else {
            writeDirect(entry.storage, entry.recordId, entry.data, entry.offset);
        }
    }

    public int getWriteCount() {
        return writeCount;
    }

    public int getReadCount() {
        return readCount;
    }

    public void flushLog() throws SQLException {
        if (log != null) {
            log.flush();
        }
    }

    public String toString() {
        return getClass().getName() + ":" + fileName;
    }

}

⌨️ 快捷键说明

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