Commit 922b606d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 94e71512
......@@ -112,7 +112,7 @@ type LiveCacheControl interface {
// XXX type Class string ?
// function representing new of a class.
type classNewFunc func(base *PyPersistent) IPyPersistent // XXX Py -> ø
type classNewFunc func(base *Persistent) IPersistent
// {} class -> new(pyobj XXX)
var classTab = make(map[string]classNewFunc)
......@@ -129,36 +129,36 @@ func RegisterClass(class string, classNew classNewFunc) {
// newGhost creates new ghost object corresponding to class and oid.
func (conn *Connection) newGhost(class string, oid Oid) IPersistent {
pyobj := &PyPersistent{
Persistent: Persistent{jar: conn, oid: oid, serial: 0, state: GHOST},
pyclass: pyclass,
}
base := &Persistent{class: class, jar: conn, oid: oid, serial: 0, state: GHOST}
// switch on pyclass and transform e.g. "zodb.BTree.Bucket" -> *ZBucket
classNew := classTab[class]
var instance IPersistent
if classNew != nil {
instance = classNew(pyobj)
instance = classNew(base)
} else {
instance = &Broken{PyPersistent: pyobj}
instance = &Broken{Persistent: base}
}
pyobj.instance = instance
base.instance = instance
return instance
}
// Broken is used for classes that were not registered.
type Broken struct {
*Persistent
pystate interface{} // XXX py -> ø ?
state *mem.Buf
}
func (b *Broken) DropState() {
b.pystate = nil
b.state.XRelease()
b.state = nil
}
func (b *Broken) PySetState(pystate interface{}) error {
b.pystate = pystate
func (b *Broken) SetState(state *mem.Buf) error {
b.state.XRelease()
state.Incref()
b.state = state
return nil
}
......@@ -206,7 +206,7 @@ func (conn *Connection) get(class string, oid Oid) (IPersistent, error) {
if checkClass {
// XXX get obj class via reflection?
if cls := obj.PyClass(); class != cls {
if cls := obj.zclass(); class != cls {
return nil, &OpError{
URL: conn.stor.URL(),
Op: fmt.Sprintf("@%s: get", conn.at), // XXX abuse
......
......@@ -31,6 +31,8 @@ import (
//
// XXX safe to access from multiple goroutines simultaneously.
type IPersistent interface {
zclass() string // ZODB class of this object. XXX remove from IPersistent?
PJar() *Connection // Connection this in-RAM object is part of.
POid() Oid // object ID in the database.
......@@ -117,6 +119,8 @@ const (
// Persistent is common base implementation for in-RAM representation of database objects.
type Persistent struct {
class string // zodb class of this object. XXX try not to store and retrieve via reflect?
jar *Connection
oid Oid
serial Tid
......@@ -128,6 +132,7 @@ type Persistent struct {
loading *loadState
}
func (obj *Persistent) zclass() string { return obj.class }
func (obj *Persistent) PJar() *Connection { return obj.jar }
func (obj *Persistent) POid() Oid { return obj.oid }
func (obj *Persistent) PSerial() Tid { return obj.serial }
......
......@@ -28,7 +28,7 @@ import (
type IPyPersistent interface {
IPersistent
PyClass() pickle.Class // python class of this object
//PyClass() pickle.Class // python class of this object
// PyState() interface{} // object state. python passes this to pyclass.__new__().__setstate__()
// IPyPersistent must be stateful for persistency to work
......@@ -44,7 +44,7 @@ type PyPersistent struct {
pyclass pickle.Class
}
func (pyobj *PyPersistent) PyClass() pickle.Class { return pyobj.pyclass }
//func (pyobj *PyPersistent) PyClass() pickle.Class { return pyobj.pyclass }
//func (pyobj *PyPersistent) PyState() interface{} { return pyobj.pystate }
// PyStateful is the interface describing in-RAM object whose data state can be
......@@ -75,10 +75,11 @@ func (pyobj *PyPersistent) SetState(state *mem.Buf) error {
return err // XXX err ctx
}
if pyclass != pyobj.pyclass {
class := pyclassPath(pyclass)
if class != pyobj.class {
// complain that pyclass changed
// (both ref and object data use pyclass so it indeed can be different)
return &wrongClassError{want: pyobj.pyclass, have: pyclass} // XXX + err ctx
return &wrongClassError{want: pyobj.class, have: class} // XXX + err ctx
}
return pyobj.pyinstance().PySetState(pystate) // XXX err ctx = ok?
......@@ -143,6 +144,12 @@ func (d *dummyPyInstance) PySetState(pystate interface{}) error {
// ----------------------------------------
// pyclassPath returns full path for a python class.
//
// for example class "ABC" in module "wendelin.lib" has its full path as "wendelin.lib.ABC".
func pyclassPath(pyclass pickle.Class) string {
return pyclass.Module + "." + pyclass.Name
}
// loadpy loads object specified by oid and decodes it as a ZODB Python object.
//
......@@ -156,11 +163,10 @@ func (conn *Connection) loadpy(ctx context.Context, oid Oid) (class string, pyst
defer buf.Release()
pyclass, pystate, err = PyData(buf.Data).Decode()
pyclass, pystate, err := PyData(buf.Data).Decode()
if err != nil {
return "", nil, 0, err // XXX err ctx
}
class := pyclass.Module + "." + pyclass.Name // full pyclass path
return class, pystate, serial, nil
return pyclassPath(pyclass), pystate, serial, nil
}
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