Fix memory leak in secondary, cleanup code.

This commit is contained in:
jdl 2024-01-06 20:50:20 +01:00
parent 6b0b7408bc
commit 0518c5dcca
10 changed files with 27 additions and 100 deletions

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.22
require ( require (
github.com/google/btree v1.1.2 github.com/google/btree v1.1.2
go.uber.org/goleak v1.3.0
golang.org/x/net v0.15.0 golang.org/x/net v0.15.0
golang.org/x/sys v0.12.0 golang.org/x/sys v0.12.0
) )

10
go.sum
View File

@ -1,6 +1,16 @@
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/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -12,7 +12,6 @@ const (
pathStreamWAL = "stream-wal" pathStreamWAL = "stream-wal"
) )
// TODO: Remove this!
func (rep *Replicator) Handle(w http.ResponseWriter, r *http.Request) { func (rep *Replicator) Handle(w http.ResponseWriter, r *http.Request) {
// We'll handle two types of requests: HTTP GET requests for JSON, or // We'll handle two types of requests: HTTP GET requests for JSON, or
// streaming requets for state or wall. // streaming requets for state or wall.

11
lib/rep/main_test.go Normal file
View File

@ -0,0 +1,11 @@
package rep
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}

View File

@ -36,8 +36,8 @@ type App struct {
// SendState: The primary may need to send storage state to a secondary node. // SendState: The primary may need to send storage state to a secondary node.
SendState func(conn net.Conn) error SendState func(conn net.Conn) error
// (1) RecvState: Secondary nodes may need to load state from the primary if the // (1) RecvState: Secondary nodes may need to load state from the primary if
// WAL is too far behind. // the WAL is too far behind.
RecvState func(conn net.Conn) error RecvState func(conn net.Conn) error
// (2) InitStorage: Prepare application storage for possible calls to // (2) InitStorage: Prepare application storage for possible calls to

View File

@ -56,6 +56,7 @@ func (h TestAppHarness) Run(t *testing.T) {
WALSegMaxAgeSec: 1, WALSegMaxAgeSec: 1,
WALSegGCAgeSec: 1, WALSegGCAgeSec: 1,
}) })
defer app2.Close()
val.MethodByName(method.Name).Call([]reflect.Value{ val.MethodByName(method.Name).Call([]reflect.Value{
reflect.ValueOf(t), reflect.ValueOf(t),

View File

@ -1,7 +1,6 @@
package mdb package mdb
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"hash/crc64" "hash/crc64"
@ -25,8 +24,6 @@ type Collection[T any] struct {
uniqueIndices []*Index[T] uniqueIndices []*Index[T]
ByID *Index[T] ByID *Index[T]
buf *bytes.Buffer
} }
type CollectionConfig[T any] struct { type CollectionConfig[T any] struct {
@ -67,7 +64,6 @@ func NewCollection[T any](db *Database, name string, conf *CollectionConfig[T])
validate: conf.Validate, validate: conf.Validate,
indices: []*Index[T]{}, indices: []*Index[T]{},
uniqueIndices: []*Index[T]{}, uniqueIndices: []*Index[T]{},
buf: &bytes.Buffer{},
} }
db.addCollection(c.collectionID, c, &collectionState[T]{ db.addCollection(c.collectionID, c, &collectionState[T]{

View File

@ -99,6 +99,7 @@ func (db *Database) repApply(rec wal.Record) (err error) {
} }
tx.seqNum = rec.SeqNum tx.seqNum = rec.SeqNum
tx.timestampMS = rec.TimestampMS tx.timestampMS = rec.TimestampMS
tx.setReadOnly()
db.snapshot.Store(tx) db.snapshot.Store(tx)
return nil return nil
} }

View File

@ -72,7 +72,7 @@ func testRunner_testCase(t *testing.T, testCase DBTestCase) {
} }
// TODO: Why is this necessary? // TODO: Why is this necessary?
time.Sleep(time.Second) //time.Sleep(time.Second)
finalStep := testCase.Steps[len(testCase.Steps)-1] finalStep := testCase.Steps[len(testCase.Steps)-1]
secondarySnapshot := db2.Snapshot() secondarySnapshot := db2.Snapshot()

View File

@ -1,92 +0,0 @@
package mdb
/*
type txAggregator struct {
Stop chan struct{}
Done *sync.WaitGroup
ModChan chan txMod
W *cswal.Writer
Index *pagefile.Index
Snapshot *atomic.Pointer[Snapshot]
}
func (p txAggregator) Run() {
defer p.Done.Done()
defer p.W.Close()
var (
tx *Snapshot
mod txMod
rec cswal.Record
err error
toNotify = make([]chan error, 0, 1024)
)
READ_FIRST:
toNotify = toNotify[:0]
select {
case mod = <-p.ModChan:
goto BEGIN
case <-p.Stop:
goto END
}
BEGIN:
tx = p.Snapshot.Load().begin()
goto APPLY_MOD
CLONE:
tx = tx.clone()
goto APPLY_MOD
APPLY_MOD:
if err = mod.Update(tx); err != nil {
mod.Resp <- err
goto ROLLBACK
}
toNotify = append(toNotify, mod.Resp)
goto NEXT
ROLLBACK:
if len(toNotify) == 0 {
goto READ_FIRST
}
tx = tx.rollback()
goto NEXT
NEXT:
select {
case mod = <-p.ModChan:
goto CLONE
default:
goto WRITE
}
WRITE:
rec, err = writeChangesToWAL(tx.changes, p.Index, p.W)
if err == nil {
tx.seqNum = rec.SeqNum
tx.updatedAt = rec.CreatedAt
tx.setReadOnly()
p.Snapshot.Store(tx)
}
for i := range toNotify {
toNotify[i] <- err
}
goto READ_FIRST
END:
}
*/