diff --git a/cmd/build.go b/cmd/build.go index 26bc487a..a4c85a31 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -24,6 +24,7 @@ import ( . "github.com/mudler/luet/pkg/config" . "github.com/mudler/luet/pkg/logger" pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/solver" tree "github.com/mudler/luet/pkg/tree" "github.com/spf13/cobra" @@ -81,6 +82,7 @@ var buildCmd = &cobra.Command{ onlyTarget, _ := cmd.Flags().GetBool("only-target-package") full, _ := cmd.Flags().GetBool("full") skip, _ := cmd.Flags().GetBool("skip-if-metadata-exists") + concurrent, _ := cmd.Flags().GetBool("solver-concurrent") compilerSpecs := compiler.NewLuetCompilationspecs() var compilerBackend compiler.CompilerBackend @@ -148,7 +150,14 @@ var buildCmd = &cobra.Command{ opts.SkipIfMetadataExists = skip opts.PackageTargetOnly = onlyTarget - luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts) + var solverOpts solver.Options + if concurrent { + solverOpts = solver.Options{Type: solver.SingleCoreSimple} + } else { + solverOpts = solver.Options{Type: solver.ParallelSimple} + } + + luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts, solverOpts) luetCompiler.SetConcurrency(concurrency) luetCompiler.SetCompressionType(compiler.CompressionImplementation(compressionType)) if full { @@ -241,6 +250,7 @@ func init() { buildCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") buildCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate") buildCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts") + buildCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)") RootCmd.AddCommand(buildCmd) } diff --git a/cmd/install.go b/cmd/install.go index 3834778c..ab254747 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -19,6 +19,7 @@ import ( "path/filepath" installer "github.com/mudler/luet/pkg/installer" + "github.com/mudler/luet/pkg/solver" helpers "github.com/mudler/luet/cmd/helpers" . "github.com/mudler/luet/pkg/config" @@ -73,11 +74,19 @@ var installCmd = &cobra.Command{ force := LuetCfg.Viper.GetBool("force") nodeps := LuetCfg.Viper.GetBool("nodeps") onlydeps := LuetCfg.Viper.GetBool("onlydeps") + concurrent, _ := cmd.Flags().GetBool("solver-concurrent") + LuetCfg.GetSolverOptions().Type = stype LuetCfg.GetSolverOptions().LearnRate = float32(rate) LuetCfg.GetSolverOptions().Discount = float32(discount) LuetCfg.GetSolverOptions().MaxAttempts = attempts + if concurrent { + LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple + } else { + LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple + } + Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) // Load config protect configs @@ -121,6 +130,7 @@ func init() { installCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)") installCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies") installCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)") + installCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)") RootCmd.AddCommand(installCmd) } diff --git a/cmd/tree/pkglist.go b/cmd/tree/pkglist.go index 536c10e3..9559382f 100644 --- a/cmd/tree/pkglist.go +++ b/cmd/tree/pkglist.go @@ -116,7 +116,7 @@ func NewTreePkglistCommand() *cobra.Command { if deps { emptyInstallationDb := pkg.NewInMemoryDatabase(false) - depSolver = solver.NewSolver(pkg.NewInMemoryDatabase(false), + depSolver = solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), reciper.GetDatabase(), emptyInstallationDb) diff --git a/cmd/tree/validate.go b/cmd/tree/validate.go index 2f5e3cb3..2f1e7495 100644 --- a/cmd/tree/validate.go +++ b/cmd/tree/validate.go @@ -85,7 +85,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe if opts.WithSolver { emptyInstallationDb := pkg.NewInMemoryDatabase(false) - depSolver = solver.NewSolver(pkg.NewInMemoryDatabase(false), + depSolver = solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple},pkg.NewInMemoryDatabase(false), reciper.GetDatabase(), emptyInstallationDb) } diff --git a/cmd/uninstall.go b/cmd/uninstall.go index f559b780..8258fd8d 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -23,6 +23,7 @@ import ( installer "github.com/mudler/luet/pkg/installer" . "github.com/mudler/luet/pkg/logger" pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/solver" "github.com/spf13/cobra" ) @@ -61,12 +62,17 @@ var uninstallCmd = &cobra.Command{ full, _ := cmd.Flags().GetBool("full") checkconflicts, _ := cmd.Flags().GetBool("conflictscheck") fullClean, _ := cmd.Flags().GetBool("full-clean") + concurrent, _ := cmd.Flags().GetBool("solver-concurrent") LuetCfg.GetSolverOptions().Type = stype LuetCfg.GetSolverOptions().LearnRate = float32(rate) LuetCfg.GetSolverOptions().Discount = float32(discount) LuetCfg.GetSolverOptions().MaxAttempts = attempts - + if concurrent { + LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple + } else { + LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple + } Debug("Solver", LuetCfg.GetSolverOptions().CompactString()) inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{ @@ -110,6 +116,7 @@ func init() { uninstallCmd.Flags().Bool("full", false, "Attempts to remove as much packages as possible which aren't required (slow)") uninstallCmd.Flags().Bool("conflictscheck", true, "Check if the package marked for deletion is required by other packages") uninstallCmd.Flags().Bool("full-clean", false, "(experimental) Uninstall packages and all the other deps/revdeps of it.") + uninstallCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)") RootCmd.AddCommand(uninstallCmd) } diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 4882acf7..6169ce62 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -22,6 +22,7 @@ import ( installer "github.com/mudler/luet/pkg/installer" . "github.com/mudler/luet/pkg/logger" pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/solver" "github.com/spf13/cobra" ) @@ -63,11 +64,17 @@ var upgradeCmd = &cobra.Command{ universe, _ := cmd.Flags().GetBool("universe") clean, _ := cmd.Flags().GetBool("clean") sync, _ := cmd.Flags().GetBool("sync") + concurrent, _ := cmd.Flags().GetBool("solver-concurrent") LuetCfg.GetSolverOptions().Type = stype LuetCfg.GetSolverOptions().LearnRate = float32(rate) LuetCfg.GetSolverOptions().Discount = float32(discount) LuetCfg.GetSolverOptions().MaxAttempts = attempts + if concurrent { + LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple + } else { + LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple + } Debug("Solver", LuetCfg.GetSolverOptions().String()) @@ -118,6 +125,7 @@ func init() { upgradeCmd.Flags().Bool("universe", false, "Use ONLY the SAT solver to compute upgrades (experimental)") upgradeCmd.Flags().Bool("clean", false, "Try to drop removed packages (experimental, only when --universe is enabled)") upgradeCmd.Flags().Bool("sync", false, "Upgrade packages with new revisions (experimental)") + upgradeCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)") RootCmd.AddCommand(upgradeCmd) } diff --git a/pkg/compiler/artifact_test.go b/pkg/compiler/artifact_test.go index 5237d7a6..83713c24 100644 --- a/pkg/compiler/artifact_test.go +++ b/pkg/compiler/artifact_test.go @@ -21,6 +21,7 @@ import ( "path/filepath" . "github.com/mudler/luet/pkg/compiler/backend" + "github.com/mudler/luet/pkg/solver" . "github.com/mudler/luet/pkg/compiler" helpers "github.com/mudler/luet/pkg/helpers" @@ -41,7 +42,7 @@ var _ = Describe("Artifact", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/compiler/backend/simpledocker_test.go b/pkg/compiler/backend/simpledocker_test.go index 07a9d341..3c66de51 100644 --- a/pkg/compiler/backend/simpledocker_test.go +++ b/pkg/compiler/backend/simpledocker_test.go @@ -18,6 +18,7 @@ package backend_test import ( . "github.com/mudler/luet/pkg/compiler" . "github.com/mudler/luet/pkg/compiler/backend" + "github.com/mudler/luet/pkg/solver" "io/ioutil" "os" @@ -40,7 +41,7 @@ var _ = Describe("Docker backend", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 15fec76a..dae707df 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -48,9 +48,10 @@ type LuetCompiler struct { Concurrency int CompressionType CompressionImplementation Options CompilerOptions + SolverOptions solver.Options } -func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, opt *CompilerOptions) Compiler { +func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, opt *CompilerOptions, solvopts solver.Options) Compiler { // The CompilerRecipe will gives us a tree with only build deps listed. return &LuetCompiler{ Backend: backend, @@ -65,6 +66,7 @@ func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, opt *Compi Concurrency: opt.Concurrency, Clean: opt.Clean, Options: *opt, + SolverOptions: solvopts, } } @@ -511,7 +513,7 @@ func (cs *LuetCompiler) ComputeMinimumCompilableSet(p ...CompilationSpec) ([]Com func (cs *LuetCompiler) ComputeDepTree(p CompilationSpec) (solver.PackagesAssertions, error) { - s := solver.NewResolver(pkg.NewInMemoryDatabase(false), cs.Database, pkg.NewInMemoryDatabase(false), cs.Options.SolverOptions.Resolver()) + s := solver.NewResolver(cs.SolverOptions, pkg.NewInMemoryDatabase(false), cs.Database, pkg.NewInMemoryDatabase(false), cs.Options.SolverOptions.Resolver()) solution, err := s.Install(pkg.Packages{p.GetPackage()}) if err != nil { diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index 84162db1..054bfb08 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -23,6 +23,7 @@ import ( sd "github.com/mudler/luet/pkg/compiler/backend" helpers "github.com/mudler/luet/pkg/helpers" pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -38,7 +39,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -82,7 +83,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -108,7 +109,7 @@ var _ = Describe("Compiler", func() { }) }) - Context("Templated packages",func(){ + Context("Templated packages", func() { It("Renders", func() { generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) tmpdir, err := ioutil.TempDir("", "package") @@ -117,10 +118,10 @@ var _ = Describe("Compiler", func() { err = generalRecipe.Load("../../tests/fixtures/templates") Expect(err).ToNot(HaveOccurred()) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - pkg ,err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + pkg, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) spec, err := compiler.FromPackage(pkg) @@ -141,7 +142,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -198,7 +199,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -240,7 +241,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -275,7 +276,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -313,7 +314,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "pkgs-checker", Category: "package", Version: "9999"}) Expect(err).ToNot(HaveOccurred()) @@ -354,7 +355,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -398,7 +399,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -440,7 +441,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) @@ -478,7 +479,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) Expect(err).ToNot(HaveOccurred()) @@ -517,7 +518,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(4)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) @@ -569,7 +570,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) @@ -612,7 +613,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) @@ -645,7 +646,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{ Name: "dironly", @@ -700,7 +701,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) @@ -736,7 +737,7 @@ var _ = Describe("Compiler", func() { err := generalRecipe.Load("../../tests/fixtures/includeimage") Expect(err).ToNot(HaveOccurred()) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) specs, err := compiler.FromDatabase(generalRecipe.GetDatabase(), true, "") Expect(err).ToNot(HaveOccurred()) @@ -755,7 +756,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) - compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/compiler/spec_test.go b/pkg/compiler/spec_test.go index e189aad7..a2d2ac69 100644 --- a/pkg/compiler/spec_test.go +++ b/pkg/compiler/spec_test.go @@ -23,6 +23,7 @@ import ( . "github.com/mudler/luet/pkg/compiler" helpers "github.com/mudler/luet/pkg/helpers" pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -61,7 +62,7 @@ var _ = Describe("Spec", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) @@ -114,7 +115,7 @@ RUN echo bar > /test2`)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase(), NewDefaultCompilerOptions(), solver.Options{Type: solver.SingleCoreSimple}) spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/config/config.go b/pkg/config/config.go index 6c518b22..9d5131e4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -64,10 +64,11 @@ type LuetGeneralConfig struct { } type LuetSolverOptions struct { - Type string `mapstructure:"type"` - LearnRate float32 `mapstructure:"rate"` - Discount float32 `mapstructure:"discount"` - MaxAttempts int `mapstructure:"max_attempts"` + Type string `mapstructure:"type"` + LearnRate float32 `mapstructure:"rate"` + Discount float32 `mapstructure:"discount"` + MaxAttempts int `mapstructure:"max_attempts"` + Implementation solver.SolverType `mapstructure:"implementation"` } func (opts LuetSolverOptions) Resolver() solver.PackageResolver { diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index 050551b0..6f120911 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -77,7 +77,7 @@ func (l *LuetInstaller) Upgrade(s *System) error { allRepos := pkg.NewInMemoryDatabase(false) syncedRepos.SyncDatabase(allRepos) // compute a "big" world - solv := solver.NewResolver(s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) + solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) var uninstall pkg.Packages var solution solver.PackagesAssertions @@ -357,7 +357,7 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy var solution solver.PackagesAssertions if !l.Options.NoDeps { - solv := solver.NewResolver(s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) + solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) solution, err = solv.Install(p) if err != nil && !l.Options.Force { return errors.Wrap(err, "Failed solving solution for package") @@ -662,7 +662,7 @@ func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error { if !l.Options.NoDeps { Info("Finding :package:", p.HumanReadableString(), "dependency graph :deciduous_tree:") - solv := solver.NewResolver(installedtmp, installedtmp, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) + solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, installedtmp, installedtmp, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) var solution pkg.Packages var err error if l.Options.FullCleanUninstall { diff --git a/pkg/solver/decoder_test.go b/pkg/solver/decoder_test.go index 175f86cb..88ed6d1d 100644 --- a/pkg/solver/decoder_test.go +++ b/pkg/solver/decoder_test.go @@ -30,13 +30,13 @@ var _ = Describe("Decoder", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(dbInstalled, dbDefinitions, db) + s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Assertion ordering", func() { diff --git a/pkg/solver/resolver_test.go b/pkg/solver/resolver_test.go index 242d67a8..793c47a5 100644 --- a/pkg/solver/resolver_test.go +++ b/pkg/solver/resolver_test.go @@ -28,13 +28,13 @@ var _ = Describe("Resolver", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(dbInstalled, dbDefinitions, db) + s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Conflict set", func() { diff --git a/pkg/solver/solver.go b/pkg/solver/solver.go index 69699144..b2dbcd84 100644 --- a/pkg/solver/solver.go +++ b/pkg/solver/solver.go @@ -26,6 +26,13 @@ import ( pkg "github.com/mudler/luet/pkg/package" ) +type SolverType int + +const ( + SingleCoreSimple = 0 + ParallelSimple = iota +) + // PackageSolver is an interface to a generic package solving algorithm type PackageSolver interface { SetDefinitionDatabase(pkg.PackageDatabase) @@ -56,16 +63,30 @@ type Solver struct { Resolver PackageResolver } -// NewSolver accepts as argument two lists of packages, the first is the initial set, -// the second represent all the known packages. -func NewSolver(installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase) PackageSolver { - return NewResolver(installed, definitiondb, solverdb, &DummyPackageResolver{}) +type Options struct { + Type SolverType + Concurrency int } -// NewReSolver accepts as argument two lists of packages, the first is the initial set, +// NewSolver accepts as argument two lists of packages, the first is the initial set, // the second represent all the known packages. -func NewResolver(installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase, re PackageResolver) PackageSolver { - return &Solver{InstalledDatabase: installed, DefinitionDatabase: definitiondb, SolverDatabase: solverdb, Resolver: re} +func NewSolver(t Options, installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase) PackageSolver { + return NewResolver(t, installed, definitiondb, solverdb, &DummyPackageResolver{}) +} + +// NewResolver accepts as argument two lists of packages, the first is the initial set, +// the second represent all the known packages. +// Using constructors as in the future we foresee warmups for hot-restore solver cache +func NewResolver(t Options, installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase, re PackageResolver) PackageSolver { + var s PackageSolver + switch t.Type { + case SingleCoreSimple: + s = &Solver{InstalledDatabase: installed, DefinitionDatabase: definitiondb, SolverDatabase: solverdb, Resolver: re} + case ParallelSimple: + s = &Parallel{InstalledDatabase: installed, DefinitionDatabase: definitiondb, ParallelDatabase: solverdb, Resolver: re, Concurrency: t.Concurrency} + } + + return s } // SetDefinitionDatabase is a setter for the definition Database @@ -448,7 +469,7 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser } } - s2 := NewSolver(installedcopy, s.DefinitionDatabase, pkg.NewInMemoryDatabase(false)) + s2 := NewSolver(Options{Type: SingleCoreSimple}, installedcopy, s.DefinitionDatabase, pkg.NewInMemoryDatabase(false)) s2.SetResolver(s.Resolver) if !full { ass := PackagesAssertions{} @@ -522,7 +543,7 @@ func (s *Solver) Uninstall(c pkg.Package, checkconflicts, full bool) (pkg.Packag } } - s2 := NewSolver(pkg.NewInMemoryDatabase(false), s.DefinitionDatabase, pkg.NewInMemoryDatabase(false)) + s2 := NewSolver(Options{Type: SingleCoreSimple}, pkg.NewInMemoryDatabase(false), s.DefinitionDatabase, pkg.NewInMemoryDatabase(false)) s2.SetResolver(s.Resolver) // Get the requirements to install the candidate asserts, err := s2.Install(pkg.Packages{candidate}) diff --git a/pkg/solver/solver_test.go b/pkg/solver/solver_test.go index 16028bd4..04856a38 100644 --- a/pkg/solver/solver_test.go +++ b/pkg/solver/solver_test.go @@ -28,13 +28,13 @@ var _ = Describe("Solver", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(dbInstalled, dbDefinitions, db) + s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Simple set", func() { It("Solves correctly if the selected package has no requirements or conflicts and we have nothing installed yet", func() { @@ -52,7 +52,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) @@ -75,7 +75,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{B}) Expect(err).ToNot(HaveOccurred()) @@ -101,7 +101,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) @@ -130,7 +130,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) @@ -156,7 +156,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(err).ToNot(HaveOccurred()) @@ -181,7 +181,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -209,7 +209,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -236,7 +236,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -263,7 +263,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{C}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -291,7 +291,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{&pkg.DefaultPackage{Name: "c", Version: ">1.0", Category: "test"}}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -317,7 +317,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -345,7 +345,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A, B}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -391,7 +391,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{C}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -431,7 +431,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A, B}) Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) @@ -476,7 +476,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A2, B}) Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) @@ -514,7 +514,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A2}) Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) @@ -555,7 +555,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Install([]pkg.Package{A2}) Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) @@ -591,7 +591,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Uninstall(A, true, true) Expect(err).ToNot(HaveOccurred()) @@ -617,7 +617,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Uninstall(&pkg.DefaultPackage{Name: "A", Version: ">1.0"}, true, true) Expect(err).ToNot(HaveOccurred()) @@ -768,7 +768,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.UninstallUniverse(pkg.Packages{A}) Expect(err).ToNot(HaveOccurred()) @@ -794,7 +794,7 @@ var _ = Describe("Solver", func() { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(dbInstalled, dbDefinitions, db) + s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.UninstallUniverse(pkg.Packages{ &pkg.DefaultPackage{Name: "A", Version: ">1.0"}})