From 99513a5d567e494e1fc451bafdab9e1095569596 Mon Sep 17 00:00:00 2001 From: Alex Gaetano Padula Date: Fri, 10 Oct 2025 10:33:51 -0400 Subject: [PATCH 1/2] update c lib to v2.4.2 --- c/go.mod | 2 +- c/go.sum | 4 ++-- sstable_test.go | 22 +++++----------------- utils.go | 14 +++++++++++++- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/c/go.mod b/c/go.mod index d9ecb66..a0caa7f 100644 --- a/c/go.mod +++ b/c/go.mod @@ -2,7 +2,7 @@ module wildcat_c go 1.25 -require github.com/wildcatdb/wildcat/v2 v2.4.1 +require github.com/wildcatdb/wildcat/v2 v2.4.2 require ( go.mongodb.org/mongo-driver v1.17.3 // indirect diff --git a/c/go.sum b/c/go.sum index b1dbeff..cbc2680 100644 --- a/c/go.sum +++ b/c/go.sum @@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/wildcatdb/wildcat/v2 v2.4.1 h1:jYx8jtRuj1/BbVta3VayRneU9wdft4EWZLv1mDJaNMg= -github.com/wildcatdb/wildcat/v2 v2.4.1/go.mod h1:MhT0iAaj4C6cpzKvSA/Pmm5M59jFuSxDi+E0vixOXM4= +github.com/wildcatdb/wildcat/v2 v2.4.2 h1:qTWgX81/b/C7VjCAaR+cViceHJmuYnBffZ6KNP1RYU4= +github.com/wildcatdb/wildcat/v2 v2.4.2/go.mod h1:MN8GlHCJjYD8SQvNC6iEreIpkqT22CN3PfCEjYUrqA4= go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= diff --git a/sstable_test.go b/sstable_test.go index a5cbd31..48bc27a 100644 --- a/sstable_test.go +++ b/sstable_test.go @@ -174,7 +174,7 @@ func TestSSTable_ConcurrentAccess(t *testing.T) { } } - forceManyWrites(t, db, 100) + testForceManyWrites(t, db, 100) time.Sleep(500 * time.Millisecond) // Allow background flush to complete // Number of concurrent readers and operations per reader @@ -297,9 +297,10 @@ func TestSSTable_ConcurrentAccess(t *testing.T) { } } -// Helper function to force a flush to SSTable by writing many keys -func forceManyWrites(t *testing.T, db *DB, count int) { - // Write enough data to trigger memtable flush +// forceManyWrites Helper function to force a flush to SSTable by writing many keys +func testForceManyWrites(t *testing.T, db *DB, count int) { + + // Write enough data to trigger memtable flush(es) for testing for i := 0; i < count; i++ { key := fmt.Sprintf("flush_key%d", i) value := fmt.Sprintf("flush_value%d", i) @@ -313,19 +314,6 @@ func forceManyWrites(t *testing.T, db *DB, count int) { } } -// Helper function to check if a byte slice starts with a prefix -func startsWith(data, prefix []byte) bool { - if len(data) < len(prefix) { - return false - } - for i := 0; i < len(prefix); i++ { - if data[i] != prefix[i] { - return false - } - } - return true -} - func TestSSTable_MVCCWithMultipleVersions(t *testing.T) { dir, err := os.MkdirTemp("", "db_sstable_mvcc_multiple_versions_test") if err != nil { diff --git a/utils.go b/utils.go index bd943a8..1ff7f8f 100644 --- a/utils.go +++ b/utils.go @@ -9,7 +9,6 @@ import ( func extractIDFromFilename(filename string) int64 { parts := strings.Split(filename, ".") - // WAL file names in wildcat are . if len(parts) != 2 { return 0 } @@ -21,3 +20,16 @@ func extractIDFromFilename(filename string) int64 { return ts } + +// startsWith Helper function to check if a byte slice starts with a prefix +func startsWith(data, prefix []byte) bool { + if len(data) < len(prefix) { + return false + } + for i := 0; i < len(prefix); i++ { + if data[i] != prefix[i] { + return false + } + } + return true +} From 2347d9779d4b1ea5c5725ffbb21a38c248cffd5b Mon Sep 17 00:00:00 2001 From: Alex Gaetano Padula Date: Fri, 10 Oct 2025 10:56:39 -0400 Subject: [PATCH 2/2] prevent race condition in queueMemtable by capturing memtable reference once --- flusher.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flusher.go b/flusher.go index e9d71d2..ead3042 100644 --- a/flusher.go +++ b/flusher.go @@ -29,8 +29,9 @@ func newFlusher(db *DB) *Flusher { // queueMemtable queues the current active memtable for flushing to disk. func (flusher *Flusher) queueMemtable() error { + currentMemtable := flusher.db.memtable.Load().(*Memtable) - if atomic.LoadInt64(&flusher.lastQueuedId) == flusher.db.memtable.Load().(*Memtable).id { + if atomic.LoadInt64(&flusher.lastQueuedId) == currentMemtable.id { return nil // Already queued } @@ -54,17 +55,16 @@ func (flusher *Flusher) queueMemtable() error { // Add the new WAL to the LRU cache flusher.db.lru.Put(newMemtable.wal.path, walBm, func(key string, value interface{}) { + // Close the block manager when evicted from LRU if bm, ok := value.(*blockmanager.BlockManager); ok { _ = bm.Close() } }) - lastMemt := flusher.db.memtable.Load().(*Memtable) - // Push the current memtable to the immutable queue - flusher.immutable.Enqueue(lastMemt) - atomic.StoreInt64(&flusher.lastQueuedId, lastMemt.id) + flusher.immutable.Enqueue(currentMemtable) + atomic.StoreInt64(&flusher.lastQueuedId, currentMemtable.id) flusher.db.log(fmt.Sprintf("Flusher: new active memtable created with WAL %s", newMemtable.wal.path))