From cdaa79ada1de3ee92814c669309dd65a3cf7a023 Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Tue, 15 Apr 2025 16:32:29 +0200 Subject: [PATCH] core/filtermaps: add fastCopy and fullCopy of filter maps --- core/filtermaps/filtermaps.go | 18 +++++++++++++++--- core/filtermaps/map_renderer.go | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/filtermaps/filtermaps.go b/core/filtermaps/filtermaps.go index 0ba36ee3de..1d6bb75c18 100644 --- a/core/filtermaps/filtermaps.go +++ b/core/filtermaps/filtermaps.go @@ -139,11 +139,23 @@ type FilterMaps struct { // as transparent (uncached/unchanged). type filterMap []FilterRow -// copy returns a copy of the given filter map. Note that the row slices are -// copied but their contents are not. This permits extending the rows further +// fastCopy returns a copy of the given filter map. Note that the row slices are +// copied but their contents are not. This permits appending to the rows further // (which happens during map rendering) without affecting the validity of // copies made for snapshots during rendering. -func (fm filterMap) copy() filterMap { +// Appending to the rows of both the original map and the fast copy, or two fast +// copies of the same map would result in data corruption, therefore a fast copy +// should always be used in a read only way. +func (fm filterMap) fastCopy() filterMap { + c := make(filterMap, len(fm)) + copy(c, fm) + return c +} + +// fullCopy returns a copy of the given filter map, also making a copy of each +// individual filter row, ensuring that a modification to either one will never +// affect the other. +func (fm filterMap) fullCopy() filterMap { c := make(filterMap, len(fm)) for i, row := range fm { c[i] = make(FilterRow, len(row)) diff --git a/core/filtermaps/map_renderer.go b/core/filtermaps/map_renderer.go index abd5b39e80..b03c4f3302 100644 --- a/core/filtermaps/map_renderer.go +++ b/core/filtermaps/map_renderer.go @@ -104,7 +104,7 @@ func (f *FilterMaps) renderMapsFromSnapshot(cp *renderedMap) (*mapRenderer, erro return &mapRenderer{ f: f, currentMap: &renderedMap{ - filterMap: cp.filterMap.copy(), + filterMap: cp.filterMap.fullCopy(), mapIndex: cp.mapIndex, lastBlock: cp.lastBlock, blockLvPtrs: cp.blockLvPtrs, @@ -260,7 +260,7 @@ func (r *mapRenderer) makeSnapshot() { panic("iterator state inconsistent with last block") } r.f.renderSnapshots.Add(r.currentMap.lastBlock, &renderedMap{ - filterMap: r.currentMap.filterMap.copy(), + filterMap: r.currentMap.filterMap.fastCopy(), mapIndex: r.currentMap.mapIndex, lastBlock: r.currentMap.lastBlock, lastBlockId: r.f.targetView.getBlockId(r.currentMap.lastBlock),