Commit 6ba3593d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 7be36e9e
......@@ -36,7 +36,7 @@ type KEY int64
// are chained together via 'next', so that the entire BTree contents
// can be traversed in sorted order quickly and easily.
type ZBucket struct {
pyobj *pyObject
*pyObject
next *ZBucket // the bucket with the next-larger keys
keys []KEY // 'len' keys, in increasing order
......@@ -54,7 +54,7 @@ type zBTreeItem struct {
// See https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/Development.txt#L198
// for details.
type ZBTree struct {
pyobj *pyObject
*pyObject
// firstbucket points to the bucket containing the smallest key in
// the BTree. This is found by traversing leftmost child pointers
......@@ -154,7 +154,7 @@ func (t *ZBTree) PDeactivate() {
// XXX check if activated?
t.firstbucket = nil
t.data = nil
t.pyobj.PDeactivate()
t.pyObject.PDeactivate()
}
func (t *ZBTree) PActivate(ctx context.Context) error {
......@@ -186,18 +186,18 @@ func (b *ZBucket) PDeactivate() {
b.next = nil
b.keys = nil
b.values = nil
b.pyobj.PDeactivate()
b.pyObject.PDeactivate()
}
func (b *ZBucket) PActivate(ctx context.Context) error {
// XXX check if already activated
err := b.pyobj.PActivate(ctx)
err := b.pyObject.PActivate(ctx)
if err != nil {
return err
}
t, ok := b.pyobj.pystate.(pickle.Tuple)
t, ok := b.pyObject.pystate.(pickle.Tuple)
if !ok || !(1 <= len(t) && len(t) <= 2) {
// XXX complain
}
......@@ -239,12 +239,12 @@ func (b *ZBucket) PActivate(ctx context.Context) error {
// ----------------------------------------
func bucketNew(pyobj *pyObject) interface{} {
return &ZBucket{pyobj: pyobj}
func bucketNew(pyobj *pyObject) PyObject {
return &ZBucket{pyObject: pyobj}
}
func btreeNew(pyobj *pyObject) interface{} {
return &ZBTree{pyobj: pyobj}
func btreeNew(pyobj *pyObject) PyObject {
return &ZBTree{pyObject: pyobj}
}
func init() {
......
......@@ -24,6 +24,23 @@ import (
pickle "github.com/kisielk/og-rek"
)
// Object is the interface that every object representing any ZODB object implements.
type Object interface {
Jar() *Connection
Oid() zodb.Oid
Serial() zodb.Tid
// XXX activate/deactivate/invalidate here?
}
// PyObject is the interface that every object representing Python ZODB object implements.
type PyObject interface {
Object
PyClass() pickle.Class
// PyState?
}
// object is common base for in-process representation of ZODB object.
type object struct {
jar *Connection
......@@ -31,6 +48,10 @@ type object struct {
serial zodb.Tid
}
func (obj *object) Jar() *Connection { return obj.jar }
func (obj *object) Oid() zodb.Oid { return obj.oid }
func (obj *object) Serial() zodb.Tid { return obj.serial }
// pyObject is common base for in-process representation of ZODB Python objects.
type pyObject struct {
object
......@@ -39,6 +60,9 @@ type pyObject struct {
pystate interface{} // object state. python passes this to pyclass.__new__().__setstate__()
}
func (pyobj *pyObject) PyClass() pickle.Class { return pyobj.pyclass }
// Connection represents a view of ZODB database.
//
// The view is representing state of ZODB objects as of `at` transaction.
......@@ -232,24 +256,26 @@ func (e *wrongClassError) Error() string {
//
// use-case: in ZODB references are (pyclass, oid), so new ghost is created
// without further loading anything.
func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (interface{}/*PyObject*/, error) {
func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error) {
conn.objmu.Lock() // XXX -> rlock
wobj := conn.objtab[oid]
var xobj interface{}
var pyobj PyObject
checkClass := false
if wobj != nil {
xobj = wobj.Get()
if xobj := wobj.Get(); xobj != nil {
pyobj = xobj.(PyObject)
}
}
if xobj == nil {
xobj = conn.newGhost(pyclass, oid)
conn.objtab[oid] = NewWeakRef(xobj)
if pyobj == nil {
pyobj = conn.newGhost(pyclass, oid)
conn.objtab[oid] = NewWeakRef(pyobj)
} else {
checkClass = true
}
conn.objmu.Unlock()
if checkClass {
if cls := xobj.PyClass(); pyclass != cls {
if cls := pyobj.PyClass(); pyclass != cls {
return nil, &zodb.OpError{
URL: conn.stor.URL(),
Op: fmt.Sprintf("@%s: get", conn.at), // XXX abuse
......@@ -259,7 +285,7 @@ func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (interface{}/*Py
}
}
return xobj, nil
return pyobj, nil
}
......@@ -364,18 +390,18 @@ func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickl
}
// path(class) -> new(pyobj)
var classTab = make(map[string]func(*pyObject)interface{})
var classTab = make(map[string]func(*pyObject)PyObject)
// registerClass registers python class to be transformed to Go instance
// created via classNew.
//
// must be called from global init().
func registerClass(classPath string, classNew func(*pyObject)interface{}) {
func registerClass(classPath string, classNew func(*pyObject)PyObject) {
classTab[classPath] = classNew
}
// newGhost creates new ghost object corresponding to pyclass and oid.
func (conn *Connection) newGhost(pyclass pickle.Class, oid zodb.Oid) interface{} {
func (conn *Connection) newGhost(pyclass pickle.Class, oid zodb.Oid) PyObject {
pyobj := &pyObject{
object: object{jar: conn, oid: oid, serial: 0},
pyclass: pyclass,
......
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