Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
7757f824
Commit
7757f824
authored
Jul 27, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
9c1b50a6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
50 additions
and
36 deletions
+50
-36
go/zodb/connection.go
go/zodb/connection.go
+27
-13
go/zodb/persistent.go
go/zodb/persistent.go
+20
-3
go/zodb/zodbpy.go
go/zodb/zodbpy.go
+3
-20
No files found.
go/zodb/connection.go
View file @
7757f824
...
@@ -110,14 +110,25 @@ type LiveCacheControl interface {
...
@@ -110,14 +110,25 @@ type LiveCacheControl interface {
// ---- class <-> type; new ghost ----
// ---- class <-> type; new ghost ----
var
class2Type
=
make
(
map
[
string
]
reflect
.
Type
)
// {} class -> (type, stateType)
// zclass describes one ZODB class in relation to Go type.
var
type2Class
=
make
(
map
[
reflect
.
Type
]
string
)
// {} type -> (class, stateType)
type
zclass
struct
{
class
string
typ
reflect
.
Type
// application go type corresponding to class
stateType
reflect
.
Type
// *typ and *stateType are convertible; *stateType provides Statufl & co.
}
var
classTab
=
make
(
map
[
string
]
*
zclass
)
// {} class -> zclass
var
typeTab
=
make
(
map
[
reflect
.
Type
]
*
zclass
)
// {} type -> zclass
// zclassOf returns ZODB class of a Go object.
// zclassOf returns ZODB class of a Go object.
//
//
// If ZODB class was not registered for obj's type, "" is returned.
// If ZODB class was not registered for obj's type, "" is returned.
func
zclassOf
(
obj
IPersistent
)
string
{
func
zclassOf
(
obj
IPersistent
)
string
{
return
type2Class
[
reflect
.
TypeOf
(
obj
)]
zc
,
ok
:=
typeTab
[
reflect
.
TypeOf
(
obj
)]
if
!
ok
{
return
""
}
return
zc
.
class
}
}
var
rIPersistent
=
reflect
.
TypeOf
((
*
IPersistent
)(
nil
))
.
Elem
()
// typeof(IPersistent)
var
rIPersistent
=
reflect
.
TypeOf
((
*
IPersistent
)(
nil
))
.
Elem
()
// typeof(IPersistent)
...
@@ -133,7 +144,7 @@ var rPyStateful = reflect.TypeOf((*PyStateful)(nil)).Elem() // typeof(PyStatef
...
@@ -133,7 +144,7 @@ var rPyStateful = reflect.TypeOf((*PyStateful)(nil)).Elem() // typeof(PyStatef
// typ must be convertible to stateType; stateType must implement Ghostable and
// typ must be convertible to stateType; stateType must implement Ghostable and
// either Stateful or PyStateful(*)
// either Stateful or PyStateful(*)
//
//
//
M
ust be called from global init().
//
RegisterClass m
ust be called from global init().
//
//
// (*) the rationale for stateType coming separately is that this way for
// (*) the rationale for stateType coming separately is that this way for
// application types it is possible not to expose Ghostable and Stateful
// application types it is possible not to expose Ghostable and Stateful
...
@@ -147,8 +158,8 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
...
@@ -147,8 +158,8 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
if
class
==
""
{
if
class
==
""
{
badf
(
"class must be not empty"
)
badf
(
"class must be not empty"
)
}
}
if
typ
,
already
:=
class2Type
[
class
];
already
{
if
zc
,
already
:=
classTab
[
class
];
already
{
badf
(
"class already registered for %q"
,
typ
)
badf
(
"class already registered for %q"
,
zc
.
typ
)
}
}
// typ must have IPersistent embedded
// typ must have IPersistent embedded
...
@@ -183,8 +194,9 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
...
@@ -183,8 +194,9 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
// XXX check if class was already registered
// XXX check if class was already registered
// XXX check class != ""
// XXX check class != ""
class2Type
[
class
]
=
typ
zc
:=
&
zclass
{
class
:
class
,
typ
:
typ
,
stateType
:
stateType
}
type2Class
[
typ
]
=
class
classTab
[
class
]
=
zc
typeTab
[
typ
]
=
zc
}
}
...
@@ -192,11 +204,11 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
...
@@ -192,11 +204,11 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
func
(
conn
*
Connection
)
newGhost
(
class
string
,
oid
Oid
)
IPersistent
{
func
(
conn
*
Connection
)
newGhost
(
class
string
,
oid
Oid
)
IPersistent
{
// switch on class and transform e.g. "zodb.BTree.Bucket" -> btree.Bucket
// switch on class and transform e.g. "zodb.BTree.Bucket" -> btree.Bucket
var
xpobj
reflect
.
Value
// *typ
var
xpobj
reflect
.
Value
// *typ
typ
:=
class2Type
[
class
]
zc
:=
classTab
[
class
]
if
typ
==
nil
{
if
zc
==
nil
{
xpobj
=
reflect
.
ValueOf
(
&
Broken
{
class
:
class
})
xpobj
=
reflect
.
ValueOf
(
&
Broken
{
class
:
class
})
}
else
{
}
else
{
xpobj
=
reflect
.
New
(
typ
)
xpobj
=
reflect
.
New
(
zc
.
typ
)
}
}
base
:=
&
Persistent
{
jar
:
conn
,
oid
:
oid
,
serial
:
0
,
state
:
GHOST
}
base
:=
&
Persistent
{
jar
:
conn
,
oid
:
oid
,
serial
:
0
,
state
:
GHOST
}
...
@@ -216,12 +228,14 @@ type Broken struct {
...
@@ -216,12 +228,14 @@ type Broken struct {
state
*
mem
.
Buf
state
*
mem
.
Buf
}
}
func
(
b
*
Broken
)
DropState
()
{
type
brokenState
Broken
func
(
b
*
brokenState
)
DropState
()
{
b
.
state
.
XRelease
()
b
.
state
.
XRelease
()
b
.
state
=
nil
b
.
state
=
nil
}
}
func
(
b
*
Broken
)
SetState
(
state
*
mem
.
Buf
)
error
{
func
(
b
*
brokenState
)
SetState
(
state
*
mem
.
Buf
)
error
{
b
.
state
.
XRelease
()
b
.
state
.
XRelease
()
state
.
Incref
()
state
.
Incref
()
b
.
state
=
state
b
.
state
=
state
...
...
go/zodb/persistent.go
View file @
7757f824
...
@@ -110,7 +110,10 @@ const (
...
@@ -110,7 +110,10 @@ const (
// no STICKY - we pin objects in RAM with PActivate
// no STICKY - we pin objects in RAM with PActivate
)
)
// Persistent is common base implementation for in-RAM representation of database objects.
// Persistent is common base IPersistent implementation for in-RAM
// representation of database objects.
//
// XXX it requires it to embed and provide Ghostable + Stateful.
type
Persistent
struct
{
type
Persistent
struct
{
jar
*
Connection
jar
*
Connection
oid
Oid
oid
Oid
...
@@ -119,7 +122,10 @@ type Persistent struct {
...
@@ -119,7 +122,10 @@ type Persistent struct {
mu
sync
.
Mutex
mu
sync
.
Mutex
state
ObjectState
state
ObjectState
refcnt
int32
refcnt
int32
instance
interface
{
IPersistent
;
Ghostable
;
Stateful
}
// Persistent should be the base for the instance
// Persistent should be the base for the instance.
// instance is additionally either Stateful | PyStateful.
instance
interface
{
IPersistent
;
Ghostable
}
// XXX Ghostable also not good here
loading
*
loadState
loading
*
loadState
}
}
...
@@ -203,7 +209,18 @@ func (obj *Persistent) PActivate(ctx context.Context) (err error) {
...
@@ -203,7 +209,18 @@ func (obj *Persistent) PActivate(ctx context.Context) (err error) {
// try to pass loaded state to object
// try to pass loaded state to object
if
err
==
nil
{
if
err
==
nil
{
err
=
obj
.
instance
.
SetState
(
state
)
// XXX err ctx
// XXX wrong: obj.instance is not Stateful (not to show it to public API)
switch
inst
:=
obj
.
instance
.
(
type
)
{
case
Stateful
:
err
=
inst
.
SetState
(
state
)
// XXX err ctx
case
PyStateful
:
err
=
pySetState
(
inst
,
state
)
// XXX err ctx
default
:
panic
(
"!stateful instance"
)
}
state
.
Release
()
state
.
Release
()
if
err
==
nil
{
if
err
==
nil
{
obj
.
state
=
UPTODATE
obj
.
state
=
UPTODATE
...
...
go/zodb/zodbpy.go
View file @
7757f824
...
@@ -24,14 +24,6 @@ import (
...
@@ -24,14 +24,6 @@ import (
pickle
"github.com/kisielk/og-rek"
pickle
"github.com/kisielk/og-rek"
)
)
// PyPersistent is common base implementation for in-RAM representation of ZODB Python objects.
type
PyPersistent
struct
{
Persistent
}
//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
// PyStateful is the interface describing in-RAM object whose data state can be
// exchanged as Python data.
// exchanged as Python data.
type
PyStateful
interface
{
type
PyStateful
interface
{
...
@@ -44,24 +36,15 @@ type PyStateful interface {
...
@@ -44,24 +36,15 @@ type PyStateful interface {
//PyGetState() interface{} TODO
//PyGetState() interface{} TODO
}
}
// ---- PyPersistent <-> Persistent state exchange ----
// pySetState decodes raw state as zodb/py serialized stream, and sets decoded
// state on PyStateful obj.
// pyinstance returns .instance upcasted to XXXPy.
func
pySetState
(
obj
PyStateful
,
state
*
mem
.
Buf
)
error
{
//
// this should be always safe because we always create pyObjects via
// newGhost which passes IPyPersistent as instance to IPersistent. XXX no longer true
func
(
pyobj
*
PyPersistent
)
pyinstance
()
interface
{
IPersistent
;
Ghostable
;
PyStateful
}
{
return
pyobj
.
instance
.
(
interface
{
IPersistent
;
Ghostable
;
PyStateful
})
}
func
(
pyobj
*
PyPersistent
)
SetState
(
state
*
mem
.
Buf
)
error
{
pyclass
,
pystate
,
err
:=
PyData
(
state
.
Data
)
.
Decode
()
pyclass
,
pystate
,
err
:=
PyData
(
state
.
Data
)
.
Decode
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
// XXX err ctx
return
err
// XXX err ctx
}
}
class
:=
pyclassPath
(
pyclass
)
class
:=
pyclassPath
(
pyclass
)
obj
:=
pyobj
.
pyinstance
()
if
objClass
:=
zclassOf
(
obj
);
class
!=
objClass
{
if
objClass
:=
zclassOf
(
obj
);
class
!=
objClass
{
// complain that pyclass changed
// complain that pyclass changed
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment