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
0f146bcb
Commit
0f146bcb
authored
Jul 19, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
f532e0f2
Changes
1
Show 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
.
WantEvict
(
obj
.
instance
)
{
return
false
}
}
if
drop
{
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