NameServer模块阅读2:KVConfigManager

摘要

本节讲解顺序如下

KVConfigManager作用
字段
  lock 读写锁
  configTable 内存记录的配置
方法
  构造函数
  load:加载配置文件,读取到内存的configTable中
  putKVConfig:添加一条记录
  deleteKVConfig:删除一条记录
  persist:将内存记录的configTable持久化到配置文件
  getKVListByNamespace:拿到configTable对应namespace的所有记录
  getKVConfig:获取configTable中namespace,key对应的一条记录
  printAllPeriodically:打印configTable所有配置,被周期性的调用
思考
refer

说明

KVConfigManager作用是

加载namesrvController指定的kvConfig配置文件(常为xxx/kvConfig.json)到内存
读取或增加,删除kvConfig记录
将内存记录的配置,持久化到文件
打印所有kvConfig配置

字段

    private static final Logger log = LoggerFactory.getLogger(LoggerName.NAMESRV_LOGGER_NAME);

    private final NamesrvController namesrvController;//NameServer控制类

    private final ReadWriteLock lock = new ReentrantReadWriteLock();//读写锁
    private final HashMap> configTable =
        new HashMap>();

主要注意

lock 是一个读写锁,用来控制并发
configTable 就是在内存中记录住的kv配置,第一级key为NameSpace(暂时什么用还不清楚)

方法

构造函数

    public KVConfigManager(NamesrvController namesrvController) {
        this.namesrvController = namesrvController;
    }

传入一个NamesrvController,目的是为了后面获取到kvConfig的配置路径

load

加载配置文件,读取到内存的configTable中

源码如下

    public void load() {
        String content = null;
        try {
            //解析kvConfigPath,默认为NamesrvConfig.kvConfigPath(../kvConfig.json),解析文件,得到内容,赋给content
            content = MixAll.file2String(this.namesrvController.getNamesrvConfig().getKvConfigPath());
        } catch (IOException e) {
            log.warn("Load KV config table exception", e);
        }
        if (content != null) {
            KVConfigSerializeWrapper kvConfigSerializeWrapper =
                KVConfigSerializeWrapper.fromJson(content, KVConfigSerializeWrapper.class);//根据json的文本内容解析得到KVConfigSerializeWrapper对象
            if (null != kvConfigSerializeWrapper) {
                this.configTable.putAll(kvConfigSerializeWrapper.getConfigTable());//存入configTable
                log.info("load KV config table OK");
            }
        }
    }

步骤就是

根据kvConfigPath得到文件内容
以json格式解析得到KVConfigSerializeWrapper对象

放入configTable属性中

putKVConfig

添加一条记录

源码如下

    public void putKVConfig(final String namespace, final String key, final String value) {
        try {
            this.lock.writeLock().lockInterruptibly();
            try {
                HashMap kvTable = this.configTable.get(namespace);
                if (null == kvTable) {
                    kvTable = new HashMap();
                    this.configTable.put(namespace, kvTable);
                    log.info("putKVConfig create new Namespace {}", namespace);
                }

                final String prev = kvTable.put(key, value);
                if (null != prev) {//有旧的key,更新
                    log.info("putKVConfig update config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                } else {//没有,创建新的
                    log.info("putKVConfig create new config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                }
            } finally {
                this.lock.writeLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("putKVConfig InterruptedException", e);
        }

        this.persist();//持久化到文件
    }

步骤就是

放入configTable中,namespace对应一级key,key对应二级
然后将configTable进行持久化到文件

deleteKVConfig

删除一条记录

源码如下

    public void deleteKVConfig(final String namespace, final String key) {
        try {
            this.lock.writeLock().lockInterruptibly();
            try {
                HashMap kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    String value = kvTable.remove(key);
                    log.info("deleteKVConfig delete a config item, Namespace: {} Key: {} Value: {}",
                        namespace, key, value);
                }
            } finally {
                this.lock.writeLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("deleteKVConfig InterruptedException", e);
        }

        this.persist();//持久化到文件
    }

步骤就是

从configTable删除对应记录
然后将configTable持久化到文件

persist

将内存记录的configTable持久化到配置文件

源码如下

    public void persist() {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                //把configTable放入KVConfigSerializeWrapper
                KVConfigSerializeWrapper kvConfigSerializeWrapper = new KVConfigSerializeWrapper();
                kvConfigSerializeWrapper.setConfigTable(this.configTable);
                //把KVConfigSerializeWrapper转成json串
                String content = kvConfigSerializeWrapper.toJson();

                if (null != content) {
                    //把内容写入 kvConfig的文件
                    MixAll.string2File(content, this.namesrvController.getNamesrvConfig().getKvConfigPath());
                }
            } catch (IOException e) {
                log.error("persist kvconfig Exception, "
                    + this.namesrvController.getNamesrvConfig().getKvConfigPath(), e);
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("persist InterruptedException", e);
        }

    }

步骤就是

1.把configTable放入KVConfigSerializeWrapper
2.把KVConfigSerializeWrapper转成json串
3.把json串写入kvConfig文件

getKVListByNamespace

拿到configTable对应namespace的所有记录

源码如下

    /**
     * 拿到configTable对应namespace的所有记录,
     * 返回encode得到的byte[]
     */
    public byte[] getKVListByNamespace(final String namespace) {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                HashMap kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    KVTable table = new KVTable();
                    table.setTable(kvTable);
                    return table.encode();
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("getKVListByNamespace InterruptedException", e);
        }

        return null;
    }

getKVConfig

获取configTable中namespace,key对应的一条记录
源码如下

    public String getKVConfig(final String namespace, final String key) {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                HashMap kvTable = this.configTable.get(namespace);
                if (null != kvTable) {
                    return kvTable.get(key);
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("getKVConfig InterruptedException", e);
        }

        return null;
    }

printAllPeriodically

打印configTable所有配置,被周期性的调用

源码如下

public void printAllPeriodically() {
        try {
            this.lock.readLock().lockInterruptibly();
            try {
                log.info("--------------------------------------------------------");

                {
                    log.info("configTable SIZE: {}", this.configTable.size());
                    Iterator>> it =
                        this.configTable.entrySet().iterator();
                    while (it.hasNext()) {//一级key
                        Entry> next = it.next();
                        Iterator> itSub = next.getValue().entrySet().iterator();
                        while (itSub.hasNext()) {//二级key
                            Entry nextSub = itSub.next();
                            log.info("configTable NS: {} Key: {} Value: {}", next.getKey(), nextSub.getKey(),
                                nextSub.getValue());
                        }
                    }
                }
            } finally {
                this.lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            log.error("printAllPeriodically InterruptedException", e);
        }
    }

思考

注意lock的使用

在各方法中适宜的调用读锁和写锁

问题

NameSpace有什么用?

只知道是一个区分的一级key

refer

你可能感兴趣的:(NameServer模块阅读2:KVConfigManager)