rework indexing strategy to use an enum (#694)

This commit is contained in:
Dmitriy Ryajov 2024-02-07 13:13:27 -06:00 committed by GitHub
parent 2cf892c467
commit 2fc538337b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 71 additions and 67 deletions

View File

@ -130,10 +130,10 @@ proc prepareEncodingData(
##
let
strategy = SteppedIndexingStrategy.new(
strategy = SteppedStrategy.init(
firstIndex = 0,
lastIndex = params.rounded - 1,
numberOfIterations = params.steps
iterations = params.steps
)
indicies = toSeq(strategy.getIndicies(step))
pendingBlocksIter = self.getPendingBlocks(manifest, indicies.filterIt(it < manifest.blocksCount))
@ -179,10 +179,10 @@ proc prepareDecodingData(
##
let
strategy = SteppedIndexingStrategy.new(
strategy = SteppedStrategy.init(
firstIndex = 0,
lastIndex = encoded.blocksCount - 1,
numberOfIterations = encoded.steps
iterations = encoded.steps
)
indicies = toSeq(strategy.getIndicies(step))
pendingBlocksIter = self.getPendingBlocks(encoded, indicies)

View File

@ -1,5 +1,3 @@
import std/sequtils
import ./errors
import ./utils
import ./utils/asynciter
@ -7,6 +5,19 @@ import ./utils/asynciter
{.push raises: [].}
type
StrategyType* = enum
# Simplest approach:
# 0 => 0, 1, 2
# 1 => 3, 4, 5
# 2 => 6, 7, 8
LinearStrategy,
# Stepped indexing:
# 0 => 0, 3, 6
# 1 => 1, 4, 7
# 2 => 2, 5, 8
SteppedStrategy
# Representing a strategy for grouping indices (of blocks usually)
# Given an interation-count as input, will produce a seq of
# selected indices.
@ -15,57 +26,39 @@ type
IndexingWrongIndexError* = object of IndexingError
IndexingWrongIterationsError* = object of IndexingError
IndexingStrategy* = ref object of RootObj
IndexingStrategy* = object
strategyType*: StrategyType
firstIndex*: int # Lowest index that can be returned
lastIndex*: int # Highest index that can be returned
numberOfIterations*: int # getIndices(iteration) will run from 0 ..< numberOfIterations
iterations*: int # getIndices(iteration) will run from 0 ..< iterations
step*: int
# Simplest approach:
# 0 => 0, 1, 2
# 1 => 3, 4, 5
# 2 => 6, 7, 8
LinearIndexingStrategy* = ref object of IndexingStrategy
# Stepped indexing:
# 0 => 0, 3, 6
# 1 => 1, 4, 7
# 2 => 2, 5, 8
SteppedIndexingStrategy* = ref object of IndexingStrategy
proc checkIteration(
self: IndexingStrategy,
iteration: int): void {.raises: [IndexingError].} =
if iteration >= self.numberOfIterations:
func checkIteration(self: IndexingStrategy, iteration: int): void {.raises: [IndexingError].} =
if iteration >= self.iterations:
raise newException(
IndexingError,
"Indexing iteration can't be greater than or equal to numberOfIterations.")
method getIndicies*(
self: IndexingStrategy,
iteration: int): Iter[int] {.base, raises: [IndexingError].} =
raiseAssert("Not implemented")
"Indexing iteration can't be greater than or equal to iterations.")
proc getIter(first, last, step: int): Iter[int] =
var
finish = false
cur = first
proc get(): int =
func get(): int =
result = cur
cur += step
if cur > last:
finish = true
proc isFinished(): bool =
func isFinished(): bool =
finish
Iter.new(get, isFinished)
method getIndicies*(
self: LinearIndexingStrategy,
func getLinearIndicies(
self: IndexingStrategy,
iteration: int): Iter[int] {.raises: [IndexingError].} =
self.checkIteration(iteration)
let
@ -74,33 +67,44 @@ method getIndicies*(
getIter(first, last, 1)
method getIndicies*(
self: SteppedIndexingStrategy,
func getSteppedIndicies(
self: IndexingStrategy,
iteration: int): Iter[int] {.raises: [IndexingError].} =
self.checkIteration(iteration)
let
first = self.firstIndex + iteration
last = self.lastIndex
getIter(first, last, self.numberOfIterations)
getIter(first, last, self.iterations)
func getIndicies*(
self: IndexingStrategy,
iteration: int): Iter[int] {.raises: [IndexingError].} =
case self.strategyType
of StrategyType.LinearStrategy:
self.getLinearIndicies(iteration)
of StrategyType.SteppedStrategy:
self.getSteppedIndicies(iteration)
func init*(
strategy: StrategyType,
firstIndex, lastIndex, iterations: int): IndexingStrategy {.raises: [IndexingError].} =
proc new*(
T: type IndexingStrategy,
firstIndex, lastIndex, numberOfIterations: int): T {.raises: [IndexingError].} =
if firstIndex > lastIndex:
raise newException(
IndexingWrongIndexError,
"firstIndex (" & $firstIndex & ") can't be greater than lastIndex (" & $lastIndex & ")")
if numberOfIterations <= 0:
if iterations <= 0:
raise newException(
IndexingWrongIterationsError,
"numberOfIteration (" & $numberOfIterations & ") must be greater than zero.")
"iterations (" & $iterations & ") must be greater than zero.")
T(
IndexingStrategy(
strategyType: strategy,
firstIndex: firstIndex,
lastIndex: lastIndex,
numberOfIterations: numberOfIterations,
step: divUp((lastIndex - firstIndex), numberOfIterations))
iterations: iterations,
step: divUp((lastIndex - firstIndex), iterations))

View File

@ -341,7 +341,7 @@ proc new*(
let
strategy = if strategy.isNone:
? SteppedIndexingStrategy.new(
? SteppedStrategy.init(
0, manifest.blocksCount - 1, manifest.numSlots).catch
else:
strategy.get

View File

@ -4,9 +4,9 @@ import pkg/questionable
import pkg/chronos
type
Function*[T, U] = proc(fut: T): U {.raises: [CatchableError], gcsafe, closure.}
IsFinished* = proc(): bool {.raises: [], gcsafe, closure.}
GenNext*[T] = proc(): T {.raises: [CatchableError], gcsafe, closure.}
Function*[T, U] = proc(fut: T): U {.raises: [CatchableError], gcsafe, noSideEffect.}
IsFinished* = proc(): bool {.raises: [], gcsafe, noSideEffect.}
GenNext*[T] = proc(): T {.raises: [CatchableError], gcsafe.}
Iter*[T] = ref object
finished: bool
next*: GenNext[T]

View File

@ -83,7 +83,7 @@ proc createSlotTree(self: ProvingTestEnvironment, dSlotIndex: uint64): Future[Po
let
slotSize = (bytesPerBlock * numberOfSlotBlocks).uint64
blocksInSlot = slotSize div bytesPerBlock.uint64
datasetBlockIndexingStrategy = SteppedIndexingStrategy.new(0, self.datasetBlocks.len - 1, totalNumberOfSlots)
datasetBlockIndexingStrategy = SteppedStrategy.init(0, self.datasetBlocks.len - 1, totalNumberOfSlots)
datasetBlockIndices = toSeq(datasetBlockIndexingStrategy.getIndicies(dSlotIndex.int))
let

View File

@ -201,7 +201,7 @@ suite "Slot builder":
test "Should build slot hashes for all slots":
let
steppedStrategy = SteppedIndexingStrategy.new(0, numTotalBlocks - 1, numSlots)
steppedStrategy = SteppedStrategy.init(0, numTotalBlocks - 1, numSlots)
slotBuilder = SlotsBuilder.new(
localStore,
protectedManifest,
@ -224,7 +224,7 @@ suite "Slot builder":
test "Should build slot trees for all slots":
let
steppedStrategy = SteppedIndexingStrategy.new(0, numTotalBlocks - 1, numSlots)
steppedStrategy = SteppedStrategy.init(0, numTotalBlocks - 1, numSlots)
slotBuilder = SlotsBuilder.new(
localStore,
protectedManifest,
@ -272,7 +272,7 @@ suite "Slot builder":
test "Should build correct verification root":
let
steppedStrategy = SteppedIndexingStrategy.new(0, numTotalBlocks - 1, numSlots)
steppedStrategy = SteppedStrategy.init(0, numTotalBlocks - 1, numSlots)
slotBuilder = SlotsBuilder.new(
localStore,
protectedManifest,
@ -301,7 +301,7 @@ suite "Slot builder":
test "Should build correct verification root manifest":
let
steppedStrategy = SteppedIndexingStrategy.new(0, numTotalBlocks - 1, numSlots)
steppedStrategy = SteppedStrategy.init(0, numTotalBlocks - 1, numSlots)
slotBuilder = SlotsBuilder.new(
localStore,
protectedManifest,

View File

@ -14,8 +14,8 @@ for offset in @[0, 1, 2, 100]:
firstIndex = 0 + offset
lastIndex = 12 + offset
nIters = 3
linear = LinearIndexingStrategy.new(firstIndex, lastIndex, nIters)
stepped = SteppedIndexingStrategy.new(firstIndex, lastIndex, nIters)
linear = LinearStrategy.init(firstIndex, lastIndex, nIters)
stepped = SteppedStrategy.init(firstIndex, lastIndex, nIters)
test "linear":
check:
@ -31,32 +31,32 @@ for offset in @[0, 1, 2, 100]:
suite "Indexing strategies":
let
linear = LinearIndexingStrategy.new(0, 10, 3)
stepped = SteppedIndexingStrategy.new(0, 10, 3)
linear = LinearStrategy.init(0, 10, 3)
stepped = SteppedStrategy.init(0, 10, 3)
test "smallest range 0":
let
l = LinearIndexingStrategy.new(0, 0, 1)
s = SteppedIndexingStrategy.new(0, 0, 1)
l = LinearStrategy.init(0, 0, 1)
s = SteppedStrategy.init(0, 0, 1)
check:
toSeq(l.getIndicies(0)) == @[0]
toSeq(s.getIndicies(0)) == @[0]
test "smallest range 1":
let
l = LinearIndexingStrategy.new(0, 1, 1)
s = SteppedIndexingStrategy.new(0, 1, 1)
l = LinearStrategy.init(0, 1, 1)
s = SteppedStrategy.init(0, 1, 1)
check:
toSeq(l.getIndicies(0)) == @[0, 1]
toSeq(s.getIndicies(0)) == @[0, 1]
test "first index must be smaller than last index":
expect IndexingWrongIndexError:
discard LinearIndexingStrategy.new(10, 0, 1)
discard LinearStrategy.init(10, 0, 1)
test "numberOfIterations must be greater than zero":
test "iterations must be greater than zero":
expect IndexingWrongIterationsError:
discard LinearIndexingStrategy.new(0, 10, 0)
discard LinearStrategy.init(0, 10, 0)
test "linear - oob":
expect IndexingError: