Skip to content

Commit

Permalink
fix(store): handle nil end in cachekv/iterator (cosmos#12945)
Browse files Browse the repository at this point in the history
Closes: cosmos#12661

Adds support for nil end semantics to iterators in cachekv store, addressing [this workaround](https://github.com/osmosis-labs/osmosis/blob/4176b287d48338870bfda3029bfa20a6e45ac126/osmoutils/store_helper.go#L37-L41).

Note that this has the effect of sorting the dirty cache into the BTree cache store in the bounds `[startIndex, end-of-cache-space]`

---

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
  • Loading branch information
kocubinski authored and yihuang committed Jan 5, 2023
1 parent 52ed70c commit 2279a7c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes

* (store) [#13516](https://github.com/cosmos/cosmos-sdk/pull/13516) Fix state listener that was observing writes at wrong time.
* (store) [#12945](https://github.com/cosmos/cosmos-sdk/pull/12945) Fix nil end semantics in store/cachekv/iterator when iterating a dirty cache.

## v0.45.11 - 2022-11-09

Expand Down
21 changes: 14 additions & 7 deletions store/cachekv/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ const minSortSize = 1024
// Constructs a slice of dirty items, to use w/ memIterator.
func (store *Store) dirtyItems(start, end []byte) {
startStr, endStr := conv.UnsafeBytesToStr(start), conv.UnsafeBytesToStr(end)
if startStr > endStr {
if end != nil && startStr > endStr {
// Nothing to do here.
return
}
Expand All @@ -296,6 +296,7 @@ func (store *Store) dirtyItems(start, end []byte) {
// than just not having the cache.
if n < minSortSize {
for key := range store.unsortedCache {
// dbm.IsKeyInDomain is nil safe and returns true iff key is greater than start
if dbm.IsKeyInDomain(conv.UnsafeStrToBytes(key), start, end) {
cacheValue := store.cache[key]
unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value})
Expand All @@ -313,7 +314,7 @@ func (store *Store) dirtyItems(start, end []byte) {
}
sort.Strings(strL)

startIndex, endIndex := findStartEndIndex(strL, startStr, endStr)
startIndex, endIndex := findStartEndIndex(strL, startStr, endStr, end)

// Since we spent cycles to sort the values, we should process and remove a reasonable amount
// ensure start to end is at least minSortSize in size
Expand All @@ -337,18 +338,24 @@ func (store *Store) dirtyItems(start, end []byte) {
store.clearUnsortedCacheSubset(kvL, stateAlreadySorted)
}

func findStartEndIndex(strL []string, startStr, endStr string) (int, int) {
func findStartEndIndex(strL []string, startStr, endStr string, end []byte) (int, int) {
// Now find the values within the domain
// [start, end)
startIndex := findStartIndex(strL, startStr)
endIndex := findEndIndex(strL, endStr)
if startIndex < 0 {
startIndex = 0
}

if endIndex < 0 {
var endIndex int
if end == nil {
endIndex = len(strL) - 1
} else {
endIndex = findEndIndex(strL, endStr)
}
if startIndex < 0 {
startIndex = 0
if endIndex < 0 {
endIndex = len(strL) - 1
}

return startIndex, endIndex
}

Expand Down

0 comments on commit 2279a7c

Please sign in to comment.