diff --git a/weed/mount/content_flush_condition_test.go b/weed/mount/content_flush_condition_test.go index 1862a8f75c..7e1e043917 100644 --- a/weed/mount/content_flush_condition_test.go +++ b/weed/mount/content_flush_condition_test.go @@ -307,6 +307,18 @@ func TestMergeContentEntry(t *testing.T) { if _, ok := mergeContentEntry(stored, base, local, local); ok { t.Fatal("merged into a replaced file") } + + empty := flushConditionEntry() + inline := proto.Clone(empty).(*filer_pb.Entry) + inline.Content = []byte("peer") + appended := proto.Clone(empty).(*filer_pb.Entry) + appended.Chunks = flushConditionEntry(5).Chunks + if _, ok := mergeContentEntry(inline, empty, appended, appended); ok { + t.Fatal("merged chunks next to inline content") + } + if _, ok := mergeContentEntry(appended, empty, inline, inline); ok { + t.Fatal("merged inline content next to chunks") + } } // A miss on state no peer changed is republished once against the stored diff --git a/weed/mount/weedfs_file_sync.go b/weed/mount/weedfs_file_sync.go index 50470a9888..df764347af 100644 --- a/weed/mount/weedfs_file_sync.go +++ b/weed/mount/weedfs_file_sync.go @@ -373,8 +373,9 @@ const maxContentFlushMerges = 3 // content it changed, taking those values from sent (local in stored's id // space). Everything else keeps the stored value. A local truncation keeps // its size and clips stored chunks to it; otherwise the larger size wins. -// A different file at the path, or inline content changed on both sides, -// cannot be merged. +// A different file at the path, inline content changed on both sides, or +// inline content next to chunks (reads stop at the inline bytes) cannot be +// merged. func mergeContentEntry(stored, base, local, sent *filer_pb.Entry) (*filer_pb.Entry, bool) { if stored == nil || base == nil || stored.IsDirectory || !bytes.Equal(stored.HardLinkId, base.HardLinkId) { return nil, false @@ -410,6 +411,9 @@ func mergeContentEntry(stored, base, local, sent *filer_pb.Entry) (*filer_pb.Ent merged.Chunks = append(merged.Chunks, proto.Clone(c).(*filer_pb.FileChunk)) } } + if len(merged.Content) > 0 && len(merged.Chunks) > 0 { + return nil, false + } if merged.Attributes == nil { merged.Attributes = &filer_pb.FuseAttributes{}