mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-15 11:00:51 +02:00
filer: route exclusive and conditional creates to the entry's ring owner (#11109)
* proto: resync the java copy of filer.proto The Makefile keeps other/java/client/src/main/proto/filer.proto a verbatim copy, but AssignVolumeResponse.fsync and SubscribeMetadataResponse.flushed_ts_ns landed without it. Copy them over; no behaviour change. Claude-Session: https://claude.ai/code/session_01Fx1Hx8RqsJqHpbfbgTf4WJ * filer: route exclusive and conditional creates to the entry's ring owner CreateEntry with o_excl is a FindEntry-then-Insert. The per-path lock added for it makes that atomic only on the filer running it, and the store's insert is an upsert on every backend, so two filers both pass the existence check and both report success. mkdir(2) then succeeds twice for the same path. The same hole sits under the condition precondition, whose comment already told callers to route the key's writes to the owner filer themselves. Do it on the server instead, with the mechanism ObjectTransaction already uses: resolve the entry's ring owner and forward one hop, bounded by is_moved. The ring's membership comes from the master, so it tolerates a stale view and reassigns when a filer dies, neither of which a client's configured filer list can do. Every creator gets this — mount, S3, the filer's own HTTP surface, the Java client — not only the ones that opted in. Plain creates are upserts whoever applies them, so they stay local and pay nothing. The route key shares the S3 gateway's namespace so an object's ObjectTransaction and its CreateEntry land on the same filer's per-path lock. Claude-Session: https://claude.ai/code/session_01Fx1Hx8RqsJqHpbfbgTf4WJ
This commit is contained in:
@@ -250,9 +250,11 @@ message CreateEntryRequest {
|
||||
repeated int32 signatures = 5;
|
||||
bool skip_check_parent_directory = 6;
|
||||
// Optional precondition evaluated against the current entry atomically with
|
||||
// the write, under the filer's per-path lock. The caller must route the
|
||||
// key's writes to this entry's owner filer for the check to be authoritative.
|
||||
// the write, under the filer's per-path lock.
|
||||
WriteCondition condition = 7;
|
||||
// Set on a create a filer forwarded to the entry's ring owner, so the owner
|
||||
// applies it locally instead of forwarding again. Clients leave it unset.
|
||||
bool is_moved = 8;
|
||||
}
|
||||
|
||||
// WriteCondition is the precondition the filer evaluates against the existing
|
||||
@@ -561,6 +563,9 @@ message AssignVolumeResponse {
|
||||
string error = 8;
|
||||
Location location = 9;
|
||||
repeated Location replicas = 10;
|
||||
// fsync is the storage rule's fsync decision for the assigned path, so the
|
||||
// client can carry it onto the volume server upload request.
|
||||
bool fsync = 11;
|
||||
}
|
||||
|
||||
message LookupVolumeRequest {
|
||||
@@ -576,7 +581,6 @@ message Location {
|
||||
string public_url = 2;
|
||||
uint32 grpc_port = 3;
|
||||
string data_center = 4;
|
||||
bool data_in_remote = 5;
|
||||
}
|
||||
message LookupVolumeResponse {
|
||||
map<string, Locations> locations_map = 1;
|
||||
|
||||
Reference in New Issue
Block a user