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 ...
随机推荐
- 飞鱼相册笔记(1)----外置SD卡文件夹名称不区分大小写
飞鱼相册笔记(1)----外置SD卡文件夹名称不区分大小写 在飞鱼相册发布的第一个测试版中,很多用户表示无法查看外置SD卡中的照片.乍一听觉得加个外置SD卡的根目录,然后在扫描所有图片的时候把这个根目 ...
- 万水千山ABP - 单租户时,成功保存数据后,数据不显示
问题描述: ABP 禁用了多租户,在编辑一个实体记录后,能成功地保存数据,但数据列表中看不到这条记录.打开数据表查看,发现该实体记录的 TenantId 字段值成了 Null , 而不是预期的默认租户 ...
- parted分区详解 查看UUID两种方式 blkid 和 ls -l /dev/disk/by-uuid
通常我们用的比较多的一般都是fdisk工具来进行分区,但是现在由于磁盘越来越廉价,而且磁盘空间越来越大:而fdisk工具他对分区是有大小限制的,它只能划分小于2T的磁盘.但是现在的磁盘空间很多都已经是 ...
- C#程序自动更新软件版本号
最近因为服务器程序管理多,所以在查看服务器程序的时候,只能通过EXE的编译时间来判断服务器程序版本时间,费神伤身啊 现在想了一个方式,在目录下新增一个version文件,里面写上年月日,并且只是在程序 ...
- macOS High Sierra Terminal巨卡问题的解决
输入命令特别卡,拖拽窗口也特别卡,想到可能和界面渲染有关系,到设置里面把不透明度调成满值,问题解决. 真正的技术原因是看iOS开发相关的书的时候,书里面有这方面渲染消耗的提示说明.
- HTML学习笔记5:修饰符和特殊标签
①修饰符: 作用:修饰显示的方式,并不改变网页的结构,需要修饰的内容写在修饰标签内 常用文字和段落修饰符: 文字斜体:<i></i> 或 <em> ...
- 想做微信小程序第三方代理,各位觉得一键生成平台能赚到钱吗?
这几年生意不景气,这是很多人的共识.从2009年开始,各种专家就判断"明年经济是最差的一年."然后,这个明年,一直"明"到了2018年,到最后,我们发现,经济就 ...
- HBuilder 打包流程
1.运行HBuilder---百度搜索HBuilder,官网下载安装包,解压,运行HBuilder.exe.注册账号,并登陆 2.新建app---在左边右键,选择新建APP,或者,点击中间的新建app ...
- C# 发展史
C# 发展史 Intro 本文主要总结介绍C# 每个版本带来的不同的语言特性. C#,读作C Sharp,是微软推出的一种基于.NET平台的.面向对象的高级编程语言.是微软公司在2000年发布的一种新 ...
- Spring Boot 快速入门笔记
Spirng boot笔记 简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...