Skip to content

Commit

Permalink
Merge pull request #846 from ApptiveGrid/BTree-DataPage-Recycle
Browse files Browse the repository at this point in the history
Implement recyclePage: for Btree Data pages
  • Loading branch information
noha authored Oct 22, 2024
2 parents dd43f13 + b8892d5 commit 754d899
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 35 deletions.
24 changes: 24 additions & 0 deletions src/Soil-Core-Tests/SoilBTreeTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,30 @@ SoilBTreeTest >> testRemoveKey [
self should: [ index removeKey: 20 ] raise: KeyNotFound.
]

{ #category : #tests }
SoilBTreeTest >> testRemovePage [

| capacityFirst offset capacity iterator |
capacityFirst := index firstPage itemCapacity.
1 to: capacityFirst do: [ :n |
index at: n put: (n asByteArrayOfSize: 8) ].
self assert: index pages size equals: 3.
offset := capacityFirst.
iterator := index newIterator.
2 to: 6 do: [ :p |
index at: offset + 1 put: ((offset + 1) asByteArrayOfSize: 8).
capacity := index lastPage itemCapacity.
offset + 2 to: (offset + capacity) do: [:n | .
index at: n put: (n asByteArrayOfSize: 8) ].
offset := offset + capacity ].
self assert: index pages size equals: 13.
index recyclePage: (index pages at: 3).
self assert: index pages size equals: 13.
"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 ]) ]

]

{ #category : #tests }
SoilBTreeTest >> testSize [

Expand Down
6 changes: 6 additions & 0 deletions src/Soil-Core/SoilBTreeHeaderPage.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ SoilBTreeHeaderPage >> decreaseSize [
needWrite := true
]

{ #category : #accessing }
SoilBTreeHeaderPage >> firstFreePageIndex [

^ firstFreePageIndex
]

{ #category : #accessing }
SoilBTreeHeaderPage >> firstFreePageIndex: anObject [

Expand Down
30 changes: 30 additions & 0 deletions src/Soil-Core/SoilBasicBTree.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ SoilBasicBTree >> pageClass [
^ SoilBTreeDataPage
]

{ #category : #removing }
SoilBasicBTree >> recyclePage: aPage [
"the header stays untouched even it it gets empty"
aPage isHeaderPage ifTrue: [ ^ aPage ].
"remove page from chain of item pages"
self removePage: aPage.
"add page to free list chain"
^ self addToFreePages: aPage
]

{ #category : #removing }
SoilBasicBTree >> removeKey: key ifAbsent: aBlock [
| removedItem |
Expand All @@ -127,6 +137,26 @@ SoilBasicBTree >> removeKey: key ifAbsent: aBlock [
^removedItem value
]

{ #category : #removing }
SoilBasicBTree >> removePage: aPage [
| iterator previousPage |
(aPage offset > 1) ifFalse: [ ^ aPage ].

"We use the iterator to find the previousPage, to change it's next pointer to my next"
iterator := self newIterator.
previousPage := iterator findPreviousPageOf: aPage.
previousPage next: aPage next.

"now remove all keys, this will update the index pages"

aPage items reverseDo: [ :item | item ifNotNil: [self removeKey: item key] ].

"finally remove the page from the store"
store removePageAt: aPage offset.
^ aPage

]

{ #category : #accessing }
SoilBasicBTree >> rootPage [
^ self store pageAt: 2
Expand Down
5 changes: 5 additions & 0 deletions src/Soil-Core/SoilFreePage.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ SoilFreePage >> isDirty [
^ needWrite
]

{ #category : #testing }
SoilFreePage >> isIndexPage [
^ false
]

{ #category : #accessing }
SoilFreePage >> label [
^ 'free page'
Expand Down
35 changes: 35 additions & 0 deletions src/Soil-Core/SoilIndex.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,32 @@ SoilIndex >> addDirtyPage: aPage [

]

{ #category : #adding }
SoilIndex >> addToFreePages: aPage [
| currentFreePage newFreePage |
newFreePage := aPage asSoilFreePage.
store pageAt: aPage offset put: newFreePage.
currentFreePage := self firstFreePage
ifNil: [
"if there is no first free page yet make aPage the
first free page"
self headerPage firstFreePageIndex: newFreePage offset.
^ newFreePage ].
"if there is a first free page start scanning from here for a
free page that has room to store another free page"
[ currentFreePage hasRoom ] whileFalse: [
"if there is no room for the page to store and the current
free page does not have a next pointer we make aPage the
next"
currentFreePage next isZero
ifTrue: [
currentFreePage next: newFreePage offset.
^ newFreePage ]
ifFalse: [ currentFreePage := store pageAt: currentFreePage next ]].
currentFreePage addPage: newFreePage.
^ newFreePage
]

{ #category : #private }
SoilIndex >> at: key [
^ self
Expand Down Expand Up @@ -91,6 +117,15 @@ SoilIndex >> first: anInteger [
^ self newIterator first: anInteger
]

{ #category : #accessing }
SoilIndex >> firstFreePage [
| index |
index := self headerPage firstFreePageIndex.
^ index isZero
ifTrue: [ ^ nil ]
ifFalse: [ store pageAt: index ]
]

{ #category : #accessing }
SoilIndex >> firstPage [
^ self headerPage
Expand Down
35 changes: 0 additions & 35 deletions src/Soil-Core/SoilSkipList.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,6 @@ SoilSkipList >> acceptSoil: aSoilVisitor [
^ aSoilVisitor visitSkipList: self
]

{ #category : #adding }
SoilSkipList >> addToFreePages: aPage [
| currentFreePage newFreePage |
newFreePage := aPage asSoilFreePage.
store pageAt: aPage offset put: newFreePage.
currentFreePage := self firstFreePage
ifNil: [
"if there is no first free page yet make aPage the
first free page"
self headerPage firstFreePageIndex: newFreePage offset.
^ newFreePage ].
"if there is a first free page start scanning from here for a
free page that has room to store another free page"
[ currentFreePage hasRoom ] whileFalse: [
"if there is no room for the page to store and the current
free page does not have a next pointer we make aPage the
next"
currentFreePage next isZero
ifTrue: [
currentFreePage next: newFreePage offset.
^ newFreePage ]
ifFalse: [ currentFreePage := store pageAt: currentFreePage next ]].
currentFreePage addPage: newFreePage.
^ newFreePage
]

{ #category : #'as yet unclassified' }
SoilSkipList >> allocatePage [
^ self newPage
Expand Down Expand Up @@ -72,15 +46,6 @@ SoilSkipList >> destroy [
path ensureDelete
]

{ #category : #accessing }
SoilSkipList >> firstFreePage [
| offset |
offset := self headerPage firstFreePageIndex.
^ offset isZero
ifTrue: [ ^ nil ]
ifFalse: [ store pageAt: offset ]
]

{ #category : #deleting }
SoilSkipList >> flush [
self store flush
Expand Down

0 comments on commit 754d899

Please sign in to comment.