persist the binary cache index in the misc cache and expose remote specs to spack spec#21538
persist the binary cache index in the misc cache and expose remote specs to spack spec#21538cosmicexplorer wants to merge 9 commits intospack:developfrom
spack spec#21538Conversation
5d3d83b to
139c1dc
Compare
2567de6 to
3a24d33
Compare
3a8d033 to
793e196
Compare
spack spec
|
@tgamblin This should be ready for review. The PR has been split into 4 independent commits, which makes it very easy for me to break out parts of it into pre-work PRs. I believe it should be clear upon inspection that the final commit is the only one that changes behavior, but it is very easy for me to split this up if needed. Note that (as in the TODO section) that |
793e196 to
a70cade
Compare
|
Ok, the test should finally be passing now! 🎉 |
5021164 to
186d53b
Compare
|
Re @tgamblin @tldahlgren -- the workflow that this enables is also where it currently might cause a performance regression: in particular, when a hash prefix is used on the command line, spack will now unconditionally search all mirrors for that hash when parsing the spec. This is noted in two places:
Let me know if this is worth further investigation here. The perf regression would be in the case of I think it would probably be good to ensure that |
7b9253d to
ab0f227
Compare
048c972 to
b0f7f8c
Compare
I am pretty sure it was because of an unrelated change I made to |
fe1afde to
3c401eb
Compare
- move misc_cache_location() out of the misc cache singleton - ensure binary indices are instantiated from within the misc cache - add remote buildcache entries to local db and update them every time the buildcache is fetched - factor out _unverified_context() for python 2.6 - move mirror_directory_def into conftest.py SpecIndex can now be instantiated and run successfully - now to integrate with `spack spec` make spack spec work polish @named_tuple() tmp Revert "polish @named_tuple()" This reverts commit 034e64e066c59094842ac28df5b9fec4e164a0d7. all named_tuple tmp introduce Timestamp, TimeRange, IndexEntry, and IndexQuery tmp make more things use the new spec_index ensure buildcache list reads from the spec index make spack find search remote indices add back all the changes that are in other PRs `spack find -m -L --allarch xz` works all of the changes i've made today. the test fails to find compilers remove the two .pyi files, and most of the lang.py edits make mypy pass, and remove circular import workarounds add @gen_str_repr decorator make `find` and `buildcache list` work again make `find` and `buildcache list` work make test pass!!! make it possible to run spack on 2.6 again make mypy and flake8 pass undo incorrect changes undo lang.py changes undo changes to add types everywhere fix buildcache list clean up the spec by hash lookup mypy and vermin checks undo concretizer.lp change undo typing-only changes fix tmp fix variant parsing? fix failure in BoolValuedVariant unnecessary changes tmp cmp make tests pass (?) add additional assertions add callable annotations fix types novm argparse Revert "novm argparse" This reverts commit d9a80de472043521a92013d89b950038ddfd801f. ah make `spack.util.py2` work like `typing` undo tons of typing changes tmp undo typing tmp tmp typing revert revert modifications to lang.py add types and fix tests and revert lang.py changes test fixes add __repr__() to everything in spec_index.py make test_buildcache_create() pass further test fixes add types and fix tests and revert lang.py changes ok ok2
idk idk2 make it work
3c401eb to
60a1e6c
Compare
c421ff0 to
b4e35b1
Compare
tgamblin
left a comment
There was a problem hiding this comment.
This is the first half of the review -- mostly about what probably shouldn't be in this PR... moving on to the parts that should :)
| concretize = kwargs.get('concretize', False) | ||
| normalize = kwargs.get('normalize', False) | ||
| tests = kwargs.get('tests', False) | ||
| index_location = kwargs.get('index_location', None) |
There was a problem hiding this comment.
This shouldn't be exposed to cmd/__init__.py -- if the spec parser needs it, the spec parser should ask for it from the spec index.
| if not self.archive_file: | ||
| raise NoArchiveFileError("Cannot call archive() before fetching.") | ||
|
|
||
| import spack.util.web as web_util |
There was a problem hiding this comment.
was this needed to avoid a circular import?
| # Check and record the values that are not allowed | ||
| not_allowed_values = [ | ||
| x for x in value | ||
| # TODO: avoid the multiple special-cases for '*' with a wrappper class. |
There was a problem hiding this comment.
this TODO doesn't have to do with this PR
|
|
||
| from spack.error import SpackError | ||
| from spack.database import InstallStatuses | ||
| from spack.error import SpackError |
There was a problem hiding this comment.
no reason to do this in this PR. Remove.
|
|
||
| specs = spack.cmd.parse_specs(args.specs) | ||
| merged = spack.spec_index.IndexLocation.LOCAL_AND_REMOTE() | ||
| specs = spack.cmd.parse_specs(args.specs, index_location=merged) |
There was a problem hiding this comment.
this PR should not affect every call to parse_specs - remove this and make the spec parser know about the index. the index can learn about what potential places there are to get hashes by looking at spack's mirror configuration.
| for sha256, package_to_patch in other.index.items(): | ||
| p2p = self.index.setdefault(sha256, {}) | ||
| p2p.update(package_to_patch) | ||
| self._update_index(other.index) |
There was a problem hiding this comment.
these changes seem very unrelated to the PR.
| index_location = spack.spec_index.IndexLocation.LOCAL() | ||
| if isinstance(spec_like, six.string_types): | ||
| spec_list = SpecParser(self).parse(spec_like) | ||
| spec_list = SpecParser(self, index_location=index_location).parse(spec_like) |
There was a problem hiding this comment.
I do not think that we should change the whole spec constructor just for this -- I think the index location should be hidden from users of Spec.
| query_spec = [query_spec] | ||
| recorded_spec = rec.spec | ||
| if for_all_architectures: | ||
| recorded_spec = recorded_spec.without_architecture_or_compiler() |
There was a problem hiding this comment.
--allarch is not a concern that we should be letting into database.py. It's really a UI concern, not a core database concern. If the user wants to see only some architectures, they should filter results outside the DB or we should make a better query object. We shouldn't have a specific for_all_architectures argument here.
| if f.__doc__ is None: | ||
| f.__doc__ = "" | ||
| f.__doc__ += _query_docstring | ||
| return f |
There was a problem hiding this comment.
this is cool but do we need it in this PR?
| spec._add_dependency(child, dtypes) | ||
|
|
||
| def _read_from_file(self, filename): | ||
| def fill_from_file(self, filename): |
There was a problem hiding this comment.
Why is the name changed here? I guess you needed to makem the json one public, and it makes sense to make this one public too. That's fine but I'd call them read_from_file and read_from_json.
tgamblin
left a comment
There was a problem hiding this comment.
ok here are some more comments.
| import spack.spec | ||
|
|
||
|
|
||
| class ConcretizedSpec(object): |
There was a problem hiding this comment.
Not clear to me why we need this class. Is the existing Spec API bad for this? I don't see anything on here that we can't do with Spec.
|
|
||
|
|
||
| class IndexEntry(object): | ||
| concretized_spec = None # type: ConcretizedSpec |
There was a problem hiding this comment.
I think this should just be Spec
|
|
||
| class IndexEntry(object): | ||
| concretized_spec = None # type: ConcretizedSpec | ||
| record = None # type: spack.database.InstallRecord |
There was a problem hiding this comment.
This is odd to me b/c the record should already have a spec.
|
|
||
| @add_metaclass(ABCMeta) | ||
| class PartialHash(object): | ||
| FULL_HASH_STRING_LENGTH = 32 # type: ClassVar[int] |
There was a problem hiding this comment.
would rather not have this defined in multiple places.
| pass | ||
|
|
||
|
|
||
| class ConcreteHash(CompleteHash): |
There was a problem hiding this comment.
All the hash types here are losing me -- do we need them? I think hashes can be much simpler than this...
|
|
||
| @add_metaclass(ABCMeta) | ||
| class SpecIndexable(object): | ||
| """Interface to look up and traverse known specs from multiple sources.""" |
There was a problem hiding this comment.
we don't need to make interface types in Spack -- we tend to stay away from them.
| pass | ||
|
|
||
|
|
||
| class SpecIndex(object): |
There was a problem hiding this comment.
right now this is IMO overly complex -- it needs to be refactored to just take a list of DB's, and to look up hashes in those. Where the hashes come from should be someone else's concern.
the local DB is a DB, the remote DB is a DB, etc. -- they're all the same. I don't think we need separate methods or anything for each kind of DB. I was expecting that this would just look up hashes and map them to specs, from several DBs.
| return '{0}(indices={1!r})'.format(type(self).__name__, self.indices) | ||
|
|
||
|
|
||
| class IndexLocation(object): |
There was a problem hiding this comment.
this can get removed -- we shouldn't need to care about the index location.
| """Share a merged BinaryCacheIndex for remote buildcaches, in the user's homedir.""" | ||
| cache_root = os.path.join(misc_cache_location(), 'indices') | ||
| cache_root = spack.util.path.canonicalize_path(cache_root) | ||
| return cache_root |
| raise InvalidIndexHash(expect_hash, locally_computed_hash, | ||
| 'remote index at {0}'.format(mirror_url), | ||
| 'this indicates an error in index tranmission') | ||
| # tty.error(msg_tmpl.format(locally_computed_hash, expect_hash)) |
|
Going to break this out into multiple other PRs despite as well as because of the immense effort required to get it passing CI. |
|
Reopening this so I don't forget about it. |
|
Closing, since there has been no activity in a while. Feel free to reopen if you want to continue work on this. |
Description
Closes #19085. Intends to solve the same problem.
Changes
spack buildcache createfrom buildcache list: add listed specs to database as not installed #19085.The PR has been split into several independent commits, with all of the work below in the final commit:
spack buildcache listuse the directory~/.spack/caches/indices(usingconfig:misc_cacheas the root) to persist theBinaryCacheIndex.spec_index.py:InstallRecordfromdatabase.py.IndexQueryclass which performs the logic ofDatabase._query().SpecIndexto expose only local, only remote, or both local and remote specs for querying.spack spec,spack find, andspack installconcretize specs by referring to the appropriateSpecIndexinstance.Result
The following works: