Skip to content

Commit b135bef

Browse files
authored
sort using slices.Sort (#243)
- Update sorting to use `slices.Sort` for improved efficiency. - Add `Key.Compare` to compare datastore keys when sorting. - Add `query.Compare` function to compare Entry values according to orders. - Remove unnecessary slice copy when reversing key. - Additional updates for code conventions.
1 parent ac3ba45 commit b135bef

File tree

10 files changed

+104
-69
lines changed

10 files changed

+104
-69
lines changed

autobatch/autobatch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (d *Datastore) Flush(ctx context.Context) error {
117117
}
118118
}
119119
// clear out buffer
120-
d.buffer = make(map[ds.Key]op, d.maxBufferEntries)
120+
clear(d.buffer)
121121

122122
return b.Commit(ctx)
123123
}

basic_ds.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func NewMapDatastore() (d *MapDatastore) {
2727
}
2828

2929
// Put implements Datastore.Put
30-
func (d *MapDatastore) Put(ctx context.Context, key Key, value []byte) (err error) {
30+
func (d *MapDatastore) Put(ctx context.Context, key Key, value []byte) error {
3131
d.values[key] = value
3232
return nil
3333
}
@@ -38,7 +38,7 @@ func (d *MapDatastore) Sync(ctx context.Context, prefix Key) error {
3838
}
3939

4040
// Get implements Datastore.Get
41-
func (d *MapDatastore) Get(ctx context.Context, key Key) (value []byte, err error) {
41+
func (d *MapDatastore) Get(ctx context.Context, key Key) ([]byte, error) {
4242
val, found := d.values[key]
4343
if !found {
4444
return nil, ErrNotFound
@@ -47,21 +47,21 @@ func (d *MapDatastore) Get(ctx context.Context, key Key) (value []byte, err erro
4747
}
4848

4949
// Has implements Datastore.Has
50-
func (d *MapDatastore) Has(ctx context.Context, key Key) (exists bool, err error) {
50+
func (d *MapDatastore) Has(ctx context.Context, key Key) (bool, error) {
5151
_, found := d.values[key]
5252
return found, nil
5353
}
5454

5555
// GetSize implements Datastore.GetSize
56-
func (d *MapDatastore) GetSize(ctx context.Context, key Key) (size int, err error) {
56+
func (d *MapDatastore) GetSize(ctx context.Context, key Key) (int, error) {
5757
if v, found := d.values[key]; found {
5858
return len(v), nil
5959
}
6060
return -1, ErrNotFound
6161
}
6262

6363
// Delete implements Datastore.Delete
64-
func (d *MapDatastore) Delete(ctx context.Context, key Key) (err error) {
64+
func (d *MapDatastore) Delete(ctx context.Context, key Key) error {
6565
delete(d.values, key)
6666
return nil
6767
}
@@ -124,7 +124,7 @@ func (d *LogDatastore) Children() []Datastore {
124124
}
125125

126126
// Put implements Datastore.Put
127-
func (d *LogDatastore) Put(ctx context.Context, key Key, value []byte) (err error) {
127+
func (d *LogDatastore) Put(ctx context.Context, key Key, value []byte) error {
128128
log.Printf("%s: Put %s\n", d.Name, key)
129129
// log.Printf("%s: Put %s ```%s```", d.Name, key, value)
130130
return d.child.Put(ctx, key, value)
@@ -137,25 +137,25 @@ func (d *LogDatastore) Sync(ctx context.Context, prefix Key) error {
137137
}
138138

139139
// Get implements Datastore.Get
140-
func (d *LogDatastore) Get(ctx context.Context, key Key) (value []byte, err error) {
140+
func (d *LogDatastore) Get(ctx context.Context, key Key) ([]byte, error) {
141141
log.Printf("%s: Get %s\n", d.Name, key)
142142
return d.child.Get(ctx, key)
143143
}
144144

145145
// Has implements Datastore.Has
146-
func (d *LogDatastore) Has(ctx context.Context, key Key) (exists bool, err error) {
146+
func (d *LogDatastore) Has(ctx context.Context, key Key) (bool, error) {
147147
log.Printf("%s: Has %s\n", d.Name, key)
148148
return d.child.Has(ctx, key)
149149
}
150150

151151
// GetSize implements Datastore.GetSize
152-
func (d *LogDatastore) GetSize(ctx context.Context, key Key) (size int, err error) {
152+
func (d *LogDatastore) GetSize(ctx context.Context, key Key) (int, error) {
153153
log.Printf("%s: GetSize %s\n", d.Name, key)
154154
return d.child.GetSize(ctx, key)
155155
}
156156

157157
// Delete implements Datastore.Delete
158-
func (d *LogDatastore) Delete(ctx context.Context, key Key) (err error) {
158+
func (d *LogDatastore) Delete(ctx context.Context, key Key) error {
159159
log.Printf("%s: Delete %s\n", d.Name, key)
160160
return d.child.Delete(ctx, key)
161161
}
@@ -203,20 +203,20 @@ func (d *LogDatastore) Batch(ctx context.Context) (Batch, error) {
203203
}
204204

205205
// Put implements Batch.Put
206-
func (d *LogBatch) Put(ctx context.Context, key Key, value []byte) (err error) {
206+
func (d *LogBatch) Put(ctx context.Context, key Key, value []byte) error {
207207
log.Printf("%s: BatchPut %s\n", d.Name, key)
208208
// log.Printf("%s: Put %s ```%s```", d.Name, key, value)
209209
return d.child.Put(ctx, key, value)
210210
}
211211

212212
// Delete implements Batch.Delete
213-
func (d *LogBatch) Delete(ctx context.Context, key Key) (err error) {
213+
func (d *LogBatch) Delete(ctx context.Context, key Key) error {
214214
log.Printf("%s: BatchDelete %s\n", d.Name, key)
215215
return d.child.Delete(ctx, key)
216216
}
217217

218218
// Commit implements Batch.Commit
219-
func (d *LogBatch) Commit(ctx context.Context) (err error) {
219+
func (d *LogBatch) Commit(ctx context.Context) error {
220220
log.Printf("%s: BatchCommit\n", d.Name)
221221
return d.child.Commit(ctx)
222222
}

datastore.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,13 @@ var ErrNotFound error = &dsError{error: errors.New("datastore: key not found"),
206206
// }
207207
func GetBackedHas(ctx context.Context, ds Read, key Key) (bool, error) {
208208
_, err := ds.Get(ctx, key)
209-
switch err {
210-
case nil:
211-
return true, nil
212-
case ErrNotFound:
213-
return false, nil
214-
default:
209+
if err != nil {
210+
if err == ErrNotFound {
211+
return false, nil
212+
}
215213
return false, err
216214
}
215+
return true, nil
217216
}
218217

219218
// GetBackedSize provides a default Datastore.GetSize implementation.
@@ -224,10 +223,10 @@ func GetBackedHas(ctx context.Context, ds Read, key Key) (bool, error) {
224223
// }
225224
func GetBackedSize(ctx context.Context, ds Read, key Key) (int, error) {
226225
value, err := ds.Get(ctx, key)
227-
if err == nil {
228-
return len(value), nil
226+
if err != nil {
227+
return -1, err
229228
}
230-
return -1, err
229+
return len(value), nil
231230
}
232231

233232
type Batch interface {

key.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package datastore
33
import (
44
"encoding/json"
55
"path"
6+
"slices"
67
"strings"
78

89
dsq "github.com/ipfs/go-datastore/query"
@@ -90,26 +91,37 @@ func (k Key) Equal(k2 Key) bool {
9091
return k.string == k2.string
9192
}
9293

93-
// Less checks whether this key is sorted lower than another.
94-
func (k Key) Less(k2 Key) bool {
94+
// Compare returns -1 if this key is sorted lower than another, 1 if this key
95+
// is sorted greater that another, and 0 if the two keys sort the same.
96+
func (k Key) Compare(k2 Key) int {
9597
list1 := k.List()
9698
list2 := k2.List()
99+
list2end := len(list2) - 1
97100
for i, c1 := range list1 {
98-
if len(list2) < (i + 1) {
99-
return false
101+
if list2end < i {
102+
return 1
100103
}
101-
102104
c2 := list2[i]
103105
if c1 < c2 {
104-
return true
105-
} else if c1 > c2 {
106-
return false
106+
return -1
107+
}
108+
if c1 > c2 {
109+
return 1
107110
}
108111
// c1 == c2, continue
109112
}
110113

111-
// list1 is shorter or exactly the same.
112-
return len(list1) < len(list2)
114+
// if list1 is shorter.
115+
if len(list1) < len(list2) {
116+
return -1
117+
}
118+
// Lists are the same.
119+
return 0
120+
}
121+
122+
// Less checks whether this key is sorted lower than another.
123+
func (k Key) Less(k2 Key) bool {
124+
return k.Compare(k2) == -1
113125
}
114126

115127
// List returns the `list` representation of this Key.
@@ -126,11 +138,8 @@ func (k Key) List() []string {
126138
// NewKey("/Actor:JohnCleese/MontyPython/Comedy")
127139
func (k Key) Reverse() Key {
128140
l := k.List()
129-
r := make([]string, len(l))
130-
for i, e := range l {
131-
r[len(l)-i-1] = e
132-
}
133-
return KeyWithNamespaces(r)
141+
slices.Reverse(l)
142+
return KeyWithNamespaces(l)
134143
}
135144

136145
// Namespaces returns the `namespaces` making up this Key.

keytransform/keytransform.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,12 @@ orders:
130130
continue
131131
case dsq.OrderByKey, *dsq.OrderByKey,
132132
dsq.OrderByKeyDescending, *dsq.OrderByKeyDescending:
133-
// if the key transform preserves order, we can delegate
134-
// to the child datastore.
133+
// if the key transform preserves order, we can delegate to the
134+
// child datastore.
135135
if orderPreserving {
136-
// When sorting, we compare with the first
137-
// Order, then, if equal, we compare with the
138-
// second Order, etc. However, keys are _unique_
139-
// so we'll never apply any additional orders
136+
// When sorting, we compare with the first Order, then, if
137+
// equal, we compare with the second Order, etc. However, keys
138+
// are _unique_ so we'll never apply any additional orders
140139
// after ordering by key.
141140
child.Orders = child.Orders[:i+1]
142141
break orders

keytransform/keytransform_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package keytransform_test
22

33
import (
44
"context"
5-
"sort"
5+
"slices"
66
"testing"
77

88
ds "github.com/ipfs/go-datastore"
@@ -71,8 +71,12 @@ func TestBasic(t *testing.T) {
7171
require.Equal(t, len(listA), len(listB))
7272

7373
// sort them cause yeah.
74-
sort.Sort(ds.KeySlice(listA))
75-
sort.Sort(ds.KeySlice(listB))
74+
slices.SortFunc(listA, func(a, b ds.Key) int {
75+
return a.Compare(b)
76+
})
77+
slices.SortFunc(listB, func(a, b ds.Key) int {
78+
return a.Compare(b)
79+
})
7680

7781
for i, kA := range listA {
7882
kB := listB[i]

mount/mount.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"context"
88
"errors"
99
"fmt"
10-
"sort"
10+
"slices"
1111
"strings"
1212
"sync"
1313

@@ -33,9 +33,10 @@ type Mount struct {
3333
// to least specific.
3434
func New(mounts []Mount) *Datastore {
3535
// make a copy so we're sure it doesn't mutate
36-
m := make([]Mount, len(mounts))
37-
copy(m, mounts)
38-
sort.Slice(m, func(i, j int) bool { return m[i].Prefix.String() > m[j].Prefix.String() })
36+
m := slices.Clone(mounts)
37+
slices.SortFunc(m, func(a, b Mount) int {
38+
return strings.Compare(b.Prefix.String(), a.Prefix.String())
39+
})
3940
return &Datastore{mounts: m}
4041
}
4142

namespace/namespace_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ package namespace_test
22

33
import (
44
"context"
5-
"sort"
5+
"slices"
6+
"strings"
67
"testing"
78

89
ds "github.com/ipfs/go-datastore"
@@ -62,8 +63,12 @@ func testBasic(t *testing.T, prefix string) {
6263
require.Equal(t, len(listA), len(listB))
6364

6465
// sort them cause yeah.
65-
sort.Sort(ds.KeySlice(listA))
66-
sort.Sort(ds.KeySlice(listB))
66+
slices.SortFunc(listA, func(a, b ds.Key) int {
67+
return a.Compare(b)
68+
})
69+
slices.SortFunc(listB, func(a, b ds.Key) int {
70+
return a.Compare(b)
71+
})
6772

6873
for i, kA := range listA {
6974
kB := listB[i]
@@ -103,7 +108,9 @@ func TestQuery(t *testing.T) {
103108

104109
results, err := qres.Rest()
105110
require.NoError(t, err)
106-
sort.Slice(results, func(i, j int) bool { return results[i].Key < results[j].Key })
111+
slices.SortFunc(results, func(a, b dsq.Entry) int {
112+
return strings.Compare(a.Key, b.Key)
113+
})
107114

108115
for i, ent := range results {
109116
require.Equal(t, expect[i].Key, ent.Key)
@@ -121,7 +128,9 @@ func TestQuery(t *testing.T) {
121128

122129
results, err = qres.Rest()
123130
require.NoError(t, err)
124-
sort.Slice(results, func(i, j int) bool { return results[i].Key < results[j].Key })
131+
slices.SortFunc(results, func(a, b dsq.Entry) int {
132+
return strings.Compare(a.Key, b.Key)
133+
})
125134

126135
for i, ent := range results {
127136
require.Equal(t, expect[i].Key, ent.Key)

null_ds.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func NewNullDatastore() *NullDatastore {
2525
}
2626

2727
// Put implements Datastore.Put
28-
func (d *NullDatastore) Put(ctx context.Context, key Key, value []byte) (err error) {
28+
func (d *NullDatastore) Put(ctx context.Context, key Key, value []byte) error {
2929
return nil
3030
}
3131

@@ -35,22 +35,22 @@ func (d *NullDatastore) Sync(ctx context.Context, prefix Key) error {
3535
}
3636

3737
// Get implements Datastore.Get
38-
func (d *NullDatastore) Get(ctx context.Context, key Key) (value []byte, err error) {
38+
func (d *NullDatastore) Get(ctx context.Context, key Key) ([]byte, error) {
3939
return nil, ErrNotFound
4040
}
4141

4242
// Has implements Datastore.Has
43-
func (d *NullDatastore) Has(ctx context.Context, key Key) (exists bool, err error) {
43+
func (d *NullDatastore) Has(ctx context.Context, key Key) (bool, error) {
4444
return false, nil
4545
}
4646

4747
// Has implements Datastore.GetSize
48-
func (d *NullDatastore) GetSize(ctx context.Context, key Key) (size int, err error) {
48+
func (d *NullDatastore) GetSize(ctx context.Context, key Key) (int, error) {
4949
return -1, ErrNotFound
5050
}
5151

5252
// Delete implements Datastore.Delete
53-
func (d *NullDatastore) Delete(ctx context.Context, key Key) (err error) {
53+
func (d *NullDatastore) Delete(ctx context.Context, key Key) error {
5454
return nil
5555
}
5656

@@ -89,15 +89,15 @@ func (d *NullDatastore) NewTransaction(ctx context.Context, readOnly bool) (Txn,
8989

9090
type nullTxn struct{}
9191

92-
func (t *nullTxn) Get(ctx context.Context, key Key) (value []byte, err error) {
92+
func (t *nullTxn) Get(ctx context.Context, key Key) ([]byte, error) {
9393
return nil, nil
9494
}
9595

96-
func (t *nullTxn) Has(ctx context.Context, key Key) (exists bool, err error) {
96+
func (t *nullTxn) Has(ctx context.Context, key Key) (bool, error) {
9797
return false, nil
9898
}
9999

100-
func (t *nullTxn) GetSize(ctx context.Context, key Key) (size int, err error) {
100+
func (t *nullTxn) GetSize(ctx context.Context, key Key) (int, error) {
101101
return 0, nil
102102
}
103103

0 commit comments

Comments
 (0)