mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-07 12:37:41 +01:00
filer: no lazy remote fetch inside a store transaction
A rename onto an existing target deletes the target inside the store transaction, then CreateEntry's FindEntry misses the row and runs the lazy remote fetch, which persists the archive copy on a second connection. The store wrapper drops that call's deadline, so the UPDATE waits without bound on the row lock of the transaction's own uncommitted DELETE while the rename goroutine holds the path's exclusive locks: every later lookup, rename and delete of the path on that filer waits forever. A lookup whose context carries the store transaction skips the fetch. (cherry picked from commit b69e9535c2597d0c8e856f031d3778fddfd4159c)
This commit is contained in:
1 parent
0dd33f5f0f
commit
5dd033fc3e
2 files changed
+28
No files matched your search
@@ -41,6 +41,12 @@ func (f *Filer) maybeLazyFetchFromRemote(ctx context.Context, p util.FullPath) (
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A lookup inside a store transaction persists on a second connection,
|
||||||
|
// which waits on the row locks the transaction holds.
|
||||||
|
if ctx.Value("tx") != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
if f.RemoteStorage == nil {
|
if f.RemoteStorage == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -734,6 +734,28 @@ func TestMaybeLazyFetchFromRemote_ContextGuardPreventsRecursion(t *testing.T) {
|
|||||||
assert.Equal(t, 0, countingStub.statCalls, "guard should prevent StatFile from being called")
|
assert.Equal(t, 0, countingStub.statCalls, "guard should prevent StatFile from being called")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMaybeLazyFetchFromRemote_SkipsInsideStoreTransaction(t *testing.T) {
|
||||||
|
const storageType = "stub_lazy_tx"
|
||||||
|
countingStub := &countingRemoteClient{
|
||||||
|
stubRemoteClient: stubRemoteClient{
|
||||||
|
statResult: &filer_pb.RemoteEntry{RemoteMtime: 1, RemoteSize: 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f, _ := newMountedTestFiler(t, storageType, countingStub, 0)
|
||||||
|
|
||||||
|
// the key a store transaction travels under (abstract_sql getTxOrDB)
|
||||||
|
txCtx := context.WithValue(context.Background(), "tx", struct{}{})
|
||||||
|
entry, err := f.maybeLazyFetchFromRemote(txCtx, "/buckets/mybucket/dir/a.txt")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Nil(t, entry)
|
||||||
|
assert.Equal(t, 0, countingStub.statCalls, "a lookup inside a transaction must not consult the remote")
|
||||||
|
|
||||||
|
entry, err = f.maybeLazyFetchFromRemote(context.Background(), "/buckets/mybucket/dir/a.txt")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, entry)
|
||||||
|
assert.NotZero(t, countingStub.statCalls, "the same lookup outside a transaction consults the remote")
|
||||||
|
}
|
||||||
|
|
||||||
func TestMaybeLazyFetchFromRemote_GuardedClientRejectsEndpoint(t *testing.T) {
|
func TestMaybeLazyFetchFromRemote_GuardedClientRejectsEndpoint(t *testing.T) {
|
||||||
const storageType = "stub_lazy_guarded"
|
const storageType = "stub_lazy_guarded"
|
||||||
countingStub := &countingRemoteClient{
|
countingStub := &countingRemoteClient{
|
||||||
|
|||||||
Reference in new issue
Block a user