Commit 5bb19440 authored by Kirill Smelkov's avatar Kirill Smelkov

X draftly finished catobj

parent 2055fb37
......@@ -70,7 +70,7 @@ func (c *Client) LastTid() (zodb.Tid, error) {
}
func (c *Client) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error) {
panic("TODO")
panic("TODO") // XXX
}
func (c *Client) Iterate(tidMin, tidMax zodb.Tid) zodb.IStorageIterator {
......
......@@ -637,6 +637,7 @@ func (dh *DataHeader) loadNext(r io.ReaderAt /* *os.File */, txnh *TxnHeader) er
// LoadData loads data for the data record taking backpointers into account
// Data is loaded into *buf, which, if needed, is reallocated to hold all loading data size XXX
// NOTE on success dh state is changed to data header of original data transaction
// NOTE "deleted" records are indicated via returning *buf=nil
// TODO buf -> slab
func (dh *DataHeader) LoadData(r io.ReaderAt /* *os.File */, buf *[]byte) error {
// scan via backpointers
......@@ -737,10 +738,10 @@ func (fs *FileStorage) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error)
// lookup in index position of oid data record within latest transaction who changed this oid
dataPos, ok := fs.index.Get(xid.Oid)
if !ok {
// XXX drop oid from ErrOidMissing ?
return nil, zodb.Tid(0), &ErrXidLoad{xid, zodb.ErrOidMissing{Oid: xid.Oid}}
return nil, zodb.Tid(0), &zodb.ErrOidMissing{Oid: xid.Oid}
}
// FIXME zodb.TidMax is only 7fff... tid from outside can be ffff...
dh := DataHeader{Oid: xid.Oid, Tid: zodb.TidMax, PrevRevPos: dataPos}
tidBefore := xid.XTid.Tid
if !xid.XTid.TidBefore {
......@@ -754,15 +755,17 @@ func (fs *FileStorage) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error)
if err == io.EOF {
// no such oid revision
err = &zodb.ErrXidMissing{Xid: xid}
} else {
err = &ErrXidLoad{xid, err}
}
return nil, zodb.Tid(0), &ErrXidLoad{xid, err}
return nil, zodb.Tid(0), err
}
}
// found dh.Tid < tidBefore; check it really satisfies xid.XTid
if !xid.XTid.TidBefore && dh.Tid != xid.XTid.Tid {
// XXX unify with ^^^
return nil, zodb.Tid(0), &ErrXidLoad{xid, &zodb.ErrXidMissing{Xid: xid}}
return nil, zodb.Tid(0), &zodb.ErrXidMissing{Xid: xid}
}
// even if we will scan back via backpointers, the tid returned should
......@@ -774,6 +777,11 @@ func (fs *FileStorage) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error)
if err != nil {
return nil, zodb.Tid(0), &ErrXidLoad{xid, err}
}
if data == nil {
// data was deleted
// XXX or allow this and return via data=nil ?
return nil, zodb.Tid(0), &zodb.ErrXidMissing{Xid: xid}
}
return data, tid, nil
}
......
......@@ -62,6 +62,8 @@ func (tid Tid) Valid() bool {
// ----------------------------------------
// ErrOidMissing is an error which tells that there is no such oid in the database at all
// XXX do we need distinction in between ErrOidMissing & ErrXidMissing ?
// (think how client should handle error from Load ?)
type ErrOidMissing struct {
Oid Oid
}
......@@ -140,6 +142,7 @@ type IStorage interface {
// LoadSerial and LoadBefore generalized into 1 Load (see Xid for details)
// TODO data []byte -> something allocated from slab ?
// XXX currently deleted data is returned as data=nil -- is it ok?
Load(xid Xid) (data []byte, tid Tid, err error) // XXX -> StorageRecordInformation ?
// -> Prefetch(xid Xid) ...
......
......@@ -28,8 +28,21 @@ import (
"../../zodb"
)
// Catobj dumps content of one ZODB object XXX text
// Catobj dumps content of one ZODB object
// The object is printed in raw form without any headers (see Dumpobj)
func Catobj(w io.Writer, stor zodb.IStorage, xid zodb.Xid) error {
data, _, err := stor.Load(xid)
if err != nil {
return err
}
_, err = w.Write(data) // NOTE delted data are returned as err by Load
return err // XXX err ctx ?
}
// Dumpobj dumps content of one ZODB object with zodbdump-like header
func Dumpobj(w io.Writer, stor zodb.IStorage, xid zodb.Xid, hashOnly bool) error {
var objInfo zodb.StorageRecordInformation
data, tid, err := stor.Load(xid)
......@@ -37,13 +50,13 @@ func Catobj(w io.Writer, stor zodb.IStorage, xid zodb.Xid) error {
return err
}
// XXX hack - rework IStorage.Load to fill-in objInfo directly
// XXX hack - TODO rework IStorage.Load to fill-in objInfo directly
objInfo.Oid = xid.Oid
objInfo.Tid = tid
objInfo.Data = data
objInfo.DataTid = tid // XXX wrong
objInfo.DataTid = tid // XXX generally wrong
d := dumper{W: w} // XXX HashOnly + raw dump
d := dumper{W: w, HashOnly: hashOnly}
err = d.DumpData(&objInfo)
return err
}
......@@ -62,14 +75,20 @@ xid is object address (see 'zodb help xid').
Options:
-h --help this help text.
// -hashonly dump only hashes of objects without content. XXX
-hashonly dump only hashes of objects without content.
-raw dump object data without any headers. Only one object allowed.
`)
}
func catobjMain(argv []string) {
hashOnly := false
raw := false
flags := flag.FlagSet{Usage: func() { catobjUsage(os.Stderr) }}
flags.Init("", flag.ExitOnError)
// flags.BoolVar(&hashOnly, "hashonly", hashOnly, "dump only hashes of objects")
flags.BoolVar(&hashOnly, "hashonly", hashOnly, "dump only hashes of objects")
flags.BoolVar(&raw, "raw", hashOnly, "dump object data without any headers. Only one object allowed.")
// TODO also -batch to serve objects a-la `git cat-file --batch` ?
flags.Parse(argv[1:])
argv = flags.Args()
......@@ -79,6 +98,10 @@ func catobjMain(argv []string) {
}
storUrl := argv[0]
if hashOnly && raw {
log.Fatal("-hashonly & -raw are incompatible")
}
xidv := []zodb.Xid{}
for _, arg := range argv[1:] {
xid, err := zodb.ParseXid(arg)
......@@ -89,14 +112,26 @@ func catobjMain(argv []string) {
xidv = append(xidv, xid)
}
if raw && len(xidv) > 1 {
log.Fatal("only 1 object allowed with -raw")
}
stor, err := zodb.OpenStorageURL(storUrl) // TODO read-only
if err != nil {
log.Fatal(err)
}
// TODO defer stor.Close()
catobj := func(xid zodb.Xid) error {
if raw {
return Catobj(os.Stdout, stor, xid)
} else {
return Dumpobj(os.Stdout, stor, xid, hashOnly)
}
}
for _, xid := range xidv {
err = Catobj(os.Stdout, stor, xid)
err = catobj(xid)
if err != nil {
log.Fatal(err)
}
......
......@@ -66,11 +66,16 @@ Please see zodburi documentation for full details:
http://docs.pylonsproject.org/projects/zodburi/
`
var HelpTopics = HelpRegistry{
{"zurl", "specifying database URL", helpZURL},
}
const helpXid =
`TODO describe
// TODO xid
=tid:oid
<tid:oid
`
// TODO dump format
var HelpTopics = HelpRegistry{
{"zurl", "specifying database URL", helpZURL},
{"xid", "specifying object address", helpXid},
}
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