Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
Kirill Smelkov
neo
Commits
525305a0
Commit
525305a0
authored
Jul 13, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
7bf85a48
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
106 additions
and
33 deletions
+106
-33
go/zodb/btree/btree.go
go/zodb/btree/btree.go
+29
-19
go/zodb/cache.go
go/zodb/cache.go
+2
-0
go/zodb/pydata.go
go/zodb/pydata.go
+75
-14
No files found.
go/zodb/btree/btree.go
View file @
525305a0
...
...
@@ -18,40 +18,51 @@
// XXX name -> zbtree ?
package
btree
// ZBucket mimics ?OBucket from btree/py, with ? being any integer.
import
(
"context"
"sort"
"lab.nexedi.com/kirr/neo/go/zodb"
)
// XXX temp
type
KEY
int64
// Bucket mimics ?OBucket from btree/py, with ? being any integer.
//
// py description:
//
original
py description:
//
// A Bucket wraps contiguous vectors of keys and values. Keys are unique,
// and stored in sorted order. The 'values' pointer may be NULL if the
// Bucket is used to implement a set. Buckets serving as leafs of BTrees
// are chained together via 'next', so that the entire BTree contents
// can be traversed in sorted order quickly and easily.
type
Z
Bucket
struct
{
type
Bucket
struct
{
pyobj
*
zodb
.
PyObject
next
*
Z
Bucket
// the bucket with the next-larger keys
next
*
Bucket
// the bucket with the next-larger keys
keys
[]
KEY
// 'len' keys, in increasing order
values
[]
interface
{}
// 'len' corresponding values XXX merge k/v ?
}
// zBTreeItem mimics BTreeItem from btree/py.
type
zBTreeItem
{
type
zBTreeItem
struct
{
key
KEY
child
interface
{}
//
ZBTree or Z
Bucket
child
interface
{}
//
BTree or
Bucket
}
//
Z
BTree mimics ?OBTree from btree/py, with ? being any integer.
// BTree mimics ?OBTree from btree/py, with ? being any integer.
//
// See https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/Development.txt#L198
// for details.
type
Z
BTree
struct
{
type
BTree
struct
{
pyobj
*
zodb
.
PyObject
// firstbucket points to the bucket containing the smallest key in
// the BTree. This is found by traversing leftmost child pointers
// (data[0].child) until reaching a Bucket.
firstbucket
*
Z
Bucket
firstbucket
*
Bucket
// The BTree points to 'len' children, via the "child" fields of the data
// array. There are len-1 keys in the 'key' fields, stored in increasing
...
...
@@ -66,7 +77,7 @@ type ZBTree struct {
//
// It loads intermediate BTree nodes from database on demand as needed.
// XXX ok -> ErrKeyNotFound?
func
(
t
*
Z
BTree
)
Get
(
ctx
context
.
Context
,
key
KEY
)
(
interface
{},
bool
,
error
)
{
func
(
t
*
BTree
)
Get
(
ctx
context
.
Context
,
key
KEY
)
(
interface
{},
bool
,
error
)
{
t
.
PActivate
(
ctx
)
// XXX err
if
len
(
t
.
data
)
==
0
{
...
...
@@ -85,14 +96,15 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) {
})
switch
child
:=
t
.
data
[
i
]
.
child
.
(
type
)
{
case
*
Z
BTree
:
case
*
BTree
:
// XXX t.PAllowDeactivate
t
=
child
t
.
PActivate
(
ctx
)
// XXX err
case
*
Z
Bucket
:
case
*
Bucket
:
child
.
PActivate
(
ctx
)
// XXX err
return
child
.
Get
(
key
),
nil
x
,
ok
:=
child
.
get
(
key
)
return
x
,
ok
,
nil
}
}
}
...
...
@@ -100,12 +112,12 @@ func (t *ZBTree) Get(ctx context.Context, key KEY) (interface{}, bool, error) {
// get searches Bucket by key.
//
// no loading from database is done. The bucket must be already activated.
func
(
b
*
Z
Bucket
)
get
(
key
KEY
)
(
interface
{},
bool
)
{
func
(
b
*
Bucket
)
get
(
key
KEY
)
(
interface
{},
bool
)
{
// XXX b.PActivate ? XXX better caller? (or inside if get -> Get)
// search i: K(i-1) < k ≤ K(i) ; K(-1) = -∞, K(len) = +∞
i
:=
sort
.
Search
(
len
(
b
.
keys
),
func
(
i
int
)
bool
{
return
key
<=
t
.
data
[
i
]
.
key
return
key
<=
b
.
keys
[
i
]
})
if
i
==
len
(
b
.
keys
)
||
b
.
keys
[
i
]
!=
key
{
...
...
@@ -142,10 +154,8 @@ func (b *ZBucket) get(key KEY) (interface{}, bool) {
// In the above, key[i] means self->data[i].key, and similarly for child[i].
// XXX ZBTree.Get(key)
// XXX ZBucket.MinKey ?
// XXX ZBucket.MaxKey ?
// XXX Bucket.MinKey ?
// XXX Bucket.MaxKey ?
// from https://github.com/zopefoundation/BTrees/blob/4.5.0-1-gc8bf24e/BTrees/BucketTemplate.c#L1195:
...
...
go/zodb/cache.go
View file @
525305a0
...
...
@@ -35,6 +35,8 @@ import (
// TODO maintain nhit / nmiss + way to read cache stats
// TODO optimize cache more so that miss overhead becomes negligible
// TODO Drop(xid) -> make sure data for xid is no longer in cache
// Cache provides RAM caching layer that can be used over a storage.
type
Cache
struct
{
loader
interface
{
...
...
go/zodb/pydata.go
View file @
525305a0
...
...
@@ -23,11 +23,68 @@ package zodb
import
(
"bytes"
"errors"
"fmt"
//
"fmt"
pickle
"github.com/kisielk/og-rek"
)
// XXX move out of py
// Object is in-process representaion of a ZODB object.
type
Object
interface
{
Jar
()
*
Connection
Oid
()
Oid
Serial
()
Tid
Data
()
*
mem
.
Buf
// XXX for raw, py -> PyObject
// XXX register(jar, oid) - register to database ? (for Connection.Add)
// PActivate
// PDeactivate
// PInvalidate
}
// XXX
type
DataManager
interface
{
//LoadObject(obj Object)
//LoadObject(oid Oid)
LoadState
(
obj
)
// XXX oldstate(oid, tid)
// XXX register(obj)
}
// Connection represent client-visible part of a connection to ZODB database.
//
// XXX consitent view for some `at`.
// XXX not needed? (just DB.Open() -> root object and connection not be visible)?
type
Connection
interface
{
// Get returns object by oid.
// XXX multiple calls to Get with same oid return the same object.
// XXX root object has oid=0.
Get
(
ctx
context
.
Context
,
oid
Oid
)
(
Object
,
error
)
// XXX Add(obj Object) -> add obj to database and assign it an oid
// obj must be not yet added
// XXX ReadCurrent(obj)
// XXX Close() error
}
// PyData represents raw data stored into ZODB by Python applications.
//
// The format is based on python pickles. Basically every serialized object has
...
...
@@ -48,14 +105,15 @@ type PyData []byte
// PyObject represents persistent Python object.
//
// PyObject can be decoded from PyData.
// PyObject can be decoded from PyData.
XXX
type
PyObject
struct
{
//oid Oid
//serial Tid
Jar
*
Connection
// XXX -> ro
Oid
Oid
// XXX -> ro
Serial
Tid
// XXX -> ro
// XXX + Oid, Serial ? (_p_oid, _p_serial)
pyClass
pickle
.
Class
// python class of this object XXX -> ro
State
interface
{}
// object state. python passes this to pyclass.__new__().__setstate__()
PyClass
pickle
.
Class
// python class of this object XXX -> ro ?
PyState
interface
{}
// object state. python passes this to pyclass.__new__().__setstate__()
}
...
...
@@ -67,18 +125,19 @@ type PyLoader interface {
}
/*
// Decode decodes raw ZODB python data into PyObject. XXX -> (pyclass, pystate)
//func (d PyData) Decode() (*PyObject, error) {
func
(
d
PyData
)
Decode
()
(
pyclass
Py
Class
,
pystate
interface
{},
_
error
)
{
func (d PyData) Decode() (pyclass
pickle.
Class, pystate interface{}, _ error) {
p := pickle.NewDecoder(bytes.NewReader([]byte(d)))
xklass, err := p.Decode()
if err != nil {
return
nil
,
fmt
.
Errorf
(
"pydata: decode: class description: %s"
,
err
)
return nil,
nil,
fmt.Errorf("pydata: decode: class description: %s", err)
}
klass, err := normPyClass(xklass)
if err != nil {
return
nil
,
fmt
.
Errorf
(
"pydata: decode: class description: %s"
,
err
)
return nil,
nil,
fmt.Errorf("pydata: decode: class description: %s", err)
}
state, err := p.Decode()
...
...
@@ -86,8 +145,10 @@ func (d PyData) Decode() (pyclass PyClass, pystate interface{}, _ error) {
return nil, fmt.Errorf("pydata: decode: object state: %s", err)
}
return
&
PyObject
{
pyClass
:
klass
,
State
:
state
},
nil
//return &PyObject{pyClass: klass, State: state}, nil
return klass, state, nil
}
*/
// ClassName returns fully-qualified python class name used for object type.
...
...
@@ -150,7 +211,7 @@ func normPyClass(xklass interface{}) (pickle.Class, error) {
return
pickle
.
Class
{},
errInvalidPyClass
}
// PyClass returns Python class of the object.
func
(
pyobj
*
PyObject
)
PyClass
()
pickle
.
Class
{
return
pyobj
.
pyClass
}
//
//
PyClass returns Python class of the object.
//
func (pyobj *PyObject) PyClass() pickle.Class {
//
return pyobj.pyClass
//
}
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