jldb/mdb/testdb_test.go

152 lines
2.4 KiB
Go

package mdb
import (
"crypto/rand"
"errors"
"hash/crc32"
"log"
mrand "math/rand"
"runtime"
"slices"
"sync"
"sync/atomic"
"time"
)
type DataItem struct {
ID uint64
Data []byte
}
type DataCollection struct {
*Collection[DataItem]
}
func NewDataCollection(db *Database) DataCollection {
return DataCollection{
Collection: NewCollection(db, "Data", &CollectionConfig[DataItem]{
Copy: func(in *DataItem) *DataItem {
out := &DataItem{}
*out = *in
out.Data = slices.Clone(in.Data)
return out
},
}),
}
}
type CRCItem struct {
ID uint64 // Always 1
CRC32 uint32
}
type CRCCollection struct {
*Collection[CRCItem]
}
func NewCRCCollection(db *Database) CRCCollection {
return CRCCollection{
Collection: NewCollection[CRCItem](db, "CRC", nil),
}
}
type DataDB struct {
*Database
Datas DataCollection
CRCs CRCCollection
}
func OpenDataDB(rootDir string) (DataDB, error) {
db := New(Config{
RootDir: rootDir,
Primary: true,
})
testdb := DataDB{
Database: db,
Datas: NewDataCollection(db),
CRCs: NewCRCCollection(db),
}
return testdb, testdb.Open()
}
func (db DataDB) ModifyFor(dt time.Duration) {
wg := sync.WaitGroup{}
var count int64
for i := 0; i < runtime.NumCPU(); i++ {
wg.Add(1)
go func() {
defer wg.Done()
t0 := time.Now()
for time.Since(t0) < dt {
atomic.AddInt64(&count, 1)
db.modifyOnce()
}
}()
}
wg.Wait()
log.Printf("Modified: %d", count)
}
func (db DataDB) modifyOnce() {
isErr := mrand.Float64() < 0.1
err := db.Update(func(tx *Snapshot) error {
h := crc32.NewIEEE()
for dataID := uint64(1); dataID < 10; dataID++ {
d := DataItem{
ID: dataID,
Data: make([]byte, 256),
}
rand.Read(d.Data)
h.Write(d.Data)
if err := db.Datas.Upsert(tx, &d); err != nil {
return err
}
}
crc := CRCItem{
ID: 1,
}
if !isErr {
crc.CRC32 = h.Sum32()
return db.CRCs.Upsert(tx, &crc)
}
crc.CRC32 = 1
if err := db.CRCs.Upsert(tx, &crc); err != nil {
return err
}
return errors.New("ERROR")
})
if isErr != (err != nil) {
panic(err)
}
}
func (db DataDB) ComputeCRC(tx *Snapshot) uint32 {
h := crc32.NewIEEE()
for dataID := uint64(1); dataID < 10; dataID++ {
d := db.Datas.ByID.Get(tx, &DataItem{ID: dataID})
if d == nil {
continue
}
h.Write(d.Data)
}
return h.Sum32()
}
func (db DataDB) ReadCRC(tx *Snapshot) uint32 {
r := db.CRCs.ByID.Get(tx, &CRCItem{ID: 1})
if r == nil {
return 0
}
return r.CRC32
}