diff --git a/cache/cache.go b/cache/cache.go index ec87fb535..5de251bfc 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -14,6 +14,9 @@ import ( "os" + "os/signal" + "syscall" + "github.com/ncw/rclone/fs" "github.com/pkg/errors" "golang.org/x/net/context" @@ -195,6 +198,9 @@ type Storage interface { // Purge will flush the entire cache Purge() + + // Close should be called when the program ends gracefully + Close() } // Fs represents a wrapped fs.Fs @@ -328,6 +334,16 @@ func NewFs(name, rpath string) (fs.Fs, error) { if err != nil { return nil, err } + // Trap SIGINT and SIGTERM to close the DB handle gracefully + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + go func() { + s := <-c + fs.Debugf(f, "Got signal: %v", s) + if s == syscall.SIGINT || s == syscall.SIGTERM { + f.cache.Close() + } + }() fs.Infof(name, "Chunk Memory: %v", f.chunkMemory) fs.Infof(name, "Chunk Size: %v", fs.SizeSuffix(f.chunkSize)) diff --git a/cache/storage_persistent.go b/cache/storage_persistent.go index 9df75aa75..b6545986a 100644 --- a/cache/storage_persistent.go +++ b/cache/storage_persistent.go @@ -739,6 +739,14 @@ func (b *Persistent) iterateBuckets(buk *bolt.Bucket, bucketFn func(name string) return err } +// Close should be called when the program ends gracefully +func (b *Persistent) Close() { + err := b.db.Close() + if err != nil { + fs.Errorf(b, "closing handle: %v", err) + } +} + // itob returns an 8-byte big endian representation of v. func itob(v int64) []byte { b := make([]byte, 8)