Commit 8e7e9dcb authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 8192892a
...@@ -178,14 +178,16 @@ func (b *Bucket) get(key KEY) (interface{}, bool) { ...@@ -178,14 +178,16 @@ func (b *Bucket) get(key KEY) (interface{}, bool) {
// //
// In the above, key[i] means self->data[i].key, and similarly for child[i]. // In the above, key[i] means self->data[i].key, and similarly for child[i].
type btreeState BTree // hide state methods from public API
// DropState implements zodb.Stateful. // DropState implements zodb.Stateful.
func (t *BTree) DropState() { func (t *btreeState) DropState() {
t.firstbucket = nil t.firstbucket = nil
t.data = nil t.data = nil
} }
// PySetState implements zodb.PyStateful to set btree data from pystate. // PySetState implements zodb.PyStateful to set btree data from pystate.
func (bt *BTree) PySetState(pystate interface{}) error { func (bt *btreeState) PySetState(pystate interface{}) error {
// empty btree // empty btree
if _, ok := pystate.(pickle.None); ok { if _, ok := pystate.(pickle.None); ok {
bt.firstbucket = nil bt.firstbucket = nil
...@@ -201,7 +203,7 @@ func (bt *BTree) PySetState(pystate interface{}) error { ...@@ -201,7 +203,7 @@ func (bt *BTree) PySetState(pystate interface{}) error {
// btree with 1 child bucket without oid // btree with 1 child bucket without oid
if len(t) == 1 { if len(t) == 1 {
bucket := &Bucket{PyPersistent: nil /* FIXME */} bucket := &Bucket{PyPersistent: nil /* FIXME */}
err := bucket.PySetState(t[0]) err := (*bucketState)(bucket).PySetState(t[0])
if err != nil { if err != nil {
// XXX // XXX
} }
...@@ -265,15 +267,17 @@ func (bt *BTree) PySetState(pystate interface{}) error { ...@@ -265,15 +267,17 @@ func (bt *BTree) PySetState(pystate interface{}) error {
// <self->next iff non-NULL> // <self->next iff non-NULL>
// ) // )
type bucketState Bucket // hide state methods from public API
// DropState implements Stateful to discard bucket state. // DropState implements Stateful to discard bucket state.
func (b *Bucket) DropState() { func (b *bucketState) DropState() {
b.next = nil b.next = nil
b.keys = nil b.keys = nil
b.values = nil b.values = nil
} }
// PySetState implements PyStateful to set bucket data from pystate. // PySetState implements PyStateful to set bucket data from pystate.
func (b *Bucket) PySetState(pystate interface{}) error { func (b *bucketState) PySetState(pystate interface{}) error {
t, ok := pystate.(pickle.Tuple) t, ok := pystate.(pickle.Tuple)
if !ok || !(1 <= len(t) && len(t) <= 2) { if !ok || !(1 <= len(t) && len(t) <= 2) {
// XXX complain // XXX complain
...@@ -318,6 +322,7 @@ func (b *Bucket) PySetState(pystate interface{}) error { ...@@ -318,6 +322,7 @@ func (b *Bucket) PySetState(pystate interface{}) error {
// ---- register classes to ZODB ---- // ---- register classes to ZODB ----
func init() { func init() {
zodb.RegisterClass("zodb.BTree.LOBucket", reflect.TypeOf(Bucket{})) t := reflect.TypeOf
zodb.RegisterClass("zodb.BTree.LOBtree", reflect.TypeOf(BTree{})) zodb.RegisterClass("zodb.BTree.LOBucket", t(Bucket{}), t(bucketState{}))
zodb.RegisterClass("zodb.BTree.LOBtree", t(BTree{}), t(btreeState{}))
} }
...@@ -110,8 +110,8 @@ type LiveCacheControl interface { ...@@ -110,8 +110,8 @@ type LiveCacheControl interface {
// ---- class <-> type; new ghost ---- // ---- class <-> type; new ghost ----
var class2Type = make(map[string]reflect.Type) // {} class -> type var class2Type = make(map[string]reflect.Type) // {} class -> (type, stateType)
var type2Class = make(map[reflect.Type]string) // {} type -> class var type2Class = make(map[reflect.Type]string) // {} type -> (class, stateType)
// zclassOf returns ZODB class of a Go object. // zclassOf returns ZODB class of a Go object.
// //
...@@ -128,11 +128,17 @@ var rPyStateful = reflect.TypeOf((*PyStateful)(nil)).Elem() // typeof(PyStatef ...@@ -128,11 +128,17 @@ var rPyStateful = reflect.TypeOf((*PyStateful)(nil)).Elem() // typeof(PyStatef
// RegisterClass registers ZODB class to correspond to Go type. // RegisterClass registers ZODB class to correspond to Go type.
// //
// type must embed IPersistent. // typ must embed IPersistent; *typ must implement IPersistent.
// *type must implement IPersistent, Ghostable and either Stateful or PyStateful. //
// typ must be convertible to stateType; stateType must implement Ghostable and
// either Stateful or PyStateful(*)
// //
// Must be called from global init(). // Must be called from global init().
func RegisterClass(class string, typ reflect.Type) { //
// (*) the rationale for stateType coming separately is that this way for
// application types it is possible not to expose Ghostable and Stateful
// methods in their public API.
func RegisterClass(class string, typ, stateType reflect.Type) {
badf := func(format string, argv ...interface{}) { badf := func(format string, argv ...interface{}) {
msg := fmt.Sprintf(format, argv...) msg := fmt.Sprintf(format, argv...)
panic(fmt.Sprintf("zodb: register class (%q, %q): %s", class, typ, msg)) panic(fmt.Sprintf("zodb: register class (%q, %q): %s", class, typ, msg))
...@@ -146,6 +152,8 @@ func RegisterClass(class string, typ reflect.Type) { ...@@ -146,6 +152,8 @@ func RegisterClass(class string, typ reflect.Type) {
} }
// typ must have IPersistent embedded // typ must have IPersistent embedded
// TODO later change to directly embedding non-pointer Persistent | PyPersistent
// (optimize memory + less allocation)
basef, ok := typ.FieldByName("IPersistent") basef, ok := typ.FieldByName("IPersistent")
if !(ok && basef.Anonymous && basef.Type == rIPersistent) { if !(ok && basef.Anonymous && basef.Type == rIPersistent) {
badf("type does not embed IPersistent") badf("type does not embed IPersistent")
......
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