Skip to content

Commit

Permalink
Merge pull request #84 from mcarmonaa/improvement/siva-reload-metadata
Browse files Browse the repository at this point in the history
siva: reload metadata
  • Loading branch information
jfontan committed Aug 20, 2019
2 parents 63019a4 + b4407c0 commit 0972e27
Show file tree
Hide file tree
Showing 5 changed files with 411 additions and 270 deletions.
76 changes: 31 additions & 45 deletions siva/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
Expand All @@ -31,7 +32,7 @@ type Library struct {
locReg *locationRegistry
locMu sync.Mutex
options *LibraryOptions
metadata *LibraryMetadata
metadata *libMetadata
}

// LibraryOptions hold configuration options for the library.
Expand Down Expand Up @@ -61,23 +62,20 @@ type LibraryOptions struct {
// Performance enables performance options in read only git repositories
// (ExclusiveAccess and KeepDescriptors).
Performance bool
// DontGenerateID stops the library from generating a library ID if it's
// not provided or already in metadata.
DontGenerateID bool
// MetadataReadOnly doesn't create or modify metadata for the library.
MetadataReadOnly bool
}

var _ borges.Library = (*Library)(nil)

const (
timeout = 20 * time.Second
// txTimeout is the default transaction TransactionTimeout.
timeout = 20 * time.Second
txTimeout = 60 * time.Second
registryCacheSize = 10000
)

// NewLibrary creates a new siva.Library. If id is not provided the library ID
// is read from the existing metadata or generated if not available and the
// option DontGenerateID is not set.
// NewLibrary creates a new siva.Library. When is not in MetadataReadOnly it
// will generate an id if not provided the first time the metadata is created.
func NewLibrary(
id string,
fs billy.Filesystem,
Expand All @@ -90,24 +88,23 @@ func NewLibrary(
ops = &(*options)
}

metadata, err := loadLibraryMetadata(fs)
if err != nil {
// TODO: skip metadata if corrupted?
return nil, err
}
var (
metadata *libMetadata
err error
)

if metadata == nil {
metadata = NewLibraryMetadata("", -1)
if ops.MetadataReadOnly {
metadata, err = loadLibraryMetadata(fs)
} else {
metadata, err = loadOrCreateLibraryMetadata(id, fs)
}

if id == "" {
if metadata.ID == "" && !ops.DontGenerateID {
metadata.GenerateID()
}
if err != nil && !os.IsNotExist(err) {
return nil, err
}

if metadata != nil && id == "" {
id = metadata.ID
} else {
metadata.SetID(id)
}

if ops.RegistryCache <= 0 {
Expand Down Expand Up @@ -137,21 +134,14 @@ func NewLibrary(
tmp = osfs.New(dir)
}

lib := &Library{
return &Library{
id: borges.LibraryID(id),
fs: fs,
tmp: tmp,
locReg: lr,
options: ops,
metadata: metadata,
}

err = lib.SaveMetadata()
if err != nil {
return nil, err
}

return lib, nil
}, nil
}

// ID implements borges.Library interface.
Expand Down Expand Up @@ -349,24 +339,20 @@ func (l *Library) locations(ctx context.Context) ([]borges.Location, error) {
}

// Version returns version stored in metadata or -1 if not defined.
func (l *Library) Version() int {
return l.metadata.Version()
}

// SetVersion sets the current version to the given number.
func (l *Library) SetVersion(n int) {
if l.metadata == nil {
l.metadata = NewLibraryMetadata(string(l.id), -1)
func (l *Library) Version() (int, error) {
if l.metadata != nil {
return l.metadata.version()
}

l.metadata.SetVersion(n)
return -1, nil
}

// SaveMetadata writes the metadata to the library yaml file.
func (l *Library) SaveMetadata() error {
if l.metadata != nil && l.metadata.dirty {
return l.metadata.Save(l.fs)
// SetVersion sets the current version to the given number.
func (l *Library) SetVersion(n int) error {
if l.metadata == nil {
return nil
}

return nil
l.metadata.setVersion(n)
return l.metadata.save()
}
71 changes: 44 additions & 27 deletions siva/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Location struct {
lib *Library
checkpoint *checkpoint
txer *transactioner
metadata *LocationMetadata
metadata *locationMetadata

// references and config cache
refs memory.ReferenceStorage
Expand All @@ -58,10 +58,14 @@ func newLocation(
path string,
create bool,
) (*Location, error) {
metadata, err := loadLocationMetadata(lib.fs, locationMetadataPath(path))
if err != nil {
// TODO: skip metadata if corrupted? log a warning?
return nil, err
var metadata *locationMetadata
if lib.metadata != nil {
var err error
metadata, err = loadOrCreateLocationMetadata(lib.fs, string(id))
if err != nil {
// TODO: skip metadata if corrupted? log a warning?
return nil, err
}
}

cp, err := newCheckpoint(lib.fs, path, create)
Expand Down Expand Up @@ -104,7 +108,11 @@ func (l *Location) checkAndUpdate() error {
return err
}

version := l.lib.Version()
version, err := l.lib.Version()
if err != nil {
return err
}

if l.fSize == stat.Size() && l.fTime == stat.ModTime() &&
l.version == version && l.checkpoint.Offset() == cp.Offset() {
return nil
Expand Down Expand Up @@ -175,9 +183,18 @@ func (l *Location) fs(mode borges.Mode, cp *checkpoint) (sivafs.SivaFS, error) {
return nil, borges.ErrLocationNotExists.New(string(l.id))
}

if l.metadata != nil {
version := l.lib.Version()
if o := l.metadata.Offset(version); o > 0 {
if l.lib.metadata != nil {
version, err := l.lib.Version()
if err != nil {
return nil, err
}

o, err := l.metadata.offset(version)
if err != nil {
return nil, err
}

if o > 0 {
offset = o
}
}
Expand Down Expand Up @@ -561,40 +578,40 @@ func (l *Location) repository(
return newRepository(id, sto, fs, mode, l.lib.options.Transactional, l)
}

func (l *Location) createMetadata() {
if l.metadata == nil {
l.metadata = NewLocationMetadata(make(map[int]Version))
}
}

// LastVersion returns the last defined version number in metadata or -1 if
// there are not versions.
func (l *Location) LastVersion() int {
return l.metadata.Last()
return l.metadata.last()
}

// Version returns an specific version. Second return value is false if the
// version does not exist.
func (l *Location) Version(v int) (Version, bool) {
return l.metadata.Version(v)
// Version returns an specific version. If the given version does not exist
// an error is returned.
func (l *Location) Version(v int) (*Version, error) {
if l.lib.metadata != nil {
return l.metadata.version(v)
}

return nil, errLocVersionNotExists.New()
}

// SetVersion adds or changes a version to the location.
func (l *Location) SetVersion(n int, v Version) {
l.createMetadata()
l.metadata.SetVersion(n, v)
func (l *Location) SetVersion(n int, v *Version) {
if l.lib.metadata != nil {
l.metadata.setVersion(n, v)
}
}

// DeleteVersion removes the given version number.
func (l *Location) DeleteVersion(n int) {
l.createMetadata()
l.metadata.DeleteVersion(n)
if l.lib.metadata != nil {
l.metadata.deleteVersion(n)
}
}

// SaveMetadata writes the location metadata to disk.
func (l *Location) SaveMetadata() error {
if l.metadata != nil && l.metadata.Dirty() {
return l.metadata.Save(l.lib.fs, l.path)
if l.metadata != nil {
return l.metadata.save()
}

return nil
Expand Down

0 comments on commit 0972e27

Please sign in to comment.