|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/rqlite/rqlite/v8/command/proto"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Provider implements the uploader Provider interface, allowing the
|
|
|
|
// Store to be used as a DataProvider for an uploader.
|
|
|
|
type Provider struct {
|
|
|
|
str *Store
|
|
|
|
vacuum bool
|
|
|
|
compress bool
|
|
|
|
|
|
|
|
nRetries int
|
|
|
|
retryInterval time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewProvider returns a new instance of Provider. If v is true, the
|
|
|
|
// SQLite database will be VACUUMed before being provided. If c is
|
|
|
|
// true, the SQLite database will be compressed before being provided.
|
|
|
|
func NewProvider(s *Store, v, c bool) *Provider {
|
|
|
|
return &Provider{
|
|
|
|
str: s,
|
|
|
|
vacuum: v,
|
|
|
|
compress: c,
|
|
|
|
nRetries: 10,
|
|
|
|
retryInterval: 500 * time.Millisecond,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LastModified returns the time the data managed by the Provider was
|
|
|
|
// last modified.
|
|
|
|
func (p *Provider) LastModified() (time.Time, error) {
|
|
|
|
stats.Add(numProviderChecks, 1)
|
|
|
|
return p.str.db.LastModified()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Provider writes the SQLite database to the given path. If path exists,
|
|
|
|
// it will be overwritten.
|
|
|
|
func (p *Provider) Provide(w io.Writer) (t time.Time, retErr error) {
|
|
|
|
stats.Add(numProviderProvides, 1)
|
|
|
|
defer func() {
|
|
|
|
if retErr != nil {
|
|
|
|
stats.Add(numProviderProvidesFail, 1)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
br := &proto.BackupRequest{
|
|
|
|
Format: proto.BackupRequest_BACKUP_REQUEST_FORMAT_BINARY,
|
|
|
|
Vacuum: p.vacuum,
|
|
|
|
Compress: p.compress,
|
|
|
|
}
|
|
|
|
nRetries := 0
|
|
|
|
for {
|
|
|
|
err := p.str.Backup(br, w)
|
|
|
|
if err == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
time.Sleep(p.retryInterval)
|
|
|
|
nRetries++
|
|
|
|
if nRetries > p.nRetries {
|
|
|
|
return time.Time{}, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p.str.db.LastModified()
|
|
|
|
}
|