Commit a365cf6e authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 088f59c8
...@@ -113,7 +113,8 @@ type LiveCache struct { ...@@ -113,7 +113,8 @@ type LiveCache struct {
// Hopefully we don't have cycles with BTree/Bucket. // Hopefully we don't have cycles with BTree/Bucket.
sync.Mutex sync.Mutex
objtab map[Oid]*weak.Ref // oid -> weak.Ref(IPersistent) objtab map[Oid]*weak.Ref // oid -> weak.Ref(IPersistent); potentially have a referee
pinned map[Oid]IPersistent // objects that are pinned and don't have any referee currently
// hooks for application to influence live caching decisions. // hooks for application to influence live caching decisions.
control LiveCacheControl control LiveCacheControl
...@@ -169,6 +170,7 @@ func newConnection(db *DB, at Tid) *Connection { ...@@ -169,6 +170,7 @@ func newConnection(db *DB, at Tid) *Connection {
at: at, at: at,
cache: LiveCache{ cache: LiveCache{
objtab: make(map[Oid]*weak.Ref), objtab: make(map[Oid]*weak.Ref),
pinned: make(map[Oid]IPersistent),
}, },
} }
} }
...@@ -204,12 +206,40 @@ func (cache *LiveCache) Get(oid Oid) IPersistent { ...@@ -204,12 +206,40 @@ func (cache *LiveCache) Get(oid Oid) IPersistent {
obj = xobj.(IPersistent) obj = xobj.(IPersistent)
} }
} }
if obj == nil {
obj = cache.pinned[oid]
// XXX -> weakref?
// XXX -> start lookup from pinned?
}
return obj return obj
} }
// set sets objects corresponding ... XXX // set sets objects corresponding to oid.
func (cache *LiveCache) set(oid Oid, obj IPersistent) { func (cache *LiveCache) set(oid Oid, obj IPersistent) {
var pc PCachePolicy // XXX -> cp, pol? ... ?
if cc := cache.control; cc != nil {
pc = cache.control.PCacheClassify(obj)
}
// XXX remember pc in obj .pcachePolicy?
// XXX del .objtab[oid] ?
// XXX del .pinned[oid] ?
if pc & PCachePinObject != 0 {
cache.pinned[oid] = obj
} else {
cache.objtab[oid] = weak.NewRef(obj) cache.objtab[oid] = weak.NewRef(obj)
}
}
// forEach calls f for all objects in the cache.
func (cache *LiveCache) forEach(f func(IPersistent)) {
for _, obj := range cache.pinned {
f(obj)
}
for _, wobj := range cache.objtab {
if xobj := wobj.Get(); xobj != nil {
f(xobj.(IPersistent))
}
}
} }
// SetControl installs c to handle cache decisions. // SetControl installs c to handle cache decisions.
...@@ -220,6 +250,7 @@ func (cache *LiveCache) set(oid Oid, obj IPersistent) { ...@@ -220,6 +250,7 @@ func (cache *LiveCache) set(oid Oid, obj IPersistent) {
// It is not safe to call SetControl simultaneously to other cache operations. // It is not safe to call SetControl simultaneously to other cache operations.
func (cache *LiveCache) SetControl(c LiveCacheControl) { func (cache *LiveCache) SetControl(c LiveCacheControl) {
cache.control = c cache.control = c
// XXX reclassify all objects
} }
// get is like Get, but used when we already know object class. // get is like Get, but used when we already know object class.
...@@ -232,7 +263,7 @@ func (conn *Connection) get(class string, oid Oid) (IPersistent, error) { ...@@ -232,7 +263,7 @@ func (conn *Connection) get(class string, oid Oid) (IPersistent, error) {
obj := conn.cache.Get(oid) obj := conn.cache.Get(oid)
if obj == nil { if obj == nil {
obj = newGhost(class, oid, conn) obj = newGhost(class, oid, conn)
conn.cache.objtab[oid] = weak.NewRef(obj) // XXX -> conn.cache.set(oid, obj) conn.cache.set(oid, obj)
checkClass = false checkClass = false
} }
conn.cache.Unlock() conn.cache.Unlock()
......
...@@ -565,14 +565,9 @@ func (conn *Connection) resync1(at Tid) { ...@@ -565,14 +565,9 @@ func (conn *Connection) resync1(at Tid) {
defer conn.cache.Unlock() defer conn.cache.Unlock()
if δall { if δall {
// XXX keep synced with LiveCache details conn.cache.forEach(func(obj IPersistent) {
// XXX -> conn.cache.forEach?
for _, wobj := range conn.cache.objtab {
obj, _ := wobj.Get().(IPersistent)
if obj != nil {
obj.PInvalidate() obj.PInvalidate()
} })
}
} else { } else {
for oid := range δobj { for oid := range δobj {
obj := conn.cache.Get(oid) obj := conn.cache.Get(oid)
......
...@@ -384,7 +384,7 @@ func (t *tPersistentConn) checkObj(obj *MyObject, oid Oid, serial Tid, state Obj ...@@ -384,7 +384,7 @@ func (t *tPersistentConn) checkObj(obj *MyObject, oid Oid, serial Tid, state Obj
connObj := cache.Get(oid) connObj := cache.Get(oid)
cache.Unlock() cache.Unlock()
if obj != connObj { if obj != connObj {
t.Fatalf("cache.get %s -> not same object:\nhave: %#v\nwant: %#v", oid, connObj, oid) t.Fatalf("cache.get %s -> not same object:\nhave: %#v\nwant: %#v", oid, connObj, obj)
} }
// and conn.Get must return exactly obj. // and conn.Get must return exactly obj.
...@@ -393,7 +393,7 @@ func (t *tPersistentConn) checkObj(obj *MyObject, oid Oid, serial Tid, state Obj ...@@ -393,7 +393,7 @@ func (t *tPersistentConn) checkObj(obj *MyObject, oid Oid, serial Tid, state Obj
t.Fatal(err) t.Fatal(err)
} }
if obj != connObj { if obj != connObj {
t.Fatalf("conn.get %s -> not same object:\nhave: %#v\nwant: %#v", oid, connObj, oid) t.Fatalf("conn.get %s -> not same object:\nhave: %#v\nwant: %#v", oid, connObj, obj)
} }
checkObj(t.T, obj, t.conn, oid, serial, state, refcnt) checkObj(t.T, obj, t.conn, oid, serial, state, refcnt)
...@@ -788,11 +788,11 @@ func TestLiveCache(t0 *testing.T) { ...@@ -788,11 +788,11 @@ func TestLiveCache(t0 *testing.T) {
assert.NotEqual(xobj2, nil) assert.NotEqual(xobj2, nil)
assert.NotEqual(xobj3, nil) assert.NotEqual(xobj3, nil)
obj2 = xobj2.(*MyObject) obj2 = xobj2.(*MyObject)
obj3 = xobj2.(*MyObject) obj3 = xobj3.(*MyObject)
t.checkObj(obj2, 102, at1, UPTODATE, 0, "труд") t.checkObj(obj2, 102, at1, UPTODATE, 0, "труд")
t.checkObj(obj3, 103, InvalidTid, GHOST, 0) t.checkObj(obj3, 103, InvalidTid, GHOST, 0)
assert.Equal(obj2._v_cookie, "zzz") // XXX labour assert.Equal(obj2._v_cookie, "labour")
assert.Equal(obj3._v_cookie, "may") assert.Equal(obj3._v_cookie, "may")
obj1 = t.Get(101) obj1 = t.Get(101)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment