diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index d69ab93d..23d5bb58 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -236,14 +236,11 @@ func (l *LuetInstaller) computeSwap(syncedRepos Repositories, toRemove pkg.Packa toInstall = syncedRepos.ResolveSelectors(toInstall) // First check what would have been done - installedtmp := pkg.NewInMemoryDatabase(false) - - for _, i := range s.Database.World() { - _, err := installedtmp.CreatePackage(i) - if err != nil { - return nil, nil, nil, nil, errors.Wrap(err, "Failed create temporary in-memory db") - } + installedtmp, err := s.Database.Copy() + if err != nil { + return nil, nil, nil, nil, errors.Wrap(err, "Failed create temporary in-memory db") } + systemAfterChanges := &System{Database: installedtmp} packs, err := l.computeUninstall(systemAfterChanges, toRemove...) @@ -772,13 +769,10 @@ func (l *LuetInstaller) computeUninstall(s *System, packs ...pkg.Package) (pkg.P // Create a temporary DB with the installed packages // so the solver is much faster finding the deptree - installedtmp := pkg.NewInMemoryDatabase(false) - - for _, i := range s.Database.World() { - _, err := installedtmp.CreatePackage(i) - if err != nil { - return toUninstall, errors.Wrap(err, "Failed create temporary in-memory db") - } + // First check what would have been done + installedtmp, err := s.Database.Copy() + if err != nil { + return toUninstall, errors.Wrap(err, "Failed create temporary in-memory db") } if !l.Options.NoDeps { diff --git a/pkg/package/database.go b/pkg/package/database.go index e5c69f10..b42b4dbc 100644 --- a/pkg/package/database.go +++ b/pkg/package/database.go @@ -28,6 +28,9 @@ type PackageDatabase interface { } type PackageSet interface { + Clone(PackageDatabase) error + Copy() (PackageDatabase, error) + GetRevdeps(p Package) (Packages, error) GetPackages() []string //Ids CreatePackage(pkg Package) (string, error) diff --git a/pkg/package/database_boltdb.go b/pkg/package/database_boltdb.go index 15e1c04f..2a94be28 100644 --- a/pkg/package/database_boltdb.go +++ b/pkg/package/database_boltdb.go @@ -47,6 +47,14 @@ func NewBoltDatabase(path string) PackageDatabase { return &BoltDatabase{Path: path, ProvidesDatabase: map[string]map[string]Package{}} } +func (db *BoltDatabase) Clone(to PackageDatabase) error { + return clone(db, to) +} + +func (db *BoltDatabase) Copy() (PackageDatabase, error) { + return copy(db) +} + func (db *BoltDatabase) Get(s string) (string, error) { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { diff --git a/pkg/package/database_common.go b/pkg/package/database_common.go new file mode 100644 index 00000000..0810257d --- /dev/null +++ b/pkg/package/database_common.go @@ -0,0 +1,38 @@ +// Copyright © 2020 Ettore Di Giacinto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package pkg + +import "github.com/pkg/errors" + +func clone(src, dst PackageDatabase) error { + for _, i := range src.World() { + _, err := dst.CreatePackage(i) + if err != nil { + return errors.Wrap(err, "Failed create package "+i.HumanReadableString()) + } + } + return nil +} + +func copy(src PackageDatabase) (PackageDatabase, error) { + dst := NewInMemoryDatabase(false) + + if err := clone(src, dst); err != nil { + return dst, errors.Wrap(err, "Failed create temporary in-memory db") + } + + return dst, nil +} diff --git a/pkg/package/database_mem.go b/pkg/package/database_mem.go index da6606ca..c05084c3 100644 --- a/pkg/package/database_mem.go +++ b/pkg/package/database_mem.go @@ -270,6 +270,14 @@ func (db *InMemoryDatabase) getProvide(p Package) (Package, error) { return db.FindPackage(pa) } +func (db *InMemoryDatabase) Clone(to PackageDatabase) error { + return clone(db, to) +} + +func (db *InMemoryDatabase) Copy() (PackageDatabase, error) { + return copy(db) +} + func (db *InMemoryDatabase) encodePackage(p Package) (string, string, error) { pd, ok := p.(*DefaultPackage) if !ok { diff --git a/pkg/solver/parallel.go b/pkg/solver/parallel.go index 4cc382fd..a91937f5 100644 --- a/pkg/solver/parallel.go +++ b/pkg/solver/parallel.go @@ -446,10 +446,9 @@ func (s *Parallel) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAsse removed := pkg.Packages{} // TODO: this is memory expensive, we need to optimize this - universe := pkg.NewInMemoryDatabase(false) - - for _, p := range s.DefinitionDatabase.World() { - universe.CreatePackage(p) + universe, err := s.DefinitionDatabase.Copy() + if err != nil { + return nil, nil, errors.Wrap(err, "couldn't build world copy") } for _, p := range s.Installed() { universe.CreatePackage(p) @@ -558,9 +557,9 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss toInstall := pkg.Packages{} // we do this in memory so we take into account of provides - universe := pkg.NewInMemoryDatabase(false) - for _, p := range s.DefinitionDatabase.World() { - universe.CreatePackage(p) + universe, err := s.DefinitionDatabase.Copy() + if err != nil { + return nil, nil, errors.Wrap(err, "Could not copy def db") } installedcopy := pkg.NewInMemoryDatabase(false) diff --git a/pkg/solver/solver.go b/pkg/solver/solver.go index 5553ce97..65c5f812 100644 --- a/pkg/solver/solver.go +++ b/pkg/solver/solver.go @@ -402,10 +402,11 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert replacements := map[pkg.Package]pkg.Package{} // TODO: this is memory expensive, we need to optimize this - universe := pkg.NewInMemoryDatabase(false) - for _, p := range s.DefinitionDatabase.World() { - universe.CreatePackage(p) + universe, err := s.DefinitionDatabase.Copy() + if err != nil { + return nil, nil, errors.Wrap(err, "Failed copying db") } + for _, p := range s.Installed() { universe.CreatePackage(p) } @@ -501,10 +502,10 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser toUninstall := pkg.Packages{} toInstall := pkg.Packages{} - // we do this in memory so we take into account of provides - universe := pkg.NewInMemoryDatabase(false) - for _, p := range s.DefinitionDatabase.World() { - universe.CreatePackage(p) + // we do this in memory so we take into account of provides, and its faster + universe, err := s.DefinitionDatabase.Copy() + if err != nil { + return nil, nil, errors.Wrap(err, "failed creating db copy") } installedcopy := pkg.NewInMemoryDatabase(false)