Skip to content

Commit

Permalink
[IMPROVED] Do not hold filestore lock during remove that needs to do …
Browse files Browse the repository at this point in the history
…IO. (#4123)

When removing a msg and we need to load the msg block and incur IO,
unlock fs lock to avoid stalling other activity on other blocks. E.g
removing and adding msgs at the same time.

Signed-off-by: Derek Collison <derek@nats.io>
  • Loading branch information
derekcollison committed May 2, 2023
2 parents ff6c803 + 4a58fef commit 188eea4
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions server/filestore.go
Expand Up @@ -2716,18 +2716,38 @@ func (fs *fileStore) removeMsg(seq uint64, secure, viaLimits, needFSLock bool) (
// Now just load regardless.
// TODO(dlc) - Figure out a way not to have to load it in, we need subject tracking outside main data block.
if mb.cacheNotLoaded() {
if err := mb.loadMsgsWithLock(); err != nil {
// We do not want to block possible activity within another msg block.
// We have to unlock both locks and acquire the mb lock in the loadMsgs() call to avoid a deadlock if another
// go routine was trying to get fs then this mb lock at the same time. E.g. another call to remove for same block.
mb.mu.Unlock()
fsUnlock()
if err := mb.loadMsgs(); err != nil {
return false, err
}
fsLock()
// We need to check if things changed out from underneath us.
if fs.closed {
fsUnlock()
return false, ErrStoreClosed
}
mb.mu.Lock()
if mb.closed || seq < mb.first.seq {
mb.mu.Unlock()
fsUnlock()
return false, err
return false, nil
}
// cacheLookup below will do dmap check so no need to repeat here.
}

var smv StoreMsg
sm, err := mb.cacheLookup(seq, &smv)
if err != nil {
mb.mu.Unlock()
fsUnlock()
// Mimic err behavior from above check to dmap. No error returned if already removed.
if err == errDeletedMsg {
err = nil
}
return false, err
}
// Grab size
Expand Down

0 comments on commit 188eea4

Please sign in to comment.