最近这两天闲了一些,准备好好学一下golang。

学习一门语言最好的办法就是通过项目学习,所以我就找了个评价比较高代码不太大的项目 boltdb,开始学习。

Open

为了方便理解,我们假设执行Open是这一句话

db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})

系统首先创建一个数据库的结构体

type DB struct {
    StrictMode bool
    NoSync bool
    NoGrowSync bool
    MmapFlags int
    MaxBatchSize int
    MaxBatchDelay time.Duration
    AllocSize int
    path     string
    file     *os.File
    lockfile *os.File 
    dataref  []byte   
    data     *[maxMapSize]byte
    datasz   int
    filesz   int 
    meta0    *meta
    meta1    *meta
    pageSize int
    opened   bool
    rwtx     *Tx
    txs      []*Tx
    freelist *freelist
    stats    Stats
    pagePool sync.Pool
    batchMu sync.Mutex
    batch   *batch
    rwlock   sync.Mutex   
    metalock sync.Mutex  
    mmaplock sync.RWMutex 
    statlock sync.RWMutex
    ops struct {
        writeAt func(b []byte, off int64) (n int, err error)
    }
    readOnly bool
}

实例化

这个结构体变量有点多,我们按照程序顺序解释我们遇到的程序。
首先默认设置这个db已经Open,然后如果没有配置的话,就设置不超时,我们设置的超时时间为1s,也就是如果1s没有操作的话,就结束了。
其他的我们都没配置,都是变量的默认值。
首先在数据库变大的时候先不同步。
Options里面的MmapFlags是为了大量读取数据所使用的,然而默认配置并没有设置,也就是说这个默认是关闭的。
除此之外,还配置了默认执行Batch的大小,延时还有分配的大小。
最后根据是否配置数据库为只读模式,配置接下来的操作方式flagos.O_RDWR或者os.O_RDONLY。我们没有指定ReadOnly,所以数据库是读写模式。
到此,系统默认数据库已经配置完毕。

创建

接下来的系统创建就很简单了,直接根据我们以上的配置和文件路径创建文件即可

db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode)

然后系统为了防止一个数据库同时被两个进程使用,为文件创建了一个锁,保证在读写模式的时候,只会有一个进程在调用。
然后我们的数据库支持按指定便宜存储,所以定了了一个writeat函数。
最后我们要为程序指定一个PageSize,这样是为了高效的从系统读取写入数据。
这块的逻辑也很简单,整体顺序就是看下文件是否是首次创建的,如果不是的话就读去文件的meta数据,读取出来设置的meta数据,有错误的话就用系统的默认PageSize。
如果是第一次创建,就对本文件进行初始化操作。具体的初始化操作涉及系统的操作,我们留到以后分析。
然后就可以配置数据库的分页池,把上数据库文件直接映射到内存上,然后读取freelist(还不是太理解含义)
到目前为止,数据库实例化成功。

golang boltdb 源码

发表新评论