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

Implement default cache with a minimal set of package-level functions. #192

Merged
merged 5 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions cmd/cdi/cmd/cdi-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import (

func cdiListVendors() {
var (
registry = cdi.GetRegistry()
vendors = registry.SpecDB().ListVendors()
cache = cdi.GetDefaultCache()
vendors = cache.ListVendors()
)

if len(vendors) == 0 {
Expand All @@ -41,20 +41,20 @@ func cdiListVendors() {
fmt.Printf("CDI vendors found:\n")
for idx, vendor := range vendors {
fmt.Printf(" %d. %q (%d CDI Spec Files)\n", idx, vendor,
len(registry.SpecDB().GetVendorSpecs(vendor)))
len(cache.GetVendorSpecs(vendor)))
}
}

func cdiListClasses() {
var (
registry = cdi.GetRegistry()
vendors = map[string][]string{}
cache = cdi.GetDefaultCache()
vendors = map[string][]string{}
)

for _, class := range registry.SpecDB().ListClasses() {
for _, class := range cache.ListClasses() {
vendors[class] = []string{}
for _, vendor := range registry.SpecDB().ListVendors() {
for _, spec := range registry.SpecDB().GetVendorSpecs(vendor) {
for _, vendor := range cache.ListVendors() {
for _, spec := range cache.GetVendorSpecs(vendor) {
if spec.GetClass() == class {
vendors[class] = append(vendors[class], vendor)
}
Expand All @@ -68,7 +68,7 @@ func cdiListClasses() {
}

fmt.Printf("CDI device classes found:\n")
for idx, class := range registry.SpecDB().ListClasses() {
for idx, class := range cache.ListClasses() {
sort.Strings(vendors[class])
fmt.Printf(" %d. %s (%d vendors: %s)\n", idx, class,
len(vendors[class]), strings.Join(vendors[class], ", "))
Expand All @@ -77,8 +77,8 @@ func cdiListClasses() {

func cdiListDevices(verbose bool, format string) {
var (
registry = cdi.GetRegistry()
devices = registry.DeviceDB().ListDevices()
cache = cdi.GetDefaultCache()
devices = cache.ListDevices()
)

if len(devices) == 0 {
Expand All @@ -88,7 +88,7 @@ func cdiListDevices(verbose bool, format string) {

fmt.Printf("CDI devices found:\n")
for idx, device := range devices {
cdiPrintDevice(idx, registry.DeviceDB().GetDevice(device), verbose, format, 2)
cdiPrintDevice(idx, cache.GetDevice(device), verbose, format, 2)
}
}

Expand Down Expand Up @@ -119,9 +119,9 @@ func cdiPrintDevice(idx int, dev *cdi.Device, verbose bool, format string, level

func cdiShowSpecDirs() {
var (
registry = cdi.GetRegistry()
specDirs = registry.GetSpecDirectories()
cdiErrors = registry.GetErrors()
cache = cdi.GetDefaultCache()
specDirs = cache.GetSpecDirectories()
cdiErrors = cache.GetErrors()
)
fmt.Printf("CDI Spec directories in use:\n")
for prio, dir := range specDirs {
Expand All @@ -139,12 +139,12 @@ func cdiShowSpecDirs() {

func cdiInjectDevices(format string, ociSpec *oci.Spec, patterns []string) error {
var (
registry = cdi.GetRegistry()
matches = map[string]struct{}{}
devices = []string{}
cache = cdi.GetDefaultCache()
matches = map[string]struct{}{}
devices = []string{}
)

for _, device := range registry.DeviceDB().ListDevices() {
for _, device := range cache.ListDevices() {
for _, glob := range patterns {
match, err := filepath.Match(glob, device)
if err != nil {
Expand All @@ -161,7 +161,7 @@ func cdiInjectDevices(format string, ociSpec *oci.Spec, patterns []string) error
}
sort.Strings(devices)

unresolved, err := registry.InjectDevices(ociSpec, devices...)
unresolved, err := cache.InjectDevices(ociSpec, devices...)

if len(unresolved) > 0 {
fmt.Printf("Unresolved CDI devices:\n")
Expand Down Expand Up @@ -242,18 +242,18 @@ func collectCDIDevicesFromOCISpec(spec *oci.Spec) []string {

func cdiListSpecs(verbose bool, format string, vendors ...string) {
var (
registry = cdi.GetRegistry()
cache = cdi.GetDefaultCache()
)

format = chooseFormat(format, "format-as.yaml")

if len(vendors) == 0 {
vendors = registry.SpecDB().ListVendors()
vendors = cache.ListVendors()
}

if len(vendors) == 0 {
fmt.Printf("No CDI Specs found.\n")
cdiErrors := registry.GetErrors()
cdiErrors := cache.GetErrors()
if len(cdiErrors) > 0 {
for path, specErrors := range cdiErrors {
fmt.Printf("%s has errors:\n", path)
Expand All @@ -266,9 +266,9 @@ func cdiListSpecs(verbose bool, format string, vendors ...string) {
}

fmt.Printf("CDI Specs found:\n")
for _, vendor := range registry.SpecDB().ListVendors() {
klihub marked this conversation as resolved.
Show resolved Hide resolved
for _, vendor := range cache.ListVendors() {
fmt.Printf("Vendor %s:\n", vendor)
for _, spec := range registry.SpecDB().GetVendorSpecs(vendor) {
for _, spec := range cache.GetVendorSpecs(vendor) {
cdiPrintSpec(spec, verbose, format, 2)
cdiPrintSpecErrors(spec, verbose, 2)
}
Expand All @@ -285,8 +285,8 @@ func cdiPrintSpec(spec *cdi.Spec, verbose bool, format string, level int) {

func cdiPrintSpecErrors(spec *cdi.Spec, verbose bool, level int) {
var (
registry = cdi.GetRegistry()
cdiErrors = registry.GetErrors()
cache = cdi.GetDefaultCache()
cdiErrors = cache.GetErrors()
)

if len(cdiErrors) > 0 {
Expand All @@ -302,7 +302,7 @@ func cdiPrintSpecErrors(spec *cdi.Spec, verbose bool, level int) {
}
}

func cdiPrintRegistry(args ...string) {
func cdiPrintCache(args ...string) {
if len(args) == 0 {
args = []string{"all"}
}
Expand All @@ -328,17 +328,17 @@ func cdiPrintRegistry(args ...string) {
}
}

func cdiPrintRegistryErrors() {
func cdiPrintCacheErrors() {
var (
registry = cdi.GetRegistry()
cdiErrors = registry.GetErrors()
cache = cdi.GetDefaultCache()
cdiErrors = cache.GetErrors()
)

if len(cdiErrors) == 0 {
return
}

fmt.Printf("CDI Registry has errors:\n")
fmt.Printf("CDI Cache has errors:\n")
for path, specErrors := range cdiErrors {
fmt.Printf("Spec file %s:\n", path)
for idx, err := range specErrors {
Expand Down
4 changes: 2 additions & 2 deletions cmd/cdi/cmd/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func monitorSpecDirs(args ...string) {

case _ = <-refresh:
refresh = nil
cdiPrintRegistry(args...)
cdiPrintCache(args...)
}
}
}()
Expand All @@ -142,7 +142,7 @@ func monitorDirectories(dirs ...string) (*fsnotify.Watcher, error) {

for _, dir := range dirs {
if _, err = os.Stat(dir); err != nil {
fmt.Printf("WARNING: failed to stat dir %q, NOT watching it...", dir)
fmt.Printf("WARNING: failed to stat dir %q, NOT watching it...\n", dir)
continue
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/cdi/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func initSpecDirs() {
cdi.WithSpecDirs(specDirs...),
)
if len(cdi.GetRegistry().GetErrors()) > 0 {
cdiPrintRegistryErrors()
cdiPrintCacheErrors()
}
}
}
70 changes: 70 additions & 0 deletions pkg/cdi/default-cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright © 2024 The CDI Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cdi

import (
"sync"

oci "github.com/opencontainers/runtime-spec/specs-go"
)

var (
defaultCache *Cache
getDefaultOnce sync.Once
)

func getOrCreateDefaultCache(options ...Option) (*Cache, bool) {
var created bool
getDefaultOnce.Do(func() {
defaultCache = newCache(options...)
created = true
})
return defaultCache, created
}

// GetDefaultCache returns the default CDI cache instance.
func GetDefaultCache() *Cache {
cache, _ := getOrCreateDefaultCache()
return cache
}

// Configure applies options to the default CDI cache. Updates and refreshes
// the default cache if options are not empty.
func Configure(options ...Option) {
cache, created := getOrCreateDefaultCache(options...)
if len(options) == 0 || created {
return
}
cache.Configure(options...)
}
klihub marked this conversation as resolved.
Show resolved Hide resolved

// Refresh explicitly refreshes the default CDI cache instance.
func Refresh() error {
return GetDefaultCache().Refresh()
}

// InjectDevices injects the given qualified devices to the given OCI Spec.
// using the default CDI cache instance to resolve devices.
func InjectDevices(ociSpec *oci.Spec, devices ...string) ([]string, error) {
return GetDefaultCache().InjectDevices(ociSpec, devices...)
}

// GetErrors returns all errors encountered during the last refresh of
// the default CDI cache instance.
func GetErrors() map[string][]error {
return GetDefaultCache().GetErrors()
}
Loading