1. package volume

  1. import (
  1.     "github.com/syndtr/goleveldb/leveldb"
  1.     "sync"
  1.     "encoding/binary"
  1.     "github.com/syndtr/goleveldb/leveldb/util"
  1.     "errors"
  1.     "path/filepath"
  1.     "strconv"
  1.     "fmt"
  1. )

  1. const (
  1.     ReversedsizeOffsetPrefix = '\x11' //key= "\x01"+Reversesize(8 byte)+offset(8 byte) value=[]
  1.     OffsetSizePrefix = '\x22' //key= "\x02"+offset(8 byte)+size(8 byte) value=[]
  1. )

  1. /*
  1. status主要存储空闲块的offset size
  1. */
  1. type Status struct {
  1.     path string
  1.     db *leveldb.DB
  1.     spaceMutex sync.Mutex
  1. }
  1. //创建空闲文件 元数据
  1. func NewStatus(dir string, vid uint64) (status *Status, err error) {
  1.     path := filepath.Join(dir, strconv.FormatUint(vid, 10) + ".status")
  1.     status = new(Status)
  1.     status.path = path
  1.     status.db, err = leveldb.OpenFile(path, nil)
  1.     return status, err
  1. }
  1. //分配空间
  1. func (s *Status)newSpace(size uint64) (offset uint64, err error) {
  1.     s.spaceMutex.Lock()
  1.     defer s.spaceMutex.Unlock()

  1.     //这里根据size倒序存储,使最大的空间最先被获取
  1.     iter := s.db.NewIterator(util.BytesPrefix([]byte{ReversedsizeOffsetPrefix}), nil)
  1.     defer iter.Release()
  1.     iter.Next()
  1.     key := iter.Key()
  1.     if len(key) == 0 {
  1.         return 0, errors.New("can't get free space")
  1.     }

  1.     freeSize := binary.BigEndian.Uint64(key[1:9]) ^ (^uint64(0))
  1.     if freeSize < size {
  1.         return 0, errors.New("can't get free space")
  1.     }
  1.     offset = binary.BigEndian.Uint64(key[9:])

  1.     transaction, err := s.db.OpenTransaction()
  1.     if err != nil {
  1.         return 0, err
  1.     }

  1.     transaction.Delete(key, nil)

  1.     key = getOffsetSizeKey(offset, freeSize)
  1.     transaction.Delete(key, nil)

  1.     //如果空闲块大小大于所请求大小,则将剩下空闲块,重新记录
  1.     if freeSize > size {
  1.         key = getReversedsizeOffset(offset + size, freeSize - size)
  1.         transaction.Put(key, nil, nil)

  1.         key = getOffsetSizeKey(offset + size, freeSize - size)
  1.         transaction.Put(key, nil, nil)
  1.     }

  1.     err = transaction.Commit()
  1.     return offset, err
  1. }
  1. // 释放文件空间
  1. func (s *Status)freeSpace(offset uint64, size uint64) error {
  1.     s.spaceMutex.Lock()
  1.     defer s.spaceMutex.Unlock()
  1.        //这里根据size倒序存储,使最大的空间最先被获取
  1.     iter := s.db.NewIterator(util.BytesPrefix([]byte{OffsetSizePrefix}), nil)
  1.     defer iter.Release()
  1.     key := getOffsetSizeKey(offset, 0)
  1.     iter.Seek(key)
  1.     transaction, err := s.db.OpenTransaction()
  1.     if err != nil {
  1.         return err
  1.     }
  1.     //如果与下一块空闲块相邻,则合成一块空闲块
  1.     key = iter.Key()
  1.     if len(key) != 0 {
  1.         nOffset := binary.BigEndian.Uint64(key[1:9])
  1.         nSize := binary.BigEndian.Uint64(key[9:])
  1.         if nOffset < offset + size {
  1.             panic(fmt.Errorf("nOffset: %d < offset: %d + size: %d", nOffset, offset, size))
  1.         } else if nOffset == offset + size {
  1.             transaction.Delete(key, nil)
  1.             size += nSize
  1.             key = getReversedsizeOffset(nOffset, nSize)
  1.             transaction.Delete(key, nil)
  1.         }
  1.     }
  1.     //如果与上一块空闲块相邻,则合成一块空闲块
  1.     iter.Prev()
  1.     key = iter.Key()
  1.     if len(key) != 0 {
  1.         pOffset := binary.BigEndian.Uint64(key[1:9])
  1.         pSize := binary.BigEndian.Uint64(key[9:])
  1.         if pOffset + pSize > offset {
  1.             panic(fmt.Errorf("pOffset: %d + pSize: %d > offset: %d", pOffset, pSize, offset))
  1.         } else if pOffset + pSize == offset {
  1.             transaction.Delete(key, nil)
  1.             offset = pOffset
  1.             size += pSize
  1.             key = getReversedsizeOffset(pOffset, pSize)
  1.             transaction.Delete(key, nil)
  1.         }
  1.     }
  1.     key = getOffsetSizeKey(offset, size)
  1.     transaction.Put(key, nil, nil)
  1.     key = getReversedsizeOffset(offset, size)
  1.     transaction.Put(key, nil, nil)
  1.     return transaction.Commit()
  1. }
  1. //
  1. func (s *Status)getMaxFreeSpace() uint64 {
  1.     iter := s.db.NewIterator(util.BytesPrefix([]byte{ReversedsizeOffsetPrefix}), nil)
  1.     defer iter.Release()
  1.     iter.Next()
  1.     key := iter.Key()
  1.     if len(key) == 0 {
  1.         return 0
  1.     }
  1.     freeSize := binary.BigEndian.Uint64(key[1:9]) ^ (^uint64(0))
  1.     return freeSize
  1. }
  1. //获取偏移量 文件key
  1. func getOffsetSizeKey(offset, size uint64) []byte {
  1.     key := make([]byte, 1 + 16)
  1.     key[0] = OffsetSizePrefix
  1.     binary.BigEndian.PutUint64(key[1:9], offset)
  1.     binary.BigEndian.PutUint64(key[9:], size)
  1.     return key
  1. }
  1. //
  1. func getReversedsizeOffset(offset, size uint64) []byte {
  1.     key := make([]byte, 1 + 16)
  1.     key[0] = ReversedsizeOffsetPrefix
  1.     binary.BigEndian.PutUint64(key[9:], offset)
  1.     binary.BigEndian.PutUint64(key[1:9], size ^ (^uint64(0)))
  1.     return key
  1. }

