83df0ee1b0
1. Added KeyValueStore.Iterate for implementing the different List, ListV2 etc. implementations. This allows for more efficient use of memory depending on the situation. 2. Implemented an inmemory teststore for running tests. This should allow to replace MockKeyValueStore in most places. 3. Rewrote tests 4. Pulled out logger from bolt implementation so it can be used for all other storage implementations. 5. Fixed multiple things in bolt and redis implementations.
97 lines
2.1 KiB
Go
97 lines
2.1 KiB
Go
// Copyright (C) 2018 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package storage
|
|
|
|
import (
|
|
"bytes"
|
|
"sort"
|
|
)
|
|
|
|
// IteratorFunc implements basic iterator
|
|
type IteratorFunc func(item *ListItem) bool
|
|
|
|
// Next returns the next item
|
|
func (next IteratorFunc) Next(item *ListItem) bool { return next(item) }
|
|
|
|
// SelectPrefixed keeps only items that have prefix
|
|
// items will be reused and modified
|
|
// TODO: remove this
|
|
func SelectPrefixed(items Items, prefix []byte) Items {
|
|
result := items[:0]
|
|
for _, item := range items {
|
|
if bytes.HasPrefix(item.Key, prefix) {
|
|
result = append(result, item)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// SortAndCollapse sorts items and combines elements based on Delimiter
|
|
// items will be reused and modified
|
|
// TODO: remove this
|
|
func SortAndCollapse(items Items, prefix []byte) Items {
|
|
sort.Sort(items)
|
|
result := items[:0]
|
|
|
|
var currentPrefix []byte
|
|
var prefixed bool
|
|
for _, item := range items {
|
|
if prefixed {
|
|
if bytes.HasPrefix(item.Key, currentPrefix) {
|
|
continue
|
|
}
|
|
prefixed = false
|
|
}
|
|
|
|
if p := bytes.IndexByte(item.Key[len(prefix):], Delimiter); p >= 0 {
|
|
currentPrefix = item.Key[:len(prefix)+p+1]
|
|
prefixed = true
|
|
result = append(result, ListItem{
|
|
Key: currentPrefix,
|
|
IsPrefix: true,
|
|
})
|
|
} else {
|
|
result = append(result, item)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ReverseItems reverses items in the list
|
|
// items will be reused and modified
|
|
// TODO: remove this
|
|
func ReverseItems(items Items) Items {
|
|
for i := len(items)/2 - 1; i >= 0; i-- {
|
|
k := len(items) - 1 - i
|
|
items[i], items[k] = items[k], items[i]
|
|
}
|
|
return items
|
|
}
|
|
|
|
// ReverseKeys reverses the list of keys
|
|
func ReverseKeys(keys Keys) Keys {
|
|
for i := len(keys)/2 - 1; i >= 0; i-- {
|
|
k := len(keys) - 1 - i
|
|
keys[i], keys[k] = keys[k], keys[i]
|
|
}
|
|
return keys
|
|
}
|
|
|
|
// StaticIterator implements an iterator over list of items
|
|
type StaticIterator struct {
|
|
Items Items
|
|
Index int
|
|
}
|
|
|
|
// Next returns the next item from the iterator
|
|
func (it *StaticIterator) Next(item *ListItem) bool {
|
|
if it.Index >= len(it.Items) {
|
|
return false
|
|
}
|
|
*item = it.Items[it.Index]
|
|
it.Index++
|
|
return true
|
|
}
|