diff --git a/field.go b/field.go index 8e73ca88e..30529ea32 100644 --- a/field.go +++ b/field.go @@ -300,10 +300,12 @@ 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 snapshot to. + snapshotPath := path + snapshotExt - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + // Open or create file. + file, err := os.OpenFile(snapshotPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return errors.Wrap(err, "opening available shards file") } @@ -316,6 +318,11 @@ func (f *Field) unprotectedSaveAvailableShards() error { } bw.Flush() + // Move snapshot to data file location. + if err := os.Rename(snapshotPath, 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