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 ...
随机推荐
- 使用vs2010 opencv2.4.4编译release版本程序
大体上要注意一下几点内容: 1.vc++目录的选择上,库目录选择为opencv目录中的staticlib目录 2.在链接->输入->附加依赖库,中添加,相应的staticlib库目录中的所 ...
- IOS空数据页面,网络加载失败以及重新登陆View的封装(不需要继承)
一.问题 对于B2C和B2B项目的开发者,可能会有一个订单列表为空,或者其他收藏页面为空,用户token失效,判断用户要重新登陆,以及后台服务错误等提示.本篇课文,看完大约10分钟. 原本自己不想写空 ...
- 收藏 - android
收藏 - android开发 2018-05-04 16:39:36 介绍:这篇文章是收藏系列的开山第一篇,主要收藏了跟android开发有关的一些内容,也算是内容汇总,后期会持续更新: 内容目录 1 ...
- plsql developer 使用 oracle instantclient的安装和配置
本文由ibyedo1贡献 1.下载 oracle instantclient basic package,在 oracle 官网下载就可以,地址如下: http://www.oracle.com/te ...
- 我的sql数据库存储过程分页- -
以前用到数据库存储过程分页的时候都是用 not in 但是最近工作的时候,随着数据库记录的不断增大,发现not in的效率 真的不行 虽然都设置了索引,但是当记录达到10w的时候就发现不行了,都是需要 ...
- windows下mongodb安装详解
1.打开官网https://www.mongodb.com/download-center?jmp=nav#community 注:这里小伙伴们可是开启下FQ软件psiphon 3下载(不开启FQ好像 ...
- Ubuntu设置代理的方法
用过Linux的都知道,众多的PROXY配置,让人应接不暇,本文列出常见的一些PROXY的配置 1.apt-get proxy 的配置sudo gedit /etc/apt/apt.conf NOTE ...
- App免费推广途径概要
说在前面的话:免费其实挺花功夫的,所有的营销的前提是产品和服务是值得推荐的. 1.技术操作维度:ASO,SEO, ASO简单介绍:http://baike.baidu.com/subview/1368 ...
- Vue--学习过程中遇到的坑
在这里总结一下学习Vue遇到的易错点,持续更新 1.实例化一个Vue对象: 通过new Vue({ el:'#id', data:{ a:'字符串1', b:‘字符串2’ }) 这里的Vue必须大写V ...
- C#文件和字节流的转换方法
1.读取文件,并转换为字节流 FileStream fs = new FileStream(filename,FileMode.Open,FileAccess.Read); byte[] infbyt ...