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
0f146bcb
Commit
0f146bcb
authored
Jul 19, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
f532e0f2
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
60 additions
and
42 deletions
+60
-42
wcfs/zodb.go
wcfs/zodb.go
+60
-42
No files found.
wcfs/zodb.go
View file @
0f146bcb
...
...
@@ -18,7 +18,7 @@ import (
"context"
"fmt"
"sync"
"sync/atomic"
//
"sync/atomic"
"lab.nexedi.com/kirr/neo/go/zodb"
...
...
@@ -109,7 +109,7 @@ const (
// no STICKY - we pin objects in RAM with PActivate
)
// object is common base
for in-RAM implementations
of ZODB objects.
// object is common base
implementation for in-RAM representation
of ZODB objects.
type
object
struct
{
jar
*
Connection
oid
zodb
.
Oid
...
...
@@ -124,30 +124,28 @@ func (obj *object) PJar() *Connection { return obj.jar }
func
(
obj
*
object
)
POid
()
zodb
.
Oid
{
return
obj
.
oid
}
func
(
obj
*
object
)
PSerial
()
zodb
.
Tid
{
return
obj
.
serial
}
// pyObject is common base
for in-RAM implementations
of ZODB Python objects.
// pyObject is common base
implementation for in-RAM representation
of ZODB Python objects.
type
pyObject
struct
{
object
pyclass
pickle
.
Class
// protected by object.mu
instance
PyStateful
loaded
*
loaded
// loaderr error // if there was error at state loading
// ready chan struct{} // activation complete
loading
*
loadState
}
func
(
pyobj
*
pyObject
)
PyClass
()
pickle
.
Class
{
return
pyobj
.
pyclass
}
//func (pyobj *pyObject) PyState() interface{} { return pyobj.pystate }
// load
ed
indicates object's load state/result.
// load
State
indicates object's load state/result.
//
// when !ready the loading is in progress.
// when ready the loading has been completed.
type
load
ed
struct
{
type
load
State
struct
{
ready
chan
struct
{}
// closed when loading finishes
// error from the load.
// if there was no error loaded data goes to object state.
// if there was no error
,
loaded data goes to object state.
err
error
}
...
...
@@ -426,6 +424,8 @@ func (d *dummyPyInstance) PySetState(pystate interface{}) error {
// activate increments object reference counter.
//
// it returns whether object data needs to be loaded.
// the caller must adjust .state after loading is complete.
//
// must be called with .mu held.
func
(
obj
*
object
)
activate
()
(
load
bool
)
{
obj
.
refcnt
++
...
...
@@ -452,28 +452,40 @@ func (obj *object) deactivate() (drop bool) {
panic
(
"deactivate: refcnt < 0"
)
}
if
obj
.
refcnt
>
0
{
return
// users still left
return
false
// users still left
}
// no users left. Let's see whether we should transition this object to ghost.
drop
=
true
if
obj
.
state
>=
CHANGED
{
drop
=
false
return
false
}
// XXX -> pyObject?
if
drop
{
if
cc
:=
obj
.
jar
.
cacheControl
;
cc
!=
nil
{
drop
=
cc
.
WantEvict
(
obj
.
instance
)
if
cc
:=
obj
.
jar
.
cacheControl
;
cc
!=
nil
{
if
!
cc
.
WantEvict
(
obj
.
instance
)
{
return
false
}
}
if
drop
{
obj
.
serial
=
0
obj
.
instance
.
DropState
()
obj
.
serial
=
0
obj
.
instance
.
DropState
()
obj
.
state
=
GHOST
return
true
}
// invalidate XXX
//
// must be called with .mu held.
func
(
obj
*
object
)
invalidate
()
{
if
obj
.
refcnt
!=
0
{
// object is currently in use
panic
(
"invalidate: refcnt != 0"
)
}
return
drop
obj
.
serial
=
0
obj
.
instance
.
DropState
()
obj
.
state
=
GHOST
}
...
...
@@ -485,16 +497,17 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
if
err
!=
nil
{
// no need to check for drop - the state is already
// dropped - we just need to decref here.
// XXX locking?
pyobj
.
deactivate
()
//
// XXX locking
pyobj
.
deactivate
()
// XXX -> drop?
}
}()
if
!
doload
{
// someone else is already activated/activating the object.
// wait for its loading to complete and we are done.
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
...
...
@@ -504,10 +517,11 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
}
// we become responsible for loading the object
loading
:=
&
load
ing
{
ready
:
make
(
chan
struct
{})}
loading
:=
&
load
State
{
ready
:
make
(
chan
struct
{})}
pyobj
.
loading
=
loading
// XXX assert before it was = nil ?
pyobj
.
mu
.
Unlock
()
// do the loading outside of pyobj lock
pyclass
,
pystate
,
serial
,
err
:=
pyobj
.
jar
.
loadpy
(
ctx
,
pyobj
.
oid
)
if
err
==
nil
&&
pyclass
!=
pyobj
.
pyclass
{
// complain pyclass changed
...
...
@@ -516,8 +530,12 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
pystate
=
nil
}
// relock the object
pyobj
.
mu
.
Lock
()
// XXX assert pyobj.loading == loading
// XXX assert pyobj.state == GHOST
pyobj
.
serial
=
serial
// pyobj.pystate = pystate
...
...
@@ -525,36 +543,36 @@ func (pyobj *pyObject) PActivate(ctx context.Context) (err error) {
err
=
pyobj
.
instance
.
PySetState
(
pystate
)
// XXX err ctx
}
if
err
!=
nil
{
pyobj
.
instance
.
DropState
()
pyobj
.
instance
.
DropState
()
// XXX already in deactivate
}
else
{
pyobj
.
state
=
UPTODATE
}
// XXX unlock
loading
.
err
=
err
pyobj
.
mu
.
Unlock
()
close
(
loading
.
ready
)
return
err
// XXX err ctx
}
// PDeactivate implements Object.
func
(
pyobj
*
pyObject
)
PDeactivate
()
{
drop
:=
pyobj
.
pdeactivate
()
if
!
drop
{
return
}
pyobj
.
mu
.
Lock
()
defer
pyobj
.
mu
.
Unlock
()
// we have to drop pyobject state
// XXX locking?
// pyobj.pystate = nil
pyobj
.
instance
.
DropState
()
pyobj
.
loaderr
=
nil
pyobj
.
ready
=
make
(
chan
struct
{})
drop
:=
pyobj
.
deactivate
()
if
drop
{
pyobj
.
loading
=
nil
}
}
//
XXX pyobj.PInvalidate() = deactivate without checking if state != modified
//
PInvalidate() implements Object.
func
(
pyobj
*
pyObject
)
PInvalidate
()
{
// XXX panic if refcnt != 0 (object being used)
pyobj
.
instance
.
DropState
()
pyobj
.
loaderr
=
nil
pyobj
.
ready
=
make
(
chan
struct
{})
pyobj
.
mu
.
Lock
()
defer
pyobj
.
mu
.
Unlock
()
pyobj
.
invalidate
()
pyobj
.
loading
=
nil
}
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