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 ...
随机推荐
- IOS中用到的缓存
App已经与我们形影不离了,不管在地铁上.公交上还是在会场你总能看到很多人拿出来手机,刷一刷微博,看看新闻. 据不完全统计有近一半的用户在非Wifi环境打开App,以下为一个典型iPhone和Andr ...
- WebService学习--(三)使用JDK开发WebService
一.WebService的开发手段 使用Java开发WebService时可以使用以下两种开发手段 1. 使用JDK开发(1.6及以上版本) 2.使用CXF框架开发(工作中) 二.使用JDK开发Web ...
- jquery 加法 乘法运算 精确计算函数
int类型相加不会出现问题,但小数点相加就会出现问题 //乘法函数 var accMul = function(arg1, arg2){ var m=0,s1=arg1.toString(),s2=a ...
- 第8章-Java集合 --- 概述
第8章-Java集合 --- 概述 (1)Java集合类是一种特别有用的工具类,可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如 栈.队列等. (2)Java集合大致可分为Set.List ...
- 使用nginx sticky实现基于cookie的负载均衡
在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...
- php coding中的一些小问题
最近在SAE上写微博应用,碰到一些小问题,记下来,以供参考: 1.出错提示: Fatal error: Can't use function return value in write context ...
- composer安装yii2
这几天准备入门yii2,但是对于一个看php不到5天的小白来说,只能说路途艰辛,不过,总算是解决了,先放一张大图 感受一下成功的喜悦...(文章最后有惊喜哦) ok,下面就描述一下安装的步骤: 1.安 ...
- 分布式配置管理平台XXL-CONF
<分布式配置管理平台XXL-CONF> 一.简介 1.1 概述 XXL-CONF 是一个分布式配置管理平台,提供统一的配置管理服务.现已开放源代码,开箱即用. 1.2 特性 1. ...
- 前端开发APP,从HBuilder开始~ 【转】
内容简介 介绍目前前端人员开发app的几种方法,具体介绍hbuilder开发app,一扇赞新的大门~ 无所不能的js 最开始js仅仅局限于网页上一些效果,操作网页内容等, 但是nodejs把js带入了 ...
- git merge与 git rebase区别及实例
接Git分支创建与合并,在分支合并时,有两种方式:git merge 和git rebase. git merge:将两个分支,合并提交为一个新提交,并且新提交有2个parent. git rebas ...