Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: brendonh/loge
base: 2ebc211227
...
head fork: brendonh/loge
compare: 34003284d9
Checking mergeability… Don't worry, you can still create the pull request.
  • 4 commits
  • 10 files changed
  • 0 commit comments
  • 1 contributor
View
13 src/loge/database.go
@@ -111,11 +111,9 @@ func (db *LogeDB) EnsureObj(objRef ObjRef, load bool) *LogeObject {
var key = objRef.Key
var objKey = objRef.String()
-
var typ = db.types[typeName]
db.lock.SpinLock()
-
var obj, ok = db.cache[objKey]
if ok && (obj.Loaded || !load) {
@@ -139,6 +137,7 @@ func (db *LogeDB) EnsureObj(objRef ObjRef, load bool) *LogeObject {
var links Links
if load {
links = db.store.GetLinks(typ, objRef.LinkName, key)
+ obj.Loaded = true
}
var linkSet = NewLinkSet()
@@ -155,6 +154,7 @@ func (db *LogeDB) EnsureObj(objRef ObjRef, load bool) *LogeObject {
if load {
object = db.store.Get(typ, key)
+ obj.Loaded = true
}
if object == nil {
@@ -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
123 src/loge/leveldb.go
@@ -15,6 +15,7 @@ const VERSION = 1
const LINK_TAG uint16 = 2
const LINK_INFO_TAG uint16 = 3
+const INDEX_TAG uint16 = 4
const START_TAG uint16 = 8
type LevelDBStore struct {
@@ -29,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
@@ -38,6 +46,7 @@ type LevelDBWriteBatch struct {
type LevelDBWriteEntry struct {
Key []byte
Val []byte
+ Delete bool
}
var writeOptions = levigo.NewWriteOptions()
@@ -199,7 +208,11 @@ func (store *LevelDBStore) Get(typ *LogeType, key LogeKey) interface{} {
func (store *LevelDBStore) GetLinks(typ *LogeType, linkName string, objKey LogeKey) Links {
var vt = store.types.Type(typ.Name)
- var linkInfo = typ.Links[linkName]
+ var linkInfo, ok = typ.Links[linkName]
+ if !ok {
+ panic(fmt.Sprintf("Link info missing for %s", linkName))
+ }
+
var key = encodeTaggedKey([]uint16{LINK_TAG, vt.Tag, linkInfo.Tag}, string(objKey))
val, err := store.db.Get(readOptions, key)
@@ -218,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,
@@ -226,10 +300,6 @@ func (store *LevelDBStore) NewWriteBatch() LogeWriteBatch {
}
}
-// -----------------------------------------------
-// Write Batches
-// -----------------------------------------------
-
func (store *LevelDBStore) Writer() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -239,13 +309,18 @@ func (store *LevelDBStore) Writer() {
}
batch.result<- batch.Write()
}
- fmt.Printf("Writer closing\n")
store.flushed = true
}
func (batch *LevelDBWriteBatch) Store(obj *LogeObject) error {
var vt = batch.store.types.Type(obj.Type.Name)
var key = vt.EncodeKey(string(obj.Key))
+
+ if !obj.Current.HasValue() {
+ batch.Delete(key)
+ return nil
+ }
+
var val, err = vt.EncodeObj(obj.Current.Object)
if err != nil {
@@ -272,11 +347,29 @@ func (batch *LevelDBWriteBatch) StoreLinks(linkObj *LogeObject) error {
batch.Append(key, val)
+ 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 = encodeIndexKey(prefix, target, source)
+ batch.Append(key, []byte{})
+ }
+
+
return nil
}
func (batch *LevelDBWriteBatch) Append(key []byte, val []byte) {
- batch.batch = append(batch.batch, LevelDBWriteEntry{ key, val })
+ batch.batch = append(batch.batch, LevelDBWriteEntry{ key, val, false })
+}
+
+func (batch *LevelDBWriteBatch) Delete(key []byte) {
+ batch.batch = append(batch.batch, LevelDBWriteEntry{ key, nil, true })
}
func (batch *LevelDBWriteBatch) Commit() error {
@@ -288,13 +381,16 @@ func (batch *LevelDBWriteBatch) Write() error {
var wb = levigo.NewWriteBatch()
defer wb.Close()
for _, entry := range batch.batch {
- wb.Put(entry.Key, entry.Val)
+ if entry.Delete {
+ wb.Delete(entry.Key)
+ } else {
+ wb.Put(entry.Key, entry.Val)
+ }
}
return batch.store.db.Write(writeOptions, wb)
}
-
// -----------------------------------------------
// Key encoding
// -----------------------------------------------
@@ -309,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
10 src/loge/links.go
@@ -39,7 +39,7 @@ func (links Links) Remove(key string) Links {
type LinkSet struct {
- Original Links
+ Original Links `loge:"keep"`
Added Links
Removed Links
}
@@ -67,7 +67,8 @@ func (ls *LinkSet) Freeze() {
func (ls *LinkSet) Set(keys []string) {
- sort.Strings(keys)
+ // XXX BGH TODO: Delta this
+ sort.Strings(keys)
ls.Removed = ls.Original
ls.Added = keys
}
@@ -81,6 +82,11 @@ func (ls *LinkSet) Add(key string) {
}
func (ls *LinkSet) Remove(key string) {
+ // XXX BGH Hrgh
+ if (!ls.Original.Has(key) && !ls.Added.Has(key)) || ls.Removed.Has(key) {
+ return
+ }
+
ls.Added = ls.Added.Remove(key)
ls.Removed = ls.Removed.Add(key)
}
View
5 src/loge/objects.go
@@ -43,10 +43,13 @@ func InitializeObject(db *LogeDB, t *LogeType, key LogeKey) *LogeObject {
func (obj *LogeObject) NewVersion() *LogeObjectVersion {
var current = obj.Current
+
+ var newObj = obj.Type.Copy(current.Object)
+
return &LogeObjectVersion{
LogeObj: obj,
Version: current.Version + 1,
- Object: obj.Type.Copy(current.Object),
+ Object: newObj,
Dirty: true,
}
}
View
11 src/loge/storage.go
@@ -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
22 src/loge/transactions.go
@@ -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{
@@ -78,6 +83,23 @@ func (t *Transaction) AddLink(typeName string, linkName string, key LogeKey, tar
t.getLink(MakeLinkRef(typeName, linkName, key), true, true).Add(string(target))
}
+func (t *Transaction) RemoveLink(typeName string, linkName string, key LogeKey, target LogeKey) {
+ t.getLink(MakeLinkRef(typeName, linkName, key), true, true).Remove(string(target))
+}
+
+func (t *Transaction) SetLinks(typeName string, linkName string, key LogeKey, targets []LogeKey) {
+ // XXX BGH: Yargh
+ var stringTargets = make([]string, 0, len(targets))
+ for _, key := range targets {
+ stringTargets = append(stringTargets, string(key))
+ }
+ 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)
return version.Object.(*LinkSet)
View
11 src/logetest/bench.go
@@ -5,24 +5,13 @@ import (
"fmt"
"time"
"runtime"
- _ "runtime/pprof"
- _ "os"
)
const TOTAL = 1000000
const BATCH_SIZE = 10000
func WriteBench() {
- // f, err := os.Create("bench.prof")
- // if err != nil {
- // fmt.Printf("Oh no: %v\n", err)
- // return
- // }
- // pprof.StartCPUProfile(f)
- // defer pprof.StopCPUProfile()
-
var db = loge.NewLogeDB(loge.NewLevelDBStore("data/bench"))
- //var db = loge.NewLogeDB(loge.NewMemStore())
defer db.Close()
View
105 src/logetest/links.go
@@ -0,0 +1,105 @@
+package main
+
+import (
+ "loge"
+ "fmt"
+)
+
+func LinkSandbox() {
+ var db = loge.NewLogeDB(loge.NewLevelDBStore("data/links"))
+ defer db.Close()
+
+ db.CreateType("person", 1, &Person{}, nil)
+
+ db.CreateType("pet", 1, &Pet{}, loge.LinkSpec{
+ "owner": "person",
+ })
+
+ db.Transact(func (t *loge.Transaction) {
+ t.SetObj("person", "Brendon", &Person{ "Brendon", 31, []uint16{} })
+ t.SetObj("person", "Mike", &Person{ "Mike", 38, []uint16{} })
+ t.SetObj("pet", "Ted", &Pet { "Ted", "dog" })
+ t.SetObj("pet", "Bones", &Pet { "Bones", "dog" })
+ t.SetObj("pet", "BaoBao", &Pet { "BaoBao", "dog" })
+ t.SetObj("pet", "Ruby", &Pet { "Ruby", "dog" })
+ t.SetObj("pet", "HenYou", &Pet { "HenYou", "dog" })
+ t.SetObj("pet", "Garcon", &Pet { "Garcon", "dog" })
+ t.SetObj("pet", "Flower", &Pet { "Flower", "cat" })
+
+ t.SetLinks("pet", "owner", "Ted", []loge.LogeKey{"Brendon"})
+ t.SetLinks("pet", "owner", "Bones", []loge.LogeKey{"Brendon"})
+ t.SetLinks("pet", "owner", "BaoBao", []loge.LogeKey{"Brendon"})
+ t.SetLinks("pet", "owner", "Ruby", []loge.LogeKey{"Brendon"})
+ t.SetLinks("pet", "owner", "HenYou", []loge.LogeKey{"Mike"})
+ t.SetLinks("pet", "owner", "Garcon", []loge.LogeKey{"Mike"})
+ t.SetLinks("pet", "owner", "Flower", []loge.LogeKey{"Mike"})
+ }, 0)
+
+ db.Transact(func (t *loge.Transaction) {
+ t.RemoveLink("pet", "owner", "Ruby", "Brendon")
+ t.AddLink("pet", "owner", "Ruby", "Mike")
+ }, 0)
+
+ db.Transact(func (t *loge.Transaction) {
+ 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
4 src/logetest/main.go
@@ -12,7 +12,9 @@ type Pet struct {
}
func main() {
- WriteBench()
+ LinkBench()
+ //LinkSandbox()
+ //WriteBench()
//Sandbox()
//Example()
}
View
14 src/logetest/sandbox.go
@@ -27,17 +27,9 @@ func Sandbox() {
}
trans.SetObj("person", "brendon", &brend)
+ }, 0)
- var ted = Pet{
- Name: "Ted",
- Species: "Hairball",
- }
- trans.SetObj("pet", "ted", &ted)
-
- var owner = trans.ReadLinks("pet", "owner", "ted")
- fmt.Printf("Owner: %v\n", owner)
-
- trans.AddLink("pet", "owner", "ted", "brendon")
-
+ db.Transact(func(trans *loge.Transaction) {
+ trans.DeleteObj("person", "brendon")
}, 0)
}

No commit comments for this range

Something went wrong with that request. Please try again.