Merge pull request #103 from barakmich/materializer_iterator

Fix Materializer iterator
This commit is contained in:
Barak Michener 2014-08-06 15:52:36 -04:00
commit 272829f3e9
5 changed files with 50 additions and 24 deletions

View file

@ -32,6 +32,10 @@ type result struct {
tags map[string]graph.Value
}
type hashable interface {
Hashable() interface{}
}
type Materialize struct {
uid uint64
tags graph.Tagger
@ -200,7 +204,11 @@ func (it *Materialize) Contains(v graph.Value) bool {
if it.aborted {
return it.subIt.Contains(v)
}
if i, ok := it.containsMap[v]; ok {
key := v
if h, ok := v.(hashable); ok {
key = h.Hashable()
}
if i, ok := it.containsMap[key]; ok {
it.index = i
it.subindex = 0
return graph.ContainsLogOut(it, v, true)
@ -228,7 +236,7 @@ func (it *Materialize) NextResult() bool {
func (it *Materialize) materializeSet() {
i := 0
for {
val, ok := graph.Next(it.subIt)
id, ok := graph.Next(it.subIt)
if !ok {
break
}
@ -237,6 +245,10 @@ func (it *Materialize) materializeSet() {
it.aborted = true
break
}
val := id
if h, ok := id.(hashable); ok {
val = h.Hashable()
}
if _, ok := it.containsMap[val]; !ok {
it.containsMap[val] = len(it.values)
it.values = append(it.values, nil)
@ -244,11 +256,11 @@ func (it *Materialize) materializeSet() {
index := it.containsMap[val]
tags := make(map[string]graph.Value)
it.subIt.TagResults(tags)
it.values[index] = append(it.values[index], result{id: val, tags: tags})
it.values[index] = append(it.values[index], result{id: id, tags: tags})
for it.subIt.NextResult() == true {
tags := make(map[string]graph.Value)
it.subIt.TagResults(tags)
it.values[index] = append(it.values[index], result{id: val, tags: tags})
it.values[index] = append(it.values[index], result{id: id, tags: tags})
}
}
if it.aborted {

View file

@ -117,8 +117,8 @@ func (it *AllIterator) Next() (graph.Value, bool) {
it.Close()
return nil, false
}
it.result = out
return out, true
it.result = Token(out)
return it.result, true
}
func (it *AllIterator) ResultTree() *graph.ResultTree {

View file

@ -42,7 +42,7 @@ type Iterator struct {
}
func NewIterator(prefix string, d quad.Direction, value graph.Value, qs *TripleStore) *Iterator {
vb := value.([]byte)
vb := value.(Token)
p := make([]byte, 0, 2+qs.hasher.Size())
p = append(p, []byte(prefix)...)
p = append(p, []byte(vb[1:])...)
@ -105,7 +105,7 @@ func (it *Iterator) TagResults(dst map[string]graph.Value) {
}
func (it *Iterator) Clone() graph.Iterator {
out := NewIterator(it.originalPrefix, it.dir, it.checkId, it.qs)
out := NewIterator(it.originalPrefix, it.dir, Token(it.checkId), it.qs)
out.tags.CopyFrom(it)
return out
}
@ -134,12 +134,12 @@ func (it *Iterator) Next() (graph.Value, bool) {
if bytes.HasPrefix(it.iter.Key(), it.nextPrefix) {
out := make([]byte, len(it.iter.Key()))
copy(out, it.iter.Key())
it.result = out
it.result = Token(out)
ok := it.iter.Next()
if !ok {
it.Close()
}
return out, true
return Token(out), true
}
it.Close()
it.result = nil
@ -216,7 +216,7 @@ func PositionOf(prefix []byte, d quad.Direction, qs *TripleStore) int {
}
func (it *Iterator) Contains(v graph.Value) bool {
val := v.([]byte)
val := v.(Token)
if val[0] == 'z' {
return false
}
@ -227,7 +227,7 @@ func (it *Iterator) Contains(v graph.Value) bool {
}
} else {
nameForDir := it.qs.Quad(v).Get(it.dir)
hashForDir := it.qs.ValueOf(nameForDir).([]byte)
hashForDir := it.qs.ValueOf(nameForDir).(Token)
if bytes.Equal(hashForDir, it.checkId) {
return true
}
@ -236,12 +236,20 @@ func (it *Iterator) Contains(v graph.Value) bool {
}
func (it *Iterator) Size() (int64, bool) {
return it.qs.SizeOf(it.checkId), true
return it.qs.SizeOf(Token(it.checkId)), true
}
func (it *Iterator) DebugString(indent int) string {
size, _ := it.Size()
return fmt.Sprintf("%s(%s %d tags: %v dir: %s size:%d %s)", strings.Repeat(" ", indent), it.Type(), it.UID(), it.tags.Tags(), it.dir, size, it.qs.NameOf(it.checkId))
return fmt.Sprintf("%s(%s %d tags: %v dir: %s size:%d %s)",
strings.Repeat(" ", indent),
it.Type(),
it.UID(),
it.tags.Tags(),
it.dir,
size,
it.qs.NameOf(Token(it.checkId)),
)
}
var levelDBType graph.Type

View file

@ -42,6 +42,12 @@ const (
DefaultWriteBufferSize = 20
)
type Token []byte
func (t Token) Hashable() interface{} {
return string(t)
}
type TripleStore struct {
dbOpts *opt.Options
db *leveldb.DB
@ -308,7 +314,7 @@ func (qs *TripleStore) Close() {
func (qs *TripleStore) Quad(k graph.Value) quad.Quad {
var triple quad.Quad
b, err := qs.db.Get(k.([]byte), qs.readopts)
b, err := qs.db.Get(k.(Token), qs.readopts)
if err != nil && err != leveldb.ErrNotFound {
glog.Error("Error: couldn't get triple from DB.")
return quad.Quad{}
@ -334,7 +340,7 @@ func (qs *TripleStore) convertStringToByteHash(s string) []byte {
}
func (qs *TripleStore) ValueOf(s string) graph.Value {
return qs.createValueKeyFor(s)
return Token(qs.createValueKeyFor(s))
}
func (qs *TripleStore) valueData(value_key []byte) ValueData {
@ -362,14 +368,14 @@ func (qs *TripleStore) NameOf(k graph.Value) string {
glog.V(2).Info("k was nil")
return ""
}
return qs.valueData(k.([]byte)).Name
return qs.valueData(k.(Token)).Name
}
func (qs *TripleStore) SizeOf(k graph.Value) int64 {
if k == nil {
return 0
}
return int64(qs.valueData(k.([]byte)).Size)
return int64(qs.valueData(k.(Token)).Size)
}
func (qs *TripleStore) getSize() {
@ -432,17 +438,17 @@ func (qs *TripleStore) TriplesAllIterator() graph.Iterator {
}
func (qs *TripleStore) TripleDirection(val graph.Value, d quad.Direction) graph.Value {
v := val.([]uint8)
v := val.(Token)
offset := PositionOf(v[0:2], d, qs)
if offset != -1 {
return append([]byte("z"), v[offset:offset+qs.hasher.Size()]...)
return Token(append([]byte("z"), v[offset:offset+qs.hasher.Size()]...))
} else {
return qs.Quad(val).Get(d)
return Token(qs.Quad(val).Get(d))
}
}
func compareBytes(a, b graph.Value) bool {
return bytes.Equal(a.([]uint8), b.([]uint8))
return bytes.Equal(a.(Token), b.(Token))
}
func (qs *TripleStore) FixedIterator() graph.FixedIterator {

View file

@ -37,8 +37,8 @@ import (
// pointers to structs, or merely triples, or whatever works best for the
// backing store.
//
// These must be comparable, ie, not arrays or maps, as they may be used as keys
// for maps.
// These must be comparable, or implement a `Hashable() interface{}` function
// so that they may be stored in maps.
type Value interface{}
type TripleStore interface {