This repository was archived by the owner on Feb 16, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 122
Expand file tree
/
Copy pathnotificationReload.c
More file actions
204 lines (172 loc) · 5.95 KB
/
notificationReload.c
File metadata and controls
204 lines (172 loc) · 5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**
* @file
*
* @brief Example for notification library which reloads KDB when Elektra's
* configuration (e.g. mount points or global plugins) has changed.
* This example also shows how to pass user data using elektraIo*GetData().
*
* Requires:
* - io_glib binding
* - Transport plugins (e.g. kdb global-mount zeromqsend zeromqrecv && kdb run-hub-zeromq)
*
* Relevant keys for this example:
* - /sw/example/notification/#0/current/value: Set to any integer value
* Add additional transport plugins and remove the original pair afterwards or
* mount a file which sets the key above to a different value and unmount it again
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*
*/
#include <kdb.h>
#include <kdbhelper.h> // elektraFree
#include <kdbio.h> // I/O binding functions (elektraIo*)
#include <kdbio/glib.h> // I/O binding constructor for glib (elektraIoGlibNew)
#include <kdbnotification.h> // notification functions
#include <glib-unix.h> // g_unix_signal_add()
#include <glib.h> // glib functions
#include <signal.h> // signal()
#include <stdio.h> // printf() & co
#include <stdlib.h> // exit()
#define TWO_SECONDS 2000
#define RELOAD_INTERVAL 100
/**
* Data container for this example to demo
* usage of the elektraIo*GetData() functions.
*
* Members could also be globals.
*/
typedef struct ExampleUserData
{
GMainLoop * loop;
KDB * kdb;
Key * parentKey;
KeySet * config;
ElektraIoInterface * binding;
Key * intKeyToWatch;
int valueToPrint;
ElektraIoTimerOperation * timer;
ElektraIoTimerOperation * reload;
} ExampleUserData;
static void elektraChangedCallback (Key * changedKey ELEKTRA_UNUSED, void * context);
/**
* Initializes KDB on first call and performs cleanup before initialization on
* subsequent calls.
*
* @param timerOp unused
*/
static void initKdb (ElektraIoTimerOperation * timerOp ELEKTRA_UNUSED)
{
ExampleUserData * data = (ExampleUserData *) elektraIoTimerGetData (timerOp);
int didReload = 0;
// Stop reload task
elektraIoTimerSetEnabled (data->reload, 0);
elektraIoBindingUpdateTimer (data->reload);
if (data->kdb != NULL)
{
// Cleanup notifications and close KDB
kdbClose (data->kdb, data->parentKey);
didReload = 1;
}
KeySet * contract = ksNew (0, KS_END);
elektraIoContract (contract, data->binding);
elektraNotificationContract (contract);
data->kdb = kdbOpen (contract, data->parentKey);
if (data->kdb == NULL)
{
printf ("could not open KDB, aborting\n");
exit (1);
}
int result = elektraNotificationRegisterInt (data->kdb, data->intKeyToWatch, &data->valueToPrint);
if (!result)
{
printf ("could not register variable, aborting\n");
exit (1);
}
Key * elektraKey = keyNew ("/elektra", KEY_END);
if (!elektraNotificationRegisterCallbackSameOrBelow (data->kdb, elektraKey, elektraChangedCallback, data))
{
printf ("could not register for changes to Elektra's configuration, aborting\n");
exit (1);
}
keyDel (elektraKey);
// Get configuration
kdbGet (data->kdb, data->config, data->parentKey);
if (didReload)
{
printf ("KDB reloaded.\n");
}
}
static gboolean onSIGNAL (gpointer user_data)
{
ExampleUserData * data = (ExampleUserData *) user_data;
// Cleanup
elektraIoBindingRemoveTimer (data->timer);
elektraFree (data->timer);
elektraIoBindingRemoveTimer (data->reload);
elektraFree (data->reload);
kdbClose (data->kdb, data->parentKey);
elektraIoBindingCleanup (data->binding);
g_main_loop_quit (data->loop);
return FALSE;
}
/**
* This function is called whenever Elektra's configuration has changed.
*
* @param changedKey unused
* @param context unused
*/
static void elektraChangedCallback (Key * changedKey ELEKTRA_UNUSED, void * context)
{
printf ("\nElektra's configuration has changed.\n");
// Enable operation to reload KDB as soon as possible
ExampleUserData * data = (ExampleUserData *) context;
elektraIoTimerSetEnabled (data->reload, 1);
elektraIoBindingUpdateTimer (data->reload);
}
static void printVariable (ElektraIoTimerOperation * timerOp)
{
// int value = *(int *) elektraIoTimerGetData (timerOp);
ExampleUserData * data = (ExampleUserData *) elektraIoTimerGetData (timerOp);
printf ("\nMy integer value is %d\n", data->valueToPrint);
}
int main (void)
{
ExampleUserData * data = elektraCalloc (sizeof (*data));
if (data == NULL)
{
printf ("elektraCalloc failed");
return 1;
}
// Create glib main loop
GMainContext * context = NULL; // use default context
data->loop = g_main_loop_new (context, 0);
data->binding = elektraIoGlibNew (context);
// Signal Handling
g_unix_signal_add (SIGINT, onSIGNAL, data);
data->config = ksNew (20, KS_END);
data->parentKey = keyNew ("/sw/example/notification/#0/current", KEY_END);
data->intKeyToWatch = keyNew ("/sw/example/notification/#0/current/value", KEY_END);
// Setup timer that repeatedly prints the variable
data->timer = elektraIoNewTimerOperation (TWO_SECONDS, 1, printVariable, data);
elektraIoBindingAddTimer (data->binding, data->timer);
// Setup timer for reloading Elektra's configuration
data->reload = elektraIoNewTimerOperation (RELOAD_INTERVAL, 0, initKdb, data);
elektraIoBindingAddTimer (data->binding, data->reload);
printf ("Reloading Notification Example Application\n");
printf ("Please note that notification transport plugins are required see\n"
" https://www.libelektra.org/tutorials/notifications#notification-configuration!\n");
printf ("- Set \"%s\" to any integer value\n", keyName (data->intKeyToWatch));
printf ("- Try to add additional transport plugins and remove the original pair afterwards\n");
printf ("- Mount a file which sets the key above to a different value and unmount it\n");
printf ("Send SIGINT (Ctl+C) to exit.\n\n");
// Initialize KDB
initKdb (data->reload);
printVariable (data->timer); // "value" was automatically updated
g_main_loop_run (data->loop);
g_main_loop_unref (data->loop);
ksDel (data->config);
keyDel (data->intKeyToWatch);
keyDel (data->parentKey);
elektraFree (data);
printf ("cleanup done!\n");
}