github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/swarm/storage/memstore.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // memory storage layer for the package blockhash 18 19 package storage 20 21 import ( 22 "sync" 23 ) 24 25 const ( 26 memTreeLW = 2 // log2(subtree count) of the subtrees 27 memTreeFLW = 14 // log2(subtree count) of the root layer 28 dbForceUpdateAccessCnt = 1000 29 defaultCacheCapacity = 5000 30 ) 31 32 type MemStore struct { 33 memtree *memTree 34 entryCnt, capacity uint // stored entries 35 accessCnt uint64 // access counter; oldest is thrown away when full 36 dbAccessCnt uint64 37 dbStore *DbStore 38 lock sync.Mutex 39 } 40 41 /* 42 a hash prefix subtree containing subtrees or one storage entry (but never both) 43 44 - access[0] stores the smallest (oldest) access count value in this subtree 45 - if it contains more subtrees and its subtree count is at least 4, access[1:2] 46 stores the smallest access count in the first and second halves of subtrees 47 (so that access[0] = min(access[1], access[2]) 48 - likewise, if subtree count is at least 8, 49 access[1] = min(access[3], access[4]) 50 access[2] = min(access[5], access[6]) 51 (access[] is a binary tree inside the multi-bit leveled hash tree) 52 */ 53 54 func NewMemStore(d *DbStore, capacity uint) (m *MemStore) { 55 m = &MemStore{} 56 m.memtree = newMemTree(memTreeFLW, nil, 0) 57 m.dbStore = d 58 m.setCapacity(capacity) 59 return 60 } 61 62 type memTree struct { 63 subtree []*memTree 64 parent *memTree 65 parentIdx uint 66 67 bits uint // log2(subtree count) 68 width uint // subtree count 69 70 entry *Chunk // if subtrees are present, entry should be nil 71 lastDBaccess uint64 72 access []uint64 73 } 74 75 func newMemTree(b uint, parent *memTree, pidx uint) (node *memTree) { 76 node = new(memTree) 77 node.bits = b 78 node.width = 1 << uint(b) 79 node.subtree = make([]*memTree, node.width) 80 node.access = make([]uint64, node.width-1) 81 node.parent = parent 82 node.parentIdx = pidx 83 if parent != nil { 84 parent.subtree[pidx] = node 85 } 86 87 return node 88 } 89 90 func (node *memTree) updateAccess(a uint64) { 91 aidx := uint(0) 92 var aa uint64 93 oa := node.access[0] 94 for node.access[aidx] == oa { 95 node.access[aidx] = a 96 if aidx > 0 { 97 aa = node.access[((aidx-1)^1)+1] 98 aidx = (aidx - 1) >> 1 99 } else { 100 pidx := node.parentIdx 101 node = node.parent 102 if node == nil { 103 return 104 } 105 nn := node.subtree[pidx^1] 106 if nn != nil { 107 aa = nn.access[0] 108 } else { 109 aa = 0 110 } 111 aidx = (node.width + pidx - 2) >> 1 112 } 113 114 if (aa != 0) && (aa < a) { 115 a = aa 116 } 117 } 118 } 119 120 func (s *MemStore) setCapacity(c uint) { 121 s.lock.Lock() 122 defer s.lock.Unlock() 123 124 for c < s.entryCnt { 125 s.removeOldest() 126 } 127 s.capacity = c 128 } 129 130 func (s *MemStore) getEntryCnt() uint { 131 return s.entryCnt 132 } 133 134 // entry (not its copy) is going to be in MemStore 135 func (s *MemStore) Put(entry *Chunk) { 136 if s.capacity == 0 { 137 return 138 } 139 140 s.lock.Lock() 141 defer s.lock.Unlock() 142 143 if s.entryCnt >= s.capacity { 144 s.removeOldest() 145 } 146 147 s.accessCnt++ 148 149 node := s.memtree 150 bitpos := uint(0) 151 for node.entry == nil { 152 l := entry.Key.bits(bitpos, node.bits) 153 st := node.subtree[l] 154 if st == nil { 155 st = newMemTree(memTreeLW, node, l) 156 bitpos += node.bits 157 node = st 158 break 159 } 160 bitpos += node.bits 161 node = st 162 } 163 164 if node.entry != nil { 165 166 if node.entry.Key.isEqual(entry.Key) { 167 node.updateAccess(s.accessCnt) 168 if entry.SData == nil { 169 entry.Size = node.entry.Size 170 entry.SData = node.entry.SData 171 } 172 if entry.Req == nil { 173 entry.Req = node.entry.Req 174 } 175 entry.C = node.entry.C 176 node.entry = entry 177 return 178 } 179 180 for node.entry != nil { 181 182 l := node.entry.Key.bits(bitpos, node.bits) 183 st := node.subtree[l] 184 if st == nil { 185 st = newMemTree(memTreeLW, node, l) 186 } 187 st.entry = node.entry 188 node.entry = nil 189 st.updateAccess(node.access[0]) 190 191 l = entry.Key.bits(bitpos, node.bits) 192 st = node.subtree[l] 193 if st == nil { 194 st = newMemTree(memTreeLW, node, l) 195 } 196 bitpos += node.bits 197 node = st 198 199 } 200 } 201 202 node.entry = entry 203 node.lastDBaccess = s.dbAccessCnt 204 node.updateAccess(s.accessCnt) 205 s.entryCnt++ 206 207 return 208 } 209 210 func (s *MemStore) Get(hash Key) (chunk *Chunk, err error) { 211 s.lock.Lock() 212 defer s.lock.Unlock() 213 214 node := s.memtree 215 bitpos := uint(0) 216 for node.entry == nil { 217 l := hash.bits(bitpos, node.bits) 218 st := node.subtree[l] 219 if st == nil { 220 return nil, notFound 221 } 222 bitpos += node.bits 223 node = st 224 } 225 226 if node.entry.Key.isEqual(hash) { 227 s.accessCnt++ 228 node.updateAccess(s.accessCnt) 229 chunk = node.entry 230 if s.dbAccessCnt-node.lastDBaccess > dbForceUpdateAccessCnt { 231 s.dbAccessCnt++ 232 node.lastDBaccess = s.dbAccessCnt 233 if s.dbStore != nil { 234 s.dbStore.updateAccessCnt(hash) 235 } 236 } 237 } else { 238 err = notFound 239 } 240 241 return 242 } 243 244 func (s *MemStore) removeOldest() { 245 node := s.memtree 246 247 for node.entry == nil { 248 249 aidx := uint(0) 250 av := node.access[aidx] 251 252 for aidx < node.width/2-1 { 253 if av == node.access[aidx*2+1] { 254 node.access[aidx] = node.access[aidx*2+2] 255 aidx = aidx*2 + 1 256 } else if av == node.access[aidx*2+2] { 257 node.access[aidx] = node.access[aidx*2+1] 258 aidx = aidx*2 + 2 259 } else { 260 panic(nil) 261 } 262 } 263 pidx := aidx*2 + 2 - node.width 264 if (node.subtree[pidx] != nil) && (av == node.subtree[pidx].access[0]) { 265 if node.subtree[pidx+1] != nil { 266 node.access[aidx] = node.subtree[pidx+1].access[0] 267 } else { 268 node.access[aidx] = 0 269 } 270 } else if (node.subtree[pidx+1] != nil) && (av == node.subtree[pidx+1].access[0]) { 271 if node.subtree[pidx] != nil { 272 node.access[aidx] = node.subtree[pidx].access[0] 273 } else { 274 node.access[aidx] = 0 275 } 276 pidx++ 277 } else { 278 panic(nil) 279 } 280 281 //fmt.Println(pidx) 282 node = node.subtree[pidx] 283 284 } 285 286 if node.entry.dbStored != nil { 287 <-node.entry.dbStored 288 } 289 290 if node.entry.SData != nil { 291 node.entry = nil 292 s.entryCnt-- 293 } 294 295 node.access[0] = 0 296 297 //--- 298 299 aidx := uint(0) 300 for { 301 aa := node.access[aidx] 302 if aidx > 0 { 303 aidx = (aidx - 1) >> 1 304 } else { 305 pidx := node.parentIdx 306 node = node.parent 307 if node == nil { 308 return 309 } 310 aidx = (node.width + pidx - 2) >> 1 311 } 312 if (aa != 0) && ((aa < node.access[aidx]) || (node.access[aidx] == 0)) { 313 node.access[aidx] = aa 314 } 315 } 316 }