mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-06 22:41:56 +02:00
* filer: skip UpdateEntry when inline content is unchanged SaveInsideFiler rewrites config files (IAM identities, filer.conf, remote mappings, policies) unconditionally. Each no-op UpdateEntry is a metadata event the local meta log persists to /topics/.system/log, which appends a chunk to a volume. A client that rewrites identical config on a timer, e.g. the seaweedfs-operator 5-minute resync calling UpdateUser with unchanged actions, keeps .dat/.idx files growing on an otherwise idle cluster and prevents HDD spindown (seaweedfs/seaweedfs#11571). Skip the UpdateEntry when the stored inline content is byte-identical, so unchanged writes produce no metadata event and no volume writes. * filer: test that identical SaveInsideFiler writes skip UpdateEntry * filer: require stamped Md5 before skipping identical writes An entry holding identical content but no Md5 (written before hashing, or by a tool that cleared it) would never get the stamp that IF_ETAG_MATCH conditional writes key off. Skip only when both the stored content and its Md5 match, so one write still lands to repair the stamp.
52 lines
1.9 KiB
Go
52 lines
1.9 KiB
Go
package filer
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Rewriting identical inline content must not issue UpdateEntry: each one is a
|
|
// metadata event the local meta log persists to /topics/.system/log, and a
|
|
// client that rewrites the same config on a timer (e.g. the operator's 5-minute
|
|
// resync) keeps the volumes growing on an otherwise idle cluster.
|
|
func TestSaveInsideFilerSkipsIdenticalContent(t *testing.T) {
|
|
ctx := context.Background()
|
|
client := newFakeFilerConfClient()
|
|
|
|
require.NoError(t, SaveInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "a.json", []byte("v1")))
|
|
require.Equal(t, 0, client.updateCalls)
|
|
|
|
require.NoError(t, SaveInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "a.json", []byte("v1")))
|
|
assert.Equal(t, 0, client.updateCalls)
|
|
|
|
require.NoError(t, SaveInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "a.json", []byte("v2")))
|
|
assert.Equal(t, 1, client.updateCalls)
|
|
|
|
content, err := ReadInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "a.json")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []byte("v2"), content)
|
|
}
|
|
|
|
// A legacy entry holding identical bytes but no Md5 still gets one write to
|
|
// stamp the hash that IF_ETAG_MATCH conditional writes key off; later
|
|
// identical writes skip.
|
|
func TestSaveInsideFilerStampsMd5OnLegacyEntry(t *testing.T) {
|
|
ctx := context.Background()
|
|
client := newFakeFilerConfClient()
|
|
client.entries[client.key(DirectoryEtcSeaweedFS, "b.json")] = &filer_pb.Entry{
|
|
Name: "b.json",
|
|
Content: []byte("v1"),
|
|
Attributes: &filer_pb.FuseAttributes{},
|
|
}
|
|
|
|
require.NoError(t, SaveInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "b.json", []byte("v1")))
|
|
assert.Equal(t, 1, client.updateCalls)
|
|
|
|
require.NoError(t, SaveInsideFiler(ctx, client, DirectoryEtcSeaweedFS, "b.json", []byte("v1")))
|
|
assert.Equal(t, 1, client.updateCalls)
|
|
}
|