swarm/storage: fix collectGarbage panics

This commit is contained in:
Anton Evangelatov 2018-04-11 16:57:33 +03:00
parent 398e2e4fc4
commit 1ce7775391
2 changed files with 23 additions and 23 deletions

View file

@ -52,10 +52,6 @@ const (
gcArraySize = 10000 gcArraySize = 10000
gcArrayFreeRatio = 0.1 gcArrayFreeRatio = 0.1
// key prefixes for leveldb storage
kpIndex = 0
kpData = 1
) )
var ( var (
@ -79,10 +75,14 @@ type LDBStore struct {
db *LDBDatabase db *LDBDatabase
// this should be stored in db, accessed transactionally // this should be stored in db, accessed transactionally
entryCnt, accessCnt, dataIdx, capacity uint64 entryCnt uint64 // number of items in the LevelDB
accessCnt uint64 // ever-accumulating number increased every time we read/access an entry
dataIdx uint64 // similar to entryCnt, but we only increment it
capacity uint64
bucketCnt []uint64 bucketCnt []uint64
gcPos, gcStartPos []byte gcPos []byte
gcStartPos []byte
gcArray []*gcItem gcArray []*gcItem
hashfunc SwarmHasher hashfunc SwarmHasher
@ -126,10 +126,6 @@ func NewLDBStore(path string, hash SwarmHasher, capacity uint64, po func(Key) ui
s.po = po s.po = po
s.setCapacity(capacity) s.setCapacity(capacity)
s.gcStartPos = make([]byte, 1)
s.gcStartPos[0] = kpIndex
s.gcArray = make([]*gcItem, gcArraySize)
s.bucketCnt = make([]uint64, 0x100) s.bucketCnt = make([]uint64, 0x100)
for i := 0; i < 0x100; i++ { for i := 0; i < 0x100; i++ {
k := make([]byte, 2) k := make([]byte, 2)
@ -149,6 +145,9 @@ func NewLDBStore(path string, hash SwarmHasher, capacity uint64, po func(Key) ui
s.dataIdx = BytesToU64(data) s.dataIdx = BytesToU64(data)
s.dataIdx++ s.dataIdx++
s.gcStartPos = make([]byte, 1)
s.gcStartPos[0] = keyIndex
s.gcArray = make([]*gcItem, gcArraySize)
s.gcPos, _ = s.db.Get(keyGCPos) s.gcPos, _ = s.db.Get(keyGCPos)
if s.gcPos == nil { if s.gcPos == nil {
s.gcPos = s.gcStartPos s.gcPos = s.gcStartPos
@ -192,7 +191,6 @@ func BytesToU64(data []byte) uint64 {
func U64ToBytes(val uint64) []byte { func U64ToBytes(val uint64) []byte {
data := make([]byte, 8) data := make([]byte, 8)
//binary.LittleEndian.PutUint64(data, val)
binary.BigEndian.PutUint64(data, val) binary.BigEndian.PutUint64(data, val)
return data return data
} }
@ -294,8 +292,7 @@ func gcListSelect(list []*gcItem, left int, right int, n int) int {
func (s *LDBStore) collectGarbage(ratio float32) { func (s *LDBStore) collectGarbage(ratio float32) {
it := s.db.NewIterator() it := s.db.NewIterator()
it.Seek(s.gcPos) if it.Seek(s.gcPos) {
if it.Valid() {
s.gcPos = it.Key() s.gcPos = it.Key()
} else { } else {
s.gcPos = nil s.gcPos = nil
@ -304,16 +301,16 @@ func (s *LDBStore) collectGarbage(ratio float32) {
for (gcnt < gcArraySize) && (uint64(gcnt) < s.entryCnt) { for (gcnt < gcArraySize) && (uint64(gcnt) < s.entryCnt) {
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) { if (s.gcPos == nil) || (s.gcPos[0] != keyIndex) {
it.Seek(s.gcStartPos) it.Seek(s.gcStartPos)
if it.Valid() { if it.Valid() {
s.gcPos = it.Key() s.gcPos = it.Key()
} else { } else {
s.gcPos = nil s.gcPos = s.gcStartPos
} }
} }
if (s.gcPos == nil) || (s.gcPos[0] != kpIndex) { if (s.gcPos == nil) || (s.gcPos[0] != keyIndex) {
break break
} }
@ -335,6 +332,9 @@ func (s *LDBStore) collectGarbage(ratio float32) {
} }
it.Release() it.Release()
if gcnt == 0 {
gcnt++
}
cutidx := gcListSelect(s.gcArray, 0, gcnt-1, int(float32(gcnt)*ratio)) cutidx := gcListSelect(s.gcArray, 0, gcnt-1, int(float32(gcnt)*ratio))
cutval := s.gcArray[cutidx].value cutval := s.gcArray[cutidx].value
@ -358,9 +358,9 @@ func (s *LDBStore) Export(out io.Writer) (int64, error) {
it := s.db.NewIterator() it := s.db.NewIterator()
defer it.Release() defer it.Release()
var count int64 var count int64
for ok := it.Seek([]byte{kpIndex}); ok; ok = it.Next() { for ok := it.Seek([]byte{keyIndex}); ok; ok = it.Next() {
key := it.Key() key := it.Key()
if (key == nil) || (key[0] != kpIndex) { if (key == nil) || (key[0] != keyIndex) {
break break
} }
@ -440,13 +440,13 @@ func (s *LDBStore) Import(in io.Reader) (int64, error) {
func (s *LDBStore) Cleanup() { func (s *LDBStore) Cleanup() {
//Iterates over the database and checks that there are no faulty chunks //Iterates over the database and checks that there are no faulty chunks
it := s.db.NewIterator() it := s.db.NewIterator()
startPosition := []byte{kpIndex} startPosition := []byte{keyIndex}
it.Seek(startPosition) it.Seek(startPosition)
var key []byte var key []byte
var errorsFound, total int var errorsFound, total int
for it.Valid() { for it.Valid() {
key = it.Key() key = it.Key()
if (key == nil) || (key[0] != kpIndex) { if (key == nil) || (key[0] != keyIndex) {
break break
} }
total++ total++

View file

@ -80,7 +80,7 @@ func TestMemStoreAndLDBStore(t *testing.T) {
request: false, request: false,
}, },
{ {
n: 60001, n: 3100,
chunkSize: 4096, chunkSize: 4096,
request: false, request: false,
}, },