[zypp-devel] Sat-Solver policy engine
Hi, discussions about sat-solver implementation details over the last days showed that a lot of decisions should not (cannot ?) be hardwired. Instead, a policy should be in place to make solver operation configurable. Revision 7734 of sat-solver now contains a generic policy interface (src/policy.h) and a ruby based policy implementation (src/policy-ruby.c). It currently supports a single policy for demonstration purposes. The goal is to make all policies optional and fast for the default case. I'd be interested in defining a concise list of policies. Input welcome ! Klaus --- SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Thursday 01 November 2007 03:33:23 pm Klaus Kaempf wrote:
Hi,
discussions about sat-solver implementation details over the last days showed that a lot of decisions should not (cannot ?) be hardwired.
Instead, a policy should be in place to make solver operation configurable.
Nice that this was kicked off. For some moment I was afraid we were walking in the same hardcoded direction as the current solver.
Revision 7734 of sat-solver now contains a generic policy interface (src/policy.h) and a ruby based policy implementation (src/policy-ruby.c). It currently supports a single policy for demonstration purposes.
I don't like the idea of linking the core library and all tools against ruby. I think the policy engine could be dlopened and the ruby part should be inside bindings/ruby which is the only part of the library that depends on ruby. I can't complain loud because I don't have a patch :-(
The goal is to make all policies optional and fast for the default case.
There is another issue to solve, testsuite. Tests and policies. How to solve that? Duncan What is als -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
Also, some documentation about how the policy mechanism is supposed to work would be nice to allow others to contribute here. Another comment: policy_exit(), what is the meaning of "exit" here? The policy_init() seems to allow for a "global" stuff design. Which by coincidence is the same reason why you can't use 2 ruby interpreters in the same process, because the interpreter instance is invisible, for example, what happens if 2 solver objects call policy_init()? Ho wto solve it, no idea. Only comes to my mind: Should't the policy engine use a struct with functions, which is used by the solver, instead of allocating invisible stuff? Then every policy implementation would fill it with the right functions, and the solver could ignore them if they are null. Duncan -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Duncan Mac-Vicar P.
Also, some documentation about how the policy mechanism is supposed to work would be nice to allow others to contribute here.
Actually, its a late night 20 minutes hack with the primary purpose to get the discussion started ;-)
Another comment: policy_exit(), what is the meaning of "exit" here?
Its just the counterpart for _init()
The policy_init() seems to allow for a "global" stuff design. Which by coincidence is the same reason why you can't use 2 ruby interpreters in the same process, because the interpreter instance is invisible, for example, what happens if 2 solver objects call policy_init()?
Two idenpendant solver objects can have two independant ruby processes, I don't see anything wrong with it.
Ho wto solve it, no idea. Only comes to my mind:
Should't the policy engine use a struct with functions, which is used by the solver, instead of allocating invisible stuff? Then every policy implementation would fill it with the right functions, and the solver could ignore them if they are null.
My thinking goes along the same lines: Have a table of policy function pointers, pointing to the default policy implementation. If a policy engine is loaded (dlopened), its _init() function replaces those pointers in the table for which the policy engine provides own implementations. Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Duncan Mac-Vicar P.
On Thursday 01 November 2007 03:33:23 pm Klaus Kaempf wrote:
Hi,
discussions about sat-solver implementation details over the last days showed that a lot of decisions should not (cannot ?) be hardwired.
Instead, a policy should be in place to make solver operation configurable.
Nice that this was kicked off. For some moment I was afraid we were walking in the same hardcoded direction as the current solver.
*g*
Revision 7734 of sat-solver now contains a generic policy interface (src/policy.h) and a ruby based policy implementation (src/policy-ruby.c). It currently supports a single policy for demonstration purposes.
I don't like the idea of linking the core library and all tools against ruby.
Neither do I.
I think the policy engine could be dlopened and the ruby part should be inside bindings/ruby which is the only part of the library that depends on ruby.
Right. However, I don't have any experience with dlopen. The policy engine should be specified in some .conf file.
I can't complain loud because I don't have a patch :-(
Hehe. Same with me ;-)
The goal is to make all policies optional and fast for the default case.
There is another issue to solve, testsuite. Tests and policies. How to solve that?
Lets put it on the DISCUSS list. Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
Hi, On Fri, 2 Nov 2007, Klaus Kaempf wrote:
I think the policy engine could be dlopened and the ruby part should be inside bindings/ruby which is the only part of the library that depends on ruby.
Right. However, I don't have any experience with dlopen.
For better or worse, I have :-) Though I'm not sure if that's the way to go. In my mental model it would work like this: * policies are outside of solver (I think on that we all agree), solver just calls back into them from time to time * CoolApp wants to use satsolver, and also implement its own set of policies, so it will have all the code for those very policies, * CoolApp just needs a way of communicating that set of policies to the solver Hence a function "set_policy (struct policies *)" would be completely enough. Where struct policies could look similar to this: struct policies { int (*archchanges) (Solvable *a, Solvable *b); int (*allowdowngrade) (Solvable *a); /* And so on. */ }; I.e. I would want to make the solver somehow be responsible for loading policies automagically. I would want the using applications to actually set them. Let's not write yet another plugin system. I've seen too many, most of them bad; it's usually a sign that the developers don't have any other ideas anymore. Ciao, Michael. -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Monday 05 November 2007 08:51:11 you wrote:
Hence a function "set_policy (struct policies *)" would be completely enough. Where struct policies could look similar to this:
struct policies { int (*archchanges) (Solvable *a, Solvable *b); int (*allowdowngrade) (Solvable *a); /* And so on. */ };
I had a similar structure in mind. I think the ruby bindings could implement the ruby part Klaus implemented (calling a policy from a ruby function or a ruby file). What needs to be defined: - Which policies are needed (like the 2 examples you just said) - Default policies - How to specify the policies in the testsuite Duncan -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Michael Matz
For better or worse, I have :-) Though I'm not sure if that's the way to go. In my mental model it would work like this:
* policies are outside of solver (I think on that we all agree), solver just calls back into them from time to time * CoolApp wants to use satsolver, and also implement its own set of policies, so it will have all the code for those very policies, * CoolApp just needs a way of communicating that set of policies to the solver
Fully agreed.
Hence a function "set_policy (struct policies *)" would be completely enough. Where struct policies could look similar to this:
struct policies { int (*archchanges) (Solvable *a, Solvable *b); int (*allowdowngrade) (Solvable *a); /* And so on. */ };
Right. Maybe enhanced by some versioning data to ensure the policy implementation actually matches the policy API. And we need a couple of 'first class' object definitions like Solvable, Repo and Pool so the policy engine implementations can use them uniformly.
I.e. I would want to make the solver somehow be responsible for loading policies automagically.
Time for a '/etc/solver.conf' file or a /etc/solver/policy directory to place a .so file with the policy implementation ?
I would want the using applications to actually set them.
Well, I guess we need three layers (resp. levels) 1. Solver default policy 2. System policy 3. Application policy
Let's not write yet another plugin system. I've seen too many, most of them bad; it's usually a sign that the developers don't have any other ideas anymore.
*g* Any pointers to a 'good', reusable plugin system ? Klaus --- SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Monday 05 November 2007 16:23:28 Klaus Kaempf wrote:
Time for a '/etc/solver.conf' file or a /etc/solver/policy directory to place a .so file with the policy implementation ?
That is exactly what Michael is trying to prevent. A new plugin mechanism. Basically the idea is just to offer callback interface, and the application using the solver would implement them. No need for config files or plugins. The ruby bindings could implement them, gluing them to a ruby file with functions. While ZYpp could glue them to its own config file AND/OR UI iteraction. What we need now, is the list of policies, to design that interface, and again, any idea on how to keep the testsuite running when the policies are not longer constant. Duncan -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Duncan Mac-Vicar Prett
On Monday 05 November 2007 16:23:28 Klaus Kaempf wrote:
Time for a '/etc/solver.conf' file or a /etc/solver/policy directory to place a .so file with the policy implementation ?
That is exactly what Michael is trying to prevent. A new plugin mechanism.
Basically the idea is just to offer callback interface, and the application using the solver would implement them. No need for config files or plugins.
I don't agree with applications providing the policy. I can already see zypper (being C++ code) providing a C++ policy engine, effectively circumventing system wide policies. I'd like policies to be flexible (hence the implementation using a scripting language) and usable across applications (system wide policies). Application specific policies should be possible, but the exception.
The ruby bindings could implement them, gluing them to a ruby file with functions. While ZYpp could glue them to its own config file AND/OR UI iteraction.
This sounds like implementing several policy engines, one for each application. And making them sufficiently flexible will result in every application having its own plugin mechanism.
What we need now, is the list of policies, to design that interface,
Right. So lets meet with Michael Schroeder and draft that list.
and again, any idea on how to keep the testsuite running when the policies are not longer constant.
From my POV, the testsuite is one application using policies defined for the testsuite. It also shouldn't be too hard to load different policy implementations within the 'deptestomatic' test binary.
Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
Hi, On Mon, 5 Nov 2007, Klaus Kaempf wrote:
* Duncan Mac-Vicar Prett
[Nov 05. 2007 16:33]: On Monday 05 November 2007 16:23:28 Klaus Kaempf wrote:
Time for a '/etc/solver.conf' file or a /etc/solver/policy directory to place a .so file with the policy implementation ?
That is exactly what Michael is trying to prevent. A new plugin mechanism.
Basically the idea is just to offer callback interface, and the application using the solver would implement them. No need for config files or plugins.
I don't agree with applications providing the policy. I can already see zypper (being C++ code) providing a C++ policy engine, effectively circumventing system wide policies.
You can circumvent them anyway when you're determined enough. E.g. using rpm directly. There's no hope you can employ a system wide policy without cooperation from the applications in question, they actively need to make use of them (i.e. at least activate them, and if as part of they "solver-setup" perhaps done in some library). Now _where_ those policies are actually implemented is another question. I for instance would not assume that every zypp-using app implements their own. I would expect some middle layer to provide them. That middle layer can be as configurable as you like, and also as extensible as you like, even using dynamic loading if you absolutely insist :) Or as scripts. But the point is that there should be something else than libsatsolver linking against ruby. Even that middle layer should not link directly against it, (which then unfortunately indeed requires dynamic loading :-/ ). But I would first start defining what callbacks are really required. Each and every of them will cost considerable runtime for the solver compared to what it normally can do when walking his rules. Premature optimization is the root of much evil, but the same holds for premature over-design. So if something isn't reasonably necessary to configure, better make it not a call back. Or if something trivially is a global option, don't make it a callback working on Solvables. Such and similar things should also be considered.
This sounds like implementing several policy engines, one for each application. And making them sufficiently flexible will result in every application having its own plugin mechanism.
That would be bad of course. As I wrote above, in my mind it would have been a library, which applications then are required to use. Ciao, Michael. -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Michael Matz
On Mon, 5 Nov 2007, Klaus Kaempf wrote:
This sounds like implementing several policy engines, one for each application. And making them sufficiently flexible will result in every application having its own plugin mechanism.
That would be bad of course. As I wrote above, in my mind it would have been a library, which applications then are required to use.
Yes, now we're in total agreement ! (Sorry for the short answer, I'm in a hurry :-{ ) Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
The result of our initial meeting on solver policies was just checked in as sat-solver/doc/README.policy It covers everything left on my whiteboard and in my memory ;-) While still quite rough, it covers the main aspects of the policy engine and hints towards a generic implementation. Help is appreciated in moving this forward to an initial implementation. Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Fri, Nov 09, 2007 at 02:20:27PM +0100, Klaus Kaempf wrote:
as sat-solver/doc/README.policy
http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/doc/README.policy?view... anyway, beware of overengineering. -- Martin Vidner, lazy clicker http://en.opensuse.org/User:Mvidner Kuracke oddeleni v restauraci je jako fekalni oddeleni v bazenu -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Martin Vidner
On Fri, Nov 09, 2007 at 02:20:27PM +0100, Klaus Kaempf wrote:
as sat-solver/doc/README.policy
http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/doc/README.policy?view...
anyway, beware of overengineering.
You're invited to help in this regard ;-) Klaus -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Fri, Nov 09, 2007 at 03:27:18PM +0100, Klaus Kaempf wrote:
* Martin Vidner
[Nov 09. 2007 15:12]: On Fri, Nov 09, 2007 at 02:20:27PM +0100, Klaus Kaempf wrote:
as sat-solver/doc/README.policy
http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/doc/README.policy?view...
anyway, beware of overengineering.
You're invited to help in this regard ;-)
OK... Here's how I see it in order of increasing complexity: A) No policies. Just hardcode it in the solver. B) No interface. Code it in the solver, but parametrize the decisions by /etc/zypp/zypp.conf: solver.prefer_arch_over_version = false solver.downgrade_automatic = false solver.downgrade_user = true (?) solver.uninstall solver.vendor_change C) Interface. Like (B), but separate the decision code from the solver. I see a single interface point now: policy->get_boolean("prefer_arch_over_version") D) Scriptable Pluggable Chainable whatever -- Martin Vidner, YaST developer http://en.opensuse.org/User:Mvidner Kuracke oddeleni v restauraci je jako fekalni oddeleni v bazenu -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
On Friday 09 November 2007 15:42:12 Martin Vidner wrote:
Like (B), but separate the decision code from the solver. I see a single interface point now:
policy->get_boolean("prefer_arch_over_version")
Actually most of the decisions in the solver are taken in the same way, so the solver has a list of canddates, and it choses something. If you don't want to allow downgrades, you just remove the lower versions from the list before the solver will use it, you can remove different architectures, vendors etc. The boolean approach is configuration. The policy itself will mostly get a list of solvables, and filter over them. The boolean values can be used by the policy to know what to filter. But that is not part of the solver, which will of course offer some default policy and functions to filter (so the code does not propagate from the solver complex algorithms to the policies itself) Duncan -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
* Martin Vidner
On Fri, Nov 09, 2007 at 03:27:18PM +0100, Klaus Kaempf wrote:
* Martin Vidner
[Nov 09. 2007 15:12]: On Fri, Nov 09, 2007 at 02:20:27PM +0100, Klaus Kaempf wrote:
as sat-solver/doc/README.policy
http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/doc/README.policy?view...
anyway, beware of overengineering.
You're invited to help in this regard ;-)
OK... Here's how I see it in order of increasing complexity:
A) No policies.
Just hardcode it in the solver.
B) No interface.
Code it in the solver, but parametrize the decisions by /etc/zypp/zypp.conf: solver.prefer_arch_over_version = false solver.downgrade_automatic = false solver.downgrade_user = true (?) solver.uninstall solver.vendor_change
A and B are ruled out because - we have to deliver 'role based' software management (e.g. allowing non-root user to install updates) - security demands that non-root users must not downgrade packages - however, root is allowed to install version downgrades => the 'allow downgrade' policy must be settable at runtime
C) Interface.
Like (B), but separate the decision code from the solver.
Right, policy is all about separation of the decision code from the solver.
I see a single interface point now:
policy->get_boolean("prefer_arch_over_version")
Thats how the current sat solver implementation handles it, just that the boolean values are passed via a struct.
D) Scriptable Pluggable Chainable whatever
I believe we have to target D) since it puts us 'on par' with other software management tools, e.g. yum. Klaus --- SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org For additional commands, e-mail: zypp-devel+help@opensuse.org
participants (5)
-
Duncan Mac-Vicar P.
-
Duncan Mac-Vicar Prett
-
Klaus Kaempf
-
Martin Vidner
-
Michael Matz