bbolt: main

依赖

module go.etcd.io/bbolt

go 1.12

可以看到没有依赖任何第三方组件。main函数的参数解析逻辑都是自己写的,所以导致main.go有2k+行。其实用cobra会好一点吧。

子命令

Bolt is a tool for inspecting bolt databases.

Usage:

	bolt command [arguments]

The commands are:

    bench       run synthetic benchmark against bolt
    buckets     print a list of buckets 
    check       verifies integrity of bolt database //就是tx.check
    compact     copies a bolt database, compacting it in the process
    dump        print a hexadecimal dump of a single page
    get         print the value of a key in a bucket
    info        print basic info
    keys        print a list of keys in a bucket
    help        print this screen
    page        print one or more pages in human readable format
    pages       print list of pages with their types
    page-item   print the key and value of a page item.
    stats       iterate over all pages and generate usage stats

Use "bolt [command] -h" for more information about a command.

其实db文件就是一个按照bbolt格式存储的普通文件,这些命令其实就是操作这些文件。

bench

  1. 解析参数
	var options BenchOptions

	// Parse flagset.
	fs := flag.NewFlagSet("", flag.ContinueOnError)
	fs.StringVar(&options.ProfileMode, "profile-mode", "rw", "")
	fs.StringVar(&options.WriteMode, "write-mode", "seq", "")
	fs.StringVar(&options.ReadMode, "read-mode", "seq", "")
	fs.IntVar(&options.Iterations, "count", 1000, "")
	fs.IntVar(&options.BatchSize, "batch-size", 0, "")
	fs.IntVar(&options.KeySize, "key-size", 8, "")
	fs.IntVar(&options.ValueSize, "value-size", 32, "")
	fs.StringVar(&options.CPUProfile, "cpuprofile", "", "")
	fs.StringVar(&options.MemProfile, "memprofile", "", "")
	fs.StringVar(&options.BlockProfile, "blockprofile", "", "")
	fs.Float64Var(&options.FillPercent, "fill-percent", bolt.DefaultFillPercent, "")
	fs.BoolVar(&options.NoSync, "no-sync", false, "")
	fs.BoolVar(&options.Work, "work", false, "")
	fs.StringVar(&options.Path, "path", "", "")
	fs.SetOutput(cmd.Stderr)
	if err := fs.Parse(args); err != nil {
		return nil, err
	}

这些参数是什么我们暂时不管,涉及到bbolt具体的实现,我们可以看完所有代码以后回过来看看。

  1. db文件
	if options.Path == "" {
		f, err := ioutil.TempFile("", "bolt-bench-")
		if err != nil {
			return nil, fmt.Errorf("temp file: %s", err)
		}
		f.Close()
		os.Remove(f.Name())
		options.Path = f.Name()
	}

如果没有的话就生成临时文件,注意打开以后就remove了,避免了进程崩溃不释放的情况

	// Remove path if "-work" is not set. Otherwise keep path.
	if options.Work {
		fmt.Fprintf(cmd.Stdout, "work: %s\n", options.Path)
	} else {
		defer os.Remove(options.Path)
	}

所以可以传递-path=xxx -work来保存bench过后的文件

runWrites

ProfileMode: 控制在write、read的时候是否写CPUProfile, MemProfile,BlockProfile
WriteMode: seq, rnd,seq-nest, rnd-nest,
stopProfiling: 看来pprof必须掌握啊

runReads

从runWrite写入的数据读取。

buckets

bbolt buckets path_to_db

	// Print buckets.
	return db.View(func(tx *bolt.Tx) error {
		return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
			fmt.Fprintln(cmd.Stdout, string(name))
			return nil
		})
	})

这里可以学到一个技巧:用golang的字面常量的时候会带来首位的换行,可以去掉,使用strings包的trim函数族

strings.TrimSpace(`
usage: bolt buckets PATH

Print a list of buckets.
`)

compact

compact其实就是遍历当前的db,搜集一个bucket里面的所有kv,然后一次commit到另外一个db里面去

dump

dump某一个page

获取page大小:

	// Read 4KB chunk.
	buf := make([]byte, 4096)
	if _, err := io.ReadFull(f, buf); err != nil {
		return 0, err
	}

	// Read page size from metadata.
	m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize]))
	return int(m.pageSize), nil

这怎么看起来和c语言的做法啊,为毛不用gob

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值