1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 01:57:02 +00:00

Add mutex to protect directory operations

This commit is contained in:
James Hillyerd
2017-01-22 21:57:55 -08:00
parent 85e3a77fe5
commit 9ac3c90036

View File

@@ -19,11 +19,14 @@ import (
const indexFileName = "index.gob" const indexFileName = "index.gob"
var ( var (
// indexLock is locked while reading/writing an index file // indexMx is locked while reading/writing an index file
// //
// NOTE: This is a bottleneck because it's a single lock even if we have a // NOTE: This is a bottleneck because it's a single lock even if we have a
// million index files // million index files
indexLock = new(sync.RWMutex) indexMx = new(sync.RWMutex)
// dirMx is locked while creating/removing directories
dirMx = new(sync.Mutex)
// countChannel is filled with a sequential numbers (0000..9999), which are // countChannel is filled with a sequential numbers (0000..9999), which are
// used by generateID() to generate unique message IDs. It's global // used by generateID() to generate unique message IDs. It's global
@@ -198,8 +201,8 @@ func (mb *FileMailbox) readIndex() error {
// Clear message slice, open index // Clear message slice, open index
mb.messages = mb.messages[:0] mb.messages = mb.messages[:0]
// Lock for reading // Lock for reading
indexLock.RLock() indexMx.RLock()
defer indexLock.RUnlock() defer indexMx.RUnlock()
// Check if index exists // Check if index exists
if _, err := os.Stat(mb.indexPath); err != nil { if _, err := os.Stat(mb.indexPath); err != nil {
// Does not exist, but that's not an error in our world // Does not exist, but that's not an error in our world
@@ -238,6 +241,8 @@ func (mb *FileMailbox) readIndex() error {
// createDir checks for the presence of the path for this mailbox, creates it if needed // createDir checks for the presence of the path for this mailbox, creates it if needed
func (mb *FileMailbox) createDir() error { func (mb *FileMailbox) createDir() error {
dirMx.Lock()
defer dirMx.Unlock()
if _, err := os.Stat(mb.path); err != nil { if _, err := os.Stat(mb.path); err != nil {
if err := os.MkdirAll(mb.path, 0770); err != nil { if err := os.MkdirAll(mb.path, 0770); err != nil {
log.Errorf("Failed to create directory %v, %v", mb.path, err) log.Errorf("Failed to create directory %v, %v", mb.path, err)
@@ -250,8 +255,8 @@ func (mb *FileMailbox) createDir() error {
// writeIndex overwrites the index on disk with the current mailbox data // writeIndex overwrites the index on disk with the current mailbox data
func (mb *FileMailbox) writeIndex() error { func (mb *FileMailbox) writeIndex() error {
// Lock for writing // Lock for writing
indexLock.Lock() indexMx.Lock()
defer indexLock.Unlock() defer indexMx.Unlock()
if len(mb.messages) > 0 { if len(mb.messages) > 0 {
// Ensure mailbox directory exists // Ensure mailbox directory exists
if err := mb.createDir(); err != nil { if err := mb.createDir(); err != nil {
@@ -283,6 +288,9 @@ func (mb *FileMailbox) writeIndex() error {
} else { } else {
// No messages, delete index+maildir // No messages, delete index+maildir
log.Tracef("Removing mailbox %v", mb.path) log.Tracef("Removing mailbox %v", mb.path)
// deletes are dangerous, requires write lock
dirMx.Lock()
defer dirMx.Unlock()
return os.RemoveAll(mb.path) return os.RemoveAll(mb.path)
} }