Addresses two of the three layers behind the audit's "WorkArea
collision under multi-session" risk surfaced in Phase 3:
1. Shared DATA-INIT hash literals (PRG side).
TSqlSession.prg declared `DATA hPlanCache INIT { => }` (plus
hSavepoints + hRolePerms etc.). On the gengo path that
compiles class-DATA INITs, the {=>} literal is sometimes
evaluated ONCE at class-definition time, with every
subsequent New() reusing the same hash pointer. Two pgserver
connections then read/wrote a single shared HbHash from
different goroutines, eventually hitting `concurrent map
writes` inside HbHash.ensureIndex (the lazy O(1)-lookup
index map).
The pre-existing gotcha is already documented in
TSqlExecutor.prg's hSubCache comment ("DATA INIT on hash/
array literals can end up sharing the same instance across
New() calls depending on the compile path") — TSqlSession had
missed the same workaround. Moving the explicit
`::hPlanCache := { => }` etc. into the constructor body
guarantees a fresh hash per instance.
2. Stale cross-session recCount cache (Go side).
`*DBFArea.RecCount()` in shared mode caches its result for
the duration of `recCountCacheGen`. Append() bumped the count
on disk + refreshed THIS area's count under the append-intent
lock (Phase 1 of pre-1.0 audit) but never invalidated the
cache on peer DBFArea instances — so a second pgserver
connection's RecCount() kept returning its pre-Append cached
value. The peer's SELECT then iterated 1..old_count and
missed the newly inserted row.
Append() now calls `InvalidateRecCountCache()` after
committing the bumped header. The generation counter went
to atomic.AddUint64 / atomic.LoadUint64 so the bump is
safe to fire from any goroutine without a lock around the
variable.
Measured impact
---------------
Same 3-worker concurrent-INSERT-then-SELECT stress test that was
~3/5 passing pre-fix:
before: 3 / 5 (40% — plus occasional Go-level panic)
after: 8 / 10 (80% — no panics, just intermittent missed rows)
The remaining 20% flake is on the third layer — peer mmap shows a
pre-Append snapshot when Append's `unmap()` only invalidates this
area's own mmap, not the other workareas that opened the same DBF
file independently via dbUseArea. Fixing that requires either a
cross-area registry of mmap views to invalidate, or skipping
mmap entirely when SHARED && cache-gen has bumped. Tracked as a
proper follow-up; tests/pgserver/run.sh's "Known limitation"
header now points at the narrower problem.
Standalone six-gate verification:
go test ./... ✓
FiveSql2 SQL:1999 43/43 ✓
Harbour compat 56/56 ✓
std.ch 17/17 ✓
FRB 7/7 ✓
pgserver integration 6/6 ✓
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>