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
bb378738
Commit
bb378738
authored
Jul 16, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
64356821
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
101 additions
and
30 deletions
+101
-30
wcfs/btree.go
wcfs/btree.go
+3
-2
wcfs/zodb.go
wcfs/zodb.go
+98
-28
No files found.
wcfs/btree.go
View file @
bb378738
...
...
@@ -190,9 +190,10 @@ func (b *ZBucket) PDeactivate() {
}
func
(
b
*
ZBucket
)
PActivate
(
ctx
context
.
Context
)
error
{
// PActivate implements Object.
func
(
b
*
ZBucket
)
PActivate
(
ctx
context
.
Context
)
(
bool
,
error
)
{
// XXX check if already activated
err
:=
b
.
pyObject
.
PActivate
(
ctx
)
activated
,
err
:=
b
.
pyObject
.
PActivate
(
ctx
)
if
err
!=
nil
{
return
err
}
...
...
wcfs/zodb.go
View file @
bb378738
...
...
@@ -31,8 +31,10 @@ type Object interface {
POid
()
zodb
.
Oid
PSerial
()
zodb
.
Tid
// PActivate requests in-RAM object data to be present.
// PActivate brings object to live state.
//
// It requests to persistency layer that in-RAM object data to be present.
// If object state is not in RAM - it is loaded from the database.
//
// On successful return the object data is either the same as in the
// database or, if this data was previously modified by user of
...
...
@@ -40,7 +42,7 @@ type Object interface {
//
// Object data must be accessed only after corresponding PActivate
// call, which marks that object's data as being in use.
PActivate
(
ctx
context
.
Context
)
error
// XXX + -> nuse ?
PActivate
(
ctx
context
.
Context
)
(
activated
bool
,
_
error
)
// XXX + -> nuse ?
// PDeactivate indicates that corresponding PActivate caller finished access to object's data.
//
...
...
@@ -51,15 +53,20 @@ type Object interface {
// Note that it is valid to have several concurrent uses of object
// data, each protected with corresponding PActivate/PDeactivate pair:
// As long as there is still any PActivate not yet compensated with
// corresponding PDeactivate, object data will stay alive in RAM.
// corresponding PDeactivate, object data will
assuredly
stay alive in RAM.
//
// Besides exotic cases, the caller thus must not use object's data
// after PDeactivate call.
PDeactivate
()
// XXX + -> nuse ?
PInvalidate
()
// XXX must not be called while there are users.
// PInvalidate requests in-RAM object data to be discarded.
//
// Irregardless of whether in-RAM object data is the same as in the
// database, or it was modified, that in-RAM data must be forgotten.
//
// PInvalidate must not be called while there is any in-progress
// object's data use (PActivate / PDeactivate).
PInvalidate
()
}
// PyObject is the interface that every in-RAM object representing Python ZODB object implements.
...
...
@@ -68,6 +75,7 @@ type PyObject interface {
PyClass
()
pickle
.
Class
// python class of this object
PyState
()
interface
{}
// object state. python passes this to pyclass.__new__().__setstate__()
}
// object is common base for in-RAM representation of ZODB object.
...
...
@@ -75,6 +83,8 @@ type object struct {
jar
*
Connection
oid
zodb
.
Oid
serial
zodb
.
Tid
refcnt
int32
}
func
(
obj
*
object
)
PJar
()
*
Connection
{
return
obj
.
jar
}
...
...
@@ -87,6 +97,8 @@ type pyObject struct {
pyclass
pickle
.
Class
pystate
interface
{}
loaderr
error
// if there was error at state loading
ready
chan
struct
{}
// activation complete
}
func
(
pyobj
*
pyObject
)
PyClass
()
pickle
.
Class
{
return
pyobj
.
pyclass
}
...
...
@@ -226,7 +238,7 @@ func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*Py
return nil, ctx.Err() // XXX err ctx
case <-load.ready:
// XXX check pyclass match
return load.pyobj, err
return load.pyobj,
load.
err
}
}
...
...
@@ -451,38 +463,96 @@ func (conn *Connection) newGhost(pyclass pickle.Class, oid zodb.Oid) PyObject {
}
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified
// PDeactivates transforms object to ghost state.
//
// In ghost state object data is dropped and only oid/pyclass information is left in RAM.
func
(
pyobj
*
pyObject
)
PDeactivate
()
{
// FIXME if state=modified PDeactivate must be noop.
// ----------------------------------------
pyobj
.
pystate
=
nil
pyobj
.
serial
=
0
/*
func (obj *object) PActivate(ctx context.Context) error {
// XXX
}
// PActivate brings object to live state.
//
// If object state is not in RAM - it is loaded from the database.
func
(
pyobj
*
pyObject
)
PActivate
(
ctx
context
.
Context
)
error
{
if
pyobj
.
pystate
!=
nil
{
return
nil
// already loaded
func (obj *object) PDeactivate() {
// XXX
}
// PInvalidate
*/
// object's pactivate & friends that only manage base activation state, without actually loading data.
func
(
obj
*
object
)
pactivate
(
ctx
context
.
Context
)
error
{
nuse
:=
atomic
.
AddInt32
(
&
obj
.
refcnt
,
+
1
)
if
nuse
==
1
{
// we become responsible for loading object's data.
// XXX check .tryToKeepInRam
}
}
pyclass
,
pystate
,
serial
,
err
:=
pyobj
.
jar
.
loadpy
(
ctx
,
pyobj
.
oid
)
if
err
!=
nil
{
return
err
func
(
obj
*
object
)
pdeactivate
()
{
nuse
:=
atomic
.
AddInt32
(
&
obj
.
refcnt
,
-
1
)
if
nuse
<
0
{
panic
(
"pdeactivate: nuse < 0"
)
}
if
nuse
>
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.
if
drop
{
obj
.
serial
=
0
}
}
// PActivate implements Object.
func
(
pyobj
*
pyObject
)
PActivate
(
ctx
context
.
Context
)
(
bool
,
error
)
{
load
:=
pyobj
.
object
.
pactivate
()
if
!
load
{
// someone else is already activated/activating the object.
// wait for its loading to complete and we are done.
select
{
case
<-
ctx
.
Done
:
return
false
,
ctx
.
Err
()
// XXX err ctx
case
<-
pyobj
.
ready
:
return
(
pyobj
.
loaderr
==
nil
),
pyobj
.
loaderr
// XXX err ctx?
}
}
if
pyclass
!=
pyobj
.
pyclass
{
// we become responsible for loading the object
pyclass
,
pystate
,
serial
,
err
:=
pyobj
.
jar
.
loadpy
(
ctx
,
pyobj
.
oid
)
if
err
==
nil
&&
pyclass
!=
pyobj
.
pyclass
{
// complain pyclass changed
// (both ref and object data uses pyclass so it indeed can be different)
return
&
wrongClassError
{
want
:
pyobj
.
pyclass
,
have
:
pyclass
}
// XXX + err ctx
err
=
&
wrongClassError
{
want
:
pyobj
.
pyclass
,
have
:
pyclass
}
// XXX + err ctx
pystate
=
nil
}
pyobj
.
serial
=
serial
pyobj
.
pystate
=
pystate
return
nil
pyobj
.
loaderr
=
err
close
(
pyobj
.
ready
)
return
err
// XXX err ctx
}
// PDeactivate implements Object.
func
(
pyobj
*
pyObject
)
PDeactivate
()
{
drop
:=
pyobj
.
object
.
pdeactivate
()
if
!
drop
{
return
}
// we have to drop pyobject state
// XXX locking?
pyobj
.
pystate
=
nil
pyobj
.
loaderr
=
nil
pyobj
.
ready
=
make
(
chan
struct
{})
return
drop
}
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified
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