mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Seek to offset 0 after Truncate() (#5375)
This commit is contained in:
parent
1164fc60f3
commit
047b7aff0c
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
24
cmd/utils.go
24
cmd/utils.go
@ -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
|
||||||
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user