Commit 171cdb09 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 1bbc897a
......@@ -42,6 +42,52 @@ type PyObject struct {
type Connection struct {
stor zodb.IStorage // underlying storage
at zodb.Tid // current view of database
// {} oid -> pyobj
//
// rationale:
//
// on invalidations: we need to go oid -> pyobj and invalidate it.
// -> Connection need to keep {} oid -> pyobj.
// -> we can use that {} when loading a persistent Ref twice to get to the same object.
//
// however: if Connection keeps strong link to pyobj, just
// pyobj.PDeactivate will not fully release pyobj if there are not
// references to it from other objects:
//
// - deactivate will release pyobj state (ok)
// - but there will be still reference from connection `oid -> pyobj` map to this object.
//
// -> we can solve it by using "weak" pointers in the map.
//
// NOTE we cannot use regular map and arbitrarily manually "gc" entries
// there periodically: since for a pyobj we don't know whether other
// objects are referencing it, we can't just remove pyobj's oid from
// the map - if we do so and there are other live objects that
// reference pyobj, user code can still reach pyobj via those
// references. On the other hand, if another, not yet loaded, object
// also references pyobj and gets loaded, traversing reference from
// that loaded object will load second copy of pyobj, thus breaking 1
// object in db <-> 1 live object invariant:
//
// A → B → C
// ↓ |
// D <--------- - - -> D2 (wrong)
//
// - A activate
// - D activate
// - B activate
// - D gc, A still keeps link on D
// - C activate -> it needs to get to D, but D was removed from objtab
// -> new D2 is wrongly created
//
// that's why we have to depend on Go's GC to know whether there are
// still live references left or not. And that in turn means finalizers
// and thus weak references.
//
// some link on the subject:
// https://groups.google.com/forum/#!topic/golang-nuts/PYWxjT2v6ps
objtab map[zodb.Oid]WeakRef
}
// Gets loads and decodes object from the database according to its current view.
......@@ -98,12 +144,15 @@ func (conn *Connection) newGhost(pyclass pickle.Class, oid zodb.Oid) interface{}
return &pyobj
}
// XXX pyobj.PInvalidate() = deactivate without checking if state != modified
// PDeactivates transforms object to ghost state.
//
// In ghost state object data is dropped and only oid/pyclass information is left in RAM.
//
// XXX if state=modified PDeactivate must be noop.
func (pyobj *PyObject) PDeactivate() {
// FIXME if state=modified PDeactivate must be noop.
pyobj.pystate = nil
pyobj.serial = zodb.InvalidTID
}
......
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