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 ...
随机推荐
- Docker学习笔记【四】Docker 仓库
访问仓库,仓库是集中从存放镜像的地方.类似Maven. Docker Hub 目前由Docker官方维护的一个公共仓库,其中包括15000的镜像. 注册 在 https://hub.docker.co ...
- RocketMQ源码 — 六、 RocketMQ高可用(1)
高可用究竟指的是什么?请参考:关于高可用的系统 RocketMQ做了以下的事情来保证系统的高可用 多master部署,防止单点故障 消息冗余(主从结构),防止消息丢失 故障恢复(本篇暂不讨论) 那么问 ...
- rotate image(旋转数组)
You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...
- JAVA 综合面试题
JAVA 综合面试题 2007-08-12 目录 TOC \o "1-3" \h \z \u Java面试题整理 9 Java面向对象 9 1. super()与this()的区别 ...
- 如何实现Zabbix的主动注册功能
主动注册(Active Agent Auto-Registration),顾名思义,无需在Zabbix Web上手动添加host信息,即可实现主机的监控. 它是由Agent主动向Server注册. 相 ...
- Linux 文件目录解释
/bin:bin是binary(二进制)的缩写.这个目录是对UNIX系统习惯的沿袭,存放着使用者最经常使用的命令.例如:cp,ls,cat. /boot:这里存放的是启动LINUX时使用的一些核心文件 ...
- 前端Mahsup异步依赖方式不能做业务数据依赖
很久之前流行mashup方式做内容集成,之前为了IP定位的方便,引用了第三方的IP定位JS,然后根据其内容与服务器同步地址数据并写入Cookie,可是这种方式一旦,第三方的库反应缓慢时,就会出现大问题 ...
- 推荐 git community book 中文版
官方地址:http://Git.seyren.com/index.html 或者 http://gitbook.liuhui998.com/ book@github项目地址: https://gith ...
- jvm垃圾回收(三)
一.分代思想(年轻代.老年代.永久代): 1.一个新人(new对象)会优先在伊甸园(Eden区)出生,当伊甸园(Eden区)人口达到最大容量时,JVM会派MinorGC去看看哪些人还有价值 2.伊甸园 ...
- jenkins构建基于gradle的springboot项目CI采坑(采用jar方式部署)
试了一堆插件,最后用的还是 publish over SSH jenkins基本配置不多说了,就是配置一下git仓储,配置一下gradle执行命令 clean bootRepackage 之后执行Se ...