mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-22 05:54:24 +02:00
Stop the filer test helpers from pinning gigabytes of log buffers (#10560)
* log buffer: wake the interval loop on shutdown instead of sleeping through it loopInterval parked in time.Sleep(flushInterval) and only re-checked IsStopping when it woke, so a buffer shut down early kept both loop goroutines - and the PreviousBufferCount+1 slabs of BufferSize they reach - alive for up to a full interval afterwards. Select on shutdownCh against a ticker instead, and give the loops a WaitGroup so a test can observe that they exit. * test: release the filers the server tests build Every helper here left its filer's meta log buffer running, so each test pinned PreviousBufferCount+1 buffers of BufferSize for the rest of the run: ~3.5GB of live heap across the package, which overruns the address space on linux/386 and kills the 32-bit job with an out-of-memory throw. Thread the test through the helpers so the buffer is shut down on cleanup, and shut the subscribe harness's filer down outright - its deletion loop keeps the whole filer reachable otherwise. That harness quiesces its flush path first, since Filer.Shutdown closes the store a flush still in flight would write through.
This commit is contained in:
1 parent
5a5cd15054
commit
f46b2a1925
13 files changed
+136
-72
No files matched your search
@@ -176,6 +176,11 @@ type subscribeHarness struct {
|
||||
// stalls the metadata log flush" state the whole PR exists to handle.
|
||||
gateMu sync.Mutex
|
||||
flushGate chan struct{}
|
||||
|
||||
// flushMu guards stopped against the flushes still in flight when the test
|
||||
// ends, so none of them writes through a store the cleanup has closed.
|
||||
flushMu sync.RWMutex
|
||||
stopped bool
|
||||
}
|
||||
|
||||
const testFilerIdSuffix = "0000abcd"
|
||||
@@ -221,7 +226,12 @@ func newSubscribeHarness(t *testing.T) *subscribeHarness {
|
||||
// layer the way logFlushFunc writes through real volumes.
|
||||
f.LocalMetaLogBuffer.ShutdownLogBuffer()
|
||||
f.LocalMetaLogBuffer = log_buffer.NewLogBuffer("local", time.Minute, h.flushToStore, nil, nil)
|
||||
t.Cleanup(f.LocalMetaLogBuffer.ShutdownLogBuffer)
|
||||
// Shutting the buffer down is not enough: NewFiler's deletion loop keeps the
|
||||
// filer - and so the replacement buffer's tens of megabytes - reachable for
|
||||
// the rest of the run. Quiesce the flush path first, since Filer.Shutdown
|
||||
// closes the store a flush still in flight would write through.
|
||||
t.Cleanup(f.Shutdown)
|
||||
t.Cleanup(h.stopFlushes)
|
||||
|
||||
h.fs = &FilerServer{
|
||||
filer: f,
|
||||
@@ -248,6 +258,15 @@ func (h *subscribeHarness) releaseFlushes() {
|
||||
}
|
||||
}
|
||||
|
||||
// stopFlushes lets go of any gated flush and waits for the ones in flight to
|
||||
// finish, then refuses the rest, so the store stays untouched from here on.
|
||||
func (h *subscribeHarness) stopFlushes() {
|
||||
h.releaseFlushes()
|
||||
h.flushMu.Lock()
|
||||
defer h.flushMu.Unlock()
|
||||
h.stopped = true
|
||||
}
|
||||
|
||||
func (h *subscribeHarness) flushToStore(lb *log_buffer.LogBuffer, startTime, stopTime time.Time, buf []byte, minOffset, maxOffset int64) {
|
||||
h.gateMu.Lock()
|
||||
gate := h.flushGate
|
||||
@@ -256,6 +275,12 @@ func (h *subscribeHarness) flushToStore(lb *log_buffer.LogBuffer, startTime, sto
|
||||
<-gate
|
||||
}
|
||||
|
||||
h.flushMu.RLock()
|
||||
defer h.flushMu.RUnlock()
|
||||
if h.stopped {
|
||||
return
|
||||
}
|
||||
|
||||
// The same file naming and append shape as logFlushFunc, against the fake
|
||||
// volumes: one chunk per flushed window, named for the window start minute.
|
||||
startTime, stopTime = startTime.UTC(), stopTime.UTC()
|
||||
|
||||
Reference in new issue
Block a user