Skip to content

Commit

Permalink
Add FindFrom for slicing indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
brendonh committed Feb 9, 2013
1 parent a6c14dd commit 5c342be
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 21 deletions.
10 changes: 5 additions & 5 deletions src/loge/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ func (db *LogeDB) Transact(actor Transactor, timeout time.Duration) bool {
}

func (db *LogeDB) Find(typeName string, linkName string, target LogeKey) ResultSet {
typ, ok := db.types[typeName]
if !ok {
panic(fmt.Sprintf("Type does not exist: %s", typeName))
}
return db.store.find(typ, linkName, target)
return db.store.find(db.types[typeName], linkName, target)
}

func (db *LogeDB) FindFrom(typeName string, linkName string, target LogeKey, from LogeKey, limit int) ResultSet {
return db.store.findFrom(db.types[typeName], linkName, target, from, limit)
}


Expand Down
50 changes: 38 additions & 12 deletions src/loge/leveldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type levelDBResultSet struct {
it *prefixIterator
prefixLen int
next string
limit int
count int
closed bool
}

Expand Down Expand Up @@ -197,7 +199,11 @@ func (store *levelDBStore) storeLinks(obj *logeObject) error {
// -----------------------------------------------

func (store *levelDBStore) find(typ *logeType, linkName string, key LogeKey) ResultSet {
return ldb_find(store, defaultReadOptions, typ, linkName, key)
return ldb_find(store, defaultReadOptions, typ, linkName, key, "", -1)
}

func (store *levelDBStore) findFrom(typ *logeType, linkName string, key LogeKey, from LogeKey, limit int) ResultSet {
return ldb_find(store, defaultReadOptions, typ, linkName, key, from, limit)
}

func (rs *levelDBResultSet) Valid() bool {
Expand All @@ -210,11 +216,17 @@ func (rs *levelDBResultSet) Next() LogeKey {
}
var next = rs.next
rs.it.Next()
rs.count++

if rs.it.Valid() {
rs.next = string(rs.it.Key()[rs.prefixLen:])
if rs.limit >= 0 && rs.count >= rs.limit {
rs.Close()
}
} else {
rs.Close()
}
}

return LogeKey(next)
}

