Commit 7b2dca36 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent d3c86584
...@@ -79,6 +79,7 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) { ...@@ -79,6 +79,7 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) {
if len(t.data) == 0 { if len(t.data) == 0 {
// empty btree // empty btree
t.PDeactivate()
return nil, false, nil return nil, false, nil
} }
...@@ -94,13 +95,15 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) { ...@@ -94,13 +95,15 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) {
switch child := t.data[i].child.(type) { switch child := t.data[i].child.(type) {
case *ZBTree: case *ZBTree:
// XXX t.PAllowDeactivate t.PDeactivate()
t = child t = child
t.PActivate(ctx) // XXX err t.PActivate(ctx) // XXX err
case *ZBucket: case *ZBucket:
t.PDeactivate()
child.PActivate(ctx) // XXX err child.PActivate(ctx) // XXX err
v, ok := child.get(key) v, ok := child.get(key)
child.PDeactivate()
return v, ok, nil return v, ok, nil
} }
} }
...@@ -181,8 +184,10 @@ func (t *ZBTree) PActivate(ctx context.Context) error { ...@@ -181,8 +184,10 @@ func (t *ZBTree) PActivate(ctx context.Context) error {
// PDeactivate implements Object.
func (b *ZBucket) PDeactivate() { func (b *ZBucket) PDeactivate() {
// XXX check if activated // XXX check if activated
// b.pyObject.PDeactivate() ...
b.next = nil b.next = nil
b.keys = nil b.keys = nil
b.values = nil b.values = nil
...@@ -200,7 +205,7 @@ func (b *ZBucket) PActivate(ctx context.Context) (bool, error) { ...@@ -200,7 +205,7 @@ func (b *ZBucket) PActivate(ctx context.Context) (bool, error) {
return false, nil return false, nil
} }
// FIXME other users must wait for first decode to complet // FIXME other users must wait for first decode to complete
err = b.decode() err = b.decode()
if err != nil { if err != nil {
b.pyObject.PDeactivate() b.pyObject.PDeactivate()
......
...@@ -122,15 +122,6 @@ func (pyobj *pyObject) PyClass() pickle.Class { return pyobj.pyclass } ...@@ -122,15 +122,6 @@ func (pyobj *pyObject) PyClass() pickle.Class { return pyobj.pyclass }
func (pyobj *pyObject) PyState() interface{} { return pyobj.pystate } func (pyobj *pyObject) PyState() interface{} { return pyobj.pystate }
// LiveCacheControl is the interface that allows applications to influence
// Connection's decisions with respect to its live cache.
type LiveCacheControl interface {
// WantEvict is called when object is going to be evicted from live cache and made ghost.
// If !ok the object will remain live.
WantEvict(obj Object) (ok bool)
}
// Connection represents a view of ZODB database. // Connection represents a view of ZODB database.
// //
// The view is representing state of ZODB objects as of `at` transaction. // The view is representing state of ZODB objects as of `at` transaction.
...@@ -200,6 +191,17 @@ type Connection struct { ...@@ -200,6 +191,17 @@ type Connection struct {
cacheControl LiveCacheControl cacheControl LiveCacheControl
} }
// LiveCacheControl is the interface that allows applications to influence
// Connection's decisions with respect to its live cache.
type LiveCacheControl interface {
// WantEvict is called when object is going to be evicted from live cache and made ghost.
// If !ok the object will remain live.
WantEvict(obj Object) (ok bool)
}
// ----------------------------------------
// Get returns in-RAM object corresponding to specified ZODB object according to current database view. // Get returns in-RAM object corresponding to specified ZODB object according to current database view.
// //
...@@ -211,7 +213,7 @@ type Connection struct { ...@@ -211,7 +213,7 @@ type Connection struct {
// The object's data is not neccessarily loaded after Get returns. Use // The object's data is not neccessarily loaded after Get returns. Use
// PActivate to make sure the object ifs fully loaded. // PActivate to make sure the object ifs fully loaded.
func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*PyObject*/, error) { func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*PyObject*/, error) {
conn.objmu.Lock() conn.objmu.Lock() // XXX -> rlock
wobj := conn.objtab[oid] wobj := conn.objtab[oid]
var xobj interface{} var xobj interface{}
if wobj != nil { if wobj != nil {
...@@ -263,7 +265,7 @@ func (e *wrongClassError) Error() string { ...@@ -263,7 +265,7 @@ func (e *wrongClassError) Error() string {
// //
// XXX object scope. // XXX object scope.
// //
// use-case: in ZODB references are (pyclass, oid), so new ghost is created // Use-case: in ZODB references are (pyclass, oid), so new ghost is created
// without further loading anything. // without further loading anything.
func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error) { func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error) {
conn.objmu.Lock() // XXX -> rlock conn.objmu.Lock() // XXX -> rlock
...@@ -298,22 +300,27 @@ func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error ...@@ -298,22 +300,27 @@ func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error
} }
// loadpy loads object specified by oid and decodes it as a ZODB Python object.
//
// loadpy does not create any in-RAM object associated with Connection.
// It only returns decoded database data.
func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickle.Class, pystate interface{}, serial zodb.Tid, _ error) { func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickle.Class, pystate interface{}, serial zodb.Tid, _ error) {
buf, serial, err := conn.stor.Load(ctx, zodb.Xid{Oid: oid, At: conn.at}) buf, serial, err := conn.stor.Load(ctx, zodb.Xid{Oid: oid, At: conn.at})
if err != nil { if err != nil {
return pickle.Class{}, nil, 0, err return pickle.Class{}, nil, 0, err
} }
defer buf.Release()
pyclass, pystate, err = zodb.PyData(buf.Data).Decode() pyclass, pystate, err = zodb.PyData(buf.Data).Decode()
if err != nil { if err != nil {
return pickle.Class{}, nil, 0, err // XXX err ctx return pickle.Class{}, nil, 0, err // XXX err ctx
} }
buf.Release()
return pyclass, pystate, serial, nil return pyclass, pystate, serial, nil
} }
// ---- pyclass -> new ghost ----
// path(class) -> new(pyobj) // path(class) -> new(pyobj)
var classTab = make(map[string]func(*pyObject)PyObject) var classTab = make(map[string]func(*pyObject)PyObject)
...@@ -445,5 +452,3 @@ func (pyobj *pyObject) PDeactivate() { ...@@ -445,5 +452,3 @@ func (pyobj *pyObject) PDeactivate() {
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified // XXX pyobj.PInvalidate() = deactivate without checking if state != modified
// XXX panic if refcnt != 0 (object being used) // XXX panic if refcnt != 0 (object being used)
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