Seek to offset 0 after Truncate() (#5375)

This commit is contained in:
Krishna Srinivas 2018-02-06 15:37:48 -08:00 committed by kannappanr
parent 1164fc60f3
commit 047b7aff0c
5 changed files with 72 additions and 56 deletions

View File

@ -17,7 +17,6 @@
package cmd package cmd
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -74,30 +73,11 @@ func newFormatFSV2() (format *formatFSV2) {
return f return f
} }
// Save to fs format.json
func formatFSSave(f *os.File, data interface{}) error {
b, err := json.Marshal(data)
if err != nil {
return errors2.Trace(err)
}
if err = f.Truncate(0); err != nil {
return errors2.Trace(err)
}
if _, err = f.Seek(0, io.SeekStart); err != nil {
return err
}
_, err = f.Write(b)
if err != nil {
return errors2.Trace(err)
}
return nil
}
// Returns the field formatMetaV1.Format i.e the string "fs" which is never likely to change. // Returns the field formatMetaV1.Format i.e the string "fs" which is never likely to change.
// We do not use this function in XL to get the format as the file is not fcntl-locked on XL. // We do not use this function in XL to get the format as the file is not fcntl-locked on XL.
func formatMetaGetFormatBackendFS(r io.ReadSeeker) (string, error) { func formatMetaGetFormatBackendFS(r io.ReadSeeker) (string, error) {
format := &formatMetaV1{} format := &formatMetaV1{}
if err := jsonLoadFromSeeker(r, format); err != nil { if err := jsonLoad(r, format); err != nil {
return "", err return "", err
} }
if format.Version == formatMetaVersionV1 { if format.Version == formatMetaVersionV1 {
@ -109,7 +89,7 @@ func formatMetaGetFormatBackendFS(r io.ReadSeeker) (string, error) {
// Returns formatFS.FS.Version // Returns formatFS.FS.Version
func formatFSGetVersion(r io.ReadSeeker) (string, error) { func formatFSGetVersion(r io.ReadSeeker) (string, error) {
format := &formatFSVersionDetect{} format := &formatFSVersionDetect{}
if err := jsonLoadFromSeeker(r, format); err != nil { if err := jsonLoad(r, format); err != nil {
return "", err return "", err
} }
return format.FS.Version, nil return format.FS.Version, nil
@ -135,7 +115,7 @@ func formatFSMigrateV1ToV2(wlk *lock.LockedFile, fsPath string) error {
return err return err
} }
return formatFSSave(wlk.File, newFormatFSV2()) return jsonSave(wlk.File, newFormatFSV2())
} }
// Migrate the "fs" backend. // Migrate the "fs" backend.
@ -190,7 +170,7 @@ func createFormatFS(fsFormatPath string) error {
return nil return nil
} }
return formatFSSave(lk.File, newFormatFSV1()) return jsonSave(lk.File, newFormatFSV1())
} }
// This function returns a read-locked format.json reference to the caller. // This function returns a read-locked format.json reference to the caller.

View File

@ -17,7 +17,6 @@
package cmd package cmd
import ( import (
"encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
@ -127,22 +126,14 @@ func (m fsMetaV1) ToObjectInfo(bucket, object string, fi os.FileInfo) ObjectInfo
} }
func (m *fsMetaV1) WriteTo(lk *lock.LockedFile) (n int64, err error) { func (m *fsMetaV1) WriteTo(lk *lock.LockedFile) (n int64, err error) {
var metadataBytes []byte if err = jsonSave(lk, m); err != nil {
metadataBytes, err = json.Marshal(m) return 0, err
}
fi, err := lk.Stat()
if err != nil { if err != nil {
return 0, errors.Trace(err) return 0, err
} }
return fi.Size(), nil
if err = lk.Truncate(0); err != nil {
return 0, errors.Trace(err)
}
if _, err = lk.Write(metadataBytes); err != nil {
return 0, errors.Trace(err)
}
// Success.
return int64(len(metadataBytes)), nil
} }
func parseFSVersion(fsMetaBuf []byte) string { func parseFSVersion(fsMetaBuf []byte) string {

View File

@ -84,20 +84,14 @@ func (u *uploadsV1) IsEmpty() bool {
} }
func (u *uploadsV1) WriteTo(lk *lock.LockedFile) (n int64, err error) { func (u *uploadsV1) WriteTo(lk *lock.LockedFile) (n int64, err error) {
// Serialize to prepare to write to disk. if err = jsonSave(lk, u); err != nil {
var uplBytes []byte return 0, err
uplBytes, err = json.Marshal(u) }
fi, err := lk.Stat()
if err != nil { if err != nil {
return 0, errors.Trace(err) return 0, err
} }
if err = lk.Truncate(0); err != nil { return fi.Size(), nil
return 0, errors.Trace(err)
}
_, err = lk.Write(uplBytes)
if err != nil {
return 0, errors.Trace(err)
}
return int64(len(uplBytes)), nil
} }
func (u *uploadsV1) ReadFrom(lk *lock.LockedFile) (n int64, err error) { func (u *uploadsV1) ReadFrom(lk *lock.LockedFile) (n int64, err error) {

View File

@ -265,9 +265,31 @@ func NewCustomHTTPTransport() http.RoundTripper {
} }
// Load the json (typically from disk file). // Load the json (typically from disk file).
func jsonLoadFromSeeker(r io.ReadSeeker, data interface{}) error { func jsonLoad(r io.ReadSeeker, data interface{}) error {
if _, err := r.Seek(0, io.SeekStart); err != nil { if _, err := r.Seek(0, io.SeekStart); err != nil {
return err return err
} }
return json.NewDecoder(r).Decode(data) return json.NewDecoder(r).Decode(data)
} }
// Save to disk file in json format.
func jsonSave(f interface {
io.WriteSeeker
Truncate(int64) error
}, data interface{}) error {
b, err := json.Marshal(data)
if err != nil {
return err
}
if err = f.Truncate(0); err != nil {
return err
}
if _, err = f.Seek(0, io.SeekStart); err != nil {
return err
}
_, err = f.Write(b)
if err != nil {
return err
}
return nil
}

View File

@ -365,18 +365,47 @@ func TestContains(t *testing.T) {
} }
} }
// Test jsonLoadFromSeeker. // Test jsonLoad.
func TestJSONLoadFromSeeker(t *testing.T) { func TestJSONLoad(t *testing.T) {
format := newFormatFSV1() format := newFormatFSV1()
b, err := json.Marshal(format) b, err := json.Marshal(format)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
var gotFormat formatFSV1 var gotFormat formatFSV1
if err = jsonLoadFromSeeker(bytes.NewReader(b), &gotFormat); err != nil { if err = jsonLoad(bytes.NewReader(b), &gotFormat); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if *format != gotFormat { if *format != gotFormat {
t.Fatal("jsonLoadFromSeeker() failed to decode json") t.Fatal("jsonLoad() failed to decode json")
}
}
// Test jsonSave.
func TestJSONSave(t *testing.T) {
f, err := ioutil.TempFile("", "")
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name())
// Test to make sure formatFSSave overwrites and does not append.
format := newFormatFSV1()
if err = jsonSave(f, format); err != nil {
t.Fatal(err)
}
fi1, err := f.Stat()
if err != nil {
t.Fatal(err)
}
if err = jsonSave(f, format); err != nil {
t.Fatal(err)
}
fi2, err := f.Stat()
if err != nil {
t.Fatal(err)
}
if fi1.Size() != fi2.Size() {
t.Fatal("Size should not differ after jsonSave()", fi1.Size(), fi2.Size(), f.Name())
} }
} }