1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
1.9 KiB
Go

package store
import (
"os"
"time"
"github.com/rqlite/rqlite/v8/command/proto"
"github.com/rqlite/rqlite/v8/db"
)
// 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
nRetries int
retryInterval time.Duration
}
// NewProvider returns a new instance of Provider.
func NewProvider(s *Store, v bool) *Provider {
return &Provider{
str: s,
vacuum: v,
nRetries: 10,
retryInterval: 500 * time.Millisecond,
}
}
// Check returns true if the Provider data has changed since the last time
// Check() was called with the given value of i. Check() also returns the
// current value of i, which should be passed to the next invocation of
// Check(). If Check() returns false, the returned int64 can be ignored.
func (p *Provider) Check(i int64) (int64, bool) {
stats.Add(numProviderChecks, 1)
lm, err := p.str.db.LastModified()
if err != nil {
return 0, false
}
return lm.UnixNano(), lm.UnixNano() > i
}
// Provider writes the SQLite database to the given path, ensuring the database
// is in DELETE mode. If path exists, it will be overwritten.
func (p *Provider) Provide(path string) (retErr error) {
stats.Add(numProviderProvides, 1)
defer func() {
if retErr != nil {
stats.Add(numProviderProvidesFail, 1)
}
}()
fd, err := os.Create(path)
if err != nil {
return err
}
defer fd.Close()
br := &proto.BackupRequest{
Format: proto.BackupRequest_BACKUP_REQUEST_FORMAT_BINARY,
Vacuum: p.vacuum,
}
nRetries := 0
for {
err := p.str.Backup(br, fd)
if err == nil {
break
}
time.Sleep(p.retryInterval)
nRetries++
if nRetries > p.nRetries {
return err
}
}
// Switch database to DELETE mode, to keep existing behaviour.
if err := fd.Close(); err != nil {
return err
}
if db.EnsureDeleteMode(path) != nil {
return err
}
stats.Add(numProvides, 1)
return nil
}