Skip to content

Commit

Permalink
Lab 4 Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Valerie Kwek authored and Valerie Kwek committed Dec 4, 2024
1 parent 901dae8 commit 8353d30
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 120 deletions.
84 changes: 84 additions & 0 deletions godb/evaluation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package godb

import (
"sync"
"testing"
)

func evalTransactions(t *testing.T, threads int) {
bp, hf, _, _, _, _ := transactionTestSetUpVarLen(t, 1, 1)

var startWg, readyWg sync.WaitGroup
startChan := make(chan struct{})

incrementer := func(thrId int) {
// Signal that this goroutine is ready
readyWg.Done()

// Wait for the signal to start
<-startChan

for tid := TransactionID(0); ; {
tid = NewTID()
bp.BeginTransaction(tid)

iter1, _ := hf.Iterator(tid)
readTup, _ := iter1()

var writeTup = Tuple{
Desc: readTup.Desc,
Fields: []DBValue{
readTup.Fields[0],
IntField{readTup.Fields[1].(IntField).Value + 1},
}}

dop := NewDeleteOp(hf, hf)
iterDel, _ := dop.Iterator(tid)
iterDel()

iop := NewInsertOp(hf, &Singleton{writeTup, false})
iterIns, _ := iop.Iterator(tid)
iterIns()

bp.CommitTransaction(tid)
break // Exit on success
}
startWg.Done()
}

// Prepare goroutines
readyWg.Add(threads)
startWg.Add(threads)
for i := 0; i < threads; i++ {
go incrementer(i)
}

// Wait for all goroutines to be ready
readyWg.Wait()

// Start all goroutines at once
close(startChan)

// Wait for all goroutines to finish
startWg.Wait()
}

func TestTransaction10000(t *testing.T) {
evalTransactions(t, 10000)
}

func TestTransaction15000(t *testing.T) {
evalTransactions(t, 15000)
}

func TestTransaction20000(t *testing.T) {
evalTransactions(t, 20000)
}

func TestTransaction25000(t *testing.T) {
evalTransactions(t, 25000)
}

func TestTransaction30000(t *testing.T) {
evalTransactions(t, 30000)
}
Binary file modified godb/test.dat
Binary file not shown.
120 changes: 0 additions & 120 deletions godb/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,126 +370,6 @@ func TestTransactionFiveThreads(t *testing.T) {
validateTransactions(t, 5)
}

func evalTransactions(t *testing.T, threads int) {
bp, hf, _, _, _, _ := transactionTestSetUpVarLen(t, 1, 1)

var startWg, readyWg sync.WaitGroup
startChan := make(chan struct{})

// sleep for an increasingly long time after deadlocks. this backoff helps avoid starvation
nDeadlocks := 0
var nDeadlocksMutex sync.Mutex
sleepAfterDeadlock := func(thrId int, err error) {
nDeadlocksMutex.Lock()
nDeadlocks++
t.Logf("thread %d operation failed: %v deadlock #%v", thrId, err, nDeadlocks)
sleepTime := time.Duration(rand.Intn(int(nDeadlocks) + 1))
nDeadlocksMutex.Unlock()
time.Sleep(sleepTime * time.Millisecond)
}

incrementer := func(thrId int) {
// Signal that this goroutine is ready
readyWg.Done()

// Wait for the signal to start
<-startChan

for tid := TransactionID(0); ; bp.AbortTransaction(tid) {
tid = NewTID()
bp.BeginTransaction(tid)
iter1, err := hf.Iterator(tid)
if err != nil {
continue
}

readTup, err := iter1()
if err != nil {
sleepAfterDeadlock(thrId, err)
continue
}

var writeTup = Tuple{
Desc: readTup.Desc,
Fields: []DBValue{
readTup.Fields[0],
IntField{readTup.Fields[1].(IntField).Value + 1},
}}

dop := NewDeleteOp(hf, hf)
iterDel, err := dop.Iterator(tid)
if err != nil {
continue
}
delCnt, err := iterDel()
if err != nil {
sleepAfterDeadlock(thrId, err)
continue
}
if delCnt.Fields[0].(IntField).Value != 1 {
t.Errorf("Delete Op should return 1")
}
iop := NewInsertOp(hf, &Singleton{writeTup, false})
iterIns, err := iop.Iterator(tid)
if err != nil {
continue
}
insCnt, err := iterIns()
if err != nil {
sleepAfterDeadlock(thrId, err)
continue
}

if insCnt.Fields[0].(IntField).Value != 1 {
t.Errorf("Insert Op should return 1")
}

bp.CommitTransaction(tid)
break //exit on success, so we don't do terminal abort
}
startWg.Done()
}

// Prepare goroutines
readyWg.Add(threads)
startWg.Add(threads)
for i := 0; i < threads; i++ {
go incrementer(i)
}

// Wait for all goroutines to be ready
readyWg.Wait()

// Start all goroutines at once
close(startChan)

// Wait for all goroutines to finish
startWg.Wait()
}

// Results:
// OCC - 10000: 1.321s, 15000: 2.825s, 20000: 4.685s, 25000: 7.616s, 30000: 11.300s
// 2PL - 10000: 5.695s, 15000: 7.823s, 20000: 15.074s, 25000: 17.451s, 30000: 26.546s
func TestTransaction10000(t *testing.T) {
evalTransactions(t, 10000)
}

func TestTransaction15000(t *testing.T) {
evalTransactions(t, 15000)
}

func TestTransaction20000(t *testing.T) {
evalTransactions(t, 20000)
}

func TestTransaction25000(t *testing.T) {
evalTransactions(t, 25000)
}

func TestTransaction30000(t *testing.T) {
evalTransactions(t, 30000)
}

func TestTransactionAllDirtyFails(t *testing.T) {
if os.Getenv("LAB") == "5" {
t.Skip("Test is valid up through Lab 4. Skipping.")
Expand Down
8 changes: 8 additions & 0 deletions godb/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,11 @@ func TestValidateReadRead(t *testing.T) {
t.Errorf("Commit 1: %t, Commit 2: %t", correctCommit1, correctCommit2)
}
}

/**
* Stress testing for 8 threads
*/

func TestTransactionEightThreads(t *testing.T) {
validateTransactions(t, 8)
}

0 comments on commit 8353d30

Please sign in to comment.