mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 19:56:44 +00:00
add mutex to stores
This commit is contained in:
parent
60931dfaa3
commit
05d636d47e
2 changed files with 389 additions and 371 deletions
752
bzz/dbstore.go
752
bzz/dbstore.go
|
|
@ -1,371 +1,381 @@
|
||||||
// disk storage layer for the package blockhash
|
// disk storage layer for the package blockhash
|
||||||
// inefficient work-in-progress version
|
// inefficient work-in-progress version
|
||||||
|
|
||||||
package bzz
|
package bzz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "crypto/sha256"
|
"bytes"
|
||||||
"bytes"
|
"encoding/binary"
|
||||||
"encoding/binary"
|
"sync"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
// "github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
// "path"
|
)
|
||||||
)
|
|
||||||
|
const dbMaxEntries = 5000 // max number of stored (cached) blocks
|
||||||
const dbMaxEntries = 5000 // max number of stored (cached) blocks
|
|
||||||
|
const gcArraySize = 500
|
||||||
const gcArraySize = 500
|
const gcArrayFreeRatio = 10
|
||||||
const gcArrayFreeRatio = 10
|
|
||||||
|
// key prefixes for leveldb storage
|
||||||
// key prefixes for leveldb storage
|
const kpIndex = 0
|
||||||
const kpIndex = 0
|
const kpData = 1
|
||||||
const kpData = 1
|
|
||||||
|
var keyAccessCnt = []byte{2}
|
||||||
var keyAccessCnt = []byte{2}
|
var keyEntryCnt = []byte{3}
|
||||||
var keyEntryCnt = []byte{3}
|
var keyDataIdx = []byte{4}
|
||||||
var keyDataIdx = []byte{4}
|
var keyGCPos = []byte{5}
|
||||||
var keyGCPos = []byte{5}
|
|
||||||
|
type gcItem struct {
|
||||||
type gcItem struct {
|
idx uint64
|
||||||
idx uint64
|
value uint64
|
||||||
value uint64
|
idxKey []byte
|
||||||
idxKey []byte
|
}
|
||||||
}
|
|
||||||
|
type dbStore struct {
|
||||||
type dbStore struct {
|
db *ethdb.LDBDatabase
|
||||||
db *ethdb.LDBDatabase
|
|
||||||
|
// this should be stored in db, accessed transactionally
|
||||||
// this should be stored in db, accessed transactionally
|
entryCnt, accessCnt, dataIdx uint64
|
||||||
entryCnt, accessCnt, dataIdx uint64
|
|
||||||
|
gcPos, gcStartPos []byte
|
||||||
gcPos, gcStartPos []byte
|
gcArray []*gcItem
|
||||||
gcArray []*gcItem
|
|
||||||
}
|
lock sync.Mutex
|
||||||
|
}
|
||||||
type dpaDBIndex struct {
|
|
||||||
Idx uint64
|
type dpaDBIndex struct {
|
||||||
Access uint64
|
Idx uint64
|
||||||
}
|
Access uint64
|
||||||
|
}
|
||||||
func bytesToU64(data []byte) uint64 {
|
|
||||||
|
func bytesToU64(data []byte) uint64 {
|
||||||
if len(data) < 8 {
|
|
||||||
return 0
|
if len(data) < 8 {
|
||||||
}
|
return 0
|
||||||
return binary.LittleEndian.Uint64(data)
|
}
|
||||||
|
return binary.LittleEndian.Uint64(data)
|
||||||
}
|
|
||||||
|
}
|
||||||
func u64ToBytes(val uint64) []byte {
|
|
||||||
|
func u64ToBytes(val uint64) []byte {
|
||||||
data := make([]byte, 8)
|
|
||||||
binary.LittleEndian.PutUint64(data, val)
|
data := make([]byte, 8)
|
||||||
return data
|
binary.LittleEndian.PutUint64(data, val)
|
||||||
|
return data
|
||||||
}
|
|
||||||
|
}
|
||||||
func getIndexGCValue(index *dpaDBIndex) uint64 {
|
|
||||||
|
func getIndexGCValue(index *dpaDBIndex) uint64 {
|
||||||
return index.Access
|
|
||||||
|
return index.Access
|
||||||
}
|
|
||||||
|
}
|
||||||
func (s *dbStore) updateIndexAccess(index *dpaDBIndex) {
|
|
||||||
|
func (s *dbStore) updateIndexAccess(index *dpaDBIndex) {
|
||||||
index.Access = s.accessCnt
|
|
||||||
|
index.Access = s.accessCnt
|
||||||
}
|
|
||||||
|
}
|
||||||
func getIndexKey(hash Key) []byte {
|
|
||||||
|
func getIndexKey(hash Key) []byte {
|
||||||
HashSize := len(hash)
|
|
||||||
key := make([]byte, HashSize+1)
|
HashSize := len(hash)
|
||||||
key[0] = 0
|
key := make([]byte, HashSize+1)
|
||||||
// db keys derived from hash:
|
key[0] = 0
|
||||||
// two halves swapped for uniformly distributed prefix
|
// db keys derived from hash:
|
||||||
copy(key[1:HashSize/2+1], hash[HashSize/2:HashSize])
|
// two halves swapped for uniformly distributed prefix
|
||||||
copy(key[HashSize/2+1:HashSize+1], hash[0:HashSize/2])
|
copy(key[1:HashSize/2+1], hash[HashSize/2:HashSize])
|
||||||
|
copy(key[HashSize/2+1:HashSize+1], hash[0:HashSize/2])
|
||||||
return key
|
|
||||||
}
|
return key
|
||||||
|
}
|
||||||
func getDataKey(idx uint64) []byte {
|
|
||||||
|
func getDataKey(idx uint64) []byte {
|
||||||
key := make([]byte, 9)
|
|
||||||
key[0] = 1
|
key := make([]byte, 9)
|
||||||
binary.BigEndian.PutUint64(key[1:9], idx)
|
key[0] = 1
|
||||||
|
binary.BigEndian.PutUint64(key[1:9], idx)
|
||||||
return key
|
|
||||||
}
|
return key
|
||||||
|
}
|
||||||
func encodeIndex(index *dpaDBIndex) []byte {
|
|
||||||
|
func encodeIndex(index *dpaDBIndex) []byte {
|
||||||
data, _ := rlp.EncodeToBytes(index)
|
|
||||||
return data
|
data, _ := rlp.EncodeToBytes(index)
|
||||||
|
return data
|
||||||
}
|
|
||||||
|
}
|
||||||
func encodeData(chunk *Chunk) []byte {
|
|
||||||
|
func encodeData(chunk *Chunk) []byte {
|
||||||
var rlpEntry struct {
|
|
||||||
Data []byte
|
var rlpEntry struct {
|
||||||
Size uint64
|
Data []byte
|
||||||
}
|
Size uint64
|
||||||
|
}
|
||||||
rlpEntry.Data = chunk.Data
|
|
||||||
rlpEntry.Size = uint64(chunk.Size)
|
rlpEntry.Data = chunk.Data
|
||||||
|
rlpEntry.Size = uint64(chunk.Size)
|
||||||
data, _ := rlp.EncodeToBytes(rlpEntry)
|
|
||||||
return data
|
data, _ := rlp.EncodeToBytes(rlpEntry)
|
||||||
|
return data
|
||||||
}
|
|
||||||
|
}
|
||||||
func decodeIndex(data []byte, index *dpaDBIndex) {
|
|
||||||
|
func decodeIndex(data []byte, index *dpaDBIndex) {
|
||||||
dec := rlp.NewStream(bytes.NewReader(data))
|
|
||||||
dec.Decode(index)
|
dec := rlp.NewStream(bytes.NewReader(data))
|
||||||
|
dec.Decode(index)
|
||||||
}
|
|
||||||
|
}
|
||||||
func decodeData(data []byte, chunk *Chunk) {
|
|
||||||
|
func decodeData(data []byte, chunk *Chunk) {
|
||||||
var rlpEntry struct {
|
|
||||||
Data []byte
|
var rlpEntry struct {
|
||||||
Size uint64
|
Data []byte
|
||||||
}
|
Size uint64
|
||||||
|
}
|
||||||
dec := rlp.NewStream(bytes.NewReader(data))
|
|
||||||
err := dec.Decode(&rlpEntry)
|
dec := rlp.NewStream(bytes.NewReader(data))
|
||||||
if err != nil {
|
err := dec.Decode(&rlpEntry)
|
||||||
panic(err.Error())
|
if err != nil {
|
||||||
}
|
panic(err.Error())
|
||||||
chunk.Data = rlpEntry.Data
|
}
|
||||||
chunk.Size = int64(rlpEntry.Size)
|
chunk.Data = rlpEntry.Data
|
||||||
}
|
chunk.Size = int64(rlpEntry.Size)
|
||||||
|
}
|
||||||
func gcListPartition(list []*gcItem, left int, right int, pivotIndex int) int {
|
|
||||||
pivotValue := list[pivotIndex].value
|
func gcListPartition(list []*gcItem, left int, right int, pivotIndex int) int {
|
||||||
dd := list[pivotIndex]
|
pivotValue := list[pivotIndex].value
|
||||||
list[pivotIndex] = list[right]
|
dd := list[pivotIndex]
|
||||||
list[right] = dd
|
list[pivotIndex] = list[right]
|
||||||
storeIndex := left
|
list[right] = dd
|
||||||
for i := left; i < right; i++ {
|
storeIndex := left
|
||||||
if list[i].value < pivotValue {
|
for i := left; i < right; i++ {
|
||||||
dd = list[storeIndex]
|
if list[i].value < pivotValue {
|
||||||
list[storeIndex] = list[i]
|
dd = list[storeIndex]
|
||||||
list[i] = dd
|
list[storeIndex] = list[i]
|
||||||
storeIndex++
|
list[i] = dd
|
||||||
}
|
storeIndex++
|
||||||
}
|
}
|
||||||
dd = list[storeIndex]
|
}
|
||||||
list[storeIndex] = list[right]
|
dd = list[storeIndex]
|
||||||
list[right] = dd
|
list[storeIndex] = list[right]
|
||||||
return storeIndex
|
list[right] = dd
|
||||||
}
|
return storeIndex
|
||||||
|
}
|
||||||
func gcListSelect(list []*gcItem, left int, right int, n int) int {
|
|
||||||
if left == right {
|
func gcListSelect(list []*gcItem, left int, right int, n int) int {
|
||||||
return left
|
if left == right {
|
||||||
}
|
return left
|
||||||
pivotIndex := (left + right) / 2
|
}
|
||||||
pivotIndex = gcListPartition(list, left, right, pivotIndex)
|
pivotIndex := (left + right) / 2
|
||||||
if n == pivotIndex {
|
pivotIndex = gcListPartition(list, left, right, pivotIndex)
|
||||||
return n
|
if n == pivotIndex {
|
||||||
} else {
|
return n
|
||||||
if n < pivotIndex {
|
} else {
|
||||||
return gcListSelect(list, left, pivotIndex-1, n)
|
if n < pivotIndex {
|
||||||
} else {
|
return gcListSelect(list, left, pivotIndex-1, n)
|
||||||
return gcListSelect(list, pivotIndex+1, right, n)
|
} else {
|
||||||
}
|
return gcListSelect(list, pivotIndex+1, right, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
func (s *dbStore) collectGarbage() {
|
|
||||||
|
func (s *dbStore) collectGarbage() {
|
||||||
it := s.db.NewIterator()
|
|
||||||
it.Seek(s.gcPos)
|
it := s.db.NewIterator()
|
||||||
if it.Valid() {
|
it.Seek(s.gcPos)
|
||||||
s.gcPos = it.Key()
|
if it.Valid() {
|
||||||
} else {
|
s.gcPos = it.Key()
|
||||||
s.gcPos = nil
|
} else {
|
||||||
}
|
s.gcPos = nil
|
||||||
gcnt := 0
|
}
|
||||||
|
gcnt := 0
|
||||||
for gcnt < gcArraySize {
|
|
||||||
|
for gcnt < gcArraySize {
|
||||||
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) {
|
|
||||||
it.Seek(s.gcStartPos)
|
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) {
|
||||||
if it.Valid() {
|
it.Seek(s.gcStartPos)
|
||||||
s.gcPos = it.Key()
|
if it.Valid() {
|
||||||
} else {
|
s.gcPos = it.Key()
|
||||||
s.gcPos = nil
|
} else {
|
||||||
}
|
s.gcPos = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) {
|
|
||||||
break
|
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) {
|
||||||
}
|
break
|
||||||
|
}
|
||||||
gci := new(gcItem)
|
|
||||||
gci.idxKey = s.gcPos
|
gci := new(gcItem)
|
||||||
var index dpaDBIndex
|
gci.idxKey = s.gcPos
|
||||||
decodeIndex(it.Value(), &index)
|
var index dpaDBIndex
|
||||||
gci.idx = index.Idx
|
decodeIndex(it.Value(), &index)
|
||||||
// the smaller, the more likely to be gc'd
|
gci.idx = index.Idx
|
||||||
gci.value = getIndexGCValue(&index)
|
// the smaller, the more likely to be gc'd
|
||||||
s.gcArray[gcnt] = gci
|
gci.value = getIndexGCValue(&index)
|
||||||
gcnt++
|
s.gcArray[gcnt] = gci
|
||||||
it.Next()
|
gcnt++
|
||||||
if it.Valid() {
|
it.Next()
|
||||||
s.gcPos = it.Key()
|
if it.Valid() {
|
||||||
} else {
|
s.gcPos = it.Key()
|
||||||
s.gcPos = nil
|
} else {
|
||||||
}
|
s.gcPos = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cutidx := gcListSelect(s.gcArray, 0, gcnt-1, gcnt/gcArrayFreeRatio)
|
|
||||||
cutval := s.gcArray[cutidx].value
|
cutidx := gcListSelect(s.gcArray, 0, gcnt-1, gcnt/gcArrayFreeRatio)
|
||||||
|
cutval := s.gcArray[cutidx].value
|
||||||
//fmt.Print(s.entryCnt, " ")
|
|
||||||
|
//fmt.Print(s.entryCnt, " ")
|
||||||
// actual gc
|
|
||||||
for i := 0; i < gcnt; i++ {
|
// actual gc
|
||||||
if s.gcArray[i].value < cutval {
|
for i := 0; i < gcnt; i++ {
|
||||||
batch := new(leveldb.Batch)
|
if s.gcArray[i].value < cutval {
|
||||||
batch.Delete(s.gcArray[i].idxKey)
|
batch := new(leveldb.Batch)
|
||||||
batch.Delete(getDataKey(s.gcArray[i].idx))
|
batch.Delete(s.gcArray[i].idxKey)
|
||||||
s.entryCnt--
|
batch.Delete(getDataKey(s.gcArray[i].idx))
|
||||||
batch.Put(keyEntryCnt, u64ToBytes(s.entryCnt))
|
s.entryCnt--
|
||||||
s.db.Write(batch)
|
batch.Put(keyEntryCnt, u64ToBytes(s.entryCnt))
|
||||||
}
|
s.db.Write(batch)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//fmt.Println(s.entryCnt)
|
|
||||||
|
//fmt.Println(s.entryCnt)
|
||||||
s.db.Put(keyGCPos, s.gcPos)
|
|
||||||
|
s.db.Put(keyGCPos, s.gcPos)
|
||||||
}
|
|
||||||
|
}
|
||||||
func (s *dbStore) Put(chunk *Chunk) {
|
|
||||||
|
func (s *dbStore) Put(chunk *Chunk) {
|
||||||
ikey := getIndexKey(chunk.Key)
|
|
||||||
var index dpaDBIndex
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
if s.tryAccessIdx(ikey, &index) {
|
|
||||||
return // already exists, only update access
|
ikey := getIndexKey(chunk.Key)
|
||||||
}
|
var index dpaDBIndex
|
||||||
|
|
||||||
data := encodeData(chunk)
|
if s.tryAccessIdx(ikey, &index) {
|
||||||
//data := ethutil.Encode([]interface{}{entry})
|
return // already exists, only update access
|
||||||
|
}
|
||||||
if s.entryCnt >= dbMaxEntries {
|
|
||||||
s.collectGarbage()
|
data := encodeData(chunk)
|
||||||
}
|
//data := ethutil.Encode([]interface{}{entry})
|
||||||
|
|
||||||
batch := new(leveldb.Batch)
|
if s.entryCnt >= dbMaxEntries {
|
||||||
|
s.collectGarbage()
|
||||||
s.entryCnt++
|
}
|
||||||
batch.Put(keyEntryCnt, u64ToBytes(s.entryCnt))
|
|
||||||
s.dataIdx++
|
batch := new(leveldb.Batch)
|
||||||
batch.Put(keyDataIdx, u64ToBytes(s.dataIdx))
|
|
||||||
s.accessCnt++
|
s.entryCnt++
|
||||||
batch.Put(keyAccessCnt, u64ToBytes(s.accessCnt))
|
batch.Put(keyEntryCnt, u64ToBytes(s.entryCnt))
|
||||||
|
s.dataIdx++
|
||||||
batch.Put(getDataKey(s.dataIdx), data)
|
batch.Put(keyDataIdx, u64ToBytes(s.dataIdx))
|
||||||
|
s.accessCnt++
|
||||||
index.Idx = s.dataIdx
|
batch.Put(keyAccessCnt, u64ToBytes(s.accessCnt))
|
||||||
s.updateIndexAccess(&index)
|
|
||||||
|
batch.Put(getDataKey(s.dataIdx), data)
|
||||||
idata := encodeIndex(&index)
|
|
||||||
batch.Put(ikey, idata)
|
index.Idx = s.dataIdx
|
||||||
|
s.updateIndexAccess(&index)
|
||||||
s.db.Write(batch)
|
|
||||||
|
idata := encodeIndex(&index)
|
||||||
}
|
batch.Put(ikey, idata)
|
||||||
|
|
||||||
// try to find index; if found, update access cnt and return true
|
s.db.Write(batch)
|
||||||
func (s *dbStore) tryAccessIdx(ikey []byte, index *dpaDBIndex) bool {
|
|
||||||
|
}
|
||||||
idata, err := s.db.Get(ikey)
|
|
||||||
if err != nil {
|
// try to find index; if found, update access cnt and return true
|
||||||
return false
|
func (s *dbStore) tryAccessIdx(ikey []byte, index *dpaDBIndex) bool {
|
||||||
}
|
|
||||||
decodeIndex(idata, index)
|
idata, err := s.db.Get(ikey)
|
||||||
|
if err != nil {
|
||||||
batch := new(leveldb.Batch)
|
return false
|
||||||
|
}
|
||||||
s.accessCnt++
|
decodeIndex(idata, index)
|
||||||
batch.Put(keyAccessCnt, u64ToBytes(s.accessCnt))
|
|
||||||
s.updateIndexAccess(index)
|
batch := new(leveldb.Batch)
|
||||||
idata = encodeIndex(index)
|
|
||||||
batch.Put(ikey, idata)
|
s.accessCnt++
|
||||||
|
batch.Put(keyAccessCnt, u64ToBytes(s.accessCnt))
|
||||||
s.db.Write(batch)
|
s.updateIndexAccess(index)
|
||||||
|
idata = encodeIndex(index)
|
||||||
return true
|
batch.Put(ikey, idata)
|
||||||
}
|
|
||||||
|
s.db.Write(batch)
|
||||||
func (s *dbStore) Get(key Key) (chunk *Chunk, err error) {
|
|
||||||
|
return true
|
||||||
var index dpaDBIndex
|
}
|
||||||
|
|
||||||
if s.tryAccessIdx(getIndexKey(key), &index) {
|
func (s *dbStore) Get(key Key) (chunk *Chunk, err error) {
|
||||||
var data []byte
|
|
||||||
data, err = s.db.Get(getDataKey(index.Idx))
|
s.lock.Lock()
|
||||||
if err != nil {
|
defer s.lock.Unlock()
|
||||||
return
|
|
||||||
}
|
var index dpaDBIndex
|
||||||
chunk = &Chunk{
|
|
||||||
Key: key,
|
if s.tryAccessIdx(getIndexKey(key), &index) {
|
||||||
}
|
var data []byte
|
||||||
decodeData(data, chunk)
|
data, err = s.db.Get(getDataKey(index.Idx))
|
||||||
} else {
|
if err != nil {
|
||||||
err = notFound
|
return
|
||||||
}
|
}
|
||||||
|
chunk = &Chunk{
|
||||||
return
|
Key: key,
|
||||||
|
}
|
||||||
}
|
decodeData(data, chunk)
|
||||||
|
} else {
|
||||||
func (s *dbStore) updateAccessCnt(key Key) {
|
err = notFound
|
||||||
|
}
|
||||||
var index dpaDBIndex
|
|
||||||
s.tryAccessIdx(getIndexKey(key), &index) // result_chn == nil, only update access cnt
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDbStore(path string) (s *dbStore, err error) {
|
func (s *dbStore) updateAccessCnt(key Key) {
|
||||||
|
|
||||||
s = new(dbStore)
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
s.db, err = ethdb.NewLDBDatabase(path)
|
|
||||||
if err != nil {
|
var index dpaDBIndex
|
||||||
return
|
s.tryAccessIdx(getIndexKey(key), &index) // result_chn == nil, only update access cnt
|
||||||
}
|
|
||||||
|
}
|
||||||
s.gcStartPos = make([]byte, 1)
|
|
||||||
s.gcStartPos[0] = kpIndex
|
func newDbStore(path string) (s *dbStore, err error) {
|
||||||
s.gcArray = make([]*gcItem, gcArraySize)
|
|
||||||
|
s = new(dbStore)
|
||||||
data, _ := s.db.Get(keyEntryCnt)
|
|
||||||
s.entryCnt = bytesToU64(data)
|
s.db, err = ethdb.NewLDBDatabase(path)
|
||||||
data, _ = s.db.Get(keyAccessCnt)
|
if err != nil {
|
||||||
s.accessCnt = bytesToU64(data)
|
return
|
||||||
data, _ = s.db.Get(keyDataIdx)
|
}
|
||||||
s.dataIdx = bytesToU64(data)
|
|
||||||
s.gcPos, _ = s.db.Get(keyGCPos)
|
s.gcStartPos = make([]byte, 1)
|
||||||
if s.gcPos == nil {
|
s.gcStartPos[0] = kpIndex
|
||||||
s.gcPos = s.gcStartPos
|
s.gcArray = make([]*gcItem, gcArraySize)
|
||||||
}
|
|
||||||
return
|
data, _ := s.db.Get(keyEntryCnt)
|
||||||
// fmt.Println(s.entryCnt)
|
s.entryCnt = bytesToU64(data)
|
||||||
// fmt.Println(s.accessCnt)
|
data, _ = s.db.Get(keyAccessCnt)
|
||||||
// fmt.Println(s.dataIdx)
|
s.accessCnt = bytesToU64(data)
|
||||||
|
data, _ = s.db.Get(keyDataIdx)
|
||||||
}
|
s.dataIdx = bytesToU64(data)
|
||||||
|
s.gcPos, _ = s.db.Get(keyGCPos)
|
||||||
func (s *dbStore) close() {
|
if s.gcPos == nil {
|
||||||
s.db.Close()
|
s.gcPos = s.gcStartPos
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
// fmt.Println(s.entryCnt)
|
||||||
|
// fmt.Println(s.accessCnt)
|
||||||
|
// fmt.Println(s.dataIdx)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *dbStore) close() {
|
||||||
|
s.db.Close()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package bzz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -19,6 +20,7 @@ type memStore struct {
|
||||||
accessCnt uint64 // access counter; oldest is thrown away when full
|
accessCnt uint64 // access counter; oldest is thrown away when full
|
||||||
dbAccessCnt uint64
|
dbAccessCnt uint64
|
||||||
dbStore *dbStore
|
dbStore *dbStore
|
||||||
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -141,6 +143,9 @@ func (node *memTree) updateAccess(a uint64) {
|
||||||
|
|
||||||
func (s *memStore) Put(entry *Chunk) {
|
func (s *memStore) Put(entry *Chunk) {
|
||||||
|
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
if s.entryCnt >= maxEntries {
|
if s.entryCnt >= maxEntries {
|
||||||
s.removeOldest()
|
s.removeOldest()
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +206,9 @@ func (s *memStore) Put(entry *Chunk) {
|
||||||
|
|
||||||
func (s *memStore) Get(hash Key) (chunk *Chunk, err error) {
|
func (s *memStore) Get(hash Key) (chunk *Chunk, err error) {
|
||||||
|
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
node := s.memtree
|
node := s.memtree
|
||||||
bitpos := uint(0)
|
bitpos := uint(0)
|
||||||
for node.entry == nil {
|
for node.entry == nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue