Permalink
Browse files

Fix link storage, add simple DB-level link lookup

  • Loading branch information...
1 parent e7ca7d0 commit 34003284d9a5603510b80a1187dc7a2d814e24ae @brendonh committed Feb 9, 2013
Showing with 171 additions and 16 deletions.
  1. +9 −0 src/loge/database.go
  2. +85 −13 src/loge/leveldb.go
  3. +11 −0 src/loge/storage.go
  4. +8 −0 src/loge/transactions.go
  5. +56 −2 src/logetest/links.go
  6. +2 −1 src/logetest/main.go
View
@@ -174,6 +174,15 @@ func (db *LogeDB) EnsureObj(objRef ObjRef, load bool) *LogeObject {
}
+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)
+}
+
+
func (db *LogeDB) NewWriteBatch() LogeWriteBatch {
return db.store.NewWriteBatch()
}
View
@@ -30,6 +30,13 @@ type LevelDBStore struct {
linkInfoSpec *spack.TypeSpec
}
+type LevelDBResultSet struct {
+ it *prefixIterator
+ prefixLen int
+ next string
+ closed bool
+}
+
type LevelDBWriteBatch struct {
store *LevelDBStore
batch []LevelDBWriteEntry
@@ -224,6 +231,67 @@ func (store *LevelDBStore) GetLinks(typ *LogeType, linkName string, objKey LogeK
return links
}
+
+// -----------------------------------------------
+// Search
+// -----------------------------------------------
+
+func (store *LevelDBStore) Find(typ *LogeType, linkName string, target LogeKey) ResultSet {
+ var vt = store.types.Type(typ.Name)
+ var linkInfo = typ.Links[linkName]
+
+ var prefix = append(
+ encodeTaggedKey([]uint16{INDEX_TAG, vt.Tag, linkInfo.Tag}, string(target)),
+ 0)
+
+ var it = store.iteratePrefix(prefix)
+ if !it.Valid() {
+ it.Close()
+ return &LevelDBResultSet {
+ closed: true,
+ }
+ }
+
+ var prefixLen = len(prefix)
+
+ var next = string(it.Key()[prefixLen:])
+
+ return &LevelDBResultSet{
+ it: it,
+ prefixLen: prefixLen,
+ next: next,
+ closed: false,
+ }
+}
+
+func (rs *LevelDBResultSet) Valid() bool {
+ return !rs.closed
+}
+
+func (rs *LevelDBResultSet) Next() LogeKey {
+ if rs.closed {
+ return ""
+ }
+ var next = rs.next
+ rs.it.Next()
+ if rs.it.Valid() {
+ rs.next = string(rs.it.Key()[rs.prefixLen:])
+ } else {
+ rs.Close()
+ }
+ return LogeKey(next)
+}
+
+func (rs *LevelDBResultSet) Close() {
+ rs.it.Close()
+ rs.closed = true
+}
+
+
+// -----------------------------------------------
+// Write Batches
+// -----------------------------------------------
+
func (store *LevelDBStore) NewWriteBatch() LogeWriteBatch {
return &LevelDBWriteBatch{
store: store,
@@ -232,10 +300,6 @@ func (store *LevelDBStore) NewWriteBatch() LogeWriteBatch {
}
}
-// -----------------------------------------------
-// Write Batches
-// -----------------------------------------------
-
func (store *LevelDBStore) Writer() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -283,19 +347,19 @@ func (batch *LevelDBWriteBatch) StoreLinks(linkObj *LogeObject) error {
batch.Append(key, val)
- var prefix = append(
- encodeTaggedKey([]uint16{INDEX_TAG, vt.Tag, linkInfo.Tag}, string(linkObj.Key)),
- 0)
+ var prefix = encodeTaggedKey([]uint16{INDEX_TAG, vt.Tag, linkInfo.Tag}, "")
+ var source = string(linkObj.Key)
+
+ for _, target := range set.Removed {
+ var key = encodeIndexKey(prefix, target, source)
+ batch.Delete(key)
+ }
for _, target := range set.Added {
- var key = append(prefix, []byte(target)...)
+ var key = encodeIndexKey(prefix, target, source)
batch.Append(key, []byte{})
}
- for _, target := range set.Removed {
- var key = append(prefix, []byte(target)...)
- batch.Delete(key)
- }
return nil
}
@@ -327,7 +391,6 @@ func (batch *LevelDBWriteBatch) Write() error {
return batch.store.db.Write(writeOptions, wb)
}
-
// -----------------------------------------------
// Key encoding
// -----------------------------------------------
@@ -342,6 +405,15 @@ func encodeTaggedKey(tags []uint16, key string) []byte {
return buf.Bytes()
}
+func encodeIndexKey(prefix []byte, target string, source string) []byte {
+ var buf = make([]byte, 0, len(prefix) + len(target) + len(source))
+ buf = append(buf, prefix...)
+ buf = append(buf, []byte(target)...)
+ buf = append(buf, 0)
+ buf = append(buf, []byte(source)...)
+ return buf
+}
+
// -----------------------------------------------
// Prefix iterator
// -----------------------------------------------
View
@@ -8,6 +8,8 @@ type LogeStore interface {
Get(t *LogeType, key LogeKey) interface{}
GetLinks(*LogeType, string, LogeKey) Links
+ Find(*LogeType, string, LogeKey) ResultSet
+
NewWriteBatch() LogeWriteBatch
}
@@ -17,6 +19,11 @@ type LogeWriteBatch interface {
Commit() error
}
+type ResultSet interface {
+ Next() LogeKey
+ Valid() bool
+ Close()
+}
type objectMap map[string]map[LogeKey]interface{}
@@ -75,6 +82,10 @@ func (store *MemStore) GetLinks(typ *LogeType, linkName string, key LogeKey) Lin
return Links{}
}
+func (store *MemStore) Find(typ *LogeType, linkName string, key LogeKey) ResultSet {
+ // Until I can be bothered
+ panic("Find not implemented on memstore")
+}
func (store *MemStore) NewWriteBatch() LogeWriteBatch {
return &MemStoreWriteBatch{
View
@@ -21,8 +21,13 @@ type Transaction struct {
DB *LogeDB
Versions map[string]*LogeObjectVersion
State TransactionState
+ ResultSets []*TransactionResultSet
}
+type TransactionResultSet struct {
+ trans *Transaction
+ results ResultSet
+}
func NewTransaction(db *LogeDB) *Transaction {
return &Transaction{
@@ -91,6 +96,9 @@ func (t *Transaction) SetLinks(typeName string, linkName string, key LogeKey, ta
t.getLink(MakeLinkRef(typeName, linkName, key), true, true).Set(stringTargets)
}
+// -----------------------------------------------
+// Internals
+// -----------------------------------------------
func (t *Transaction) getLink(objRef ObjRef, forWrite bool, load bool) *LinkSet {
var version = t.getObj(objRef, forWrite, load)
View
@@ -7,7 +7,6 @@ import (
func LinkSandbox() {
var db = loge.NewLogeDB(loge.NewLevelDBStore("data/links"))
-
defer db.Close()
db.CreateType("person", 1, &Person{}, nil)
@@ -45,7 +44,62 @@ func LinkSandbox() {
fmt.Printf("Ruby links: %v\n", t.ReadLinks("pet", "owner", "Ruby"))
}, 0)
+ var pets = db.Find("pet", "owner", "Brendon")
+
+ for pets.Valid() {
+ var pet = pets.Next()
+ fmt.Printf("Found Brendon pet: %s\n", pet)
+ }
+
+ pets = db.Find("pet", "owner", "Mike")
+
+ for pets.Valid() {
+ var pet = pets.Next()
+ fmt.Printf("Found Mike pet: %s\n", pet)
+ }
+
+ pets = db.Find("pet", "owner", "Nai")
+
+ for pets.Valid() {
+ var pet = pets.Next()
+ fmt.Printf("Found Nai pet: %s\n", pet)
+ }
fmt.Printf("Done\n")
}
-
+
+
+func LinkBench() {
+ var db = loge.NewLogeDB(loge.NewLevelDBStore("data/linkbench"))
+ defer db.Close()
+
+ db.CreateType("person", 1, &Person{}, nil)
+
+ db.CreateType("pet", 1, &Pet{}, loge.LinkSpec{
+ "owner": "person",
+ })
+
+ fmt.Printf("Inserting...\n")
+
+ db.Transact(func (t *loge.Transaction) {
+ t.SetObj("person", "Brendon", &Person{ "Brendon", 31, []uint16{} })
+ for i := 0; i < 10000; i++ {
+ var key = fmt.Sprintf("pet-%d", i)
+ t.SetObj("pet", loge.LogeKey(key), &Pet { key, "dog" })
+ t.AddLink("pet", "owner", loge.LogeKey(key), "Brendon")
+ }
+ }, 0)
+
+ fmt.Printf("Finding...\n")
+
+ var pets = db.Find("pet", "owner", "Brendon")
+
+ var count = 0
+
+ for pets.Valid() {
+ pets.Next()
+ count++
+ }
+
+ fmt.Printf("Found %d pets\n", count)
+}
View
@@ -12,8 +12,9 @@ type Pet struct {
}
func main() {
+ LinkBench()
//LinkSandbox()
//WriteBench()
- Sandbox()
+ //Sandbox()
//Example()
}

0 comments on commit 3400328

Please sign in to comment.