Commit ed116ae2 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent b53e278e
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
// See COPYING file for full licensing terms. // See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options. // See https://www.nexedi.com/licensing for rationale and options.
// Package fs1 provides so-called FileStorage v1 ZODB storage. // Package fs1 provides so-called FileStorage version 1 ZODB storage.
// //
// FileStorage is a single file organized as a simple append-only log of // FileStorage is a single file organized as a simple append-only log of
// transactions with data changes. Every transaction record consists of: // transactions with data changes. Every transaction record consists of:
...@@ -45,8 +45,8 @@ ...@@ -45,8 +45,8 @@
// https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fstools.py // https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fstools.py
// //
// The index format is interoperable with ZODB/py (index uses pickles which // The index format is interoperable with ZODB/py (index uses pickles which
// allows various valid encodings of a given object). Please see the following // allow various valid encodings of a given object). Please see the following
// links for original FileStorage index definition: // links for original FileStorage/py index definition:
// //
// https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fsIndex.py // https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fsIndex.py
// https://github.com/zopefoundation/ZODB/commit/1bb14faf // https://github.com/zopefoundation/ZODB/commit/1bb14faf
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
// internal workings so that it is possible to implement FileStorage-specific // internal workings so that it is possible to implement FileStorage-specific
// tools. // tools.
// //
// Please see package lab.nexedi.com/kirr/neo/go/zodb/storage/fs1/fs1tools and // See also package lab.nexedi.com/kirr/neo/go/zodb/storage/fs1/fs1tools and
// associated fs1 command for basic tools related to FileStorage maintenance. // associated fs1 command for basic tools related to FileStorage maintenance.
package fs1 package fs1
...@@ -72,30 +72,12 @@ import ( ...@@ -72,30 +72,12 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/xcommon/xbufio" "lab.nexedi.com/kirr/neo/go/xcommon/xbufio"
"lab.nexedi.com/kirr/neo/go/xcommon/xio"
"lab.nexedi.com/kirr/go123/xbytes" "lab.nexedi.com/kirr/go123/xbytes"
) )
// FileStorage is a ZODB storage which stores data in simple append-only file // FileHeader represents file header
// organized as transactional log.
type FileStorage struct {
file *os.File
index *Index // oid -> data record position in transaction which last changed oid
// transaction headers for min/max transactions committed
// XXX keep loaded with LoadNoStrings ?
txnhMin TxnHeader
txnhMax TxnHeader
// XXX topPos = txnhMax.Pos + txnhMax.Len
//topPos int64 // position pointing just past last committed transaction
// // (= size(.file) when no commit is in progress)
}
// IStorage XXX move ?
var _ zodb.IStorage = (*FileStorage)(nil)
// FileHeader represents FileStorage file header
type FileHeader struct { type FileHeader struct {
Magic [4]byte Magic [4]byte
} }
...@@ -213,23 +195,6 @@ func bug(e xerr, format string, a ...interface{}) { ...@@ -213,23 +195,6 @@ func bug(e xerr, format string, a ...interface{}) {
} }
// XXX -> xio ?
// noEOF returns err, but changes io.EOF -> io.ErrUnexpectedEOF
func noEOF(err error) error {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
// okEOF returns err, but changes io.EOF -> nil
func okEOF(err error) error {
if err == io.EOF {
err = nil
}
return err
}
// --- File header --- // --- File header ---
// Load reads and decodes file header. // Load reads and decodes file header.
...@@ -237,12 +202,12 @@ func (fh *FileHeader) Load(r io.ReaderAt) error { ...@@ -237,12 +202,12 @@ func (fh *FileHeader) Load(r io.ReaderAt) error {
_, err := r.ReadAt(fh.Magic[:], 0) _, err := r.ReadAt(fh.Magic[:], 0)
err = okEOF(err) err = okEOF(err)
if err != nil { if err != nil {
return fh.err("read", err) //return fh.err("read", err)
//return err // XXX err more context return err // XXX err more context
} }
if string(fh.Magic[:]) != Magic { if string(fh.Magic[:]) != Magic {
//return fmt.Errorf("%s: invalid magic %q", path, fh.Magic) // XXX -> decode err return fmt.Errorf("%s: invalid magic %q", xio.Name(r), fh.Magic) // XXX -> decode err
return decodeErr(fh, "invalid magic %q", fh.Magic) //return decodeErr(fh, "invalid magic %q", fh.Magic)
} }
return nil return nil
...@@ -630,6 +595,8 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt) error { ...@@ -630,6 +595,8 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt) error {
return nil return nil
} }
// TODO LoadBackRef
// LoadBack reads and decodes data header for revision linked via back-pointer. // LoadBack reads and decodes data header for revision linked via back-pointer.
// prerequisite: dh XXX .DataLen == 0 // prerequisite: dh XXX .DataLen == 0
// if link is to zero (means deleted record) io.EOF is returned // if link is to zero (means deleted record) io.EOF is returned
...@@ -782,7 +749,6 @@ func (it *Iter) NextTxn(flags TxnLoadFlags) error { ...@@ -782,7 +749,6 @@ func (it *Iter) NextTxn(flags TxnLoadFlags) error {
panic("Iter.Dir invalid") panic("Iter.Dir invalid")
} }
//fmt.Println("loaded:", it.Txnh.Tid)
if err != nil { if err != nil {
// reset .Datah to be invalid (just in case) // reset .Datah to be invalid (just in case)
it.Datah.Pos = 0 it.Datah.Pos = 0
...@@ -811,6 +777,25 @@ func Iterate(r io.ReaderAt, posStart int64, dir IterDir) *Iter { ...@@ -811,6 +777,25 @@ func Iterate(r io.ReaderAt, posStart int64, dir IterDir) *Iter {
// --- FileStorage --- // --- FileStorage ---
// FileStorage is a ZODB storage which stores data in simple append-only file
// organized as transactional log.
type FileStorage struct {
file *os.File
index *Index // oid -> data record position in transaction which last changed oid
// transaction headers for min/max transactions committed
// XXX keep loaded with LoadNoStrings ?
txnhMin TxnHeader
txnhMax TxnHeader
// XXX topPos = txnhMax.Pos + txnhMax.Len
//topPos int64 // position pointing just past last committed transaction
// // (= size(.file) when no commit is in progress)
}
// IStorage
var _ zodb.IStorage = (*FileStorage)(nil)
func (fs *FileStorage) StorageName() string { func (fs *FileStorage) StorageName() string {
return "FileStorage v1" return "FileStorage v1"
} }
...@@ -991,7 +976,7 @@ func (fs *FileStorage) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error) ...@@ -991,7 +976,7 @@ func (fs *FileStorage) Load(xid zodb.Xid) (data []byte, tid zodb.Tid, err error)
return data, tid, nil return data, tid, nil
} }
// --- zodb.IStorage iteration --- // --- ZODB-level iteration ---
// zIter is combined transaction/data-records iterator as specified by zodb.IStorage // zIter is combined transaction/data-records iterator as specified by zodb.IStorage
type zIter struct { type zIter struct {
...@@ -1181,7 +1166,7 @@ func (fs *FileStorage) computeIndex(ctx context.Context) (index *Index, err erro ...@@ -1181,7 +1166,7 @@ func (fs *FileStorage) computeIndex(ctx context.Context) (index *Index, err erro
fsSeq := xbufio.NewSeqReaderAt(fs.file) fsSeq := xbufio.NewSeqReaderAt(fs.file)
// pre-setup txnh so that txnh.LoadNext starts loading from the beginning of file // pre-setup txnh so that txnh.LoadNext starts loading from the beginning of file
txnh := &TxnHeader{Pos: index.TopPos, Len: -2} // XXX -2 txnh := &TxnHeader{Pos: index.TopPos, Len: lenIterStart}
dh := &DataHeader{} dh := &DataHeader{}
loop: loop:
...@@ -1193,14 +1178,7 @@ loop: ...@@ -1193,14 +1178,7 @@ loop:
default: default:
} }
// XXX merge logic into LoadNext/LoadPrev
switch txnh.Len {
case -2:
err = txnh.Load(fsSeq, txnh.Pos, LoadNoStrings)
default:
err = txnh.LoadNext(fsSeq, LoadNoStrings) err = txnh.LoadNext(fsSeq, LoadNoStrings)
}
if err != nil { if err != nil {
err = okEOF(err) err = okEOF(err)
break break
......
// 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 fs1
import (
"io"
)
// XXX -> xio ?
// noEOF returns err, but changes io.EOF -> io.ErrUnexpectedEOF
func noEOF(err error) error {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
// okEOF returns err, but changes io.EOF -> nil
func okEOF(err error) error {
if err == io.EOF {
err = nil
}
return 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