mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-24 15:00:43 +02:00
filer.conf: merge fsync on presence like worm (#11953)
* filer.conf: merge fsync on presence like worm fsync is a pure preference, so OR-merging it meant a nested rule could never turn a parent's fsync off. Make PathConf.fsync optional and merge it most-specific-wins, matching worm: an unset rule inherits, an explicit value overrides in either direction. readOnly and disableChunkDeletion stay OR'ed — they are fail-closed locks quota enforcement depends on. Pre-version-2 configs were written with EmitUnpopulated, so every rule carries an explicit fsync=false that meant nothing; it is dropped to unset on load so it does not read as an opt-out. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * filer.conf: test fsync override survives a save/reload round trip --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
673d1a02e0
commit
8541f959a9
10 files changed
+171
-57
No files matched your search
@@ -771,7 +771,8 @@ message FilerConf {
|
||||
string replication = 3;
|
||||
string ttl = 4;
|
||||
string disk_type = 5;
|
||||
bool fsync = 6;
|
||||
// unset inherits from the enclosing path rule, set overrides it
|
||||
optional bool fsync = 6;
|
||||
uint32 volume_growth_count = 7;
|
||||
bool read_only = 8;
|
||||
string data_center = 9;
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@ func SyncWrite(ctx context.Context) bool {
|
||||
// syncWriteContext flags ctx when the storage rule on p asks for fsync, so the
|
||||
// store write is held to the same durability as the data path.
|
||||
func (f *Filer) syncWriteContext(ctx context.Context, p util.FullPath) context.Context {
|
||||
if f.FilerConf != nil && f.FilerConf.MatchStorageRule(string(p)).Fsync {
|
||||
if f.FilerConf != nil && f.FilerConf.MatchStorageRule(string(p)).GetFsync() {
|
||||
return WithSyncWrite(ctx)
|
||||
}
|
||||
return ctx
|
||||
|
||||
+21
-12
@@ -33,10 +33,11 @@ const (
|
||||
)
|
||||
|
||||
// FilerConfVersion is stamped into every configuration this build writes.
|
||||
// Version 0 predates worm presence: it was written with EmitUnpopulated, so every
|
||||
// rule carries an explicit "worm": false that meant nothing. Reading one back as an
|
||||
// override would silently lift worm off nested paths, so it is dropped to unset.
|
||||
const FilerConfVersion = 1
|
||||
// Version 0 predates worm presence and version 1 predates fsync presence: both
|
||||
// were written with EmitUnpopulated, so every rule carries an explicit false
|
||||
// that meant nothing. Reading one back as an override would silently lift the
|
||||
// setting off nested paths, so a false from an older version is dropped to unset.
|
||||
const FilerConfVersion = 2
|
||||
|
||||
type FilerConf struct {
|
||||
rules ptrie.Trie[*filer_pb.FilerConf_PathConf]
|
||||
@@ -126,9 +127,12 @@ func (fc *FilerConf) LoadFromBytes(data []byte) (err error) {
|
||||
|
||||
func (fc *FilerConf) doLoadConf(conf *filer_pb.FilerConf) (err error) {
|
||||
for _, location := range conf.Locations {
|
||||
if conf.Version < FilerConfVersion && location.Worm != nil && !*location.Worm {
|
||||
if conf.Version < 1 && location.Worm != nil && !*location.Worm {
|
||||
location.Worm = nil
|
||||
}
|
||||
if conf.Version < 2 && location.Fsync != nil && !*location.Fsync {
|
||||
location.Fsync = nil
|
||||
}
|
||||
err = fc.SetLocationConf(location)
|
||||
if err != nil {
|
||||
// this is not recoverable
|
||||
@@ -227,7 +231,10 @@ func ClonePathConf(src *filer_pb.FilerConf_PathConf) *filer_pb.FilerConf_PathCon
|
||||
if src == nil {
|
||||
return &filer_pb.FilerConf_PathConf{}
|
||||
}
|
||||
var worm *bool
|
||||
var fsync, worm *bool
|
||||
if src.Fsync != nil {
|
||||
fsync = proto.Bool(*src.Fsync)
|
||||
}
|
||||
if src.Worm != nil {
|
||||
worm = proto.Bool(*src.Worm)
|
||||
}
|
||||
@@ -237,7 +244,7 @@ func ClonePathConf(src *filer_pb.FilerConf_PathConf) *filer_pb.FilerConf_PathCon
|
||||
Replication: src.Replication,
|
||||
Ttl: src.Ttl,
|
||||
DiskType: src.DiskType,
|
||||
Fsync: src.Fsync,
|
||||
Fsync: fsync,
|
||||
VolumeGrowthCount: src.VolumeGrowthCount,
|
||||
ReadOnly: src.ReadOnly,
|
||||
MaxFileNameLength: src.MaxFileNameLength,
|
||||
@@ -484,7 +491,7 @@ func ClearBucketLifecycleDayTTLs(ctx context.Context, client filer_pb.SeaweedFil
|
||||
// flag, a placement pin - is an operator's, and deleting the whole rule to
|
||||
// retire its TTL would take their configuration with it.
|
||||
func isLifecycleOwnedPathConf(c *filer_pb.FilerConf_PathConf) bool {
|
||||
return c.GetDiskType() == "" && !c.GetFsync() && !c.GetReadOnly() &&
|
||||
return c.GetDiskType() == "" && c.Fsync == nil && !c.GetReadOnly() &&
|
||||
c.GetDataCenter() == "" && c.GetRack() == "" && c.GetDataNode() == "" &&
|
||||
c.GetMaxFileNameLength() == 0 && !c.GetDisableChunkDeletion() &&
|
||||
c.Worm == nil && c.GetWormGracePeriodSeconds() == 0 && c.GetWormRetentionTimeSeconds() == 0
|
||||
@@ -507,7 +514,12 @@ func mergePathConf(a, b *filer_pb.FilerConf_PathConf) {
|
||||
a.Replication = util.Nvl(b.Replication, a.Replication)
|
||||
a.Ttl = util.Nvl(b.Ttl, a.Ttl)
|
||||
a.DiskType = util.Nvl(b.DiskType, a.DiskType)
|
||||
a.Fsync = b.Fsync || a.Fsync
|
||||
// fsync and worm merge on presence, so a nested rule can turn them off.
|
||||
// readOnly and disableChunkDeletion stay OR'ed on purpose: a nested rule
|
||||
// must not be able to lift a lock the bucket set.
|
||||
if b.Fsync != nil {
|
||||
a.Fsync = proto.Bool(*b.Fsync)
|
||||
}
|
||||
if b.VolumeGrowthCount > 0 {
|
||||
a.VolumeGrowthCount = b.VolumeGrowthCount
|
||||
}
|
||||
@@ -519,9 +531,6 @@ func mergePathConf(a, b *filer_pb.FilerConf_PathConf) {
|
||||
a.Rack = util.Nvl(b.Rack, a.Rack)
|
||||
a.DataNode = util.Nvl(b.DataNode, a.DataNode)
|
||||
a.DisableChunkDeletion = b.DisableChunkDeletion || a.DisableChunkDeletion
|
||||
// worm merges on presence, so a nested rule can turn it off. readOnly, fsync and
|
||||
// disableChunkDeletion stay OR'ed on purpose: a nested rule must not be able to
|
||||
// lift a lock the bucket set.
|
||||
if b.Worm != nil {
|
||||
// copy the value: a is often a scratch conf while b is a live trie entry
|
||||
a.Worm = proto.Bool(*b.Worm)
|
||||
|
||||
@@ -102,6 +102,54 @@ func TestWormLegacyFalseIsNotAnOverride(t *testing.T) {
|
||||
assert.False(t, fc.MatchStorageRule("/buckets/b/sub/x").GetWorm())
|
||||
}
|
||||
|
||||
func TestFsyncInheritance(t *testing.T) {
|
||||
fc := NewFilerConf()
|
||||
fc.doLoadConf(&filer_pb.FilerConf{
|
||||
Version: FilerConfVersion,
|
||||
Locations: []*filer_pb.FilerConf_PathConf{
|
||||
{LocationPrefix: "/buckets/b/", Fsync: proto.Bool(true), Ttl: "7d"},
|
||||
{LocationPrefix: "/buckets/b/quiet/", Collection: "quiet"},
|
||||
{LocationPrefix: "/buckets/b/scratch/", Fsync: proto.Bool(false)},
|
||||
{LocationPrefix: "/buckets/b/scratch/keep/", Fsync: proto.Bool(true)},
|
||||
},
|
||||
})
|
||||
|
||||
// a rule that says nothing about fsync keeps inheriting it, along with the ttl
|
||||
rule := fc.MatchStorageRule("/buckets/b/quiet/x")
|
||||
assert.True(t, rule.GetFsync())
|
||||
assert.Equal(t, "7d", rule.Ttl)
|
||||
|
||||
// an explicit false turns it off, and a deeper rule turns it back on
|
||||
assert.False(t, fc.MatchStorageRule("/buckets/b/scratch/x").GetFsync())
|
||||
assert.True(t, fc.MatchStorageRule("/buckets/b/scratch/keep/x").GetFsync())
|
||||
|
||||
// paths with no rule at all are unaffected
|
||||
assert.False(t, fc.MatchStorageRule("/buckets/other/x").GetFsync())
|
||||
}
|
||||
|
||||
// TestFsyncLegacyFalseIsNotAnOverride pins that the explicit "fsync": false
|
||||
// every pre-version-2 configuration carries does not read as a per-path
|
||||
// opt-out.
|
||||
func TestFsyncLegacyFalseIsNotAnOverride(t *testing.T) {
|
||||
const conf = `{
|
||||
"locations": [
|
||||
{"locationPrefix": "/buckets/b/", "fsync": true},
|
||||
{"locationPrefix": "/buckets/b/sub/", "collection": "sub", "fsync": false}
|
||||
]
|
||||
}`
|
||||
|
||||
for _, version := range []string{"", `"version": 0,`, `"version": 1,`} {
|
||||
fc := NewFilerConf()
|
||||
assert.NoError(t, fc.LoadFromBytes([]byte(`{`+version+conf[1:])))
|
||||
assert.True(t, fc.MatchStorageRule("/buckets/b/sub/x").GetFsync(), version)
|
||||
}
|
||||
|
||||
// the same file at the current version means what it says
|
||||
fc := NewFilerConf()
|
||||
assert.NoError(t, fc.LoadFromBytes([]byte(`{"version": 2,`+conf[1:])))
|
||||
assert.False(t, fc.MatchStorageRule("/buckets/b/sub/x").GetFsync())
|
||||
}
|
||||
|
||||
// TestWormSurvivesRoundTrip guards the write side: an explicit false has to be
|
||||
// stamped along with a version that says to honor it.
|
||||
func TestWormSurvivesRoundTrip(t *testing.T) {
|
||||
@@ -119,6 +167,23 @@ func TestWormSurvivesRoundTrip(t *testing.T) {
|
||||
assert.True(t, reloaded.MatchStorageRule("/buckets/b/other/x").GetWorm())
|
||||
}
|
||||
|
||||
// TestFsyncSurvivesRoundTrip guards the write side: an explicit false has to be
|
||||
// stamped along with a version that says to honor it.
|
||||
func TestFsyncSurvivesRoundTrip(t *testing.T) {
|
||||
fc := NewFilerConf()
|
||||
fc.SetLocationConf(&filer_pb.FilerConf_PathConf{LocationPrefix: "/buckets/b/", Fsync: proto.Bool(true)})
|
||||
fc.SetLocationConf(&filer_pb.FilerConf_PathConf{LocationPrefix: "/buckets/b/sub/", Fsync: proto.Bool(false)})
|
||||
fc.SetLocationConf(&filer_pb.FilerConf_PathConf{LocationPrefix: "/buckets/b/other/", Ttl: "7d"})
|
||||
|
||||
var buf bytes.Buffer
|
||||
assert.NoError(t, fc.ToText(&buf))
|
||||
|
||||
reloaded := NewFilerConf()
|
||||
assert.NoError(t, reloaded.LoadFromBytes(buf.Bytes()))
|
||||
assert.False(t, reloaded.MatchStorageRule("/buckets/b/sub/x").GetFsync())
|
||||
assert.True(t, reloaded.MatchStorageRule("/buckets/b/other/x").GetFsync())
|
||||
}
|
||||
|
||||
// TestClonePathConf verifies that ClonePathConf copies all exported fields.
|
||||
// Uses reflection to automatically detect new fields added to the protobuf,
|
||||
// ensuring the test fails if ClonePathConf is not updated for new fields.
|
||||
@@ -130,7 +195,7 @@ func TestClonePathConf(t *testing.T) {
|
||||
Replication: "001",
|
||||
Ttl: "7d",
|
||||
DiskType: "ssd",
|
||||
Fsync: true,
|
||||
Fsync: proto.Bool(true),
|
||||
VolumeGrowthCount: 5,
|
||||
ReadOnly: true,
|
||||
MaxFileNameLength: 255,
|
||||
@@ -189,9 +254,11 @@ func TestClonePathConf(t *testing.T) {
|
||||
// Verify mutation of clone doesn't affect source
|
||||
clone.Collection = "modified"
|
||||
clone.ReadOnly = false
|
||||
*clone.Fsync = false
|
||||
*clone.Worm = false
|
||||
assert.Equal(t, "test_collection", src.Collection, "Modifying clone should not affect source Collection")
|
||||
assert.Equal(t, true, src.ReadOnly, "Modifying clone should not affect source ReadOnly")
|
||||
assert.Equal(t, true, src.GetFsync(), "Modifying clone should not affect source Fsync")
|
||||
assert.Equal(t, true, src.GetWorm(), "Modifying clone should not affect source Worm")
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -786,7 +786,8 @@ message FilerConf {
|
||||
string replication = 3;
|
||||
string ttl = 4;
|
||||
string disk_type = 5;
|
||||
bool fsync = 6;
|
||||
// unset inherits from the enclosing path rule, set overrides it
|
||||
optional bool fsync = 6;
|
||||
uint32 volume_growth_count = 7;
|
||||
bool read_only = 8;
|
||||
string data_center = 9;
|
||||
|
||||
@@ -7102,20 +7102,21 @@ func (x *LocateBrokerResponse_Resource) GetResourceCount() int32 {
|
||||
}
|
||||
|
||||
type FilerConf_PathConf struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
LocationPrefix string `protobuf:"bytes,1,opt,name=location_prefix,json=locationPrefix,proto3" json:"location_prefix,omitempty"`
|
||||
Collection string `protobuf:"bytes,2,opt,name=collection,proto3" json:"collection,omitempty"`
|
||||
Replication string `protobuf:"bytes,3,opt,name=replication,proto3" json:"replication,omitempty"`
|
||||
Ttl string `protobuf:"bytes,4,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
DiskType string `protobuf:"bytes,5,opt,name=disk_type,json=diskType,proto3" json:"disk_type,omitempty"`
|
||||
Fsync bool `protobuf:"varint,6,opt,name=fsync,proto3" json:"fsync,omitempty"`
|
||||
VolumeGrowthCount uint32 `protobuf:"varint,7,opt,name=volume_growth_count,json=volumeGrowthCount,proto3" json:"volume_growth_count,omitempty"`
|
||||
ReadOnly bool `protobuf:"varint,8,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"`
|
||||
DataCenter string `protobuf:"bytes,9,opt,name=data_center,json=dataCenter,proto3" json:"data_center,omitempty"`
|
||||
Rack string `protobuf:"bytes,10,opt,name=rack,proto3" json:"rack,omitempty"`
|
||||
DataNode string `protobuf:"bytes,11,opt,name=data_node,json=dataNode,proto3" json:"data_node,omitempty"`
|
||||
MaxFileNameLength uint32 `protobuf:"varint,12,opt,name=max_file_name_length,json=maxFileNameLength,proto3" json:"max_file_name_length,omitempty"`
|
||||
DisableChunkDeletion bool `protobuf:"varint,13,opt,name=disable_chunk_deletion,json=disableChunkDeletion,proto3" json:"disable_chunk_deletion,omitempty"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
LocationPrefix string `protobuf:"bytes,1,opt,name=location_prefix,json=locationPrefix,proto3" json:"location_prefix,omitempty"`
|
||||
Collection string `protobuf:"bytes,2,opt,name=collection,proto3" json:"collection,omitempty"`
|
||||
Replication string `protobuf:"bytes,3,opt,name=replication,proto3" json:"replication,omitempty"`
|
||||
Ttl string `protobuf:"bytes,4,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
DiskType string `protobuf:"bytes,5,opt,name=disk_type,json=diskType,proto3" json:"disk_type,omitempty"`
|
||||
// unset inherits from the enclosing path rule, set overrides it
|
||||
Fsync *bool `protobuf:"varint,6,opt,name=fsync,proto3,oneof" json:"fsync,omitempty"`
|
||||
VolumeGrowthCount uint32 `protobuf:"varint,7,opt,name=volume_growth_count,json=volumeGrowthCount,proto3" json:"volume_growth_count,omitempty"`
|
||||
ReadOnly bool `protobuf:"varint,8,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"`
|
||||
DataCenter string `protobuf:"bytes,9,opt,name=data_center,json=dataCenter,proto3" json:"data_center,omitempty"`
|
||||
Rack string `protobuf:"bytes,10,opt,name=rack,proto3" json:"rack,omitempty"`
|
||||
DataNode string `protobuf:"bytes,11,opt,name=data_node,json=dataNode,proto3" json:"data_node,omitempty"`
|
||||
MaxFileNameLength uint32 `protobuf:"varint,12,opt,name=max_file_name_length,json=maxFileNameLength,proto3" json:"max_file_name_length,omitempty"`
|
||||
DisableChunkDeletion bool `protobuf:"varint,13,opt,name=disable_chunk_deletion,json=disableChunkDeletion,proto3" json:"disable_chunk_deletion,omitempty"`
|
||||
// unset inherits from the enclosing path rule, set overrides it
|
||||
Worm *bool `protobuf:"varint,14,opt,name=worm,proto3,oneof" json:"worm,omitempty"`
|
||||
WormGracePeriodSeconds uint64 `protobuf:"varint,15,opt,name=worm_grace_period_seconds,json=wormGracePeriodSeconds,proto3" json:"worm_grace_period_seconds,omitempty"`
|
||||
@@ -7190,8 +7191,8 @@ func (x *FilerConf_PathConf) GetDiskType() string {
|
||||
}
|
||||
|
||||
func (x *FilerConf_PathConf) GetFsync() bool {
|
||||
if x != nil {
|
||||
return x.Fsync
|
||||
if x != nil && x.Fsync != nil {
|
||||
return *x.Fsync
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -7764,10 +7765,10 @@ const file_filer_proto_rawDesc = "" +
|
||||
"\x03key\x18\x01 \x01(\fR\x03key\x12\x14\n" +
|
||||
"\x05value\x18\x02 \x01(\fR\x05value\"%\n" +
|
||||
"\rKvPutResponse\x12\x14\n" +
|
||||
"\x05error\x18\x01 \x01(\tR\x05error\"\xc0\x05\n" +
|
||||
"\x05error\x18\x01 \x01(\tR\x05error\"\xcf\x05\n" +
|
||||
"\tFilerConf\x12\x18\n" +
|
||||
"\aversion\x18\x01 \x01(\x05R\aversion\x12:\n" +
|
||||
"\tlocations\x18\x02 \x03(\v2\x1c.filer_pb.FilerConf.PathConfR\tlocations\x1a\xdc\x04\n" +
|
||||
"\tlocations\x18\x02 \x03(\v2\x1c.filer_pb.FilerConf.PathConfR\tlocations\x1a\xeb\x04\n" +
|
||||
"\bPathConf\x12'\n" +
|
||||
"\x0flocation_prefix\x18\x01 \x01(\tR\x0elocationPrefix\x12\x1e\n" +
|
||||
"\n" +
|
||||
@@ -7775,8 +7776,8 @@ const file_filer_proto_rawDesc = "" +
|
||||
"collection\x12 \n" +
|
||||
"\vreplication\x18\x03 \x01(\tR\vreplication\x12\x10\n" +
|
||||
"\x03ttl\x18\x04 \x01(\tR\x03ttl\x12\x1b\n" +
|
||||
"\tdisk_type\x18\x05 \x01(\tR\bdiskType\x12\x14\n" +
|
||||
"\x05fsync\x18\x06 \x01(\bR\x05fsync\x12.\n" +
|
||||
"\tdisk_type\x18\x05 \x01(\tR\bdiskType\x12\x19\n" +
|
||||
"\x05fsync\x18\x06 \x01(\bH\x00R\x05fsync\x88\x01\x01\x12.\n" +
|
||||
"\x13volume_growth_count\x18\a \x01(\rR\x11volumeGrowthCount\x12\x1b\n" +
|
||||
"\tread_only\x18\b \x01(\bR\breadOnly\x12\x1f\n" +
|
||||
"\vdata_center\x18\t \x01(\tR\n" +
|
||||
@@ -7786,9 +7787,10 @@ const file_filer_proto_rawDesc = "" +
|
||||
"\tdata_node\x18\v \x01(\tR\bdataNode\x12/\n" +
|
||||
"\x14max_file_name_length\x18\f \x01(\rR\x11maxFileNameLength\x124\n" +
|
||||
"\x16disable_chunk_deletion\x18\r \x01(\bR\x14disableChunkDeletion\x12\x17\n" +
|
||||
"\x04worm\x18\x0e \x01(\bH\x00R\x04worm\x88\x01\x01\x129\n" +
|
||||
"\x04worm\x18\x0e \x01(\bH\x01R\x04worm\x88\x01\x01\x129\n" +
|
||||
"\x19worm_grace_period_seconds\x18\x0f \x01(\x04R\x16wormGracePeriodSeconds\x12=\n" +
|
||||
"\x1bworm_retention_time_seconds\x18\x10 \x01(\x04R\x18wormRetentionTimeSecondsB\a\n" +
|
||||
"\x1bworm_retention_time_seconds\x18\x10 \x01(\x04R\x18wormRetentionTimeSecondsB\b\n" +
|
||||
"\x06_fsyncB\a\n" +
|
||||
"\x05_worm\"\xba\x01\n" +
|
||||
"&CacheRemoteObjectToLocalClusterRequest\x12\x1c\n" +
|
||||
"\tdirectory\x18\x01 \x01(\tR\tdirectory\x12\x12\n" +
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc v3.21.12
|
||||
// - protoc v7.35.0
|
||||
// source: filer.proto
|
||||
|
||||
package filer_pb
|
||||
|
||||
@@ -2659,6 +2659,16 @@ func (m *AtomicRenameEntryRequest) MarshalToSizedBufferVT(dAtA []byte) (int, err
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.FailIfTargetExists {
|
||||
i--
|
||||
if m.FailIfTargetExists {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x30
|
||||
}
|
||||
if len(m.Signatures) > 0 {
|
||||
var pksize2 int
|
||||
for _, num := range m.Signatures {
|
||||
@@ -4984,9 +4994,9 @@ func (m *FilerConf_PathConf) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
i--
|
||||
dAtA[i] = 0x38
|
||||
}
|
||||
if m.Fsync {
|
||||
if m.Fsync != nil {
|
||||
i--
|
||||
if m.Fsync {
|
||||
if *m.Fsync {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
@@ -7599,6 +7609,9 @@ func (m *AtomicRenameEntryRequest) SizeVT() (n int) {
|
||||
}
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(l)) + l
|
||||
}
|
||||
if m.FailIfTargetExists {
|
||||
n += 2
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
@@ -8501,7 +8514,7 @@ func (m *FilerConf_PathConf) SizeVT() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
if m.Fsync {
|
||||
if m.Fsync != nil {
|
||||
n += 2
|
||||
}
|
||||
if m.VolumeGrowthCount != 0 {
|
||||
@@ -16531,6 +16544,26 @@ func (m *AtomicRenameEntryRequest) UnmarshalVT(dAtA []byte) error {
|
||||
} else {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Signatures", wireType)
|
||||
}
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field FailIfTargetExists", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.FailIfTargetExists = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
@@ -22263,7 +22296,8 @@ func (m *FilerConf_PathConf) UnmarshalVT(dAtA []byte) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Fsync = bool(v != 0)
|
||||
b := bool(v != 0)
|
||||
m.Fsync = &b
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field VolumeGrowthCount", wireType)
|
||||
|
||||
@@ -337,7 +337,7 @@ func (fs *FilerServer) detectStorageOption(ctx context.Context, requestURI, qCol
|
||||
DataNode: util.Nvl(dataNode, rule.DataNode, fs.option.DataNode),
|
||||
TtlSeconds: ttlSeconds,
|
||||
DiskType: util.Nvl(diskType, overlayDisk, rule.DiskType),
|
||||
Fsync: rule.Fsync,
|
||||
Fsync: rule.GetFsync(),
|
||||
VolumeGrowthCount: rule.VolumeGrowthCount,
|
||||
MaxFileNameLength: maxFileNameLength,
|
||||
// A location that survives from a request parameter, a placement
|
||||
|
||||
@@ -67,7 +67,7 @@ func (c *commandFsConfigure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
replication := fsConfigureCommand.String("replication", "", "assign writes with this replication")
|
||||
ttl := fsConfigureCommand.String("ttl", "", "assign writes with this ttl (e.g., 1m, 1h, 1d, 1w, 1y)")
|
||||
diskType := fsConfigureCommand.String("disk", "", "[hdd|ssd|<tag>] hard drive or solid state drive or any tag")
|
||||
fsync := fsConfigureCommand.Bool("fsync", false, "fsync for the writes")
|
||||
fsync := fsConfigureCommand.Bool("fsync", false, "fsync for the writes; unset inherits from the parent path")
|
||||
isReadOnly := fsConfigureCommand.Bool("readOnly", false, "disable writes")
|
||||
worm := fsConfigureCommand.Bool("worm", false, "write-once-read-many, written files are readonly; unset inherits from the parent path")
|
||||
wormGracePeriod := fsConfigureCommand.Uint64("wormGracePeriod", 0, "grace period before worm is enforced, in seconds")
|
||||
@@ -101,7 +101,6 @@ func (c *commandFsConfigure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
Collection: *collection,
|
||||
Replication: *replication,
|
||||
Ttl: *ttl,
|
||||
Fsync: *fsync,
|
||||
MaxFileNameLength: uint32(*maxFileNameLength),
|
||||
DiskType: *diskType,
|
||||
VolumeGrowthCount: uint32(*volumeGrowthCount),
|
||||
@@ -113,10 +112,13 @@ func (c *commandFsConfigure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
WormRetentionTimeSeconds: *wormRetentionTime,
|
||||
}
|
||||
|
||||
// worm is only carried when the flag is passed, so a rule that says nothing
|
||||
// about it keeps inheriting from the enclosing path
|
||||
// fsync and worm are only carried when the flag is passed, so a rule that
|
||||
// says nothing about them keeps inheriting from the enclosing path
|
||||
fsConfigureCommand.Visit(func(f *flag.Flag) {
|
||||
if f.Name == "worm" {
|
||||
switch f.Name {
|
||||
case "fsync":
|
||||
locConf.Fsync = proto.Bool(*fsync)
|
||||
case "worm":
|
||||
locConf.Worm = proto.Bool(*worm)
|
||||
}
|
||||
})
|
||||
@@ -152,17 +154,15 @@ func (c *commandFsConfigure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
fc.DeleteLocationConf(*locationPrefix)
|
||||
} else {
|
||||
fc.AddLocationConf(locConf)
|
||||
// AddLocationConf merges these boolean fields with OR, which can never
|
||||
// turn a flag off; let an explicitly passed false win, e.g. -readOnly=false
|
||||
// to reopen a bucket that quota enforcement locked. worm does not belong
|
||||
// here: it merges on presence, so the value set above already wins.
|
||||
// AddLocationConf merges this boolean field with OR, which can never
|
||||
// turn it off; let an explicitly passed false win, e.g. -readOnly=false
|
||||
// to reopen a bucket that quota enforcement locked. fsync and worm do
|
||||
// not belong here: they merge on presence, so the values set above
|
||||
// already win.
|
||||
if mergedConf, found := fc.GetLocationConf(*locationPrefix); found {
|
||||
fsConfigureCommand.Visit(func(f *flag.Flag) {
|
||||
switch f.Name {
|
||||
case "readOnly":
|
||||
if f.Name == "readOnly" {
|
||||
mergedConf.ReadOnly = *isReadOnly
|
||||
case "fsync":
|
||||
mergedConf.Fsync = *fsync
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user