@ -448,9 +448,6 @@ func (db *DB) reload() (err error) {
db . metrics . reloads . Inc ( )
} ( )
var cs [ ] io . Closer
defer func ( ) { closeAll ( cs ... ) } ( )
dirs , err := blockDirs ( db . dir )
if err != nil {
return errors . Wrap ( err , "find blocks" )
@ -482,25 +479,25 @@ func (db *DB) reload() (err error) {
return errors . Wrap ( err , "invalid block sequence" )
}
// Close all opened blocks that no longer exist after we returned all locks.
// TODO(fabxc: probably races with querier still reading from them. Can
// we just abandon them and have the open FDs be GC'd automatically eventually?
for _ , b := range db . blocks {
if _ , ok := exist [ b . Meta ( ) . ULID ] ; ! ok {
cs = append ( cs , b )
}
}
// Swap in new blocks first for subsequently created readers to be seen.
// Then close previous blocks, which may block for pending readers to complete.
db . mtx . Lock ( )
oldBlocks := db . blocks
db . blocks = blocks
db . mtx . Unlock ( )
for _ , b := range oldBlocks {
if _ , ok := exist [ b . Meta ( ) . ULID ] ; ! ok {
b . Close ( )
}
}
// Garbage collect data in the head if the most recent persisted block
// covers data of its current time range.
if len ( blocks ) == 0 {
return nil
}
maxt := blocks [ len ( db . blocks ) - 1 ] . Meta ( ) . MaxTime
maxt := blocks [ len ( blocks ) - 1 ] . Meta ( ) . MaxTime
return errors . Wrap ( db . head . Truncate ( maxt ) , "head truncate failed" )
}
@ -593,7 +590,10 @@ func (db *DB) Snapshot(dir string) error {
db . cmtx . Lock ( )
defer db . cmtx . Unlock ( )
for _ , b := range db . Blocks ( ) {
db . mtx . RLock ( )
defer db . mtx . RUnlock ( )
for _ , b := range db . blocks {
level . Info ( db . logger ) . Log ( "msg" , "snapshotting block" , "block" , b )
if err := b . Snapshot ( dir ) ; err != nil {
@ -608,7 +608,10 @@ func (db *DB) Snapshot(dir string) error {
func ( db * DB ) Querier ( mint , maxt int64 ) ( Querier , error ) {
var blocks [ ] BlockReader
for _ , b := range db . Blocks ( ) {
db . mtx . RLock ( )
defer db . mtx . RUnlock ( )
for _ , b := range db . blocks {
m := b . Meta ( )
if intervalOverlap ( mint , maxt , m . MinTime , m . MaxTime ) {
blocks = append ( blocks , b )
@ -623,10 +626,15 @@ func (db *DB) Querier(mint, maxt int64) (Querier, error) {
}
for _ , b := range blocks {
q , err := NewBlockQuerier ( b , mint , maxt )
if err != nil {
return nil , errors . Wrapf ( err , "open querier for block %s" , b )
if err == nil {
sq . blocks = append ( sq . blocks , q )
continue
}
// If we fail, all previously opened queriers must be closed.
for _ , q := range sq . blocks {
q . Close ( )
}
sq . blocks = append ( sq . blocks , q )
return nil , errors . Wrapf ( err , "open querier for block %s" , b )
}
return sq , nil
}
@ -643,7 +651,10 @@ func (db *DB) Delete(mint, maxt int64, ms ...labels.Matcher) error {
var g errgroup . Group
for _ , b := range db . Blocks ( ) {
db . mtx . RLock ( )
defer db . mtx . RUnlock ( )
for _ , b := range db . blocks {
m := b . Meta ( )
if intervalOverlap ( mint , maxt , m . MinTime , m . MaxTime ) {
g . Go ( func ( b * Block ) func ( ) error {