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 }