diff --git a/field.go b/field.go index 8e73ca88e..3dd362ec0 100644 --- a/field.go +++ b/field.go @@ -300,12 +300,14 @@ func (f *Field) saveAvailableShards() error { } func (f *Field) unprotectedSaveAvailableShards() error { - // Open or create file. path := filepath.Join(f.path, ".available.shards") + // Create a temporary file to save to. + tempPath := path + tempExt - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + // Open or create file. + file, err := os.OpenFile(tempPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { - return errors.Wrap(err, "opening available shards file") + return errors.Wrap(err, "opening temporary available shards file") } defer file.Close() @@ -316,6 +318,11 @@ func (f *Field) unprotectedSaveAvailableShards() error { } bw.Flush() + // Move snapshot to data file location. + if err := os.Rename(tempPath, path); err != nil { + return fmt.Errorf("rename snapshot: %s", err) + } + return nil } @@ -514,6 +521,10 @@ func (f *Field) loadMeta() error { // saveMeta writes meta data for the field. func (f *Field) saveMeta() error { + path := filepath.Join(f.path, ".meta") + // Create a temporary file to marshal to. + tempPath := f.path + tempExt + // Marshal metadata. fo := f.options buf, err := proto.Marshal(fo.encode()) @@ -522,10 +533,15 @@ func (f *Field) saveMeta() error { } // Write to meta file. - if err := ioutil.WriteFile(filepath.Join(f.path, ".meta"), buf, 0666); err != nil { + if err := ioutil.WriteFile(tempPath, buf, 0666); err != nil { return errors.Wrap(err, "writing meta") } + // Move temp file to data file location. + if err := os.Rename(tempPath, path); err != nil { + return fmt.Errorf("rename temp: %s", err) + } + return nil } diff --git a/fragment.go b/fragment.go index eaccf7b86..daa621ca5 100644 --- a/fragment.go +++ b/fragment.go @@ -74,6 +74,9 @@ const ( // cacheExt is the file extension for persisted cache ids. cacheExt = ".cache" + // tempExt is the file extension for temporary files. + tempExt = ".temp" + // HashBlockSize is the number of rows in a merkle hash block. HashBlockSize = 100