Expand Down Expand Up @@ -289,6 +301,7 @@ func (context *levelDBContext) rollback() {

func (context *levelDBContext) cleanup() {
context.ldbStore.db.ReleaseSnapshot(context.snapshot)
context.readOptions.Close()
}

func (context *levelDBContext) Write() error {
Expand All @@ -314,7 +327,11 @@ func (context *levelDBContext) storeLinks(obj *logeObject) error {
}

func (context *levelDBContext) find(typ *logeType, linkName string, target LogeKey) ResultSet {
return ldb_find(context.ldbStore, context.readOptions, typ, linkName, target)
return ldb_find(context.ldbStore, context.readOptions, typ, linkName, target, "", -1)
}

func (context *levelDBContext) findFrom(typ *logeType, linkName string, key LogeKey, from LogeKey, limit int) ResultSet {
return ldb_find(context.ldbStore, context.readOptions, typ, linkName, key, from, limit)
}

func (context *levelDBContext) get(typ *logeType, key LogeKey) interface{} {
Expand All @@ -332,7 +349,7 @@ func (context *levelDBContext) getLinks(typ *logeType, linkName string, key Loge
func (store *levelDBStore) loadTypeMetadata() {
var typeType = store.types.Type("_type")
var tag = typeType.EncodeTag()
var it = store.iteratePrefix(tag, defaultReadOptions)
var it = store.iteratePrefix(tag, []byte{}, defaultReadOptions)
defer it.Close()

for it = it; it.Valid(); it.Next() {
Expand All @@ -348,7 +365,7 @@ func (store *levelDBStore) loadTypeMetadata() {

func (store *levelDBStore) tagVersions(vt *spack.VersionedType, typ *logeType) {
var prefix = encodeTaggedKey([]uint16{ldb_LINK_INFO_TAG, vt.Tag}, "")
var it = store.iteratePrefix(prefix, defaultReadOptions)
var it = store.iteratePrefix(prefix, []byte{}, defaultReadOptions)
defer it.Close()

for it = it; it.Valid(); it.Next() {
Expand All @@ -357,7 +374,6 @@ func (store *levelDBStore) tagVersions(vt *spack.VersionedType, typ *logeType) {
typ.Links[info.Name] = info
}


var maxTag uint16 = 0;
var missing = make([]*linkInfo, 0)

Expand Down Expand Up @@ -413,9 +429,13 @@ func encodeIndexKey(prefix []byte, target string, source string) []byte {
// -----------------------------------------------

func ldb_find(store *levelDBStore, readOptions *levigo.ReadOptions,
typ *logeType, linkName string, target LogeKey) ResultSet {
typ *logeType, linkName string, target LogeKey, from LogeKey, limit int) ResultSet {

fmt.Printf("Find options %v\n", readOptions)
if limit == 0 {
return &levelDBResultSet {
closed: true,
}
}

var vt = store.types.Type(typ.Name)
var linkInfo = typ.Links[linkName]
Expand All @@ -424,7 +444,7 @@ func ldb_find(store *levelDBStore, readOptions *levigo.ReadOptions,
encodeTaggedKey([]uint16{ldb_INDEX_TAG, vt.Tag, linkInfo.Tag}, string(target)),
0)

var it = store.iteratePrefix(prefix, readOptions)
var it = store.iteratePrefix(prefix, []byte(from), readOptions)
if !it.Valid() {
it.Close()
return &levelDBResultSet {
Expand All @@ -433,14 +453,15 @@ func ldb_find(store *levelDBStore, readOptions *levigo.ReadOptions,
}

var prefixLen = len(prefix)

var next = string(it.Key()[prefixLen:])

return &levelDBResultSet{
it: it,
prefixLen: prefixLen,
next: next,
closed: false,
limit: limit,
count: 0,
}
}

Expand Down Expand Up @@ -506,9 +527,14 @@ type prefixIterator struct {
Finished bool
}

func (store *levelDBStore) iteratePrefix(prefix []byte, readOptions *levigo.ReadOptions) *prefixIterator {
func (store *levelDBStore) iteratePrefix(prefix []byte, from []byte, readOptions *levigo.ReadOptions) *prefixIterator {
var it = store.db.NewIterator(readOptions)
it.Seek(prefix)
var seekPrefix = append(prefix, from...)
it.Seek(seekPrefix)

if len(from) > 0 && it.Valid() {
it.Next()
}

return &prefixIterator {
Prefix: prefix,
Expand Down
14 changes: 13 additions & 1 deletion src/loge/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ type ResultSet interface {
type storeContext interface {
get(*logeType, LogeKey) interface{}
getLinks(*logeType, string, LogeKey) []string
find(*logeType, string, LogeKey) ResultSet
store(*logeObject) error
storeLinks(*logeObject) error

find(*logeType, string, LogeKey) ResultSet
findFrom(*logeType, string, LogeKey, LogeKey, int) ResultSet
}

type transactionContext interface {
Expand Down Expand Up @@ -89,6 +91,11 @@ func (store *memStore) find(typ *logeType, linkName string, key LogeKey) ResultS
panic("Find not implemented on memstore")
}

func (store *memStore) findFrom(typ *logeType, linkName string, key LogeKey, from LogeKey, limit int) ResultSet {
// Until I can be bothered
panic("Find not implemented on memstore")
}

func (store *memStore) store(obj *logeObject) error {
obj.Lock.SpinLock()
defer obj.Lock.Unlock()
Expand Down Expand Up @@ -157,6 +164,11 @@ func (context *memContext) find(typ *logeType, linkName string, key LogeKey) Res
panic("Find not implemented on memstore")
}

func (context *memContext) findFrom(typ *logeType, linkName string, key LogeKey, from LogeKey, limit int) ResultSet {
// Until I can be bothered
panic("Find not implemented on memstore")
}

func (context *memContext) commit() error {
var store = context.mstore
store.lock.SpinLock()
Expand Down
4 changes: 4 additions & 0 deletions src/loge/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func (t *Transaction) Find(typeName string, linkName string, target LogeKey) Res
return t.context.find(t.db.types[typeName], linkName, target)
}

func (t *Transaction) FindFrom(typeName string, linkName string, target LogeKey, from LogeKey, limit int) ResultSet {
return t.context.findFrom(t.db.types[typeName], linkName, target, from, limit)
}

// -----------------------------------------------
// Internals
// -----------------------------------------------
Expand Down
18 changes: 17 additions & 1 deletion src/logetest/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func LinkBench() {
db.Transact(func (t *loge.Transaction) {
t.Set("person", "Brendon", &Person{ "Brendon", 31, []uint16{} })
for i := 0; i < 10000; i++ {
var key = fmt.Sprintf("pet-%d", i)
var key = fmt.Sprintf("pet-%04d", i)
t.Set("pet", loge.LogeKey(key), &Pet { key, "dog" })
t.AddLink("pet", "owner", loge.LogeKey(key), "Brendon")
}
Expand All @@ -102,4 +102,20 @@ func LinkBench() {
}

fmt.Printf("Found %d pets\n", count)

count = 0

var lastPet loge.LogeKey = ""

var loops = 0
for loops < 1000 {
var somePets = db.FindFrom("pet", "owner", "Brendon", lastPet, 100)
for somePets.Valid() {
lastPet = somePets.Next()
count++
}
loops++
}

fmt.Printf("Sliced %d pets\n", count)
}
4 changes: 2 additions & 2 deletions src/logetest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ type Pet struct {
}

func main() {
//LinkBench()
LinkBench()
//LinkSandbox()
WriteBench()
//WriteBench()
//Sandbox()
//Example()
}

0 comments on commit 5c342be

Please sign in to comment.