From 15352e9591e5a0abbb5691e5372d40526dfc4cd7 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Wed, 24 Aug 2016 13:04:28 +0700 Subject: [PATCH] implement garbage collection of closed streams in streamsMap ref #256 --- streams_map.go | 14 ++++++++++++++ streams_map_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/streams_map.go b/streams_map.go index eb7f309f..3fd553b4 100644 --- a/streams_map.go +++ b/streams_map.go @@ -180,3 +180,17 @@ func (m *streamsMap) NumberOfStreams() int { m.mutex.RUnlock() return n } + +// garbageCollectClosedStreams deletes nil values in the streams if they are smaller than protocol.MaxNewStreamIDDelta than the highest stream opened by the client +func (m *streamsMap) garbageCollectClosedStreams() { + m.mutex.Lock() + for id, str := range m.streams { + if str != nil { + continue + } + if id+protocol.MaxNewStreamIDDelta <= m.highestStreamOpenedByClient { + delete(m.streams, id) + } + } + m.mutex.Unlock() +} diff --git a/streams_map_test.go b/streams_map_test.go index e6259655..4c1b8260 100644 --- a/streams_map_test.go +++ b/streams_map_test.go @@ -106,6 +106,42 @@ var _ = Describe("Streams Map", func() { _, err = m.GetOrOpenStream(13) Expect(err).ToNot(HaveOccurred()) }) + + It("garbage-collects closed streams", func() { + for i := 1; i < 4*protocol.MaxNewStreamIDDelta; i += 2 { + streamID := protocol.StreamID(i) + _, err := m.GetOrOpenStream(streamID) + Expect(m.highestStreamOpenedByClient).To(Equal(streamID)) + Expect(err).NotTo(HaveOccurred()) + err = m.RemoveStream(streamID) + Expect(err).NotTo(HaveOccurred()) + } + m.garbageCollectClosedStreams() + for i := 1; i < 3*protocol.MaxNewStreamIDDelta; i += 2 { + Expect(m.streams).ToNot(HaveKey(protocol.StreamID(i))) + } + for i := 3*protocol.MaxNewStreamIDDelta + 1; i < 4*protocol.MaxNewStreamIDDelta; i += 2 { + Expect(m.streams).To(HaveKey(protocol.StreamID(i))) + } + }) + + It("does not garbage-collects open streams", func() { + for i := 1; i < 1002; i += 2 { + streamID := protocol.StreamID(i) + _, err := m.GetOrOpenStream(streamID) + Expect(m.highestStreamOpenedByClient).To(Equal(streamID)) + Expect(err).NotTo(HaveOccurred()) + if streamID != 23 { + err = m.RemoveStream(streamID) + Expect(err).NotTo(HaveOccurred()) + } + } + lengthBefore := len(m.streams) + m.garbageCollectClosedStreams() + Expect(len(m.streams)).To(BeNumerically("<", lengthBefore)) + Expect(m.streams).To(HaveKey(protocol.StreamID(23))) + Expect(m.streams[23]).ToNot(BeNil()) + }) }) })