1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "portable.h"
4 #include "portabled-image.h"
5 #include "portabled.h"
6 
manager_image_cache_get(Manager * m,const char * name_or_path)7 Image *manager_image_cache_get(Manager *m, const char *name_or_path) {
8         assert(m);
9 
10         return hashmap_get(m->image_cache, name_or_path);
11 }
12 
image_cache_flush(sd_event_source * s,void * userdata)13 static int image_cache_flush(sd_event_source *s, void *userdata) {
14         Manager *m = userdata;
15 
16         assert(s);
17         assert(m);
18 
19         hashmap_clear(m->image_cache);
20         return 0;
21 }
22 
manager_image_cache_initialize(Manager * m)23 static int manager_image_cache_initialize(Manager *m) {
24         int r;
25 
26         assert(m);
27 
28         r = hashmap_ensure_allocated(&m->image_cache, &image_hash_ops);
29         if (r < 0)
30                 return r;
31 
32         /* We flush the cache as soon as we are idle again */
33         if (!m->image_cache_defer_event) {
34                 r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_cache_flush, m);
35                 if (r < 0)
36                         return r;
37 
38                 r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
39                 if (r < 0)
40                         return r;
41         }
42 
43         r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
44         if (r < 0)
45                 return r;
46 
47         return 0;
48 }
49 
manager_image_cache_add(Manager * m,Image * image)50 int manager_image_cache_add(Manager *m, Image *image) {
51         int r;
52 
53         assert(m);
54 
55         /* We add the specified image to the cache under two keys.
56          *
57          * 1. Always under its path
58          *
59          * 2. If the image was discovered in the search path (i.e. its discoverable boolean set) we'll also add it
60          *    under its short name.
61          */
62 
63         r = manager_image_cache_initialize(m);
64         if (r < 0)
65                 return r;
66 
67         image->userdata = m;
68 
69         r = hashmap_put(m->image_cache, image->path, image);
70         if (r < 0)
71                 return r;
72 
73         image_ref(image);
74 
75         if (image->discoverable) {
76                 r = hashmap_put(m->image_cache, image->name, image);
77                 if (r < 0)
78                         return r;
79 
80                 image_ref(image);
81         }
82 
83         return 0;
84 }
85 
manager_image_cache_discover(Manager * m,Hashmap * images,sd_bus_error * error)86 int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error) {
87         Image *image;
88         int r;
89 
90         assert(m);
91 
92         /* A wrapper around image_discover() (for finding images in search path) and portable_discover_attached() (for
93          * finding attached images). */
94 
95         r = image_discover(IMAGE_PORTABLE, NULL, images);
96         if (r < 0)
97                 return r;
98 
99         HASHMAP_FOREACH(image, images)
100                 (void) manager_image_cache_add(m, image);
101 
102         return 0;
103 }
104