Commit d3c86584 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 6c0aa796
...@@ -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)
......
...@@ -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) {
......
...@@ -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 references
import ( import (
"runtime" "runtime"
......
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
}
*/
...@@ -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 is not in RAM - it is loaded from the database. // If object state was 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:
// As long as there is still any PActivate not yet compensated with // as 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 objects.
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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment