1 /*
2  * storage_event.c: storage event queue processing helpers
3  *
4  * Copyright (C) 2010-2014 Red Hat, Inc.
5  * Copyright (C) 2008 VirtualIron
6  * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library.  If not, see
20  * <http://www.gnu.org/licenses/>.
21 */
22 
23 #include <config.h>
24 
25 #include "storage_event.h"
26 #include "object_event.h"
27 #include "object_event_private.h"
28 #include "datatypes.h"
29 #include "virlog.h"
30 
31 VIR_LOG_INIT("conf.storage_event");
32 
33 struct _virStoragePoolEvent {
34     virObjectEvent parent;
35 
36     /* Unused attribute to allow for subclass creation */
37     bool dummy;
38 };
39 typedef struct _virStoragePoolEvent virStoragePoolEvent;
40 
41 struct _virStoragePoolEventLifecycle {
42     virStoragePoolEvent parent;
43 
44     int type;
45     int detail;
46 };
47 typedef struct _virStoragePoolEventLifecycle virStoragePoolEventLifecycle;
48 
49 struct _virStoragePoolEventRefresh {
50     virStoragePoolEvent parent;
51 
52     bool dummy;
53 };
54 typedef struct _virStoragePoolEventRefresh virStoragePoolEventRefresh;
55 
56 static virClass *virStoragePoolEventClass;
57 static virClass *virStoragePoolEventLifecycleClass;
58 static virClass *virStoragePoolEventRefreshClass;
59 static void virStoragePoolEventDispose(void *obj);
60 static void virStoragePoolEventLifecycleDispose(void *obj);
61 static void virStoragePoolEventRefreshDispose(void *obj);
62 
63 static int
virStoragePoolEventsOnceInit(void)64 virStoragePoolEventsOnceInit(void)
65 {
66     if (!VIR_CLASS_NEW(virStoragePoolEvent, virClassForObjectEvent()))
67         return -1;
68 
69     if (!VIR_CLASS_NEW(virStoragePoolEventLifecycle, virStoragePoolEventClass))
70         return -1;
71 
72     if (!VIR_CLASS_NEW(virStoragePoolEventRefresh, virStoragePoolEventClass))
73         return -1;
74 
75     return 0;
76 }
77 
78 VIR_ONCE_GLOBAL_INIT(virStoragePoolEvents);
79 
80 static void
virStoragePoolEventDispose(void * obj)81 virStoragePoolEventDispose(void *obj)
82 {
83     virStoragePoolEvent *event = obj;
84     VIR_DEBUG("obj=%p", event);
85 }
86 
87 
88 static void
virStoragePoolEventLifecycleDispose(void * obj)89 virStoragePoolEventLifecycleDispose(void *obj)
90 {
91     virStoragePoolEventLifecycle *event = obj;
92     VIR_DEBUG("obj=%p", event);
93 }
94 
95 
96 static void
virStoragePoolEventRefreshDispose(void * obj)97 virStoragePoolEventRefreshDispose(void *obj)
98 {
99     virStoragePoolEventRefresh *event = obj;
100     VIR_DEBUG("obj=%p", event);
101 }
102 
103 
104 static void
virStoragePoolEventDispatchDefaultFunc(virConnectPtr conn,virObjectEvent * event,virConnectObjectEventGenericCallback cb,void * cbopaque)105 virStoragePoolEventDispatchDefaultFunc(virConnectPtr conn,
106                                        virObjectEvent *event,
107                                        virConnectObjectEventGenericCallback cb,
108                                        void *cbopaque)
109 {
110     virStoragePoolPtr pool = virGetStoragePool(conn,
111                                                event->meta.name,
112                                                event->meta.uuid,
113                                                NULL, NULL);
114     if (!pool)
115         return;
116 
117     switch ((virStoragePoolEventID)event->eventID) {
118     case VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE:
119         {
120             virStoragePoolEventLifecycle *storagePoolLifecycleEvent;
121 
122             storagePoolLifecycleEvent = (virStoragePoolEventLifecycle *)event;
123             ((virConnectStoragePoolEventLifecycleCallback)cb)(conn, pool,
124                                                               storagePoolLifecycleEvent->type,
125                                                               storagePoolLifecycleEvent->detail,
126                                                               cbopaque);
127             goto cleanup;
128         }
129 
130     case VIR_STORAGE_POOL_EVENT_ID_REFRESH:
131         {
132             ((virConnectStoragePoolEventGenericCallback)cb)(conn, pool,
133                                                             cbopaque);
134             goto cleanup;
135         }
136 
137     case VIR_STORAGE_POOL_EVENT_ID_LAST:
138         break;
139     }
140     VIR_WARN("Unexpected event ID %d", event->eventID);
141 
142  cleanup:
143     virObjectUnref(pool);
144 }
145 
146 
147 /**
148  * virStoragePoolEventStateRegisterID:
149  * @conn: connection to associate with callback
150  * @state: object event state
151  * @pool: storage pool to filter on or NULL for all storage pools
152  * @eventID: ID of the event type to register for
153  * @cb: function to invoke when event occurs
154  * @opaque: data blob to pass to @callback
155  * @freecb: callback to free @opaque
156  * @callbackID: filled with callback ID
157  *
158  * Register the function @cb with connection @conn, from @state, for
159  * events of type @eventID, and return the registration handle in
160  * @callbackID.
161  *
162  * Returns: the number of callbacks now registered, or -1 on error
163  */
164 int
virStoragePoolEventStateRegisterID(virConnectPtr conn,virObjectEventState * state,virStoragePoolPtr pool,int eventID,virConnectStoragePoolEventGenericCallback cb,void * opaque,virFreeCallback freecb,int * callbackID)165 virStoragePoolEventStateRegisterID(virConnectPtr conn,
166                                    virObjectEventState *state,
167                                    virStoragePoolPtr pool,
168                                    int eventID,
169                                    virConnectStoragePoolEventGenericCallback cb,
170                                    void *opaque,
171                                    virFreeCallback freecb,
172                                    int *callbackID)
173 {
174     char uuidstr[VIR_UUID_STRING_BUFLEN];
175 
176     if (virStoragePoolEventsInitialize() < 0)
177         return -1;
178 
179     if (pool)
180         virUUIDFormat(pool->uuid, uuidstr);
181     return virObjectEventStateRegisterID(conn, state, pool ? uuidstr : NULL,
182                                          NULL, NULL,
183                                          virStoragePoolEventClass, eventID,
184                                          VIR_OBJECT_EVENT_CALLBACK(cb),
185                                          opaque, freecb,
186                                          false, callbackID, false);
187 }
188 
189 
190 /**
191  * virStoragePoolEventStateRegisterClient:
192  * @conn: connection to associate with callback
193  * @state: object event state
194  * @pool: storage pool to filter on or NULL for all storage pools
195  * @eventID: ID of the event type to register for
196  * @cb: function to invoke when event occurs
197  * @opaque: data blob to pass to @callback
198  * @freecb: callback to free @opaque
199  * @callbackID: filled with callback ID
200  *
201  * Register the function @cb with connection @conn, from @state, for
202  * events of type @eventID, and return the registration handle in
203  * @callbackID.  This version is intended for use on the client side
204  * of RPC.
205  *
206  * Returns: the number of callbacks now registered, or -1 on error
207  */
208 int
virStoragePoolEventStateRegisterClient(virConnectPtr conn,virObjectEventState * state,virStoragePoolPtr pool,int eventID,virConnectStoragePoolEventGenericCallback cb,void * opaque,virFreeCallback freecb,int * callbackID)209 virStoragePoolEventStateRegisterClient(virConnectPtr conn,
210                                        virObjectEventState *state,
211                                        virStoragePoolPtr pool,
212                                        int eventID,
213                                        virConnectStoragePoolEventGenericCallback cb,
214                                        void *opaque,
215                                        virFreeCallback freecb,
216                                        int *callbackID)
217 {
218     char uuidstr[VIR_UUID_STRING_BUFLEN];
219 
220     if (virStoragePoolEventsInitialize() < 0)
221         return -1;
222 
223     if (pool)
224         virUUIDFormat(pool->uuid, uuidstr);
225     return virObjectEventStateRegisterID(conn, state, pool ? uuidstr : NULL,
226                                          NULL, NULL,
227                                          virStoragePoolEventClass, eventID,
228                                          VIR_OBJECT_EVENT_CALLBACK(cb),
229                                          opaque, freecb,
230                                          false, callbackID, true);
231 }
232 
233 
234 /**
235  * virStoragePoolEventLifecycleNew:
236  * @name: name of the storage pool object the event describes
237  * @uuid: uuid of the storage pool object the event describes
238  * @type: type of lifecycle event
239  * @detail: more details about @type
240  *
241  * Create a new storage pool lifecycle event.
242  */
243 virObjectEvent *
virStoragePoolEventLifecycleNew(const char * name,const unsigned char * uuid,int type,int detail)244 virStoragePoolEventLifecycleNew(const char *name,
245                                 const unsigned char *uuid,
246                                 int type,
247                                 int detail)
248 {
249     virStoragePoolEventLifecycle *event;
250     char uuidstr[VIR_UUID_STRING_BUFLEN];
251 
252     if (virStoragePoolEventsInitialize() < 0)
253         return NULL;
254 
255     virUUIDFormat(uuid, uuidstr);
256     if (!(event = virObjectEventNew(virStoragePoolEventLifecycleClass,
257                                     virStoragePoolEventDispatchDefaultFunc,
258                                     VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE,
259                                     0, name, uuid, uuidstr)))
260         return NULL;
261 
262     event->type = type;
263     event->detail = detail;
264 
265     return (virObjectEvent *)event;
266 }
267 
268 
269 /**
270  * virStoragePoolEventRefreshNew:
271  * @name: name of the storage pool object the event describes
272  * @uuid: uuid of the storage pool object the event describes
273  *
274  * Create a new storage pool refresh event.
275  */
276 virObjectEvent *
virStoragePoolEventRefreshNew(const char * name,const unsigned char * uuid)277 virStoragePoolEventRefreshNew(const char *name,
278                               const unsigned char *uuid)
279 {
280     virStoragePoolEventRefresh *event;
281     char uuidstr[VIR_UUID_STRING_BUFLEN];
282 
283     if (virStoragePoolEventsInitialize() < 0)
284         return NULL;
285 
286     virUUIDFormat(uuid, uuidstr);
287     if (!(event = virObjectEventNew(virStoragePoolEventRefreshClass,
288                                     virStoragePoolEventDispatchDefaultFunc,
289                                     VIR_STORAGE_POOL_EVENT_ID_REFRESH,
290                                     0, name, uuid, uuidstr)))
291         return NULL;
292 
293     return (virObjectEvent *)event;
294 }
295