MVstore 流程

构造MVstore

    /**
     * Create and open the store.
     *
     * @param config the configuration to use
     * @throws IllegalStateException if the file is corrupt, or an exception
     *             occurred while opening
     * @throws IllegalArgumentException if the directory does not exist
     */
    MVStore(HashMap<String, Object> config) {
        this.compress = config.containsKey("compress");
        Object o = config.get("pageSplitSize");
//page分裂的阀值,默认时候6K
        pageSplitSize = o == null ? 6 * 1024 : (Integer) o;
        o = config.get("backgroundExceptionHandler");
        this.backgroundExceptionHandler = (UncaughtExceptionHandler) o;
//meta数据map
        meta = new MVMapConcurrent<String, String>(StringDataType.INSTANCE, StringDataType.INSTANCE);
        HashMap<String, String> c = New.hashMap();
        c.put("id", "0");
//新建的store currentVersion为0
        c.put("createVersion", Long.toString(currentVersion));
//meta是个copyonwrite map,读操作无锁,写时同步,初始化metamap的属性store为this,id为0,createVersion为0,writeversion也为0
        meta.init(this, c);
//如果没有设置filestore和filename都为null,直接返回,可能表示只是用内存,不持久化
        fileStore = (FileStore) config.get("fileStore");
        String fileName = (String) config.get("fileName");
        if (fileName == null && fileStore == null) {
            cache = null;
            return;
        }
        if (fileStore == null) {
            fileStore = new FileStore();
        }
//保留时间
        retentionTime = fileStore.getDefaultRetentionTime();
        boolean readOnly = config.containsKey("readOnly");
        o = config.get("cacheSize");
        int mb = o == null ? 16 : (Integer) o;
//创建缓存
        if (mb > 0) {
            int maxMemoryBytes = mb * 1024 * 1024;
            int averageMemory = Math.max(10, pageSplitSize / 2);
            int segmentCount = 16;
            int stackMoveDistance = maxMemoryBytes / averageMemory * 2 / 100;
            cache = new CacheLongKeyLIRS<Page>(
                    maxMemoryBytes, averageMemory, segmentCount, stackMoveDistance);
        }
//写缓冲默认4MB
        o = config.get("writeBufferSize");
        mb = o == null ? 4 : (Integer) o;
        int writeBufferSize =  mb * 1024 * 1024;
        int div = pageSplitSize;
//就散没有最多能有多少未保存的page
        unsavedPageCountMax = writeBufferSize / (div == 0 ? 1 : div);
        char[] encryptionKey = (char[]) config.get("encryptionKey");
        try {
//打开文件
            fileStore.open(fileName, readOnly, encryptionKey);
            if (fileStore.size() == 0) {
//如果新建,写入头
                creationTime = 0;
                creationTime = getTime();
                lastStoreTime = creationTime;
                storeHeader.put("H", "3");
                storeHeader.put("blockSize", "" + BLOCK_SIZE);
                storeHeader.put("format", "" + FORMAT_WRITE);
                storeHeader.put("creationTime", "" + creationTime);
                writeStoreHeader();
            } else {
                readStoreHeader();
                long format = DataUtils.parseLong(storeHeader.get("format"), 0);
                if (format > FORMAT_WRITE && !fileStore.isReadOnly()) {
                    throw DataUtils.newIllegalStateException(
                            DataUtils.ERROR_UNSUPPORTED_FORMAT,
                            "The write format {0} is larger than the supported format {1}, " +
                            "and the file was not opened in read-only mode",
                            format, FORMAT_WRITE);
                }
                format = DataUtils.parseLong(storeHeader.get("formatRead"), format);
                if (format > FORMAT_READ) {
                    throw DataUtils.newIllegalStateException(
                            DataUtils.ERROR_UNSUPPORTED_FORMAT,
                            "The read format {0} is larger than the supported format {1}",
                            format, FORMAT_READ);
                }
//新建rootChunkStart为0
                if (rootChunkStart > 0) {
                    readMeta();
                }
            }
//新建meta没有这个值,所以默认-1
            long rollback = DataUtils.parseLong(meta.get("rollbackOnOpen"), -1);
            if (rollback != -1) {
                rollbackTo(rollback);
            }
        } catch (IllegalStateException e) {
            try {
                closeStore(false);
            } catch (Exception e2) {
                // ignore
            }
            throw e;
        } finally {
            if (encryptionKey != null) {
                Arrays.fill(encryptionKey, (char) 0);
            }
        }
//更新上次store时间
        lastStoreTime = getTime();
//更新上次store版本
        this.lastCommittedVersion = currentVersion;
        // setWriteDelay starts the thread, but only if
        // the parameter is different than the current value
        o = config.get("writeDelay");
        int writeDelay = o == null ? 1000 : (Integer) o;
//设置延迟写时间,如果大于0,会启动后台写线程
        setWriteDelay(writeDelay);
    }

   
 private void stopBackgroundThread() {
//构造的时候调用直接return
        if (backgroundThread == null) {
            return;
        }
        Thread t = backgroundThread;
        backgroundThread = null;
        synchronized (this) {
            notify();
        }
        try {
            t.join();
        } catch (Exception e) {
            // ignore
        }
    }
    /**
     * Set the maximum delay in milliseconds to store committed changes (for
     * file-based stores).
     * <p>
     * The default is 1000, meaning committed changes are stored after at
     * most one second.
     * <p>
     * When the value is set to -1, committed changes are only written when
     * calling the store method. When the value is set to 0, committed
     * changes are immediately written on a commit, but please note this
     * decreases performance and does still not guarantee the disk will
     * actually write the data.
     *
     * @param millis the maximum delay
     */
    public void setWriteDelay(int millis) {
        if (writeDelay == millis) {
            return;
        }
        writeDelay = millis;
        if (fileStore == null) {
            return;
        }
//未做处理,直接return
        stopBackgroundThread();
        // start the background thread if needed
        if (millis > 0) {
//大于0就起后台线程,线程会wait最多sleep时间就去调后台store,并不是1s,而是0.1s
            int sleep = Math.max(1, millis / 10);
            Writer w = new Writer(this, sleep);
            Thread t = new Thread(w, "MVStore writer " + fileStore.toString());
            t.setDaemon(true);
            t.start();
            backgroundThread = t;
        }
    }
    public int getWriteDelay() {
        return writeDelay;
    }
    /**
     * A background writer to automatically store changes from time to time.
     */
    private static class Writer implements Runnable {
        private final MVStore store;
        private final int sleep;
        Writer(MVStore store, int sleep) {
            this.store = store;
            this.sleep = sleep;
        }
        @Override
        public void run() {
            while (store.backgroundThread != null) {
                synchronized (store) {
                    try {
                        store.wait(sleep);
                    } catch (InterruptedException e) {
                        // ignore
                    }
                }
                store.storeInBackground();
            }
        }
    }
  /**
     * Store all unsaved changes, if there are any that are committed.
     */
    void storeInBackground() {
        if (closed || unsavedPageCount == 0) {
            return;
        }
        // could also store when there are many unsaved pages,
        // but according to a test it doesn't really help
        if (lastStoredVersion >= lastCommittedVersion) {
            return;
        }
        long time = getTime();
//还是1s,前面没看到这个地方
        if (time <= lastStoreTime + writeDelay) {
            return;
        }
        if (!hasUnsavedChanges()) {
            return;
        }
//存储committed
        try {
            store(true);
        } catch (Exception e) {
            if (backgroundExceptionHandler != null) {
                backgroundExceptionHandler.uncaughtException(null, e);
            }
        }
    }

转载于:https://my.oschina.net/heatonn1/blog/188604

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值