github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/mmr/file_hash_store.go (about)

     1  package mmr
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"os"
     7  	"unsafe"
     8  )
     9  
    10  type fileHashStore struct {
    11  	fileName string
    12  	file     *os.File
    13  }
    14  
    15  // NewFileHashStore returns a HashStore implement in file
    16  func NewFileHashStore(name string, treeSize uint64) (hs HashStore, err error) {
    17  	f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0755)
    18  	if err != nil {
    19  		return
    20  	}
    21  	store := &fileHashStore{
    22  		fileName: name,
    23  		file:     f,
    24  	}
    25  
    26  	hashCount := getStoredHashCount(treeSize)
    27  	size := int64(hashCount) * int64(unsafe.Sizeof(HashType{}))
    28  
    29  	err = store.checkConsistence(size)
    30  	if err != nil {
    31  		return
    32  	}
    33  
    34  	_, err = store.file.Seek(size, io.SeekStart)
    35  	if err != nil {
    36  		return
    37  	}
    38  
    39  	hs = store
    40  	return
    41  }
    42  
    43  var (
    44  	errStoredHashLessThanExpected = errors.New("stored hashes are less than expected")
    45  )
    46  
    47  func (self *fileHashStore) checkConsistence(fileSize int64) (err error) {
    48  
    49  	stat, err := self.file.Stat()
    50  	if err != nil {
    51  		return
    52  	}
    53  	if stat.Size() < fileSize {
    54  		err = errStoredHashLessThanExpected
    55  		return
    56  	}
    57  
    58  	return
    59  }
    60  
    61  func (self *fileHashStore) Append(hash []HashType) error {
    62  	buf := make([]byte, 0, len(hash)*int(unsafe.Sizeof(HashType{})))
    63  	for _, h := range hash {
    64  		buf = append(buf, h[:]...)
    65  	}
    66  	_, err := self.file.Write(buf)
    67  	return err
    68  }
    69  
    70  func (self *fileHashStore) Flush() error {
    71  	return self.file.Sync()
    72  }
    73  
    74  func (self *fileHashStore) Close() {
    75  	self.file.Close()
    76  }
    77  
    78  func (self *fileHashStore) GetHash(pos uint64) (h HashType, err error) {
    79  	h = unknownHash
    80  	_, err = self.file.ReadAt(h[:], int64(pos)*int64(unsafe.Sizeof(HashType{})))
    81  	if err != nil {
    82  		return
    83  	}
    84  
    85  	return
    86  }
    87  
    88  func getStoredHashCount(treeSize uint64) int64 {
    89  	subtreesize := getMoutainSizes(treeSize)
    90  	sum := int64(0)
    91  	for _, v := range subtreesize {
    92  		sum += int64(v)
    93  	}
    94  
    95  	return sum
    96  }