Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependent contexts #247

Closed
wants to merge 5 commits into from
Closed

Conversation

ffromani
Copy link
Collaborator

In this PR we revisit how we handle context for dependent packages; a good example is the pci package, which wants to use the topology package internally. But there are more, like gpu (uses pci and topology), and in the future sriov wants as well to use pci (see #230)

While I'm happy with this PR and I believe the gains outweights the risk, let's discuss if this direction is a good one or if we want to solve the same problem in a different way.

@ffromani ffromani changed the title Dependent context Dependent contexts May 13, 2021
@ffromani
Copy link
Collaborator Author

test failures are unexpected, let me fix them before we move further with the review.

Copy link
Owner

@jaypipes jaypipes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fromanirh I'm a little confused why you want to embed a parent context inside Context... see my comment inline :)

pkg/context/context.go Show resolved Hide resolved
pkg/baseboard/baseboard.go Outdated Show resolved Hide resolved
@ffromani ffromani force-pushed the dependent-context branch 2 times, most recently from 7dbe4eb to 4bbaaa6 Compare May 26, 2021 10:21
Fix wrong comment, likely due to trivial copy/paste mistake.
No code changes.

Signed-off-by: Francesco Romani <fromani@redhat.com>
The PR jaypipes#236 fixes a snapshot
directory leakage issue, but also highlight a context
lifecycle/ownership issue.

In general in ghw each package creates its own context, including
the cases on which a package is consumed by another, for example
`topology` and `pci`. However, in this case, it would make more sense
to reuse the context from the parent package, because the two packages
are tightly coupled.

Before the introduction of the the transparent snapshot support
(jaypipes#202), the above mechanism worked,
because each context, each time, was consuming over and over again the
same parameters (e.g. environment variables); besides some resource
waste, this had no negative effect.

When introducing snapshots in the picture, repeatedly unpacking the
same snapshot to consume the same data is much more wasteful.
So it makes sense now to introduce explicitly the concept of dependent
context.

To move forward and make the ownership more explicit, we add an
internal reference count in context. This is used only to track the
context setup/teardown process.

When contexts are reused, we always have a parent module -which creates
and owns the context- which passes its context to a subordinate module,
because the parent wants to consume the service offered by the
subordinate. The subordinate (possibly further nested, or more than one)
should never attempt Setup() and Teardown(). These are responsabilities
of the parent, outer module, which owns the context.

It's impractical to conditionally call Setup() and Teardown(), so the
functions internally use and check the reference count to do the right
thing automatically.

The following are are idempotent (and safe and quickly return success)
- calling multiple times Setup() on a ready context
- calling multiple times Teardown() on a un-ready context

Signed-off-by: Francesco Romani <fromani@redhat.com>
Add NewWithContext() functions to initialize modules
reusing already prepared contexts.

This saves resources and, most important, make sure that dependent
package have a consistent view with the topmost, coordinating package.

IOW, this change is motivated by the need of making the sharing
and ownersjip links more evident, rather than resource optimization,
which is "just" a nice bonus.

Signed-off-by: Francesco Romani <fromani@redhat.com>
the pci package want to use the topology package, and passes
its context down to it.
However, nontrivial initialization is performed in pci.Info.load(),
when snapshots are consumed - most notably in test.

Hence, we need to ensure that `topology.WithContext` is called only
after context.Setup() is called for the pci context.
This is needed because in turn the pci packaged doesn't know (nor it
should) if its context is a root (= top level) context, hence if it
owns the resources which are passed to the dependent packages.

Signed-off-by: Francesco Romani <fromani@redhat.com>
@ffromani ffromani force-pushed the dependent-context branch 2 times, most recently from de7ed04 to 8294271 Compare July 1, 2021 12:43
`WithChroot` and `WithSnapshot` conflicts to each other,
and the users can get surprising results if they try to use them
at the same time.

Now: chroot is expected to be much more popular than snapshots,
being the latter useful mostly for tests or offline debug/troubleshoot,
but still the code should detect and handle these conflicts.

This is made a bit awkward because the current `context` pkg API.
Once we are free to break compatibility, we can make the flow more
linear.

Signed-off-by: Francesco Romani <fromani@redhat.com>
@ffromani
Copy link
Collaborator Author

ffromani commented Jul 1, 2021

sorry for the churn, uploaded a botched version by mistake, should be fixed now.

// and return it later, at the earliest possible occasion, in Setup()
if ctx.SnapshotPath != "" && ctx.Chroot != option.DefaultChroot {
// The env/client code supplied a value, but we are will overwrite it when unpacking shapshots!
ctx.err = fmt.Errorf("Conflicting options: chroot %q and snapshot path %q", ctx.Chroot, ctx.SnapshotPath)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fromanirh instead of the error tracking and refcounting, why don't we simply panic() here? I think panic() is entirely logical considering this situation would occur only when the user has explicitly made a mistake in their argument-passing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a note: refcounting is meant to solve a different facet of the problem (handling nested context in such a way we perform the cleanup in the expected order)
In general I prefer to avoid to panic() inside packages, this should always be an application layer decision - not a library layer decision, so I'd really try hard to find another approach if you don't like the admittedly awkward way I'm using here.
Let me look for other options

@ffromani
Copy link
Collaborator Author

I'll split this PR. The first part is in #278

@ffromani ffromani closed this Sep 21, 2021
@ffromani ffromani deleted the dependent-context branch November 23, 2021 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants