Release retired document sources outside the cache lock

This commit is contained in:
ak47 committed 2026-11-04 19:24:52 -05:00
1 parent b4896a2eb4
commit 228271b43b
3 files changed
+124 -13

No files matched your search

+64
View File
@@ -683,3 +683,67 @@ func TestCaptureFailsFastWhileProviderHung(t *testing.T) {
t.Fatalf("hung placement error = %v, want ErrProviderHung", err)
}
}
func TestDocumentSlotReleaseAllowsReentrantInvalidation(t *testing.T) {
for _, orphaned := range []bool{false, true} {
t.Run(fmt.Sprintf("orphaned=%v", orphaned), func(t *testing.T) {
adapter := New()
oldRoot := testID("/old")
newRoot := testID("/new")
oldTree, err := NewAccessibleTree(oldRoot, []TreeNode{{Snapshot: Snapshot{BusName: oldRoot.BusName, Path: oldRoot.Path}}})
if err != nil {
t.Fatal(err)
}
if orphaned {
adapter.nativeDocument = documentSourceKeys(adapter.nativeDocument, oldRoot)
} else {
adapter.documentSlotRoot = testID("/active")
adapter.documentTree = oldTree
adapter.stashedDocumentIDs = []ObjectID{oldRoot, testID("/second"), testID("/third")}
adapter.stashedDocuments = map[ObjectID]stashedDocument{oldRoot: {tree: oldTree}}
}
releases := 0
adapter.rotateDocumentSlotsAndRelease(newRoot, func(retired stashedDocument) {
releases++
if !adapter.treeMutex.TryLock() {
t.Fatal("native disposal would deadlock reentrant defunct invalidation")
}
adapter.treeMutex.Unlock()
if adapter.documentSlotRoot != newRoot || adapter.documentTree != nil {
t.Fatal("disposal observed partially rotated slots")
}
if _, retained := adapter.stashedDocuments[oldRoot]; retained {
t.Fatal("disposed document still retained")
}
adapter.invalidateTreeEvent(DefunctStateEvent, 1, oldRoot, ObjectID{})
})
if releases != 1 {
t.Fatalf("released %d documents, want 1", releases)
}
})
}
}
func BenchmarkDocumentSlotEviction(b *testing.B) {
adapter := New()
roots := make([]ObjectID, maxStashedDocuments+2)
trees := make([]*AccessibleTree, len(roots))
for i := range roots {
roots[i] = testID(fmt.Sprintf("/doc%d", i))
var err error
trees[i], err = NewAccessibleTree(roots[i], []TreeNode{{Snapshot: Snapshot{BusName: roots[i].BusName, Path: roots[i].Path}}})
if err != nil {
b.Fatal(err)
}
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
index := i % len(roots)
adapter.rotateDocumentSlots(roots[index])
if adapter.documentTree != nil {
b.Fatal("expected evicted document to need recapture")
}
adapter.documentTree = trees[index]
}
}