Commit bbff0245 authored by Kirill Smelkov's avatar Kirill Smelkov

X zodb: Polish a bit

parent 4ac3a550
......@@ -502,14 +502,19 @@ func (c *Client) Iterate(tidMin, tidMax zodb.Tid) zodb.ITxnIterator {
}
// TODO read-only support
func openClientByURL(ctx context.Context, u *url.URL) (zodb.IStorage, error) {
func openClientByURL(ctx context.Context, u *url.URL, opt *zodb.OpenOptions) (zodb.IStorage, error) {
// neo://name@master1,master2,...,masterN?options
if u.User == nil {
return nil, fmt.Errorf("neo: open %q: cluster name not specified")
}
// XXX readonly stub
// XXX place = ?
if !opt.ReadOnly {
return nil, fmt.Errorf("neo: %s: TODO write mode not implemented", u)
}
// XXX check/use other url fields
net := xnet.NetPlain("tcp") // TODO + TLS; not only "tcp" ?
......
......@@ -115,7 +115,7 @@ func main() {
func zhash(ctx context.Context, url string, h hasher, useprefetch bool, bench, check string) (err error) {
defer task.Running(&ctx, "zhash")(&err)
stor, err := zodb.OpenStorageURL(ctx, url)
stor, err := zodb.OpenStorage(ctx, url)
if err != nil {
return err
}
......@@ -124,7 +124,7 @@ func zhash(ctx context.Context, url string, h hasher, useprefetch bool, bench, c
err = xerr.First(err, err2)
}()
// XXX always open storage with cache by zodb.OpenStorageURL
// XXX always open storage with cache by zodb.OpenStorage
var cache *storage.Cache
if useprefetch {
cache = storage.NewCache(stor, 16*1024*1024)
......
......@@ -40,7 +40,7 @@ type Buf struct {
// reference counter.
//
// NOTE to allow both Bufs created via BufAlloc and via std new Buf is
// NOTE to allow both Bufs created via BufAlloc and via std new, Buf is
// created with refcnt=0. The real number of references to Buf is thus .refcnt+1
refcnt int32
}
......@@ -68,6 +68,7 @@ func BufAlloc(size int) *Buf {
return BufAlloc64(int64(size))
}
// BufAlloc64 is same as BufAlloc but accepts int64 for size.
func BufAlloc64(size int64) *Buf {
if size < 0 {
panic("invalid size")
......@@ -76,22 +77,17 @@ func BufAlloc64(size int64) *Buf {
// order = min i: 2^i >= size
order := xmath.CeilLog2(uint64(size))
//println("alloc", size, "order:", order)
order -= order0
if order < 0 {
order = 0
}
//println("\t->", order)
// if too big - allocate straightly from heap
if order >= len(bufPoolv) {
return &Buf{Data: make([]byte, size)}
}
buf := bufPoolv[order].Get().(*Buf)
//println("\tlen:", len(buf.Data), "cap:", cap(buf.Data))
buf.Data = buf.Data[:size] // leaving cap as is = 2^i
buf.refcnt = 0
return buf
......
......@@ -27,8 +27,13 @@ import (
"strings"
)
// OpenOptions describes options for OpenStorage
type OpenOptions struct {
ReadOnly bool // whether to open storage as read-only
}
// StorageOpener is a function to open a storage
type StorageOpener func (ctx context.Context, u *url.URL) (IStorage, error)
type StorageOpener func (ctx context.Context, u *url.URL, opt *OpenOptions) (IStorage, error)
// {} scheme -> StorageOpener
var storageRegistry = map[string]StorageOpener{}
......@@ -51,8 +56,7 @@ func RegisterStorage(scheme string, opener StorageOpener) {
// Storage authors should register their storages with RegisterStorage.
//
// TODO automatically wrap a storage with Cache.
// TODO readonly
func OpenStorageURL(ctx context.Context, storageURL string) (IStorage, error) {
func OpenStorage(ctx context.Context, storageURL string, opt *OpenOptions) (IStorage, error) {
// no scheme -> file://
if !strings.Contains(storageURL, "://") {
storageURL = "file://" + storageURL
......@@ -63,10 +67,13 @@ func OpenStorageURL(ctx context.Context, storageURL string) (IStorage, error) {
return nil, err
}
// XXX commonly handle some options from url -> opt?
// (e.g. ?readonly=1 -> opt.ReadOnly=true + remove ?readonly=1 from URL)
opener, ok := storageRegistry[u.Scheme]
if !ok {
return nil, fmt.Errorf("zodb: URL scheme \"%s://\" not supported", u.Scheme)
}
return opener(ctx, u)
return opener(ctx, u, opt)
}
......@@ -53,7 +53,7 @@
//
// Unless one is doing something FileStorage-specific, it is advices not to use
// fs1 package directly, and instead link-in lab.nexedi.com/kirr/neo/go/zodb/wks,
// open storage by zodb.OpenStorageURL and use it by way of zodb.IStorage interface.
// open storage by zodb.OpenStorage and use it by way of zodb.IStorage interface.
//
// The fs1 package exposes all FileStorage data format details and most of
// internal workings so that it is possible to implement FileStorage-specific
......
......@@ -22,16 +22,24 @@ package fs1
import (
"context"
"fmt"
"net/url"
"lab.nexedi.com/kirr/neo/go/zodb"
)
// TODO read-only support
func openByURL(ctx context.Context, u *url.URL) (zodb.IStorage, error) {
func openByURL(ctx context.Context, u *url.URL, opt *zodb.OpenOptions) (zodb.IStorage, error) {
// TODO handle query
// XXX u.Path is not always raw path - recheck and fix
return Open(ctx, u.Host + u.Path)
path := u.Host + u.Path
// XXX readonly stub
// XXX place = ?
if !opt.ReadOnly {
return nil, fmt.Errorf("fs1: %s: TODO write mode not implemented", path)
}
return Open(ctx, path)
}
func init() {
......
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
// Package mem implements in-memory ZODB storage
package mem
// XXX partly based on code from ZODB ?
// XXX not yet really needed
/*
import (
"../../../zodb"
)
// Storage is a ZODB storage which stores data in RAM.
type Storage struct {
}
var _ zodb.IStorage = (*Storage)(nil)
*/
......@@ -29,10 +29,24 @@ import (
"lab.nexedi.com/kirr/go123/xstrings"
)
// String converts tid to string.
//
// Default tid string representation is 16-character hex string, e.g.:
//
// 0285cbac258bf266
//
// See also: ParseTid.
func (tid Tid) String() string {
return string(tid.XFmtString(nil))
}
// String converts oid to string.
//
// Default oid string representation is 16-character hex string, e.g.:
//
// 0000000000000001
//
// See also: ParseOid.
func (oid Oid) String() string {
return string(oid.XFmtString(nil))
}
......@@ -47,8 +61,9 @@ func (oid Oid) XFmtString(b []byte) []byte {
return xfmt.AppendHex016(b, uint64(oid))
}
// XXX move me out of here
// bint converts bool to int with true => 1; false => 0
// bint converts bool to int with true => 1; false => 0.
//
// XXX place = ?
func bint(b bool) int {
if b {
return 1
......@@ -57,11 +72,38 @@ func bint(b bool) int {
}
}
// String converts xtid to string.
//
// Default xtid string representation is:
//
// - "=" or "<" character depending on whether xtid represents exact or "tid before" query
// - tid
//
// e.g.
//
// =0285cbac258bf266 - exactly 0285cbac258bf266
// <0285cbac258bf266 - before 0285cbac258bf266
//
// See also: ParseXTid.
func (xtid XTid) String() string {
// XXX also print "tid:" prefix ?
return fmt.Sprintf("%c%v", "=<"[bint(xtid.TidBefore)], xtid.Tid)
}
// String converts xid to string.
//
// Default xid string representation is:
//
// - string of xtid
// - ":"
// - string of oid
//
// e.g.
//
// =0285cbac258bf266:0000000000000001 - oid 1 at exactly 0285cbac258bf266 transaction
// <0285cbac258bf266:0000000000000001 - oid 1 at first newest transaction changing it with tid < 0285cbac258bf266
//
// See also: ParseXid.
func (xid Xid) String() string {
return xid.XTid.String() + ":" + xid.Oid.String()
}
......@@ -93,16 +135,25 @@ func parseHex64(subj, s string) (uint64, error) {
return binary.BigEndian.Uint64(b[:]), nil
}
// ParseTid parses tid from string.
//
// See also: Tid.String .
func ParseTid(s string) (Tid, error) {
x, err := parseHex64("tid", s)
return Tid(x), err
}
// ParseOid parses oid from string.
//
// See also: Oid.String .
func ParseOid(s string) (Oid, error) {
x, err := parseHex64("oid", s)
return Oid(x), err
}
// ParseXTid parses xtid from string.
//
// See also: XTid.String .
func ParseXTid(s string) (XTid, error) {
if len(s) < 1 {
goto Error
......@@ -132,6 +183,9 @@ Error:
return XTid{}, fmt.Errorf("xtid %q invalid", s)
}
// ParseXid parses xid from string.
//
// See also: Xid.String .
func ParseXid(s string) (Xid, error) {
xtids, oids, err := xstrings.Split2(s, ":")
if err != nil {
......
......@@ -76,5 +76,4 @@ func (tid Tid) Time() TimeStamp {
// TODO TidFromTime()
// TODO TidFromTimeStamp()
// TODO TidForNow() ?
......@@ -28,7 +28,6 @@
package wks
import (
_ "lab.nexedi.com/kirr/neo/go/zodb/storage/mem"
_ "lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
_ "lab.nexedi.com/kirr/neo/go/neo/client"
)
......@@ -34,7 +34,7 @@ import (
// Tid is transaction identifier.
//
// In ZODB transaction identifiers are unique 64-bit integer connected to time
// In ZODB transaction identifiers are unique 64-bit integers connected to time
// when corresponding transaction was created.
//
// See also: XTid.
......@@ -42,7 +42,7 @@ type Tid uint64
// ZODB/py defines maxtid to be max signed int64 since Jun 7 2016:
// https://github.com/zopefoundation/ZODB/commit/baee84a6
// (XXX in neo/py: SQLite does not accept numbers above 2^63-1)
// (same in neo/py with "SQLite does not accept numbers above 2^63-1" comment)
const TidMax Tid = 1<<63 - 1 // 0x7fffffffffffffff
......
......@@ -124,7 +124,7 @@ func catobjMain(argv []string) {
ctx := context.Background()
stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only
stor, err := zodb.OpenStorage(ctx, storUrl, &zodb.OpenOptions{ReadOnly: true})
if err != nil {
prog.Fatal(err)
}
......
......@@ -270,7 +270,7 @@ func dumpMain(argv []string) {
prog.Fatal(err)
}
stor, err := zodb.OpenStorageURL(context.Background(), storUrl) // TODO read-only
stor, err := zodb.OpenStorage(context.Background(), storUrl, &zodb.OpenOptions{ReadOnly: true})
if err != nil {
prog.Fatal(err)
}
......
......@@ -123,7 +123,7 @@ func infoMain(argv []string) {
ctx := context.Background()
stor, err := zodb.OpenStorageURL(ctx, storUrl) // TODO read-only
stor, err := zodb.OpenStorage(ctx, storUrl, &zodb.OpenOptions{ReadOnly: true})
if err != nil {
prog.Fatal(err)
}
......
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