Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-datastore
Commits
55256606
Unverified
Commit
55256606
authored
Apr 09, 2019
by
Steven Allen
Committed by
GitHub
Apr 09, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #125 from ipfs/fix/cleanup-query
cleanup and optimize naive query filters
parents
bce485ce
b086f25e
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
100 additions
and
104 deletions
+100
-104
batch.go
batch.go
+0
-2
key_test.go
key_test.go
+0
-11
query/filter_test.go
query/filter_test.go
+0
-6
query/order_test.go
query/order_test.go
+0
-6
query/query.go
query/query.go
+19
-7
query/query_impl.go
query/query_impl.go
+81
-72
No files found.
batch.go
View file @
55256606
package
datastore
package
datastore
type
verb
int
type
op
struct
{
type
op
struct
{
delete
bool
delete
bool
value
[]
byte
value
[]
byte
...
...
key_test.go
View file @
55256606
...
@@ -2,7 +2,6 @@ package datastore_test
...
@@ -2,7 +2,6 @@ package datastore_test
import
(
import
(
"bytes"
"bytes"
"math/rand"
"path"
"path"
"strings"
"strings"
"testing"
"testing"
...
@@ -14,16 +13,6 @@ import (
...
@@ -14,16 +13,6 @@ import (
// Hook up gocheck into the "go test" runner.
// Hook up gocheck into the "go test" runner.
func
Test
(
t
*
testing
.
T
)
{
TestingT
(
t
)
}
func
Test
(
t
*
testing
.
T
)
{
TestingT
(
t
)
}
func
randomString
()
string
{
chars
:=
"abcdefghijklmnopqrstuvwxyz1234567890"
var
buf
bytes
.
Buffer
l
:=
rand
.
Intn
(
50
)
for
j
:=
0
;
j
<
l
;
j
++
{
buf
.
WriteByte
(
chars
[
rand
.
Intn
(
len
(
chars
))])
}
return
buf
.
String
()
}
type
KeySuite
struct
{}
type
KeySuite
struct
{}
var
_
=
Suite
(
&
KeySuite
{})
var
_
=
Suite
(
&
KeySuite
{})
...
...
query/filter_test.go
View file @
55256606
...
@@ -5,12 +5,6 @@ import (
...
@@ -5,12 +5,6 @@ import (
"testing"
"testing"
)
)
type
filterTestCase
struct
{
filter
Filter
keys
[]
string
expect
[]
string
}
func
testKeyFilter
(
t
*
testing
.
T
,
f
Filter
,
keys
[]
string
,
expect
[]
string
)
{
func
testKeyFilter
(
t
*
testing
.
T
,
f
Filter
,
keys
[]
string
,
expect
[]
string
)
{
e
:=
make
([]
Entry
,
len
(
keys
))
e
:=
make
([]
Entry
,
len
(
keys
))
for
i
,
k
:=
range
keys
{
for
i
,
k
:=
range
keys
{
...
...
query/order_test.go
View file @
55256606
...
@@ -5,12 +5,6 @@ import (
...
@@ -5,12 +5,6 @@ import (
"testing"
"testing"
)
)
type
orderTestCase
struct
{
order
Order
keys
[]
string
expect
[]
string
}
func
testKeyOrder
(
t
*
testing
.
T
,
f
Order
,
keys
[]
string
,
expect
[]
string
)
{
func
testKeyOrder
(
t
*
testing
.
T
,
f
Order
,
keys
[]
string
,
expect
[]
string
)
{
e
:=
make
([]
Entry
,
len
(
keys
))
e
:=
make
([]
Entry
,
len
(
keys
))
for
i
,
k
:=
range
keys
{
for
i
,
k
:=
range
keys
{
...
...
query/query.go
View file @
55256606
...
@@ -75,7 +75,8 @@ type Entry struct {
...
@@ -75,7 +75,8 @@ type Entry struct {
}
}
// Result is a special entry that includes an error, so that the client
// Result is a special entry that includes an error, so that the client
// may be warned about internal errors.
// may be warned about internal errors. If Error is non-nil, Entry must be
// empty.
type
Result
struct
{
type
Result
struct
{
Entry
Entry
...
@@ -203,12 +204,12 @@ func NewResultBuilder(q Query) *ResultBuilder {
...
@@ -203,12 +204,12 @@ func NewResultBuilder(q Query) *ResultBuilder {
}
}
// ResultsWithChan returns a Results object from a channel
// ResultsWithChan returns a Results object from a channel
// of Result entries. Respects its own Close()
// of Result entries.
//
// DEPRECATED: This iterator is impossible to cancel correctly. Canceling it
// will leave anything trying to write to the result channel hanging.
func
ResultsWithChan
(
q
Query
,
res
<-
chan
Result
)
Results
{
func
ResultsWithChan
(
q
Query
,
res
<-
chan
Result
)
Results
{
b
:=
NewResultBuilder
(
q
)
return
ResultsWithProcess
(
q
,
func
(
worker
goprocess
.
Process
,
out
chan
<-
Result
)
{
// go consume all the entries and add them to the results.
b
.
Process
.
Go
(
func
(
worker
goprocess
.
Process
)
{
for
{
for
{
select
{
select
{
case
<-
worker
.
Closing
()
:
// client told us to close early
case
<-
worker
.
Closing
()
:
// client told us to close early
...
@@ -219,13 +220,24 @@ func ResultsWithChan(q Query, res <-chan Result) Results {
...
@@ -219,13 +220,24 @@ func ResultsWithChan(q Query, res <-chan Result) Results {
}
}
select
{
select
{
case
b
.
Outp
ut
<-
e
:
case
o
ut
<-
e
:
case
<-
worker
.
Closing
()
:
// client told us to close early
case
<-
worker
.
Closing
()
:
// client told us to close early
return
return
}
}
}
}
}
}
})
})
}
// ResultsWithProcess returns a Results object with the results generated by the
// passed subprocess.
func
ResultsWithProcess
(
q
Query
,
proc
func
(
goprocess
.
Process
,
chan
<-
Result
))
Results
{
b
:=
NewResultBuilder
(
q
)
// go consume all the entries and add them to the results.
b
.
Process
.
Go
(
func
(
worker
goprocess
.
Process
)
{
proc
(
worker
,
b
.
Output
)
})
go
b
.
Process
.
CloseAfterChildren
()
go
b
.
Process
.
CloseAfterChildren
()
return
b
.
Results
()
return
b
.
Results
()
...
...
query/query_impl.go
View file @
55256606
package
query
package
query
import
"sort"
import
(
"sort"
func
DerivedResults
(
qr
Results
,
ch
<-
chan
Result
)
Results
{
goprocess
"github.com/jbenet/goprocess"
return
&
results
{
)
query
:
qr
.
Query
(),
proc
:
qr
.
Process
(),
res
:
ch
,
}
}
// NaiveFilter applies a filter to the results.
// NaiveFilter applies a filter to the results.
func
NaiveFilter
(
qr
Results
,
filter
Filter
)
Results
{
func
NaiveFilter
(
qr
Results
,
filter
Filter
)
Results
{
ch
:=
make
(
chan
Result
)
return
ResultsFromIterator
(
qr
.
Query
(),
Iterator
{
go
func
()
{
Next
:
func
()
(
Result
,
bool
)
{
defer
close
(
ch
)
for
{
defer
qr
.
Close
()
e
,
ok
:=
qr
.
NextSync
()
if
!
ok
{
for
e
:=
range
qr
.
Next
()
{
return
Result
{},
false
}
if
e
.
Error
!=
nil
||
filter
.
Filter
(
e
.
Entry
)
{
if
e
.
Error
!=
nil
||
filter
.
Filter
(
e
.
Entry
)
{
ch
<-
e
return
e
,
tru
e
}
}
}
}
}()
},
Close
:
func
()
error
{
return
ResultsWithChan
(
qr
.
Query
(),
ch
)
return
qr
.
Close
()
},
})
}
}
// NaiveLimit truncates the results to a given int limit
// NaiveLimit truncates the results to a given int limit
func
NaiveLimit
(
qr
Results
,
limit
int
)
Results
{
func
NaiveLimit
(
qr
Results
,
limit
int
)
Results
{
ch
:=
make
(
chan
Result
)
if
limit
==
0
{
go
func
()
{
// 0 means no limit
defer
close
(
ch
)
return
qr
defer
qr
.
Close
()
l
:=
0
for
e
:=
range
qr
.
Next
()
{
if
e
.
Error
!=
nil
{
ch
<-
e
continue
}
ch
<-
e
l
++
if
limit
>
0
&&
l
>=
limit
{
break
}
}
}
}()
closed
:=
false
return
ResultsFromIterator
(
qr
.
Query
(),
Iterator
{
return
ResultsWithChan
(
qr
.
Query
(),
ch
)
Next
:
func
()
(
Result
,
bool
)
{
if
limit
==
0
{
if
!
closed
{
closed
=
true
err
:=
qr
.
Close
()
if
err
!=
nil
{
return
Result
{
Error
:
err
},
true
}
}
return
Result
{},
false
}
limit
--
return
qr
.
NextSync
()
},
Close
:
func
()
error
{
if
closed
{
return
nil
}
closed
=
true
return
qr
.
Close
()
},
})
}
}
// NaiveOffset skips a given number of results
// NaiveOffset skips a given number of results
func
NaiveOffset
(
qr
Results
,
offset
int
)
Results
{
func
NaiveOffset
(
qr
Results
,
offset
int
)
Results
{
ch
:=
make
(
chan
Result
)
return
ResultsFromIterator
(
qr
.
Query
(),
Iterator
{
go
func
()
{
Next
:
func
()
(
Result
,
bool
)
{
defer
close
(
ch
)
for
;
offset
>
0
;
offset
--
{
defer
qr
.
Close
()
res
,
ok
:=
qr
.
NextSync
()
if
!
ok
||
res
.
Error
!=
nil
{
sent
:=
0
return
res
,
ok
for
e
:=
range
qr
.
Next
()
{
}
if
e
.
Error
!=
nil
{
}
ch
<-
e
return
qr
.
NextSync
()
}
},
Close
:
func
()
error
{
if
sent
<
offset
{
return
qr
.
Close
()
sent
++
},
continue
})
}
ch
<-
e
}
}()
return
ResultsWithChan
(
qr
.
Query
(),
ch
)
}
}
// NaiveOrder reorders results according to given orders.
// NaiveOrder reorders results according to given orders.
...
@@ -83,29 +84,37 @@ func NaiveOrder(qr Results, orders ...Order) Results {
...
@@ -83,29 +84,37 @@ func NaiveOrder(qr Results, orders ...Order) Results {
return
qr
return
qr
}
}
ch
:=
make
(
chan
Result
)
return
ResultsWithProcess
(
qr
.
Query
(),
func
(
worker
goprocess
.
Process
,
out
chan
<-
Result
)
{
var
entries
[]
Entry
go
func
()
{
defer
close
(
ch
)
defer
qr
.
Close
()
defer
qr
.
Close
()
var
entries
[]
Entry
for
e
:=
range
qr
.
Next
()
{
collect
:
for
{
select
{
case
<-
worker
.
Closing
()
:
return
case
e
,
ok
:=
<-
qr
.
Next
()
:
if
!
ok
{
break
collect
}
if
e
.
Error
!=
nil
{
if
e
.
Error
!=
nil
{
ch
<-
e
out
<-
e
continue
}
}
entries
=
append
(
entries
,
e
.
Entry
)
entries
=
append
(
entries
,
e
.
Entry
)
}
}
}
sort
.
Slice
(
entries
,
func
(
i
int
,
j
int
)
bool
{
sort
.
Slice
(
entries
,
func
(
i
int
,
j
int
)
bool
{
return
Less
(
orders
,
entries
[
i
],
entries
[
j
])
return
Less
(
orders
,
entries
[
i
],
entries
[
j
])
})
})
for
_
,
e
:=
range
entries
{
for
_
,
e
:=
range
entries
{
ch
<-
Result
{
Entry
:
e
}
select
{
case
<-
worker
.
Closing
()
:
return
case
out
<-
Result
{
Entry
:
e
}
:
}
}
}()
}
})
return
DerivedResults
(
qr
,
ch
)
}
}
func
NaiveQueryApply
(
q
Query
,
qr
Results
)
Results
{
func
NaiveQueryApply
(
q
Query
,
qr
Results
)
Results
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment