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
d3c86584
Commit
d3c86584
authored
Jul 17, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
6c0aa796
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
185 additions
and
162 deletions
+185
-162
wcfs/misc.go
wcfs/misc.go
+1
-1
wcfs/wcfs.go
wcfs/wcfs.go
+2
-1
wcfs/weak.go
wcfs/weak.go
+1
-1
wcfs/xxx.go
wcfs/xxx.go
+153
-0
wcfs/zodb.go
wcfs/zodb.go
+28
-159
No files found.
wcfs/misc.go
View file @
d3c86584
...
@@ -55,7 +55,7 @@ func (f *StaticFile) Read(_ nodefs.File, dest []byte, off int64, _ *fuse.Context
...
@@ -55,7 +55,7 @@ func (f *StaticFile) Read(_ nodefs.File, dest []byte, off int64, _ *fuse.Context
// mkdir adds child to parent as directory.
// mkdir adds child to parent as directory.
//
//
// Note: parent must
to
be already in the filesystem tree - i.e. associated
// Note: parent must be already in the filesystem tree - i.e. associated
// with inode. if not - nodefs will panic in Inode.NewChild on nil dereference.
// with inode. if not - nodefs will panic in Inode.NewChild on nil dereference.
func
mkdir
(
parent
nodefs
.
Node
,
name
string
,
child
nodefs
.
Node
)
{
func
mkdir
(
parent
nodefs
.
Node
,
name
string
,
child
nodefs
.
Node
)
{
parent
.
Inode
()
.
NewChild
(
name
,
true
,
child
)
parent
.
Inode
()
.
NewChild
(
name
,
true
,
child
)
...
...
wcfs/wcfs.go
View file @
d3c86584
...
@@ -446,6 +446,7 @@ func (br *BigFileRoot) Mkdir(name string, mode uint32, _ *fuse.Context) (*nodefs
...
@@ -446,6 +446,7 @@ func (br *BigFileRoot) Mkdir(name string, mode uint32, _ *fuse.Context) (*nodefs
// ZData
// ZData
// str (chunk)
// str (chunk)
// Read implements reading from /bigfile/<bigfileX>/head/data.
// Read implements reading from /bigfile/<bigfileX>/head/data.
// XXX and from /bigfile/<bigfileX>/@<tidX>/data.
// XXX and from /bigfile/<bigfileX>/@<tidX>/data.
/*
/*
...
@@ -464,7 +465,7 @@ func (bf *BigFile) Read(_ nodefs.File, dest []byte, off int64, _ fuse.Context) (
...
@@ -464,7 +465,7 @@ func (bf *BigFile) Read(_ nodefs.File, dest []byte, off int64, _ fuse.Context) (
// For the data itself - we put it to kernel cache and always deactivate from
// For the data itself - we put it to kernel cache and always deactivate from
// ZODB right after that.
// ZODB right after that.
//
//
//
XXX
set it to Connection.CacheControl
//
TODO
set it to Connection.CacheControl
type
zodbCacheControl
struct
{}
type
zodbCacheControl
struct
{}
func
(
cc
*
zodbCacheControl
)
WantEvict
(
obj
Object
)
{
func
(
cc
*
zodbCacheControl
)
WantEvict
(
obj
Object
)
{
...
...
wcfs/weak.go
View file @
d3c86584
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
// See https://www.nexedi.com/licensing for rationale and options.
// See https://www.nexedi.com/licensing for rationale and options.
package
main
package
main
// weak reference
// weak reference
s
import
(
import
(
"runtime"
"runtime"
...
...
wcfs/xxx.go
0 → 100644
View file @
d3c86584
package
main
/*
// loadInProgress entry in Conn.objtab tells users, that try to get the entry,
// that another goroutine is already in progress of loading it.
type loadInProgress struct {
ready chan struct{} // closed when loading finishes
// result of the load
pyobj interface{} // XXX -> pyObject iface
err error
}
*/
/*
conn.objmu.Lock() // XXX -> rlock
objentry := conn.objtab[oid]
// someone else is already loading the object.
// we have to wait for that someone to finish the load.
if load, ok := objentry.(*loadInProgress); ok {
conn.objmu.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err() // XXX err ctx
case <-load.ready:
// XXX check pyclass match
return load.pyobj, load.err
}
}
// noone else is loading the object. Investigate whether it is simply not
// in objtab, or it is lost weakref, and if so we have to initiate the load.
var xobj interface{}
if objentry != nil {
wobj := objentry.(*WeakRef)
xobj = wobj.Get()
}
if xpyobj != nil {
// the object is already there
conn.objmu.Unlock()
return xpyobj, nil // XXX + activate?
}
// the object is not there, we have to (re)load it.
load := &loadInProgress{ready: make(chan struct)}
conn.objTab[oid] = load
conn.objmu.Unlock()
pyobj, err = conn.loadpy(ctx, oid)
load.pyobj = pyobj
load.err = err
close(load.ready)
// replace objtab entry with WeakRef
conn.objmu.Lock()
defer conn.objmu.Unlock()
if x := conn.objtab[oid]; x != load {
panic(fmt.Sprintf("zodb.Conn: objtab[%s]: load finished, but it is: %#v", oid, x)
}
if err != nil {
// it was loading error - remove the entry not to cause uncontrolled objtab growth.
// if this object is accessed next time - the load will be retried.
delete(conn.objtab[oid])
} else {
conn.objtab[oid] = NewWeakRef(pyobj)
}
*/
/*
{
objentry := conn.objtab[oid]
// someone else is already loading the object.
// we have to wait for that someone to finish the load.
if load, ok := objentry.(*loadInProgress); ok {
conn.objmu.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err() // XXX err ctx
case <-load.ready:
// XXX check pyclass match
return load.pyobj, err
}
}
// noone else is loading the object. Investigate whether it is simply not
// in objtab, or it is lost weakref, and if so we have to initiate the load.
var xobj interface{}
if objentry != nil {
wobj := objentry.(*WeakRef)
xobj = wobj.Get()
}
if xpyobj != nil {
// the object is already there
conn.objmu.Unlock()
return xpyobj, nil // XXX + activate?
}
// the object is not there, we have to (re)load it.
load := &loadInProgress{ready: make(chan struct)}
conn.objTab[oid] = load
conn.objmu.Unlock()
pyobj, err = conn.loadpy(ctx, oid)
load.pyobj = pyobj
load.err = err
close(load.ready)
// replace objtab entry with WeakRef
conn.objmu.Lock()
defer conn.objmu.Unlock()
if x := conn.objtab[oid]; x != load {
panic(fmt.Sprintf("zodb.Conn: objtab[%s]: load finished, but it is: %#v", oid, x)
}
if err != nil {
// it was loading error - remove the entry not to cause uncontrolled objtab growth.
// if this object is accessed next time - the load will be retried.
delete(conn.objtab[oid])
} else {
conn.objtab[oid] = NewWeakRef(pyobj)
}
}
*/
/*
// XXX -> loadpy
buf, serial, err := conn.stor.Load(ctx, zodb.Xid{Oid: oid, At: conn.at})
if err != nil {
return nil, err
}
pyclass, pystate, err := zodb.PyData(buf.Data).Decode()
if err != nil {
return nil, err // XXX err ctx
}
buf.Release()
return &pyObject{
object: object{jar: conn,oid: oid, serial: serial},
pyclass: pyclass,
pystate: pystate,
}, nil
}
*/
/*
func (conn *Connection) load(ctx context.Context, oid zodb.Oid) (*pyObject, error) {
// XXX
}
*/
wcfs/zodb.go
View file @
d3c86584
...
@@ -25,17 +25,22 @@ import (
...
@@ -25,17 +25,22 @@ import (
pickle
"github.com/kisielk/og-rek"
pickle
"github.com/kisielk/og-rek"
)
)
// XXX make methods private, e.g. _pJar ?
// Object is the interface that every in-RAM object representing any ZODB object implements.
// Object is the interface that every in-RAM object representing any ZODB object implements.
type
Object
interface
{
type
Object
interface
{
// XXX make methods private, e.g. _pJar ?
PJar
()
*
Connection
// Connection this in-RAM object is part of.
PJar
()
*
Connection
POid
()
zodb
.
Oid
// object ID in the database.
POid
()
zodb
.
Oid
// object serial as of database state for particular Connection (PJar).
// 0 if not yet loaded (XXX ok?)
PSerial
()
zodb
.
Tid
PSerial
()
zodb
.
Tid
// PActivate brings object to live state.
// PActivate brings object to live state.
//
//
// It requests to persistency layer that in-RAM object data to be present.
// It requests to persistency layer that in-RAM object data to be present.
// If object state
i
s not in RAM - it is loaded from the database.
// If object state
wa
s not in RAM - it is loaded from the database.
//
//
// On successful return the object data is either the same as in the
// On successful return the object data is either the same as in the
// database or, if this data was previously modified by user of
// database or, if this data was previously modified by user of
...
@@ -53,7 +58,7 @@ type Object interface {
...
@@ -53,7 +58,7 @@ type Object interface {
//
//
// Note that it is valid to have several concurrent uses of object
// Note that it is valid to have several concurrent uses of object
// data, each protected with corresponding PActivate/PDeactivate pair:
// data, each protected with corresponding PActivate/PDeactivate pair:
//
A
s long as there is still any PActivate not yet compensated with
//
a
s long as there is still any PActivate not yet compensated with
// corresponding PDeactivate, object data will assuredly 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
// Besides exotic cases, the caller thus must not use object's data
...
@@ -66,7 +71,18 @@ type Object interface {
...
@@ -66,7 +71,18 @@ type Object interface {
// database, or it was modified, that in-RAM data must be forgotten.
// database, or it was modified, that in-RAM data must be forgotten.
//
//
// PInvalidate must not be called while there is any in-progress
// PInvalidate must not be called while there is any in-progress
// object's data use (PActivate / PDeactivate).
// object's data use (PActivate till PDeactivate).
//
// In practice this means that:
//
// - application must make sure to finish all objects accesses
// before transaction boundary: at transaction boundary - either
// at abort or commit, the persistency layer will sync to
// database and process invalidations.
//
// - if PInvalidate is explicitly called by application, the
// application must care to make sure it does not access the
// object data simultaneously.
PInvalidate
()
PInvalidate
()
}
}
...
@@ -79,7 +95,7 @@ type PyObject interface {
...
@@ -79,7 +95,7 @@ type PyObject interface {
}
}
// object is common base for in-RAM representation of ZODB object.
// object is common base for in-RAM representation of ZODB object
s
.
type
object
struct
{
type
object
struct
{
jar
*
Connection
jar
*
Connection
oid
zodb
.
Oid
oid
zodb
.
Oid
...
@@ -119,7 +135,7 @@ type LiveCacheControl interface {
...
@@ -119,7 +135,7 @@ type LiveCacheControl interface {
//
//
// The view is representing state of ZODB objects as of `at` transaction.
// The view is representing state of ZODB objects as of `at` transaction.
//
//
//
XXX
Connection changes are private and are isolated from changes in other Connections.
// Connection changes are private and are isolated from changes in other Connections.
//
//
// XXX Connection, and {Py}Object methods that relate to it, are not safe for
// XXX Connection, and {Py}Object methods that relate to it, are not safe for
// modifications from multiple goroutines simultaneously.
// modifications from multiple goroutines simultaneously.
...
@@ -178,23 +194,12 @@ type Connection struct {
...
@@ -178,23 +194,12 @@ type Connection struct {
// Hopefully we don't have cycles with ZBtree/ZBucket XXX verify this
// Hopefully we don't have cycles with ZBtree/ZBucket XXX verify this
objmu
sync
.
Mutex
objmu
sync
.
Mutex
objtab
map
[
zodb
.
Oid
]
*
WeakRef
// oid -> WeakRef(PyObject)
objtab
map
[
zodb
.
Oid
]
*
WeakRef
// oid -> WeakRef(PyObject)
//objtab map[zodb.Oid]interface{} // oid -> WeakRef(pyObject) | loadInProgress
cacheControl
ConnCacheControl
// hooks for application to influence live caching decisions.
cacheControl
LiveCacheControl
}
}
/*
// loadInProgress entry in Conn.objtab tells users, that try to get the entry,
// that another goroutine is already in progress of loading it.
type loadInProgress struct {
ready chan struct{} // closed when loading finishes
// result of the load
pyobj interface{} // XXX -> pyObject iface
err error
}
*/
// Get returns in-RAM object corresponding to specified ZODB object according to current database view.
// Get returns in-RAM object corresponding to specified ZODB object according to current database view.
//
//
...
@@ -238,60 +243,6 @@ func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*Py
...
@@ -238,60 +243,6 @@ func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*Py
return
xobj
,
nil
return
xobj
,
nil
}
}
/*
conn.objmu.Lock() // XXX -> rlock
objentry := conn.objtab[oid]
// someone else is already loading the object.
// we have to wait for that someone to finish the load.
if load, ok := objentry.(*loadInProgress); ok {
conn.objmu.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err() // XXX err ctx
case <-load.ready:
// XXX check pyclass match
return load.pyobj, load.err
}
}
// noone else is loading the object. Investigate whether it is simply not
// in objtab, or it is lost weakref, and if so we have to initiate the load.
var xobj interface{}
if objentry != nil {
wobj := objentry.(*WeakRef)
xobj = wobj.Get()
}
if xpyobj != nil {
// the object is already there
conn.objmu.Unlock()
return xpyobj, nil // XXX + activate?
}
// the object is not there, we have to (re)load it.
load := &loadInProgress{ready: make(chan struct)}
conn.objTab[oid] = load
conn.objmu.Unlock()
pyobj, err = conn.loadpy(ctx, oid)
load.pyobj = pyobj
load.err = err
close(load.ready)
// replace objtab entry with WeakRef
conn.objmu.Lock()
defer conn.objmu.Unlock()
if x := conn.objtab[oid]; x != load {
panic(fmt.Sprintf("zodb.Conn: objtab[%s]: load finished, but it is: %#v", oid, x)
}
if err != nil {
// it was loading error - remove the entry not to cause uncontrolled objtab growth.
// if this object is accessed next time - the load will be retried.
delete(conn.objtab[oid])
} else {
conn.objtab[oid] = NewWeakRef(pyobj)
}
*/
// wrongClassError is the error cause returned when object's class is not what was expected.
// wrongClassError is the error cause returned when object's class is not what was expected.
type
wrongClassError
struct
{
type
wrongClassError
struct
{
...
@@ -347,90 +298,6 @@ func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error
...
@@ -347,90 +298,6 @@ func (conn *Connection) get(pyclass pickle.Class, oid zodb.Oid) (PyObject, error
}
}
/*
{
objentry := conn.objtab[oid]
// someone else is already loading the object.
// we have to wait for that someone to finish the load.
if load, ok := objentry.(*loadInProgress); ok {
conn.objmu.Unlock()
select {
case <-ctx.Done():
return nil, ctx.Err() // XXX err ctx
case <-load.ready:
// XXX check pyclass match
return load.pyobj, err
}
}
// noone else is loading the object. Investigate whether it is simply not
// in objtab, or it is lost weakref, and if so we have to initiate the load.
var xobj interface{}
if objentry != nil {
wobj := objentry.(*WeakRef)
xobj = wobj.Get()
}
if xpyobj != nil {
// the object is already there
conn.objmu.Unlock()
return xpyobj, nil // XXX + activate?
}
// the object is not there, we have to (re)load it.
load := &loadInProgress{ready: make(chan struct)}
conn.objTab[oid] = load
conn.objmu.Unlock()
pyobj, err = conn.loadpy(ctx, oid)
load.pyobj = pyobj
load.err = err
close(load.ready)
// replace objtab entry with WeakRef
conn.objmu.Lock()
defer conn.objmu.Unlock()
if x := conn.objtab[oid]; x != load {
panic(fmt.Sprintf("zodb.Conn: objtab[%s]: load finished, but it is: %#v", oid, x)
}
if err != nil {
// it was loading error - remove the entry not to cause uncontrolled objtab growth.
// if this object is accessed next time - the load will be retried.
delete(conn.objtab[oid])
} else {
conn.objtab[oid] = NewWeakRef(pyobj)
}
}
*/
/*
// XXX -> loadpy
buf, serial, err := conn.stor.Load(ctx, zodb.Xid{Oid: oid, At: conn.at})
if err != nil {
return nil, err
}
pyclass, pystate, err := zodb.PyData(buf.Data).Decode()
if err != nil {
return nil, err // XXX err ctx
}
buf.Release()
return &pyObject{
object: object{jar: conn,oid: oid, serial: serial},
pyclass: pyclass,
pystate: pystate,
}, nil
}
*/
/*
func (conn *Connection) load(ctx context.Context, oid zodb.Oid) (*pyObject, error) {
// XXX
}
*/
func
(
conn
*
Connection
)
loadpy
(
ctx
context
.
Context
,
oid
zodb
.
Oid
)
(
pyclass
pickle
.
Class
,
pystate
interface
{},
serial
zodb
.
Tid
,
_
error
)
{
func
(
conn
*
Connection
)
loadpy
(
ctx
context
.
Context
,
oid
zodb
.
Oid
)
(
pyclass
pickle
.
Class
,
pystate
interface
{},
serial
zodb
.
Tid
,
_
error
)
{
buf
,
serial
,
err
:=
conn
.
stor
.
Load
(
ctx
,
zodb
.
Xid
{
Oid
:
oid
,
At
:
conn
.
at
})
buf
,
serial
,
err
:=
conn
.
stor
.
Load
(
ctx
,
zodb
.
Xid
{
Oid
:
oid
,
At
:
conn
.
at
})
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -447,6 +314,7 @@ func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickl
...
@@ -447,6 +314,7 @@ func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickl
return
pyclass
,
pystate
,
serial
,
nil
return
pyclass
,
pystate
,
serial
,
nil
}
}
// path(class) -> new(pyobj)
// path(class) -> new(pyobj)
var
classTab
=
make
(
map
[
string
]
func
(
*
pyObject
)
PyObject
)
var
classTab
=
make
(
map
[
string
]
func
(
*
pyObject
)
PyObject
)
...
@@ -576,5 +444,6 @@ func (pyobj *pyObject) PDeactivate() {
...
@@ -576,5 +444,6 @@ func (pyobj *pyObject) PDeactivate() {
}
}
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified
// XXX panic if refcnt != 0 (object being used)
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