2
2
mirror of https://github.com/octoleo/restic.git synced 2024-05-31 16:10:49 +00:00

Merge pull request #1265 from restic/improve-packers

Improve packers, prepare for cache
This commit is contained in:
Alexander Neumann 2017-09-22 16:16:10 +02:00
commit 8f9bf1995b
3 changed files with 45 additions and 35 deletions

View File

@ -38,8 +38,6 @@ type packerManager struct {
}
const minPackSize = 4 * 1024 * 1024
const maxPackSize = 16 * 1024 * 1024
const maxPackers = 200
// newPackerManager returns an new packer manager which writes temporary files
// to a temporary directory
@ -52,25 +50,19 @@ func newPackerManager(be Saver, key *crypto.Key) *packerManager {
// findPacker returns a packer for a new blob of size bytes. Either a new one is
// created or one is returned that already has some blobs.
func (r *packerManager) findPacker(size uint) (packer *Packer, err error) {
func (r *packerManager) findPacker() (packer *Packer, err error) {
r.pm.Lock()
defer r.pm.Unlock()
// search for a suitable packer
if len(r.packers) > 0 {
debug.Log("searching packer for %d bytes\n", size)
for i, p := range r.packers {
if p.Packer.Size()+size < maxPackSize {
debug.Log("found packer %v", p)
// remove from list
r.packers = append(r.packers[:i], r.packers[i+1:]...)
return p, nil
}
}
p := r.packers[0]
r.packers = r.packers[1:]
return p, nil
}
// no suitable packer found, return new
debug.Log("create new pack for %d bytes", size)
debug.Log("create new pack")
tmpfile, err := fs.TempFile("", "restic-temp-pack-")
if err != nil {
return nil, errors.Wrap(err, "fs.TempFile")

View File

@ -72,7 +72,7 @@ func fillPacks(t testing.TB, rnd *randReader, be Saver, pm *packerManager, buf [
l := rnd.rand.Intn(1 << 20)
seed := rnd.rand.Int63()
packer, err := pm.findPacker(uint(l))
packer, err := pm.findPacker()
if err != nil {
t.Fatal(err)
}
@ -91,7 +91,7 @@ func fillPacks(t testing.TB, rnd *randReader, be Saver, pm *packerManager, buf [
}
bytes += l
if packer.Size() < minPackSize && pm.countPacker() < maxPackers {
if packer.Size() < minPackSize {
pm.insertPacker(packer)
continue
}

View File

@ -24,15 +24,17 @@ type Repository struct {
keyName string
idx *MasterIndex
*packerManager
treePM *packerManager
dataPM *packerManager
}
// New returns a new repository with backend be.
func New(be restic.Backend) *Repository {
repo := &Repository{
be: be,
idx: NewMasterIndex(),
packerManager: newPackerManager(be, nil),
be: be,
idx: NewMasterIndex(),
dataPM: newPackerManager(be, nil),
treePM: newPackerManager(be, nil),
}
return repo
@ -180,7 +182,18 @@ func (r *Repository) SaveAndEncrypt(ctx context.Context, t restic.BlobType, data
}
// find suitable packer and add blob
packer, err := r.findPacker(uint(len(ciphertext)))
var pm *packerManager
switch t {
case restic.TreeBlob:
pm = r.treePM
case restic.DataBlob:
pm = r.dataPM
default:
panic(fmt.Sprintf("invalid type: %v", t))
}
packer, err := pm.findPacker()
if err != nil {
return restic.ID{}, err
}
@ -191,11 +204,10 @@ func (r *Repository) SaveAndEncrypt(ctx context.Context, t restic.BlobType, data
return restic.ID{}, err
}
// if the pack is not full enough and there are less than maxPackers
// packers, put back to the list
if packer.Size() < minPackSize && r.countPacker() < maxPackers {
// if the pack is not full enough, put back to the list
if packer.Size() < minPackSize {
debug.Log("pack is not full enough (%d bytes)", packer.Size())
r.insertPacker(packer)
pm.insertPacker(packer)
return *id, nil
}
@ -239,18 +251,22 @@ func (r *Repository) SaveUnpacked(ctx context.Context, t restic.FileType, p []by
// Flush saves all remaining packs.
func (r *Repository) Flush() error {
r.pm.Lock()
defer r.pm.Unlock()
for _, pm := range []*packerManager{r.dataPM, r.treePM} {
pm.pm.Lock()
debug.Log("manually flushing %d packs", len(r.packerManager.packers))
for _, p := range r.packerManager.packers {
err := r.savePacker(p)
if err != nil {
return err
debug.Log("manually flushing %d packs", len(pm.packers))
for _, p := range pm.packers {
err := r.savePacker(p)
if err != nil {
pm.pm.Unlock()
return err
}
}
pm.packers = pm.packers[:0]
pm.pm.Unlock()
}
r.packerManager.packers = r.packerManager.packers[:0]
return nil
}
@ -372,7 +388,8 @@ func (r *Repository) SearchKey(ctx context.Context, password string, maxKeys int
}
r.key = key.master
r.packerManager.key = key.master
r.dataPM.key = key.master
r.treePM.key = key.master
r.keyName = key.Name()
r.cfg, err = restic.LoadConfig(ctx, r)
return err
@ -406,7 +423,8 @@ func (r *Repository) init(ctx context.Context, password string, cfg restic.Confi
}
r.key = key.master
r.packerManager.key = key.master
r.dataPM.key = key.master
r.treePM.key = key.master
r.keyName = key.Name()
r.cfg = cfg
_, err = r.SaveJSONUnpacked(ctx, restic.ConfigFile, cfg)