mutex.Lock during c.recoverFromCorruption()
This commit is contained in:
parent
1d11751e4e
commit
3873a4d895
|
@ -51,7 +51,12 @@ func (c *BlockCache) HashMismatch(prevhash []byte) bool {
|
||||||
return c.latestHash != nil && !bytes.Equal(c.latestHash, prevhash)
|
return c.latestHash != nil && !bytes.Equal(c.latestHash, prevhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make the block at the given height the lowest height that we don't have.
|
||||||
|
// In other words, wipe out this height and beyond.
|
||||||
|
// This should never increase the size of the cache, only decrease.
|
||||||
|
// Caller should hold c.mutex.Lock().
|
||||||
func (c *BlockCache) setDbFiles(height int) {
|
func (c *BlockCache) setDbFiles(height int) {
|
||||||
|
if height < c.nextBlock {
|
||||||
index := height - c.firstBlock
|
index := height - c.firstBlock
|
||||||
if err := c.lengthsFile.Truncate(int64(index * 4)); err != nil {
|
if err := c.lengthsFile.Truncate(int64(index * 4)); err != nil {
|
||||||
Log.Fatal("truncate lengths file failed: ", err)
|
Log.Fatal("truncate lengths file failed: ", err)
|
||||||
|
@ -63,8 +68,10 @@ func (c *BlockCache) setDbFiles(height int) {
|
||||||
c.starts = c.starts[:index+1]
|
c.starts = c.starts[:index+1]
|
||||||
c.nextBlock = height
|
c.nextBlock = height
|
||||||
c.setLatestHash()
|
c.setLatestHash()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller should hold c.mutex.Lock().
|
||||||
func (c *BlockCache) recoverFromCorruption(height int) {
|
func (c *BlockCache) recoverFromCorruption(height int) {
|
||||||
Log.Warning("CORRUPTION detected in db blocks-cache files, height ", height, " redownloading")
|
Log.Warning("CORRUPTION detected in db blocks-cache files, height ", height, " redownloading")
|
||||||
c.setDbFiles(height)
|
c.setDbFiles(height)
|
||||||
|
@ -86,6 +93,7 @@ func checksum(height int, b []byte) []byte {
|
||||||
return cs.Sum(nil)
|
return cs.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller should hold (at least) c.mutex.RLock().
|
||||||
func (c *BlockCache) readBlock(height int) *walletrpc.CompactBlock {
|
func (c *BlockCache) readBlock(height int) *walletrpc.CompactBlock {
|
||||||
blockLen := c.blockLength(height)
|
blockLen := c.blockLength(height)
|
||||||
b := make([]byte, blockLen+8)
|
b := make([]byte, blockLen+8)
|
||||||
|
@ -116,6 +124,7 @@ func (c *BlockCache) readBlock(height int) *walletrpc.CompactBlock {
|
||||||
return block
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Caller should hold c.mutex.Lock().
|
||||||
func (c *BlockCache) setLatestHash() {
|
func (c *BlockCache) setLatestHash() {
|
||||||
c.latestHash = nil
|
c.latestHash = nil
|
||||||
// There is at least one block; get the last block's hash
|
// There is at least one block; get the last block's hash
|
||||||
|
@ -132,6 +141,7 @@ func (c *BlockCache) setLatestHash() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockCache returns an instance of a block cache object.
|
// NewBlockCache returns an instance of a block cache object.
|
||||||
|
// (No locking here, we assume this is single-threaded.)
|
||||||
func NewBlockCache(dbPath string, chainName string, startHeight int, redownload bool) *BlockCache {
|
func NewBlockCache(dbPath string, chainName string, startHeight int, redownload bool) *BlockCache {
|
||||||
c := &BlockCache{}
|
c := &BlockCache{}
|
||||||
c.firstBlock = startHeight
|
c.firstBlock = startHeight
|
||||||
|
@ -298,7 +308,12 @@ func (c *BlockCache) Get(height int) *walletrpc.CompactBlock {
|
||||||
}
|
}
|
||||||
block := c.readBlock(height)
|
block := c.readBlock(height)
|
||||||
if block == nil {
|
if block == nil {
|
||||||
|
go func() {
|
||||||
|
// We hold only the read lock, need the exclusive lock.
|
||||||
|
c.mutex.Lock()
|
||||||
c.recoverFromCorruption(height)
|
c.recoverFromCorruption(height)
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return block
|
return block
|
||||||
|
|
Loading…
Reference in New Issue