Skip to content

Commit e7aa877

Browse files
committed
implementing Low level LockTable Test
1 parent 9657cba commit e7aa877

File tree

5 files changed

+204
-15
lines changed

5 files changed

+204
-15
lines changed

src/main/kotlin/simpledb/record/rowlock/RecordPage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ class RecordPage(private val tx: TransactionImpl, private val blk: BlockId, priv
8787
while (isValidSlot(slot)) {
8888
tx.rLatchPage(blk)
8989
try {
90+
tx.lockShared(blk, slot)
9091
if (tx.getInt(blk, offset(slot)) == used) {
91-
tx.lockShared(blk, slot)
9292
return slot
9393
}
9494
} finally {

src/main/kotlin/simpledb/tx/concurrency/rowlock/ConcurrencyMgr.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class ConcurrencyMgr {
1313
else blockLatch.wUnlatch(blk)
1414
}
1515
locks.clear()
16-
lockTblRowLock.unlock(tx, tx.sharedLockIRIDs + tx.exclusiveLockRIDs)
16+
lockTblRowLock.unlock(tx, tx.sharedLockRIDs + tx.exclusiveLockRIDs)
1717
}
1818

1919
fun rLatchPage(blk: BlockId) {

src/main/kotlin/simpledb/tx/concurrency/rowlock/LockTable.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,28 @@ import java.util.concurrent.locks.ReentrantLock
66

77
class LockTable {
88
private val lock = ReentrantLock()
9-
private val exclusiveLockTable: MutableMap<RID, Int> = HashMap()
10-
private val sharedLockTable: MutableMap<RID, MutableList<Int>> = HashMap()
9+
private val mutExclusiveLockTable: MutableMap<RID, Int> = HashMap()
10+
private val mutSharedLockTable: MutableMap<RID, MutableList<Int>> = HashMap()
11+
12+
val exclusiveLockTable: Map<RID, Int>
13+
get() = mutExclusiveLockTable.toMap()
14+
15+
val sharedLockTable: Map<RID, List<Int>>
16+
get() = mutSharedLockTable.toMap()
17+
1118
fun lockShared(tx: TransactionImpl, rid: RID): Boolean {
1219
lock.lock()
1320
try {
14-
val txNum = exclusiveLockTable[rid]
21+
val txNum = mutExclusiveLockTable[rid]
1522
if (txNum != null) {
1623
return txNum == tx.txNum
1724
}
18-
val txList = sharedLockTable.getOrDefault(rid, mutableListOf())
25+
val txList = mutSharedLockTable.getOrDefault(rid, mutableListOf())
1926
if (txList.contains(tx.txNum)) {
2027
return true
2128
}
2229
txList.add(tx.txNum)
23-
sharedLockTable[rid] = txList
30+
mutSharedLockTable[rid] = txList
2431
tx.addSharedLockRID(rid)
2532
return true
2633
} finally {
@@ -31,18 +38,18 @@ class LockTable {
3138
fun lockExclusive(tx: TransactionImpl, rid: RID): Boolean {
3239
lock.lock()
3340
try {
34-
val txNum = exclusiveLockTable[rid]
41+
val txNum = mutExclusiveLockTable[rid]
3542
if (txNum != null) {
3643
return txNum == tx.txNum
3744
}
38-
val txList = sharedLockTable[rid]
39-
if (txList != null) {
45+
val txList = mutSharedLockTable[rid]
46+
if (txList != null && txList.size > 0) {
4047
if (!(txList.size == 1 && txList.first() == tx.txNum)) {
4148
return false
4249
}
4350
}
4451

45-
exclusiveLockTable[rid] = tx.txNum
52+
mutExclusiveLockTable[rid] = tx.txNum
4653
tx.addExclusiveLockRID(rid)
4754
return true
4855
} finally {
@@ -54,10 +61,10 @@ class LockTable {
5461
lock.lock()
5562
try {
5663
ridList.forEach {
57-
if (exclusiveLockTable[it] == tx.txNum) {
58-
exclusiveLockTable.remove(it)
64+
if (mutExclusiveLockTable[it] == tx.txNum) {
65+
mutExclusiveLockTable.remove(it)
5966
}
60-
sharedLockTable[it]?.remove(tx.txNum)
67+
mutSharedLockTable[it]?.remove(tx.txNum)
6168
}
6269
} finally {
6370
lock.unlock()

src/main/kotlin/simpledb/tx/rowlock/TransactionImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class TransactionImpl(private val fm: FileMgr, lm: LogMgr?, private val bm: Buff
1818
private val mutSharedLockRIDs = mutableListOf<RID>()
1919
private val mutExclusiveLockRIDs = mutableListOf<RID>()
2020

21-
val sharedLockIRIDs : List<RID>
21+
val sharedLockRIDs : List<RID>
2222
get() = mutSharedLockRIDs.toList()
2323
val exclusiveLockRIDs : List<RID>
2424
get() = mutExclusiveLockRIDs.toList()
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package simpledb.tx.concurrency.rowlock
2+
3+
import org.hamcrest.MatcherAssert.assertThat
4+
import org.hamcrest.Matchers.contains
5+
import org.hamcrest.Matchers.hasItem
6+
import org.hamcrest.Matchers.hasKey
7+
import org.hamcrest.Matchers.hasSize
8+
import org.hamcrest.Matchers.`is`
9+
import org.hamcrest.Matchers.not
10+
import org.junit.jupiter.api.Test
11+
import simpledb.record.RID
12+
import simpledb.server.SimpleDB
13+
import simpledb.tx.rowlock.TransactionImpl
14+
15+
class LockTableTest {
16+
private val db = SimpleDB("dbdir/lockTableTest", 400, 8)
17+
18+
@Test
19+
fun lockSharedSucceed() {
20+
val lockTable = LockTable()
21+
val rid = RID(0, 0)
22+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
23+
24+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
25+
assertThat(tx.sharedLockRIDs, hasSize(1))
26+
assertThat(tx.sharedLockRIDs.first(), `is`(rid))
27+
assertThat(lockTable.sharedLockTable, hasKey(rid))
28+
assertThat(lockTable.sharedLockTable[rid], contains(tx.txNum))
29+
}
30+
31+
@Test
32+
fun lockSharedSucceedTwice() {
33+
val lockTable = LockTable()
34+
val rid = RID(0, 0)
35+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
36+
37+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
38+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
39+
assertThat(tx.sharedLockRIDs, hasSize(1))
40+
assertThat(tx.sharedLockRIDs.first(), `is`(rid))
41+
assertThat(lockTable.sharedLockTable, hasKey(rid))
42+
assertThat(lockTable.sharedLockTable[rid], contains(tx.txNum))
43+
}
44+
45+
@Test
46+
fun lockSharedSucceedWhenSLockAcquiredByOtherTx() {
47+
val lockTable = LockTable()
48+
val rid = RID(0, 0)
49+
50+
val otherTx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
51+
lockTable.lockShared(otherTx, rid)
52+
53+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
54+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
55+
assertThat(tx.sharedLockRIDs, hasSize(1))
56+
assertThat(tx.sharedLockRIDs.first(), `is`(rid))
57+
assertThat(lockTable.sharedLockTable, hasKey(rid))
58+
assertThat(lockTable.sharedLockTable[rid], hasItem(tx.txNum))
59+
}
60+
61+
@Test
62+
fun lockExclusiveSucceed() {
63+
val lockTable = LockTable()
64+
val rid = RID(0, 0)
65+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
66+
67+
assertThat(lockTable.lockExclusive(tx, rid), `is`(true))
68+
assertThat(tx.exclusiveLockRIDs, hasSize(1))
69+
assertThat(tx.exclusiveLockRIDs.first(), `is`(rid))
70+
assertThat(lockTable.exclusiveLockTable, hasKey(rid))
71+
assertThat(lockTable.exclusiveLockTable[rid], `is`(tx.txNum))
72+
}
73+
74+
@Test
75+
fun lockExclusiveSucceedTwice() {
76+
val lockTable = LockTable()
77+
val rid = RID(0, 0)
78+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
79+
lockTable.lockExclusive(tx, rid)
80+
81+
assertThat(lockTable.lockExclusive(tx, rid), `is`(true))
82+
assertThat(tx.exclusiveLockRIDs, hasSize(1))
83+
assertThat(tx.exclusiveLockRIDs.first(), `is`(rid))
84+
assertThat(lockTable.exclusiveLockTable, hasKey(rid))
85+
assertThat(lockTable.exclusiveLockTable[rid], `is`(tx.txNum))
86+
}
87+
88+
@Test
89+
fun lockSharedSucceedButRidNotAppendedWhenXLockAcquired() {
90+
val lockTable = LockTable()
91+
val rid = RID(0, 0)
92+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
93+
lockTable.lockExclusive(tx, rid)
94+
95+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
96+
assertThat(tx.sharedLockRIDs, hasSize(0))
97+
assertThat(lockTable.sharedLockTable, not(hasKey(rid)))
98+
}
99+
100+
@Test
101+
fun lockExclusiveSucceedWhenSLockAcquired() {
102+
val lockTable = LockTable()
103+
val rid = RID(0, 0)
104+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
105+
lockTable.lockShared(tx, rid)
106+
107+
assertThat(lockTable.lockExclusive(tx, rid), `is`(true))
108+
assertThat(tx.exclusiveLockRIDs, hasSize(1))
109+
assertThat(tx.exclusiveLockRIDs.first(), `is`(rid))
110+
assertThat(lockTable.exclusiveLockTable, hasKey(rid))
111+
assertThat(lockTable.exclusiveLockTable[rid], `is`(tx.txNum))
112+
}
113+
114+
@Test
115+
fun lockSharedFailWhenXLockAcquiredByOtherTx() {
116+
val lockTable = LockTable()
117+
val rid = RID(0, 0)
118+
119+
val otherTx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
120+
lockTable.lockExclusive(otherTx, rid)
121+
122+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
123+
assertThat(lockTable.lockShared(tx, rid), `is`(false))
124+
}
125+
126+
@Test
127+
fun lockExclusiveFailWhenSLockAcquiredByOtherTx() {
128+
val lockTable = LockTable()
129+
val rid = RID(0, 0)
130+
131+
val otherTx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
132+
lockTable.lockShared(otherTx, rid)
133+
134+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
135+
assertThat(lockTable.lockExclusive(tx, rid), `is`(false))
136+
}
137+
138+
@Test
139+
fun unlock() {
140+
val lockTable = LockTable()
141+
val rid = RID(0, 0)
142+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
143+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
144+
145+
lockTable.unlock(tx, listOf(rid))
146+
assertThat(lockTable.sharedLockTable[rid], not(hasItem(tx.txNum)))
147+
}
148+
149+
@Test
150+
fun lockExclusiveSucceedWhenSLockAcquiredAndUnlockByOtherTx() {
151+
val lockTable = LockTable()
152+
val rid = RID(0, 0)
153+
154+
val otherTx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
155+
lockTable.lockShared(otherTx, rid)
156+
lockTable.unlock(otherTx, listOf(rid))
157+
158+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
159+
assertThat(lockTable.lockExclusive(tx, rid), `is`(true))
160+
assertThat(tx.exclusiveLockRIDs, hasSize(1))
161+
assertThat(tx.exclusiveLockRIDs.first(), `is`(rid))
162+
assertThat(lockTable.exclusiveLockTable, hasKey(rid))
163+
assertThat(lockTable.exclusiveLockTable[rid], `is`(tx.txNum))
164+
}
165+
166+
@Test
167+
fun lockSharedSucceedWhenXLockAcquiredAndUnlockByOtherTx() {
168+
val lockTable = LockTable()
169+
val rid = RID(0, 0)
170+
171+
val otherTx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
172+
lockTable.lockExclusive(otherTx, rid)
173+
lockTable.unlock(otherTx, listOf(rid))
174+
175+
val tx = TransactionImpl(db.fileMgr(), db.logMgr(), db.bufferMgr())
176+
assertThat(lockTable.lockShared(tx, rid), `is`(true))
177+
assertThat(tx.sharedLockRIDs, hasSize(1))
178+
assertThat(tx.sharedLockRIDs.first(), `is`(rid))
179+
assertThat(lockTable.sharedLockTable, hasKey(rid))
180+
assertThat(lockTable.sharedLockTable[rid], hasItem(tx.txNum))
181+
}
182+
}

0 commit comments

Comments
 (0)