Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
f532e0f2
Commit
f532e0f2
authored
Jul 17, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
9605b703
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
97 additions
and
55 deletions
+97
-55
wcfs/zodb.go
wcfs/zodb.go
+97
-55
No files found.
wcfs/zodb.go
View file @
f532e0f2
...
...
@@ -86,12 +86,6 @@ type Object interface {
PInvalidate
()
}
// XXX
type
Stateful
interface
{
// XXX
DropState
()
}
// PyObject is the interface that every in-RAM object representing Python ZODB object implements.
type
PyObject
interface
{
Object
...
...
@@ -99,21 +93,21 @@ type PyObject interface {
PyClass
()
pickle
.
Class
// python class of this object
// PyState() interface{} // object state. python passes this to pyclass.__new__().__setstate__()
PyStateful
// XXX want to hide from PyObject. Rationale: we do not want e.g. PySetState to
// be available to user who holds PyObject interface: it is confusing to have
// both PActivate and PySetState at the same time.
// PyStateful
}
// XXX
type
PyStateful
interface
{
Stateful
// PySetState should set Python state of the in-RAM object.
// Analog of __setstate__() in Python.
PySetState
(
pystate
interface
{})
error
// ObjectState describe state of in-RAM object.
type
ObjectState
int
// PyGetState should return Python state of in-RAM object.
// Analog of __getstate__() in Python.
//PyGetState() interface{} XXX
}
const
(
GHOST
ObjectState
=
-
1
UPTODATE
=
0
CHANGED
=
1
// no STICKY - we pin objects in RAM with PActivate
)
// object is common base for in-RAM implementations of ZODB objects.
type
object
struct
{
...
...
@@ -121,6 +115,8 @@ type object struct {
oid
zodb
.
Oid
serial
zodb
.
Tid
mu
sync
.
Mutex
state
ObjectState
refcnt
int32
}
...
...
@@ -131,17 +127,50 @@ func (obj *object) PSerial() zodb.Tid { return obj.serial }
// pyObject is common base for in-RAM implementations of ZODB Python objects.
type
pyObject
struct
{
object
pyclass
pickle
.
Class
// pystate interface{}
// protected by object.mu
instance
PyStateful
loaderr
error
// if there was error at state loading
ready
chan
struct
{}
// activation complete
loaded
*
loaded
// loaderr error // if there was error at state loading
// ready chan struct{} // activation complete
}
func
(
pyobj
*
pyObject
)
PyClass
()
pickle
.
Class
{
return
pyobj
.
pyclass
}
//func (pyobj *pyObject) PyState() interface{} { return pyobj.pystate }
// loaded indicates object's load state/result.
//
// when !ready the loading is in progress.
// when ready the loading has been completed.
type
loaded
struct
{
ready
chan
struct
{}
// closed when loading finishes
// error from the load.
// if there was no error loaded data goes to object state.
err
error
}
// XXX
type
Stateful
interface
{
// DropState should discard in-RAM object state.
DropState
()
}
// PyStateful is the interface describing in-RAM object whose data state can be
// exchanged as Python data.
type
PyStateful
interface
{
Stateful
// PySetState should set state of the in-RAM object from Python data.
// Analog of __setstate__() in Python.
PySetState
(
pystate
interface
{})
error
// PyGetState should return state of the in-RAM object as Python data.
// Analog of __getstate__() in Python.
//PyGetState() interface{} XXX
}
// Connection represents a view of ZODB database.
//
...
...
@@ -357,7 +386,7 @@ func registerClass(classPath string, classNew func(*pyObject)PyObject) {
// newGhost creates new ghost object corresponding to pyclass and oid.
func
(
conn
*
Connection
)
newGhost
(
pyclass
pickle
.
Class
,
oid
zodb
.
Oid
)
PyObject
{
pyobj
:=
&
pyObject
{
object
:
object
{
jar
:
conn
,
oid
:
oid
,
serial
:
0
},
object
:
object
{
jar
:
conn
,
oid
:
oid
,
serial
:
0
,
state
:
GHOST
},
pyclass
:
pyclass
,
}
...
...
@@ -392,22 +421,16 @@ func (d *dummyPyInstance) PySetState(pystate interface{}) error {
// ----------------------------------------
/*
func (obj *object) PActivate(ctx context.Context) error {
// XXX
}
func (obj *object) PDeactivate() {
// XXX
}
// object's activate & friends that only manage base activation state, without actually loading data.
// PInvalidate
*/
// object's pactivate & friends that only manage base activation state, without actually loading data.
// XXX -> incref ?
func
(
obj
*
object
)
pactivate
()
(
load
bool
)
{
// activate increments object reference counter.
//
// it returns whether object data needs to be loaded.
// must be called with .mu held.
func
(
obj
*
object
)
activate
()
(
load
bool
)
{
obj
.
refcnt
++
return
(
obj
.
refcnt
==
1
&&
obj
.
state
==
GHOST
)
/*
nuse := atomic.AddInt32(&obj.refcnt, +1)
if nuse == 1 {
// we become responsible for loading object's data.
...
...
@@ -415,21 +438,28 @@ func (obj *object) pactivate() (load bool) {
return true
}
return false
*/
}
// XXX -> decref ?
func
(
obj
*
object
)
pdeactivate
()
(
drop
bool
)
{
nuse
:=
atomic
.
AddInt32
(
&
obj
.
refcnt
,
-
1
)
if
nuse
<
0
{
panic
(
"pdeactivate: nuse < 0"
)
// deactivate decrements object reference counter.
//
// it returns whether object data needs to be discarded.
// must be called with .mu held.
func
(
obj
*
object
)
deactivate
()
(
drop
bool
)
{
//nuse := atomic.AddInt32(&obj.refcnt, -1)
obj
.
refcnt
--
if
obj
.
refcnt
<
0
{
panic
(
"deactivate: refcnt < 0"
)
}
if
nuse
>
0
{
if
obj
.
refcnt
>
0
{
return
// users still left
}
// no users left. Let's see whether we should transition this object to ghost.
// TODO state=modified -> don't drop.
drop
=
true
if
obj
.
state
>=
CHANGED
{
drop
=
false
}
// XXX -> pyObject?
if
drop
{
...
...
@@ -440,7 +470,7 @@ func (obj *object) pdeactivate() (drop bool) {
if
drop
{
obj
.
serial
=
0
//obj.ins
ance.DropState()
obj
.
inst
ance
.
DropState
()
}
return
drop
...
...
@@ -449,26 +479,35 @@ func (obj *object) pdeactivate() (drop bool) {
// PActivate implements Object.
func
(
pyobj
*
pyObject
)
PActivate
(
ctx
context
.
Context
)
(
err
error
)
{
load
:=
pyobj
.
object
.
pactivate
()
pyobj
.
mu
.
Lock
()
doload
:=
pyobj
.
activate
()
defer
func
()
{
if
err
!=
nil
{
// no need to check for drop - the state is already
// dropped - we just need to decref here.
pyobj
.
object
.
pdeactivate
()
// XXX locking?
pyobj
.
deactivate
()
}
}()
if
!
load
{
if
!
doload
{
loading
:=
pyobj
.
loading
pyobj
.
mu
.
Unlock
()
// someone else is already activated/activating the object.
// wait for its loading to complete and we are done.
select
{
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
// XXX err ctx
case
<-
pyobj
.
ready
:
return
pyobj
.
loaderr
// XXX err ctx?
case
<-
loading
.
ready
:
return
loading
.
err
// XXX err ctx?
}
}
// we become responsible for loading the object
loading
:=
&
loading
{
ready
:
make
(
chan
struct
{})}
pyobj
.
loading
=
loading
// XXX assert before it was = nil ?
pyobj
.
mu
.
Unlock
()
pyclass
,
pystate
,
serial
,
err
:=
pyobj
.
jar
.
loadpy
(
ctx
,
pyobj
.
oid
)
if
err
==
nil
&&
pyclass
!=
pyobj
.
pyclass
{
// complain pyclass changed
...
...
@@ -477,6 +516,8 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
pystate
=
nil
}
pyobj
.
mu
.
Lock
()
pyobj
.
serial
=
serial
// pyobj.pystate = pystate
...
...
@@ -487,16 +528,17 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
pyobj
.
instance
.
DropState
()
}
pyobj
.
loaderr
=
err
// XXX unlock
close
(
pyobj
.
ready
)
loading
.
err
=
err
close
(
loading
.
ready
)
return
err
// XXX err ctx
}
// PDeactivate implements Object.
func
(
pyobj
*
pyObject
)
PDeactivate
()
{
drop
:=
pyobj
.
object
.
pdeactivate
()
drop
:=
pyobj
.
pdeactivate
()
if
!
drop
{
return
}
...
...
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