status.go的更多相关文章

  1. http status code

    属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...

  2. ORACLE中STATUS为INACTIVE但是SERVER为SHARED状态的会话浅析

    我们知道当ORACLE数据库启用共享服务器模式时,通过共享服务器模式连接到数据库的会话是有一些特征的.在v$session里面,其SERVER的状态一般为SHARED和NONE, 为SHARED时,表 ...

  3. 重定向Http status code 303 和 302

    http 302 http 303 Http 302 302是一个普通的重定向代码.直观的看来是,请求者(浏览器或者模拟http请求)发起一个请求,然后服务端重定向到另一个地址.而事实上,服务端仅仅是 ...

  4. 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. ...

  5. 关于XHR对象中status范围的记录

    if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ // 成功执行区域 // 2XX表示有效响应 ...

  6. 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 ...

  7. ajax response status list [转载]

    比较理想的解释方法应该以"状态:任务(目标)+过程+表现(或特征)"的表达模式来对这几个状态进行定义  [全文]  在<Pragmatic Ajax A Web 2.0 Pr ...

  8. Zabbix监控redis status

    概述 zabbix采用Trapper方式监控redis status 原理 redis-cli info命令得到redis服务器的统计信息,脚本对信息分两部分处理: (1)# Keyspace部分为Z ...

  9. Zabbix监控nginx-rtmp status(json版)

    与前面的文章 zabbix监控nginx-rtmp status(html版)区别只在于取值的页面不一样 http://127.0.0.1:81/control/get/all_streams sta ...

  10. 查看Mysql版本号 (最简单的是status )

    一.使用命令行模式进入mysql会看到最开始的提示符;二.命令行中使用status可以看到;三.使用系统函数等等,   查看版本信息 #1使用命令行模式进入mysql会看到最开始的提示符 Your M ...

随机推荐

  1. python select.select模块通信全过程详解

    要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...

  2. 使用微服务架构思想,设计部署OAuth2.0授权认证框架

    1,授权认证与微服务架构 1.1,由不同团队合作引发的授权认证问题 去年的时候,公司开发一款新产品,但人手不够,将B/S系统的Web开发外包,外包团队使用Vue.js框架,调用我们的WebAPI,但是 ...

  3. java学习面试精华

    1.线程状态转移 (1)线程生命周期中的5种状态 新建(New).就绪(Runnable).运行(Running).阻塞(Bolocked)和死亡(Dead) 新建(New):程序使用new关键字创建 ...

  4. Effective Java 第三版——40. 始终使用Override注解

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Selenium调用webdriver.chrome()出错

    问题描述: 今天因为在学习要使用selenium这个python库,我下载好了selenium,并且也Import成功了,但是在我使用webdirver.chorme()时,却提示PATH路径中没有c ...

  6. python笔记:#003#PyCharm 的初始设置

    PyCharm 的初始设置(知道) 目标 恢复 PyCharm 的初始设置 第一次启动 PyCharm 新建一个 Python 项目 设置 PyCharm 的字体显示 PyCharm 的升级以及其他 ...

  7. 论文笔记(1):Deep Learning.

    论文笔记1:Deep Learning         2015年,深度学习三位大牛(Yann LeCun,Yoshua Bengio & Geoffrey Hinton),合作在Nature ...

  8. [Java算法分析与设计]--顺序栈的实现

    在程序的世界,栈的应用是相当广泛的.其后进先出的特性,我们可以应用到诸如计算.遍历.代码格式校对等各个方面.但是你知道栈的底层是怎么实现的吗?现在跟随本篇文章我们来一睹它的庐山真面目吧. 首先我们先定 ...

  9. Java Collections类

    集合类是什么? List列表.Set集合.Map映射.工具类(Iterator迭代器.Enumeration枚举类.Arrays和Collections). Set 接口继承 Collection,但 ...

  10. 初探Margin负值(转)

    相对而言,margin 负值的使用机率在布局中似乎很少,但是我相信一旦你开始掌握就会着迷,接下来我们看看关于margin负值的一些资料: 它是一个有效的属性,至少w3c中明确描述如下:”Negativ ...