status.go
- package volume
- import (
- "github.com/syndtr/goleveldb/leveldb"
- "sync"
- "encoding/binary"
- "github.com/syndtr/goleveldb/leveldb/util"
- "errors"
- "path/filepath"
- "strconv"
- "fmt"
- )
- const (
- ReversedsizeOffsetPrefix = '\x11' //key= "\x01"+Reversesize(8 byte)+offset(8 byte) value=[]
- OffsetSizePrefix = '\x22' //key= "\x02"+offset(8 byte)+size(8 byte) value=[]
- )
- /*
- status主要存储空闲块的offset size
- */
- type Status struct {
- path string
- db *leveldb.DB
- spaceMutex sync.Mutex
- }
- //创建空闲文件 元数据
- func NewStatus(dir string, vid uint64) (status *Status, err error) {
- path := filepath.Join(dir, strconv.FormatUint(vid, 10) + ".status")
- status = new(Status)
- status.path = path
- status.db, err = leveldb.OpenFile(path, nil)
- return status, err
- }
- //分配空间
- func (s *Status)newSpace(size uint64) (offset uint64, err error) {
- s.spaceMutex.Lock()
- defer s.spaceMutex.Unlock()
- //这里根据size倒序存储,使最大的空间最先被获取
- iter := s.db.NewIterator(util.BytesPrefix([]byte{ReversedsizeOffsetPrefix}), nil)
- defer iter.Release()
- iter.Next()
- key := iter.Key()
- if len(key) == 0 {
- return 0, errors.New("can't get free space")
- }
- freeSize := binary.BigEndian.Uint64(key[1:9]) ^ (^uint64(0))
- if freeSize < size {
- return 0, errors.New("can't get free space")
- }
- offset = binary.BigEndian.Uint64(key[9:])
- transaction, err := s.db.OpenTransaction()
- if err != nil {
- return 0, err
- }
- transaction.Delete(key, nil)
- key = getOffsetSizeKey(offset, freeSize)
- transaction.Delete(key, nil)
- //如果空闲块大小大于所请求大小,则将剩下空闲块,重新记录
- if freeSize > size {
- key = getReversedsizeOffset(offset + size, freeSize - size)
- transaction.Put(key, nil, nil)
- key = getOffsetSizeKey(offset + size, freeSize - size)
- transaction.Put(key, nil, nil)
- }
- err = transaction.Commit()
- return offset, err
- }
- // 释放文件空间
- func (s *Status)freeSpace(offset uint64, size uint64) error {
- s.spaceMutex.Lock()
- defer s.spaceMutex.Unlock()
//这里根据size倒序存储,使最大的空间最先被获取
- iter := s.db.NewIterator(util.BytesPrefix([]byte{OffsetSizePrefix}), nil)
- defer iter.Release()
- key := getOffsetSizeKey(offset, 0)
- iter.Seek(key)
- transaction, err := s.db.OpenTransaction()
- if err != nil {
- return err
- }
- //如果与下一块空闲块相邻,则合成一块空闲块
- key = iter.Key()
- if len(key) != 0 {
- nOffset := binary.BigEndian.Uint64(key[1:9])
- nSize := binary.BigEndian.Uint64(key[9:])
- if nOffset < offset + size {
- panic(fmt.Errorf("nOffset: %d < offset: %d + size: %d", nOffset, offset, size))
- } else if nOffset == offset + size {
- transaction.Delete(key, nil)
- size += nSize
- key = getReversedsizeOffset(nOffset, nSize)
- transaction.Delete(key, nil)
- }
- }
- //如果与上一块空闲块相邻,则合成一块空闲块
- iter.Prev()
- key = iter.Key()
- if len(key) != 0 {
- pOffset := binary.BigEndian.Uint64(key[1:9])
- pSize := binary.BigEndian.Uint64(key[9:])
- if pOffset + pSize > offset {
- panic(fmt.Errorf("pOffset: %d + pSize: %d > offset: %d", pOffset, pSize, offset))
- } else if pOffset + pSize == offset {
- transaction.Delete(key, nil)
- offset = pOffset
- size += pSize
- key = getReversedsizeOffset(pOffset, pSize)
- transaction.Delete(key, nil)
- }
- }
- key = getOffsetSizeKey(offset, size)
- transaction.Put(key, nil, nil)
- key = getReversedsizeOffset(offset, size)
- transaction.Put(key, nil, nil)
- return transaction.Commit()
- }
- //
- func (s *Status)getMaxFreeSpace() uint64 {
- iter := s.db.NewIterator(util.BytesPrefix([]byte{ReversedsizeOffsetPrefix}), nil)
- defer iter.Release()
- iter.Next()
- key := iter.Key()
- if len(key) == 0 {
- return 0
- }
- freeSize := binary.BigEndian.Uint64(key[1:9]) ^ (^uint64(0))
- return freeSize
- }
- //获取偏移量 文件key
- func getOffsetSizeKey(offset, size uint64) []byte {
- key := make([]byte, 1 + 16)
- key[0] = OffsetSizePrefix
- binary.BigEndian.PutUint64(key[1:9], offset)
- binary.BigEndian.PutUint64(key[9:], size)
- return key
- }
- //
- func getReversedsizeOffset(offset, size uint64) []byte {
- key := make([]byte, 1 + 16)
- key[0] = ReversedsizeOffsetPrefix
- binary.BigEndian.PutUint64(key[9:], offset)
- binary.BigEndian.PutUint64(key[1:9], size ^ (^uint64(0)))
- return key
- }
status.go的更多相关文章
- http status code
属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...
- ORACLE中STATUS为INACTIVE但是SERVER为SHARED状态的会话浅析
我们知道当ORACLE数据库启用共享服务器模式时,通过共享服务器模式连接到数据库的会话是有一些特征的.在v$session里面,其SERVER的状态一般为SHARED和NONE, 为SHARED时,表 ...
- 重定向Http status code 303 和 302
http 302 http 303 Http 302 302是一个普通的重定向代码.直观的看来是,请求者(浏览器或者模拟http请求)发起一个请求,然后服务端重定向到另一个地址.而事实上,服务端仅仅是 ...
- C#、JAVA操作Hadoop(HDFS、Map/Reduce)真实过程概述。组件、源码下载。无法解决:Response status code does not indicate success: 500。
一.Hadoop环境配置概述 三台虚拟机,操作系统为:Ubuntu 16.04. Hadoop版本:2.7.2 NameNode:192.168.72.132 DataNode:192.168.72. ...
- 关于XHR对象中status范围的记录
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ // 成功执行区域 // 2XX表示有效响应 ...
- Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details
thinkphp 在Apache上配置启用伪静态,重启Apache1 restart 竟然失败了,报错 Job for httpd.service failed because the control ...
- ajax response status list [转载]
比较理想的解释方法应该以"状态:任务(目标)+过程+表现(或特征)"的表达模式来对这几个状态进行定义 [全文] 在<Pragmatic Ajax A Web 2.0 Pr ...
- Zabbix监控redis status
概述 zabbix采用Trapper方式监控redis status 原理 redis-cli info命令得到redis服务器的统计信息,脚本对信息分两部分处理: (1)# Keyspace部分为Z ...
- Zabbix监控nginx-rtmp status(json版)
与前面的文章 zabbix监控nginx-rtmp status(html版)区别只在于取值的页面不一样 http://127.0.0.1:81/control/get/all_streams sta ...
- 查看Mysql版本号 (最简单的是status )
一.使用命令行模式进入mysql会看到最开始的提示符;二.命令行中使用status可以看到;三.使用系统函数等等, 查看版本信息 #1使用命令行模式进入mysql会看到最开始的提示符 Your M ...
随机推荐
- python select.select模块通信全过程详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- 使用微服务架构思想,设计部署OAuth2.0授权认证框架
1,授权认证与微服务架构 1.1,由不同团队合作引发的授权认证问题 去年的时候,公司开发一款新产品,但人手不够,将B/S系统的Web开发外包,外包团队使用Vue.js框架,调用我们的WebAPI,但是 ...
- java学习面试精华
1.线程状态转移 (1)线程生命周期中的5种状态 新建(New).就绪(Runnable).运行(Running).阻塞(Bolocked)和死亡(Dead) 新建(New):程序使用new关键字创建 ...
- Effective Java 第三版——40. 始终使用Override注解
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Selenium调用webdriver.chrome()出错
问题描述: 今天因为在学习要使用selenium这个python库,我下载好了selenium,并且也Import成功了,但是在我使用webdirver.chorme()时,却提示PATH路径中没有c ...
- python笔记:#003#PyCharm 的初始设置
PyCharm 的初始设置(知道) 目标 恢复 PyCharm 的初始设置 第一次启动 PyCharm 新建一个 Python 项目 设置 PyCharm 的字体显示 PyCharm 的升级以及其他 ...
- 论文笔记(1):Deep Learning.
论文笔记1:Deep Learning 2015年,深度学习三位大牛(Yann LeCun,Yoshua Bengio & Geoffrey Hinton),合作在Nature ...
- [Java算法分析与设计]--顺序栈的实现
在程序的世界,栈的应用是相当广泛的.其后进先出的特性,我们可以应用到诸如计算.遍历.代码格式校对等各个方面.但是你知道栈的底层是怎么实现的吗?现在跟随本篇文章我们来一睹它的庐山真面目吧. 首先我们先定 ...
- Java Collections类
集合类是什么? List列表.Set集合.Map映射.工具类(Iterator迭代器.Enumeration枚举类.Arrays和Collections). Set 接口继承 Collection,但 ...
- 初探Margin负值(转)
相对而言,margin 负值的使用机率在布局中似乎很少,但是我相信一旦你开始掌握就会着迷,接下来我们看看关于margin负值的一些资料: 它是一个有效的属性,至少w3c中明确描述如下:”Negativ ...