Merge pull request #336 from ethersphere/more_tracing

deadlock on retrieve chunk + more tracing for internal swarm components
This commit is contained in:
Viktor Trón 2018-03-25 12:19:14 +02:00 committed by GitHub
commit defc256afe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 12 deletions

View file

@ -15,7 +15,7 @@ import (
const ( const (
timeFormat = "2006-01-02T15:04:05-0700" timeFormat = "2006-01-02T15:04:05-0700"
termTimeFormat = "01-02|15:04:05" termTimeFormat = "01-02|15:04:05.999999"
floatFormat = 'f' floatFormat = 'f'
termMsgJust = 40 termMsgJust = 40
) )

View file

@ -23,6 +23,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
) )
@ -332,6 +333,7 @@ func (self *TreeChunker) Join(key Key, chunkC chan *Chunk, depth int) LazySectio
// Size is meant to be called on the LazySectionReader // Size is meant to be called on the LazySectionReader
func (self *LazyChunkReader) Size(quitC chan bool) (n int64, err error) { func (self *LazyChunkReader) Size(quitC chan bool) (n int64, err error) {
log.Debug("lazychunkreader.size", "key", self.key)
if self.chunk != nil { if self.chunk != nil {
return self.chunk.Size, nil return self.chunk.Size, nil
} }
@ -459,15 +461,18 @@ func (self *LazyChunkReader) join(b []byte, off int64, eoff int64, depth int, tr
// block until they time out or arrive // block until they time out or arrive
// abort if quitC is readable // abort if quitC is readable
func retrieve(key Key, chunkC chan *Chunk, quitC chan bool) *Chunk { func retrieve(key Key, chunkC chan *Chunk, quitC chan bool) *Chunk {
log.Debug("retrieve", "key", key)
chunk := NewChunk(key, nil) chunk := NewChunk(key, nil)
chunk.C = make(chan bool) chunk.C = make(chan bool)
// submit chunk for retrieval // submit chunk for retrieval
log.Debug("submit chunk for retrieval", "key", key)
select { select {
case chunkC <- chunk: // submit retrieval request, someone should be listening on the other side (or we will time out globally) case chunkC <- chunk: // submit retrieval request, someone should be listening on the other side (or we will time out globally)
case <-quitC: case <-quitC:
return nil return nil
} }
// waiting for the chunk retrieval // waiting for the chunk retrieval
log.Debug("waiting for the chunk retrieval", "key", key)
select { // chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8])) select { // chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
case <-quitC: case <-quitC:
@ -478,11 +483,13 @@ func retrieve(key Key, chunkC chan *Chunk, quitC chan bool) *Chunk {
if len(chunk.SData) == 0 { if len(chunk.SData) == 0 {
return nil return nil
} }
log.Debug("chunk retrieved", "key", key)
return chunk return chunk
} }
// Read keeps a cursor so cannot be called simulateously, see ReadAt // Read keeps a cursor so cannot be called simulateously, see ReadAt
func (self *LazyChunkReader) Read(b []byte) (read int, err error) { func (self *LazyChunkReader) Read(b []byte) (read int, err error) {
log.Debug("lazychunkreader.read", "key", self.key)
read, err = self.ReadAt(b, self.off) read, err = self.ReadAt(b, self.off)
self.off += int64(read) self.off += int64(read)
@ -494,6 +501,7 @@ var errWhence = errors.New("Seek: invalid whence")
var errOffset = errors.New("Seek: invalid offset") var errOffset = errors.New("Seek: invalid offset")
func (s *LazyChunkReader) Seek(offset int64, whence int) (int64, error) { func (s *LazyChunkReader) Seek(offset int64, whence int) (int64, error) {
log.Debug("lazychunkreader.seek", "key", s.key, "offset", offset)
switch whence { switch whence {
default: default:
return 0, errWhence return 0, errWhence

View file

@ -546,6 +546,7 @@ func (s *LDBStore) CurrentStorageIndex() uint64 {
} }
func (s *LDBStore) Put(chunk *Chunk) { func (s *LDBStore) Put(chunk *Chunk) {
log.Trace("ldbstore.put", "key", chunk.Key)
ikey := getIndexKey(chunk.Key) ikey := getIndexKey(chunk.Key)
var index dpaDBIndex var index dpaDBIndex
@ -553,6 +554,7 @@ func (s *LDBStore) Put(chunk *Chunk) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
log.Trace("ldbstore.put: s.db.Get", "key", chunk.Key)
idata, err := s.db.Get(ikey) idata, err := s.db.Get(ikey)
if err != nil { if err != nil {
s.doPut(chunk, ikey, &index, po) s.doPut(chunk, ikey, &index, po)
@ -562,7 +564,7 @@ func (s *LDBStore) Put(chunk *Chunk) {
close(chunk.dbStored) close(chunk.dbStored)
}() }()
} else { } else {
log.Trace(fmt.Sprintf("DbStore: chunk already exists, only update access")) log.Trace("ldbstore.put: chunk already exists, only update access", "key", chunk.Key)
decodeIndex(idata, &index) decodeIndex(idata, &index)
close(chunk.dbStored) close(chunk.dbStored)
} }
@ -578,6 +580,7 @@ func (s *LDBStore) Put(chunk *Chunk) {
// force putting into db, does not check access index // force putting into db, does not check access index
func (s *LDBStore) doPut(chunk *Chunk, ikey []byte, index *dpaDBIndex, po uint8) { func (s *LDBStore) doPut(chunk *Chunk, ikey []byte, index *dpaDBIndex, po uint8) {
log.Trace("ldbstore.doPut", "key", chunk.Key)
data := s.encodeDataFunc(chunk) data := s.encodeDataFunc(chunk)
s.batch.Put(getDataKey(s.dataIdx, po), data) s.batch.Put(getDataKey(s.dataIdx, po), data)
index.Idx = s.dataIdx index.Idx = s.dataIdx
@ -659,6 +662,7 @@ func (s *LDBStore) tryAccessIdx(ikey []byte, index *dpaDBIndex) bool {
} }
func (s *LDBStore) Get(key Key) (chunk *Chunk, err error) { func (s *LDBStore) Get(key Key) (chunk *Chunk, err error) {
log.Trace("ldbstore.get", "key", key)
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
return s.get(key) return s.get(key)
@ -671,6 +675,7 @@ func (s *LDBStore) get(key Key) (chunk *Chunk, err error) {
var data []byte var data []byte
if s.getDataFunc != nil { if s.getDataFunc != nil {
// if getDataFunc is defined, use it to retrieve the chunk data // if getDataFunc is defined, use it to retrieve the chunk data
log.Trace("ldbstore.get retrieve with getDataFunc", "key", key)
data, err = s.getDataFunc(key) data, err = s.getDataFunc(key)
if err != nil { if err != nil {
return return
@ -680,9 +685,9 @@ func (s *LDBStore) get(key Key) (chunk *Chunk, err error) {
proximity := s.po(key) proximity := s.po(key)
datakey := getDataKey(indx.Idx, proximity) datakey := getDataKey(indx.Idx, proximity)
data, err = s.db.Get(datakey) data, err = s.db.Get(datakey)
log.Trace(fmt.Sprintf("DBStore: Chunk %v indexkey %v datakey %x proximity %d", key.Log(), indx.Idx, datakey, proximity)) log.Trace("ldbstore.get retrieve", "key", key, "indexkey", indx.Idx, "datakey", datakey, "proximity", proximity)
if err != nil { if err != nil {
log.Trace(fmt.Sprintf("DBStore: Chunk %v found but could not be accessed: %v", key.Log(), err)) log.Trace("ldbstore.get chunk found but could not be accessed", "key", key, "err", err)
s.delete(indx.Idx, getIndexKey(key), s.po(key)) s.delete(indx.Idx, getIndexKey(key), s.po(key))
return return
} }
@ -695,13 +700,14 @@ func (s *LDBStore) get(key Key) (chunk *Chunk, err error) {
hash := hasher.Sum(nil) hash := hasher.Sum(nil)
if !bytes.Equal(hash, key) { if !bytes.Equal(hash, key) {
log.Error(fmt.Sprintf("Apparent key/hash mismatch. Hash %x, key %v", hash, key[:])) log.Error("apparent key/hash mismatch", "hash", hash, "key", key[:])
s.delete(indx.Idx, getIndexKey(key), s.po(key)) s.delete(indx.Idx, getIndexKey(key), s.po(key))
log.Error("Invalid Chunk in Database. Please repair with command: 'swarm cleandb'") log.Error("invalid chunk in database.")
} }
} }
chunk = NewChunk(key, nil) chunk = NewChunk(key, nil)
close(chunk.dbStored)
decodeData(data, chunk) decodeData(data, chunk)
} else { } else {
err = ErrChunkNotFound err = ErrChunkNotFound

View file

@ -85,6 +85,7 @@ func (self *LocalStore) CacheCounter() uint64 {
// LocalStore is itself a chunk store // LocalStore is itself a chunk store
// unsafe, in that the data is not integrity checked // unsafe, in that the data is not integrity checked
func (self *LocalStore) Put(chunk *Chunk) { func (self *LocalStore) Put(chunk *Chunk) {
log.Trace("localstore.put", "key", chunk.Key)
self.mu.Lock() self.mu.Lock()
defer self.mu.Unlock() defer self.mu.Unlock()

View file

@ -144,6 +144,7 @@ func (s *MemStore) Counter() uint {
// entry (not its copy) is going to be in MemStore // entry (not its copy) is going to be in MemStore
func (s *MemStore) Put(entry *Chunk) { func (s *MemStore) Put(entry *Chunk) {
log.Trace("memstore.put", "key", entry.Key)
if s.capacity == 0 { if s.capacity == 0 {
return return
} }
@ -219,6 +220,7 @@ 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) {
log.Trace("memstore.get", "key", hash)
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -228,6 +230,7 @@ func (s *MemStore) Get(hash Key) (chunk *Chunk, err error) {
l := hash.bits(bitpos, node.bits) l := hash.bits(bitpos, node.bits)
st := node.subtree[l] st := node.subtree[l]
if st == nil { if st == nil {
log.Trace("memstore.get ErrChunkNotFound", "key", hash)
return nil, ErrChunkNotFound return nil, ErrChunkNotFound
} }
bitpos += node.bits bitpos += node.bits
@ -249,6 +252,7 @@ func (s *MemStore) Get(hash Key) (chunk *Chunk, err error) {
err = ErrChunkNotFound err = ErrChunkNotFound
} }
log.Trace("memstore.get return", "key", hash, "chunk", chunk, "err", err)
return return
} }
@ -296,11 +300,11 @@ func (s *MemStore) removeOldest() {
} }
if node.entry.ReqC == nil {
log.Trace(fmt.Sprintf("Memstore Clean: Waiting for chunk %v to be saved", node.entry.Key.Log())) log.Trace(fmt.Sprintf("Memstore Clean: Waiting for chunk %v to be saved", node.entry.Key.Log()))
<-node.entry.dbStored <-node.entry.dbStored
log.Trace(fmt.Sprintf("Memstore Clean: Chunk %v saved to DBStore. Ready to clear from mem.", node.entry.Key.Log())) log.Trace(fmt.Sprintf("Memstore Clean: Chunk %v saved to DBStore. Ready to clear from mem.", node.entry.Key.Log()))
if node.entry.ReqC == nil {
memstoreRemoveCounter.Inc(1) memstoreRemoveCounter.Inc(1)
node.entry = nil node.entry = nil
s.entryCnt-- s.entryCnt--

View file

@ -266,8 +266,6 @@ func (self *PyramidChunker) processor(id int64, jobC chan *chunkJob, chunkC chan
} }
func (self *PyramidChunker) processChunk(id int64, hasher SwarmHash, job *chunkJob, chunkC chan *Chunk, storageWG *sync.WaitGroup) { func (self *PyramidChunker) processChunk(id int64, hasher SwarmHash, job *chunkJob, chunkC chan *Chunk, storageWG *sync.WaitGroup) {
log.Debug("pyramid.chunker: processChunk()", "id", id)
hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length hasher.ResetWithLength(job.chunk[:8]) // 8 bytes of length
hasher.Write(job.chunk[8:]) // minus 8 []byte length hasher.Write(job.chunk[8:]) // minus 8 []byte length
h := hasher.Sum(nil) h := hasher.Sum(nil)