@@ -68,18 +68,19 @@ type Runtime struct {
6868 storageConfig storage.StoreOptions
6969 storageSet storageSet
7070
71- state State
72- store storage.Store
73- storageService * storageService
74- imageContext types.SystemContext
75- defaultOCIRuntime OCIRuntime
76- ociRuntimes map [string ]OCIRuntime
77- runtimeFlags []string
78- network nettypes.ContainerNetwork
79- conmonPath string
80- libimageRuntime * libimage.Runtime
81- libimageEventsShutdown chan bool
82- lockManager lock.Manager
71+ state State
72+ store storage.Store
73+ storageService * storageService
74+ imageContext types.SystemContext
75+ defaultOCIRuntime OCIRuntime
76+ ociRuntimes map [string ]OCIRuntime
77+ runtimeFlags []string
78+ network nettypes.ContainerNetwork
79+ conmonPath string
80+ libimageRuntime * libimage.Runtime
81+ libimageEventsShutdown chan bool
82+ libartifactEventsShutdown chan bool
83+ lockManager lock.Manager
8384
8485 // ArtifactStore returns the artifact store created from the runtime.
8586 ArtifactStore func () (* artStore.ArtifactStore , error )
@@ -503,6 +504,8 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
503504 runtime .ArtifactStore = sync .OnceValues (func () (* artStore.ArtifactStore , error ) {
504505 return artStore .NewArtifactStore (filepath .Join (runtime .storageConfig .GraphRoot , "artifacts" ), runtime .SystemContext ())
505506 })
507+ // Run the libartifact events routine.
508+ runtime .libartifactEvents ()
506509 }
507510
508511 // We now need to see if the system has restarted
@@ -722,6 +725,71 @@ func (r *Runtime) libimageEvents() {
722725 }()
723726}
724727
728+ // libartifactEventsMap translates a libartifact event type to a libpod event status.
729+ var libartifactEventsMap = map [artStore.EventType ]events.Status {
730+ artStore .EventTypeArtifactPull : events .Pull ,
731+ artStore .EventTypeArtifactPush : events .Push ,
732+ artStore .EventTypeArtifactRemove : events .Remove ,
733+ artStore .EventTypeArtifactAdd : events .Create ,
734+ }
735+
736+ // libartifactEvents spawns a goroutine which will listen for events on
737+ // the artStore.ArtifactStore. The goroutine will be cleaned up implicitly
738+ // when the main() exists.
739+ func (r * Runtime ) libartifactEvents () {
740+ r .libartifactEventsShutdown = make (chan bool )
741+
742+ toLibpodEventStatus := func (e * artStore.Event ) events.Status {
743+ status , found := libartifactEventsMap [e .Type ]
744+ if ! found {
745+ return "Unknown"
746+ }
747+ return status
748+ }
749+
750+ store , err := r .ArtifactStore ()
751+ if err != nil {
752+ logrus .Errorf ("Unable to initialize artifact store for events: %q" , err )
753+ return
754+ }
755+ eventChannel := store .EventChannel ()
756+
757+ go func () {
758+ sawShutdown := false
759+ for {
760+ // Make sure to read and write all events before
761+ // shutting down.
762+ for len (eventChannel ) > 0 {
763+ libartifactEvent := <- eventChannel
764+ e := events.Event {
765+ ID : libartifactEvent .ID ,
766+ Name : libartifactEvent .Name ,
767+ Status : toLibpodEventStatus (libartifactEvent ),
768+ Time : libartifactEvent .Time ,
769+ Type : events .Artifact ,
770+ }
771+ if libartifactEvent .Error != nil {
772+ e .Error = libartifactEvent .Error .Error ()
773+ }
774+ if err := r .eventer .Write (e ); err != nil {
775+ logrus .Errorf ("Unable to write artifact event: %q" , err )
776+ }
777+ }
778+
779+ if sawShutdown {
780+ close (r .libartifactEventsShutdown )
781+ return
782+ }
783+
784+ select {
785+ case <- r .libartifactEventsShutdown :
786+ sawShutdown = true
787+ case <- time .After (100 * time .Millisecond ):
788+ }
789+ }
790+ }()
791+ }
792+
725793// DeferredShutdown shuts down the runtime without exposing any
726794// errors. This is only meant to be used when the runtime is being
727795// shutdown within a defer statement; else use Shutdown
@@ -771,6 +839,13 @@ func (r *Runtime) Shutdown(force bool) error {
771839 <- r .libimageEventsShutdown
772840 }
773841
842+ if r .libartifactEventsShutdown != nil {
843+ // Tell loop to shutdown
844+ r .libartifactEventsShutdown <- true
845+ // Wait for close to signal shutdown
846+ <- r .libartifactEventsShutdown
847+ }
848+
774849 // Note that the libimage runtime shuts down the store.
775850 if err := r .libimageRuntime .Shutdown (force ); err != nil {
776851 lastError = fmt .Errorf ("shutting down container storage: %w" , err )
0 commit comments