Skip to content

Commit

Permalink
Merge pull request #192 from klihub/devel/reintroduce-default-cache
Browse files Browse the repository at this point in the history
Implement default cache with a minimal set of package-level functions.
  • Loading branch information
elezar authored Mar 1, 2024
2 parents 7b540ad + 07fed87 commit 2c40f2d
Show file tree
Hide file tree
Showing 7 changed files with 534 additions and 40 deletions.
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() {
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...)
}

// 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

0 comments on commit 2c40f2d

Please sign in to comment.