Documentation ¶
Overview ¶
Package fs1 provides so-called FileStorage version 1 ZODB storage.
FileStorage is a single file organized as a simple append-only log of transactions with data changes. Every transaction record consists of:
- transaction record header represented by TxnHeader,
- several data records corresponding to modified objects,
- redundant transaction length at the end of transaction record.
Every data record consists of:
- data record header represented by DataHeader,
- actual data following the header.
The "actual data" in addition to raw content, can be a back-pointer indicating that the actual content should be retrieved from a past revision.
In addition to append-only transaction/data log, an index is automatically maintained mapping oid -> latest data record which modified this oid. The index is used to implement zodb.IStorage.Load for latest data without linear scan.
The data format is bit-to-bit identical to FileStorage format implemented in ZODB/py. Please see the following links for original FileStorage format definition:
https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/FileStorage/format.py https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fstools.py
The index format is interoperable with ZODB/py (index uses pickles which allow various valid encodings of a given object). Please see the following links for original FileStorage/py index definition:
https://github.com/zopefoundation/ZODB/blob/a89485c1/src/ZODB/fsIndex.py https://github.com/zopefoundation/ZODB/commit/1bb14faf
Unless one is doing something FileStorage-specific, it is advised not to use fs1 package directly, and instead link-in lab.nexedi.com/kirr/neo/go/zodb/wks, open storage by zodb.Open 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 tools.
See also package lab.nexedi.com/kirr/neo/go/zodb/storage/fs1/fs1tools and associated fs1 command for basic tools related to FileStorage maintenance.
Index ¶
- Constants
- type DataHeader
- func (dh *DataHeader) Free()
- func (dh *DataHeader) Len() int64
- func (dh *DataHeader) Load(r io.ReaderAt, pos int64) error
- func (dh *DataHeader) LoadBack(r io.ReaderAt) error
- func (dh *DataHeader) LoadBackRef(r io.ReaderAt) (backPos int64, err error)
- func (dh *DataHeader) LoadData(r io.ReaderAt) (*mem.Buf, error)
- func (dh *DataHeader) LoadNext(r io.ReaderAt, txnh *TxnHeader) error
- func (dh *DataHeader) LoadPrevRev(r io.ReaderAt) error
- type FileHeader
- type FileStorage
- func (fs *FileStorage) Close() error
- func (fs *FileStorage) Iterate(_ context.Context, tidMin, tidMax zodb.Tid) zodb.ITxnIterator
- func (fs *FileStorage) LastOid(_ context.Context) (zodb.Oid, error)
- func (fs *FileStorage) Load(_ context.Context, xid zodb.Xid) (buf *mem.Buf, serial zodb.Tid, err error)
- func (fs *FileStorage) Sync(ctx context.Context) (head zodb.Tid, err error)
- func (fs *FileStorage) URL() string
- type Index
- func BuildIndex(ctx context.Context, r io.ReaderAt, progress func(*IndexUpdateProgress)) (*Index, error)
- func BuildIndexForFile(ctx context.Context, path string, progress func(*IndexUpdateProgress)) (index *Index, err error)
- func IndexNew() *Index
- func LoadIndex(r io.Reader) (fsi *Index, err error)
- func LoadIndexFile(path string) (fsi *Index, err error)
- func (a *Index) Equal(b *Index) bool
- func (fsi *Index) Save(w io.Writer) (err error)
- func (fsi *Index) SaveFile(path string) error
- func (index *Index) Update(ctx context.Context, r io.ReaderAt, topPos int64, ...) (err error)
- func (index *Index) Verify(ctx context.Context, r io.ReaderAt, ntxn int, ...) (oidChecked map[zodb.Oid]struct{}, err error)
- func (index *Index) VerifyForFile(ctx context.Context, path string, ntxn int, ...) (oidChecked map[zodb.Oid]struct{}, err error)
- type IndexCorruptError
- type IndexLoadError
- type IndexSaveError
- type IndexUpdateProgress
- type IndexVerifyProgress
- type Iter
- type IterDir
- type RecordError
- type TxnHeader
- func (txnh *TxnHeader) CloneFrom(txnh2 *TxnHeader)
- func (txnh *TxnHeader) DataLen() int64
- func (txnh *TxnHeader) DataPos() int64
- func (txnh *TxnHeader) HeaderLen() int64
- func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
- func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error
- func (txnh *TxnHeader) LoadPrev(r io.ReaderAt, flags TxnLoadFlags) error
- type TxnLoadFlags
Constants ¶
const ( Magic = "FS21" // every FileStorage file starts with this // on-disk sizes FileHeaderSize = 4 TxnHeaderFixSize = 8 + 8 + 1 + 2 + 2 + 2 // without user/desc/ext strings DataHeaderSize = 8 + 8 + 8 + 8 + 2 + 8 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type DataHeader ¶
type DataHeader struct { Pos int64 // position of data record start Oid zodb.Oid Tid zodb.Tid PrevRevPos int64 // position of this oid's previous-revision data record TxnPos int64 // position of transaction record this data record belongs to //_ uint16 // 2-bytes with zero values. (Was version length.) DataLen int64 // length of following data. if 0 -> following = 8 bytes backpointer // contains filtered or unexported fields }
DataHeader represents header of a data record.
func DataHeaderAlloc ¶
func DataHeaderAlloc() *DataHeader
DataHeaderAlloc allocates DataHeader from freelist.
func (*DataHeader) Free ¶
func (dh *DataHeader) Free()
Free puts dh back into DataHeader freelist.
Caller must not use dh after call to Free.
func (*DataHeader) Load ¶
func (dh *DataHeader) Load(r io.ReaderAt, pos int64) error
Load reads and decodes data record header @ pos.
Only the data record header is loaded, not data itself. See LoadData for actually loading record's data.
No prerequisite requirements are made to previous dh state.
func (*DataHeader) LoadBack ¶
func (dh *DataHeader) LoadBack(r io.ReaderAt) error
LoadBack reads and decodes data header for revision linked via back-pointer.
Prerequisite: dh is loaded and .DataLen == 0.
If link is to zero (means deleted record) io.EOF is returned.
func (*DataHeader) LoadBackRef ¶
func (dh *DataHeader) LoadBackRef(r io.ReaderAt) (backPos int64, err error)
LoadBackRef reads data for the data record and decodes it as backpointer reference.
Prerequisite: dh loaded and .LenData == 0 (data record with back-pointer).
func (*DataHeader) LoadData ¶
LoadData loads data for the data record taking backpointers into account.
On success dh state is changed to data header of original data transaction.
NOTE "deleted" records are indicated via returning buf with .Data=nil without error.
func (*DataHeader) LoadNext ¶
func (dh *DataHeader) LoadNext(r io.ReaderAt, txnh *TxnHeader) error
LoadNext reads and decodes data header for next data record in the same transaction.
Prerequisite: dh .Pos .DataLen are initialized.
When there is no more data records: io.EOF is returned.
func (*DataHeader) LoadPrevRev ¶
func (dh *DataHeader) LoadPrevRev(r io.ReaderAt) error
LoadPrevRev reads and decodes previous revision data record header.
Prerequisite: dh .Oid .Tid .PrevRevPos are initialized.
When there is no previous revision: io.EOF is returned.
type FileHeader ¶
type FileHeader struct {
Magic [4]byte
}
FileHeader represents header of whole data file.
type FileStorage ¶
type FileStorage struct {
// contains filtered or unexported fields
}
FileStorage is a ZODB storage which stores data in simple append-only file organized as transactional log.
It is on-disk compatible with FileStorage from ZODB/py.
func Open ¶
func Open(ctx context.Context, path string, opt *zodb.DriverOptions) (_ *FileStorage, at0 zodb.Tid, err error)
Open opens FileStorage @path.
func (*FileStorage) Close ¶
func (fs *FileStorage) Close() error
func (*FileStorage) Iterate ¶
func (fs *FileStorage) Iterate(_ context.Context, tidMin, tidMax zodb.Tid) zodb.ITxnIterator
Iterate creates zodb-level iterator for tidMin..tidMax range.
func (*FileStorage) URL ¶
func (fs *FileStorage) URL() string
type Index ¶
type Index struct { // this index covers data file up to < .TopPos // usually for whole-file index TopPos is position pointing just past // the last committed transaction. TopPos int64 *fsb.Tree }
Index is in-RAM Oid -> Data record position mapping used to associate Oid with Data record in latest transaction which changed it.
func BuildIndex ¶
func BuildIndex(ctx context.Context, r io.ReaderAt, progress func(*IndexUpdateProgress)) (*Index, error)
BuildIndex builds new in-memory index for data in r.
non-nil valid and consistent index is always returned - even in case of error the index will describe data till top-position of highest transaction that could be read without error.
In such cases the index building could be retried to be finished with index.Update().
func BuildIndexForFile ¶
func BuildIndexForFile(ctx context.Context, path string, progress func(*IndexUpdateProgress)) (index *Index, err error)
BuildIndexForFile builds new in-memory index for data in file @ path.
See BuildIndex for semantic description.
func LoadIndexFile ¶
LoadIndexFile loads index from a file @ path.
func (*Index) SaveFile ¶
SaveFile saves index to a file @ path.
Index data is first saved to a temporary file and when complete the temporary is renamed to be at requested path. This way file @ path will be updated only with complete index data.
func (*Index) Update ¶
func (index *Index) Update(ctx context.Context, r io.ReaderAt, topPos int64, progress func(*IndexUpdateProgress)) (err error)
Update updates in-memory index from r's FileStorage data in byte-range index.TopPos..topPos
The use case is: we have index computed till some position; we open FileStorage and see there is more data; we update index from data range not-yet covered by the index.
topPos=-1 means data range to update from is index.TopPos..EOF
The index stays valid even in case of error - then index is updated but only partially. The index always stays consistent as updates to it are applied as a whole once per data transaction. On return index.TopPos indicates till which position in data the index could be updated.
On success returned error is nil and index.TopPos is set to either:
- topPos (if it is != -1), or
- r's position at which read got EOF (if topPos=-1).
func (*Index) Verify ¶
func (index *Index) Verify(ctx context.Context, r io.ReaderAt, ntxn int, progress func(*IndexVerifyProgress)) (oidChecked map[zodb.Oid]struct{}, err error)
Verify checks index correctness against FileStorage data in r.
For ntxn transactions starting from index.TopPos backwards, it verifies whether oid there have correct entries in the index.
ntxn=-1 means data range to verify is till start of the file.
If whole data file was covered (either ntxn is big enough or was set = -1) additional checks are performed to make sure there is no extra entries in the index. For whole-data file cases Verify thus checks whether index is exactly the same as if it was build anew for data in range ..index.TopPos .
Returned error is either:
- of type *IndexCorruptError, when data in index was found not to match original data, or
- any other error type representing e.g. IO error when reading original data or something else.
func (*Index) VerifyForFile ¶
func (index *Index) VerifyForFile(ctx context.Context, path string, ntxn int, progress func(*IndexVerifyProgress)) (oidChecked map[zodb.Oid]struct{}, err error)
VerifyForFile checks index correctness against FileStorage data in file @ path.
See Verify for semantic description.
type IndexCorruptError ¶
type IndexCorruptError struct { DataFileName string // present if data IO object was with .Name() Detail string }
IndexCorruptError is the error type returned by index verification routines when index was found to not match original FileStorage data.
func (*IndexCorruptError) Error ¶
func (e *IndexCorruptError) Error() string
type IndexLoadError ¶
type IndexLoadError struct { Filename string // present if used IO object was with .Name() Pos int64 Err error }
IndexLoadError is the error type returned by index load routines.
func (*IndexLoadError) Error ¶
func (e *IndexLoadError) Error() string
type IndexSaveError ¶
type IndexSaveError struct {
Err error // error that occurred during the operation
}
IndexSaveError is the error type returned by index save routines.
func (*IndexSaveError) Error ¶
func (e *IndexSaveError) Error() string
type IndexUpdateProgress ¶
type IndexUpdateProgress struct { TopPos int64 // data range to update to; if = -1 -- till EOF TxnIndexed int // # transactions read/indexed so far Index *Index // index built so far Iter *Iter // iterator through data XXX needed? }
IndexUpdateProgress is data sent by Index.Update to notify about progress.
type IndexVerifyProgress ¶
type IndexVerifyProgress struct { TxnTotal int // total # of transactions to verify; if = -1 -- whole data TxnChecked int Index *Index // index verification runs for Iter *Iter // iterator through data OidChecked map[zodb.Oid]struct{} // oid checked so far }
IndexVerifyProgress is data sent by Index.Verify to notify about progress.
type Iter ¶
type Iter struct { R io.ReaderAt Dir IterDir Txnh TxnHeader // current transaction record information Datah DataHeader // current data record information }
Iter is combined 2-level iterator over transaction and data records.
func IterateFile ¶
IterateFile opens file @ path read-only and creates Iter to iterate over it.
The iteration will use buffering over os.File optimized for sequential access. You are responsible to eventually close the file after the iteration is done.
func (*Iter) NextTxn ¶
func (it *Iter) NextTxn(flags TxnLoadFlags) error
NextTxn iterates to next/previous transaction record according to iteration direction.
The data header is reset to iterate inside transaction record that becomes current.
type RecordError ¶
type RecordError struct { Path string // path of the data file; present if used IO object was with .Name() Record string // record kind - "file header", "transaction record", "data record", ... Pos int64 // position of record Subj string // subject context for the error - e.g. "read" or "check" Err error // actual error }
RecordError represents error associated with operation on a record in FileStorage data file.
func (*RecordError) Cause ¶
func (e *RecordError) Cause() error
func (*RecordError) Error ¶
func (e *RecordError) Error() string
func (*RecordError) Unwrap ¶
func (e *RecordError) Unwrap() error
type TxnHeader ¶
type TxnHeader struct { Pos int64 // position of transaction start LenPrev int64 // whole previous transaction record length (see EOF/error rules in Load) Len int64 // whole transaction record length (see EOF/error rules in Load) // transaction metadata itself zodb.TxnInfo // contains filtered or unexported fields }
TxnHeader represents header of a transaction record.
func (*TxnHeader) CloneFrom ¶
CloneFrom copies txnh2 to txnh making sure underlying slices (.workMem .User .Desc ...) are not shared.
func (*TxnHeader) HeaderLen ¶
HeaderLen returns whole transaction header length including its variable part.
NOTE: data records start right after transaction header.
func (*TxnHeader) Load ¶
Load reads and decodes transaction record header @ pos.
Both transaction header starting at pos, and redundant length of previous transaction are loaded. The data read is verified for consistency lightly.
No prerequisite requirements are made to previous txnh state.
Rules for .Len/.LenPrev returns:
.Len = -1 transaction header could not be read .Len = 0 EOF forward .Len > 0 transaction was read normally .LenPrev = -1 prev record length could not be read .LenPrev = 0 EOF backward .LenPrev > 0 LenPrev was read/checked normally
For example when pos points to the end of file .Len will be returned = -1, but .LenPrev will be usually valid if file has at least 1 transaction.
type TxnLoadFlags ¶
type TxnLoadFlags int
flags for TxnHeader.Load
const ( LoadAll TxnLoadFlags = 0x00 // load whole transaction header LoadNoStrings TxnLoadFlags = 0x01 // do not load user/desc/ext strings )
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
fs1
fs1 is a driver program for running and invoking fs1 subcommands.
|
fs1 is a driver program for running and invoking fs1 subcommands. |
Package fs1tools provides tools for managing and maintaining ZODB FileStorage v1 databases.
|
Package fs1tools provides tools for managing and maintaining ZODB FileStorage v1 databases. |
Package fsb specializes cznic/b.Tree for FileStorage index needs.
|
Package fsb specializes cznic/b.Tree for FileStorage index needs. |