Skip to content

Commit

Permalink
feat: removed ordered-map dep (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
glouvigny authored Jun 11, 2021
1 parent ccec004 commit 9b80112
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 137 deletions.
165 changes: 61 additions & 104 deletions entry/entry_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,49 @@ import (
"sync"

"berty.tech/go-ipfs-log/iface"
"github.com/iancoleman/orderedmap"
)

// OrderedMap is an ordered map of entries.
type OrderedMap struct {
lock sync.RWMutex
orderedMap *orderedmap.OrderedMap
lock sync.RWMutex
keys []string
values map[string]iface.IPFSLogEntry
copied bool
}

func (o *OrderedMap) Copy() iface.IPFSLogOrderedEntries {
o.lock.RLock()
defer o.lock.RUnlock()

return &OrderedMap{
keys: o.keys,
values: o.values,
copied: true,
}
}

func (o *OrderedMap) Reverse() iface.IPFSLogOrderedEntries {
e := o.Slice()
o.lock.RLock()
defer o.lock.RUnlock()

for i := len(e)/2 - 1; i >= 0; i-- {
opp := len(e) - 1 - i
e[i], e[opp] = e[opp], e[i]
keys := o.keys
for i := len(keys)/2 - 1; i >= 0; i-- {
opp := len(keys) - 1 - i
keys[i], keys[opp] = keys[opp], keys[i]
}

return NewOrderedMapFromEntries(e)
return &OrderedMap{
keys: o.keys,
values: o.values,
copied: true,
}
}

// NewOrderedMap creates a new OrderedMap of entries.
func NewOrderedMap() iface.IPFSLogOrderedEntries {
return &OrderedMap{
lock: sync.RWMutex{},
orderedMap: orderedmap.New(),
lock: sync.RWMutex{},
values: map[string]iface.IPFSLogEntry{},
}
}

Expand All @@ -49,28 +67,18 @@ func NewOrderedMapFromEntries(entries []iface.IPFSLogEntry) iface.IPFSLogOrdered

// Merge will fusion two OrderedMap of entries.
func (o *OrderedMap) Merge(other iface.IPFSLogOrderedEntries) iface.IPFSLogOrderedEntries {
newMap := o.Copy()

for _, k := range other.Keys() {
val, _ := other.Get(k)
newMap.Set(k, val)
}

return newMap
}

// Copy creates a copy of an OrderedMap.
func (o *OrderedMap) Copy() iface.IPFSLogOrderedEntries {
o.lock.RLock()
defer o.lock.RUnlock()

newMap := NewOrderedMap()

for _, k := range o.Keys() {
val, _ := o.Get(k)
newMap.Set(k, val)
}

for _, k := range other.Keys() {
val, _ := other.Get(k)
newMap.Set(k, val)
}

return newMap
}

Expand All @@ -79,17 +87,8 @@ func (o *OrderedMap) Get(key string) (iface.IPFSLogEntry, bool) {
o.lock.RLock()
defer o.lock.RUnlock()

val, exists := o.orderedMap.Get(key)
if !exists {
return nil, false
}

entry, ok := val.(iface.IPFSLogEntry)
if !ok {
return nil, false
}

return entry, true
val, exists := o.values[key]
return val, exists
}

// UnsafeGet retrieves an Entry using its key, returns nil if not found.
Expand All @@ -102,115 +101,73 @@ func (o *OrderedMap) UnsafeGet(key string) iface.IPFSLogEntry {
return val
}

func (o *OrderedMap) preWrite() {
if o.copied {
o.copied = false
values := map[string]iface.IPFSLogEntry{}
for k, v := range o.values {
values[k] = v
}

o.values = values
}
}

// Set defines an Entry in the map for a given key.
func (o *OrderedMap) Set(key string, value iface.IPFSLogEntry) {
o.lock.Lock()
defer o.lock.Unlock()

o.orderedMap.Set(key, value)
o.preWrite()

_, exists := o.values[key]
if !exists {
o.keys = append(o.keys, key)
}
o.values[key] = value
}

// Slice returns an ordered slice of the values existing in the map.
func (o *OrderedMap) Slice() []iface.IPFSLogEntry {
o.lock.RLock()
defer o.lock.RUnlock()

keys := o.orderedMap.Keys()
out := make([]iface.IPFSLogEntry, len(keys))
keysCount := len(o.keys)
out := make([]iface.IPFSLogEntry, keysCount)

for i, k := range keys {
for i, k := range o.keys {
out[i] = o.UnsafeGet(k)
}

return out
}

func (o *OrderedMap) First(until uint) iface.IPFSLogOrderedEntries {
o.lock.RLock()
defer o.lock.RUnlock()

keys := o.Keys()
entries := make([]iface.IPFSLogEntry, until)

for i := uint(0); i < until; i++ {
entries[i] = o.UnsafeGet(keys[i])
}

return NewOrderedMapFromEntries(entries)
}

func (o *OrderedMap) Last(after uint) iface.IPFSLogOrderedEntries {
o.lock.RLock()
defer o.lock.RUnlock()

keys := o.Keys()
entries := make([]iface.IPFSLogEntry, uint(len(keys))-after)
j := 0

for i := uint(len(keys)); i > after; i-- {
entries[j] = o.UnsafeGet(keys[i])
j++
}

return NewOrderedMapFromEntries(entries)
}

// Delete removes an Entry from the map for a given key.
func (o *OrderedMap) Delete(key string) {
o.lock.Lock()
defer o.lock.Unlock()

o.orderedMap.Delete(key)
}

// Keys retrieves the ordered list of keys in the map.
func (o *OrderedMap) Keys() []string {
o.lock.RLock()
defer o.lock.RUnlock()

return o.orderedMap.Keys()
}

// SortKeys orders the map keys using your sort func.
func (o *OrderedMap) SortKeys(sortFunc func(keys []string)) {
o.lock.Lock()
defer o.lock.Unlock()

o.orderedMap.SortKeys(sortFunc)
}

// Sort orders the map using your sort func.
func (o *OrderedMap) Sort(lessFunc func(a *orderedmap.Pair, b *orderedmap.Pair) bool) {
o.lock.Lock()
defer o.lock.Unlock()

o.orderedMap.Sort(lessFunc)
return o.keys
}

// Len gets the length of the map.
func (o *OrderedMap) Len() int {
o.lock.RLock()
defer o.lock.RUnlock()

return len(o.orderedMap.Keys())
return len(o.keys)
}

// At gets an item at the given index in the map, returns nil if not found.
func (o *OrderedMap) At(index uint) iface.IPFSLogEntry {
o.lock.RLock()
defer o.lock.RUnlock()

keys := o.Keys()

if keys == nil {
return nil
}

if uint(len(keys)) <= index {
if uint(len(o.keys)) <= index {
return nil
}

key := keys[index]
key := o.keys[index]

return o.UnsafeGet(key)
}
Expand Down
10 changes: 4 additions & 6 deletions entry/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"berty.tech/go-ipfs-log/iface"
"bytes"
"sort"

"github.com/iancoleman/orderedmap"
)

// Difference gets the list of values not present in both entries sets.
Expand Down Expand Up @@ -97,18 +95,18 @@ func FindHeads(entries iface.IPFSLogOrderedEntries) []iface.IPFSLogEntry {
}

var result []iface.IPFSLogEntry
items := orderedmap.New()
items := map[string]string{}

for _, k := range entries.Keys() {
e := entries.UnsafeGet(k)
for _, n := range e.GetNext() {
items.Set(n.String(), e.GetHash().String())
items[n.String()] = e.GetHash().String()
}
}

for _, h := range entries.Keys() {
e, ok := items.Get(h)
if ok || e != nil {
e, ok := items[h]
if ok || e != "" {
continue
}

Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.16
require (
github.com/btcsuite/btcd v0.21.0-beta
github.com/hashicorp/golang-lru v0.5.4
github.com/iancoleman/orderedmap v0.2.0
github.com/ipfs/go-cid v0.0.7
github.com/ipfs/go-datastore v0.4.5
github.com/ipfs/go-ipfs v0.8.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI=
Expand Down
12 changes: 3 additions & 9 deletions iface/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ type IPFSLog interface {
RawHeads() IPFSLogOrderedEntries
SetIdentity(identity *identityprovider.Identity)
IO() IO

Len() int
Get(c cid.Cid) (IPFSLogEntry, bool)
}

type EntrySortFn func(IPFSLogEntry, IPFSLogEntry) (int, error)
Expand All @@ -122,15 +125,6 @@ type IPFSLogOrderedEntries interface {
// Slice returns an ordered slice of the values existing in the map.
Slice() []IPFSLogEntry

// First
First(until uint) IPFSLogOrderedEntries

// Last
Last(after uint) IPFSLogOrderedEntries

// Delete removes an Entry from the map for a given key.
Delete(key string)

// Keys retrieves the ordered list of keys in the map.
Keys() []string

Expand Down
Loading

0 comments on commit 9b80112

Please sign in to comment.