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
// 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.
func mkdir(parent nodefs.Node, name string, child nodefs.Node) {
parent.Inode().NewChild(name, true, child)
......
......@@ -446,6 +446,7 @@ func (br *BigFileRoot) Mkdir(name string, mode uint32, _ *fuse.Context) (*nodefs
// ZData
// str (chunk)
// Read implements reading from /bigfile/<bigfileX>/head/data.
// XXX and from /bigfile/<bigfileX>/@<tidX>/data.
/*
......@@ -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
// ZODB right after that.
//
// XXX set it to Connection.CacheControl
// TODO set it to Connection.CacheControl
type zodbCacheControl struct {}
func (cc *zodbCacheControl) WantEvict(obj Object) {
......
......@@ -22,7 +22,7 @@
// See https://www.nexedi.com/licensing for rationale and options.
package main
// weak reference
// weak references
import (
"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 (
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.
type Object interface {
// XXX make methods private, e.g. _pJar ?
PJar() *Connection
POid() zodb.Oid
PJar() *Connection // Connection this in-RAM object is part of.
POid() zodb.Oid // object ID in the database.
// object serial as of database state for particular Connection (PJar).
// 0 if not yet loaded (XXX ok?)
PSerial() zodb.Tid
// 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.
// 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
// database or, if this data was previously modified by user of
......@@ -53,7 +58,7 @@ 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
// as long as there is still any PActivate not yet compensated with
// corresponding PDeactivate, object data will assuredly stay alive in RAM.
//
// Besides exotic cases, the caller thus must not use object's data
......@@ -66,7 +71,18 @@ type Object interface {
// 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).
// 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()
}
......@@ -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 {
jar *Connection
oid zodb.Oid
......@@ -119,7 +135,7 @@ type LiveCacheControl interface {
//
// 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
// modifications from multiple goroutines simultaneously.
......@@ -178,23 +194,12 @@ type Connection struct {
// Hopefully we don't have cycles with ZBtree/ZBucket XXX verify this
objmu sync.Mutex
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.
//
......@@ -238,60 +243,6 @@ func (conn *Connection) Get(ctx context.Context, oid zodb.Oid) (interface{} /*Py
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.
type wrongClassError struct {
......@@ -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) {
buf, serial, err := conn.stor.Load(ctx, zodb.Xid{Oid: oid, At: conn.at})
if err != nil {
......@@ -447,6 +314,7 @@ func (conn *Connection) loadpy(ctx context.Context, oid zodb.Oid) (pyclass pickl
return pyclass, pystate, serial, nil
}
// path(class) -> new(pyobj)
var classTab = make(map[string]func(*pyObject)PyObject)
......@@ -576,5 +444,6 @@ func (pyobj *pyObject) PDeactivate() {
}
// 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