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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Joshua
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