Add version guard to persistence.

This commit is contained in:
beorn7 2015-03-02 20:02:37 +01:00
parent 938290624b
commit ebac14eff3
1 changed files with 48 additions and 2 deletions

View File

@ -21,6 +21,8 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"strconv"
"strings"
"sync" "sync"
"time" "time"
@ -36,6 +38,11 @@ import (
) )
const ( const (
// Version of the storage, as it can be found in the version file.
// Increment to protect against icompatible changes.
Version = 1
versionFileName = "VERSION"
seriesFileSuffix = ".db" seriesFileSuffix = ".db"
seriesTempFileSuffix = ".db.tmp" seriesTempFileSuffix = ".db.tmp"
seriesDirNameLen = 2 // How many bytes of the fingerprint in dir name. seriesDirNameLen = 2 // How many bytes of the fingerprint in dir name.
@ -114,10 +121,49 @@ type persistence struct {
// newPersistence returns a newly allocated persistence backed by local disk storage, ready to use. // newPersistence returns a newly allocated persistence backed by local disk storage, ready to use.
func newPersistence(basePath string, chunkLen int, dirty bool) (*persistence, error) { func newPersistence(basePath string, chunkLen int, dirty bool) (*persistence, error) {
if err := os.MkdirAll(basePath, 0700); err != nil { dirtyPath := filepath.Join(basePath, dirtyFileName)
versionPath := filepath.Join(basePath, versionFileName)
if file, err := os.Open(versionPath); err == nil {
defer file.Close()
data := make([]byte, 8)
n, err := file.Read(data)
if err != nil {
return nil, err
}
if persistedVersion, err := strconv.Atoi(strings.TrimSpace(string(data[:n]))); err != nil {
return nil, fmt.Errorf("cannot parse content of %s: %s", versionPath, data[:n])
} else if persistedVersion != Version {
return nil, fmt.Errorf("found storage version %d on disk, need version %d - please wipe storage or run a version of Prometheus compatible with storage version %d", persistedVersion, Version, persistedVersion)
}
} else if os.IsNotExist(err) {
// No version file found. Let's create the directory (in case
// it's not there yet) and then check if it is actually
// empty. If not, we have found an old storage directory without
// version file, so we have to bail out.
if err := os.MkdirAll(basePath, 0700); err != nil {
return nil, err
}
d, err := os.Open(basePath)
if err != nil {
return nil, err
}
defer d.Close()
if fis, _ := d.Readdir(1); len(fis) > 0 {
return nil, fmt.Errorf("could not detect storage version on disk, assuming version 0, need version %d - please wipe storage or run a version of Prometheus compatible with storage version 0", Version)
}
// Finally we can write our own version into a new version file.
file, err := os.Create(versionPath)
if err != nil {
return nil, err
}
defer file.Close()
if _, err := fmt.Fprintf(file, "%d\n", Version); err != nil {
return nil, err
}
} else {
return nil, err return nil, err
} }
dirtyPath := filepath.Join(basePath, dirtyFileName)
fLock, dirtyfileExisted, err := flock.New(dirtyPath) fLock, dirtyfileExisted, err := flock.New(dirtyPath)
if err != nil { if err != nil {