Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BTree: implement dirty pages tracking, testRemovePagesSequential now green for Btree #847

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/Soil-Core-Tests/SoilBTreeTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ SoilBTreeTest >> testRemoveKey [
{ #category : #tests }
SoilBTreeTest >> testRemovePage [

| capacityFirst offset capacity iterator |
| capacityFirst offset capacity iterator counter |
capacityFirst := index firstPage itemCapacity.
1 to: capacityFirst do: [ :n |
index at: n put: (n asByteArrayOfSize: 8) ].
Expand All @@ -519,9 +519,18 @@ SoilBTreeTest >> testRemovePage [
self assert: index pages size equals: 13.
index recyclePage: (index pages at: 3).
self assert: index pages size equals: 13.
"page 3 is the recycled page"
self assert: index firstFreePage offset equals: 3.
"the page is a free page"
self assert: index firstFreePage class equals: SoilFreePage.
"after, index 3 should not be a value in any index page item"
index indexPages do: [ :indexPage | self assert: (indexPage items noneSatisfy: [ :item | item value == 3 ]) ]

index indexPages do: [ :indexPage | self assert: (indexPage items noneSatisfy: [ :item | item value == 3 ]) ].
"if we follow the next pointer, we find only the non-recyled data pages"
iterator := index newIterator.
counter := 0.
iterator pagesDo: [ :page | counter := counter + 1].
"13 - 1 indexPage - 1 recycled page"
self assert: counter equals: 11.
]

{ #category : #tests }
Expand Down
12 changes: 9 additions & 3 deletions src/Soil-Core-Tests/SoilIndexedDictionaryTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -694,20 +694,26 @@ SoilIndexedDictionaryTest >> testRemovePagesConcurrent [
{ #category : #tests }
SoilIndexedDictionaryTest >> testRemovePagesSequential [
| tx tx2 index indexManager |
(classToTest = SoilBTreeDictionary ) ifTrue: [ self skip ].

tx := soil newTransaction.
tx root: dict.
1 to: 1000 do: [ :n | dict at: n put: n asString ].

tx commit.

"open a second transaction ..."
tx2 := soil newTransaction.
300 to: 700 do: [ :n | tx2 root removeKey: n ].
"we remove all keys from one page to make it empty"
(classToTest = SoilBTreeDictionary)
ifTrue: [339 to: 451 do: [ :n | tx2 root removeKey: n ]]
ifFalse: [ 300 to: 700 do: [ :n | tx2 root removeKey: n ]].

tx2 commit.
indexManager := soil objectRepository firstSegment indexManager.
index := indexManager indexes anyOne.
self assert: index dirtyPages size equals: 0.
self assert: indexManager dirtyIndexes size equals: 0.
self assert: (index pages select: #needsWrite) size equals: 1
self assert: (index pages select: #needsWrite) size equals: ( (classToTest = SoilBTreeDictionary) ifTrue: [2] ifFalse: [1])


]
Expand Down
13 changes: 12 additions & 1 deletion src/Soil-Core-Tests/SoilSkipListTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ SoilSkipListTest >> testRemoveKey [
{ #category : #tests }
SoilSkipListTest >> testRemovePage [

| capacityFirst offset capacity iterator |
| capacityFirst offset capacity iterator counter |
capacityFirst := index firstPage itemCapacity.
1 to: capacityFirst do: [ :n |
index at: n put: (n asByteArrayOfSize: 8) ].
Expand All @@ -484,6 +484,17 @@ SoilSkipListTest >> testRemovePage [
self assert: index pages size equals: 6.
index recyclePage: (index pages at: 3).
self assert: index pages size equals: 6.

"page 3 is the recycled page"
self assert: index firstFreePage offset equals: 3.
"and it is a FreePage"
self assert: index firstFreePage class equals: SoilFreePage.
"if we follow the next pointer, we find only the non-recyled data pages"
iterator := index newIterator.
counter := 0.
iterator pagesDo: [ :page | counter := counter + 1].
"6 minus 1 recycled page"
self assert: counter equals: 5



Expand Down
5 changes: 0 additions & 5 deletions src/Soil-Core/SoilBTree.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ SoilBTree >> destroy [
path ensureDelete
]

{ #category : #accessing }
SoilBTree >> dirtyPages [
^ #()
]

{ #category : #testing }
SoilBTree >> isRegistered [
^ path notNil
Expand Down
2 changes: 1 addition & 1 deletion src/Soil-Core/SoilBTreeIterator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ SoilBTreeIterator >> basicAt: indexKey put: anObject [
possiblePriorValue returnValue ifNil: [
"only increase size if there was no prior value"
index increaseSize].

index addDirtyPage: currentPage.
^ possiblePriorValue returnValue
]

Expand Down
32 changes: 28 additions & 4 deletions src/Soil-Core/SoilBasicBTree.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ See SoilBTree for more information
Class {
#name : #SoilBasicBTree,
#superclass : #SoilIndex,
#instVars : [
'dirtyPages'
],
#category : #'Soil-Core-Index-BTree'
}

Expand All @@ -17,6 +20,11 @@ SoilBasicBTree class >> isAbstract [
^ self == SoilBasicBTree
]

{ #category : #adding }
SoilBasicBTree >> addDirtyPage: aPage [
dirtyPages add: aPage
]

{ #category : #converting }
SoilBasicBTree >> asCopyOnWrite [
^ SoilCopyOnWriteBTree new
Expand All @@ -29,6 +37,11 @@ SoilBasicBTree >> dataPages [
^ (self pages reject: [ :page | page isIndexPage ]) asArray
]

{ #category : #accessing }
SoilBasicBTree >> dirtyPages [
^ dirtyPages
]

{ #category : #accessing }
SoilBasicBTree >> flush [
self store flush
Expand All @@ -44,6 +57,12 @@ SoilBasicBTree >> indexPages [
^ (self pages select: [ :page | page isIndexPage ]) asArray
]

{ #category : #initialization }
SoilBasicBTree >> initialize [
super initialize.
dirtyPages := Set new
]

{ #category : #initialization }
SoilBasicBTree >> initializeFilesystem [
self store initializeFilesystem
Expand Down Expand Up @@ -129,12 +148,17 @@ SoilBasicBTree >> recyclePage: aPage [
^ self addToFreePages: aPage
]

{ #category : #removing }
SoilBasicBTree >> removeDirtyPage: aPage [
dirtyPages remove: aPage
]

{ #category : #removing }
SoilBasicBTree >> removeKey: key ifAbsent: aBlock [
| removedItem |
removedItem := self rootPage remove: key for: self.
removedItem ifNil: [aBlock value].
^removedItem value

^ (self rootPage remove: key for: self)
ifNil: [ aBlock value ]
ifNotNil: [ :removedItem | removedItem value ]
]

{ #category : #removing }
Expand Down
4 changes: 4 additions & 0 deletions src/Soil-Core/SoilCopyOnWriteBTree.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Class {
#category : #'Soil-Core-Index-BTree'
}

{ #category : #adding }
SoilCopyOnWriteBTree >> addDirtyPage: aPage [
]

{ #category : #'as yet unclassified' }
SoilCopyOnWriteBTree >> allocatePage [
^ self newPage
Expand Down
Loading