zoukankan      html  css  js  c++  java
  • 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
    }

  • 相关阅读:
    【今日CV 视觉论文速览】 19 Nov 2018
    【numpy求和】numpy.sum()求和
    【今日CV 视觉论文速览】16 Nov 2018
    【今日CV 视觉论文速览】15 Nov 2018
    poj 2454 Jersey Politics 随机化
    poj 3318 Matrix Multiplication 随机化算法
    hdu 3400 Line belt 三分法
    poj 3301 Texas Trip 三分法
    poj 2976 Dropping tests 0/1分数规划
    poj 3440 Coin Toss 概率问题
  • 原文地址:https://www.cnblogs.com/zhangboyu/p/7461618.html
Copyright © 2011-2022 走看看