]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/fd-plugins.c
Plugin implementation
[bacula/bacula] / bacula / src / filed / fd-plugins.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation, which is 
11    listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Main program to test loading and running Bacula plugins.
30  *   Destined to become Bacula pluginloader, ...
31  *
32  * Kern Sibbald, October 2007
33  */
34 #include "bacula.h"
35 #include "jcr.h"
36 #include "fd-plugins.h"
37
38 const int dbglvl = 50;
39 const char *plugin_type = "-fd.so";
40
41 /* Function pointers to be set here */
42 extern int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
43 extern int     (*plugin_bclose)(JCR *jcr);
44 extern ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
45 extern ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
46
47
48 /* Forward referenced functions */
49 static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value);
50 static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value);
51 static bRC baculaRegisterEvents(bpContext *ctx, ...);
52 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
53   int type, time_t mtime, const char *msg);
54 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
55   int level, const char *msg);
56
57 static int     my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode);
58 static int     my_plugin_bclose(JCR *jcr);
59 static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count);
60 static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count);
61
62
63 /* Bacula info */
64 static bInfo binfo = {
65    sizeof(bFuncs),
66    PLUGIN_INTERFACE_VERSION 
67 };
68
69 /* Bacula entry points */
70 static bFuncs bfuncs = {
71    sizeof(bFuncs),
72    PLUGIN_INTERFACE_VERSION,
73    baculaRegisterEvents,
74    baculaGetValue,
75    baculaSetValue,
76    baculaJobMsg,
77    baculaDebugMsg
78 };
79
80
81 /*
82  * Create a plugin event 
83  */
84 void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)     
85 {
86    bEvent event;
87    Plugin *plugin;
88    int i = 0;
89    int len;
90    char *p;
91    char *cmd = (char *)value;
92
93    if (!plugin_list) {
94       return;
95    }
96
97    bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
98    event.eventType = eventType;
99
100    Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
101    if (eventType != bEventPluginCommand) {
102       /* Pass event to every plugin */
103       foreach_alist(plugin, plugin_list) {
104          plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event, value);
105       }
106       return;
107    }
108
109    /* Handle plugin command here (backup/restore of file) */
110    if (!(p = strchr(cmd, ':'))) {
111       Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
112       return;
113    }
114    len = p - cmd;
115    if (len > 0) {
116       foreach_alist(plugin, plugin_list) {
117          Dmsg3(000, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
118          if (strncmp(plugin->file, cmd, len) == 0) {
119             Dmsg1(000, "Command plugin = %s\n", cmd);
120             plug_func(plugin)->handlePluginEvent(&plugin_ctx[i], &event, value);
121             return;
122          }
123          i++;
124       }
125    }
126       
127 }
128
129 void load_fd_plugins(const char *plugin_dir)
130 {
131    if (!plugin_dir) {
132       return;
133    }
134
135    plugin_list = New(alist(10, not_owned_by_alist));
136    load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
137    plugin_bopen     = my_plugin_bopen;
138    plugin_bclose    = my_plugin_bclose;
139    plugin_bread     = my_plugin_bread;
140    plugin_bwrite    = my_plugin_bwrite;
141
142 }
143
144 /*
145  * Create a new instance of each plugin for this Job
146  */
147 void new_plugins(JCR *jcr)
148 {
149    Plugin *plugin;
150    int i = 0;
151
152    if (!plugin_list) {
153       return;
154    }
155
156    int num = plugin_list->size();
157
158    if (num == 0) {
159       return;
160    }
161
162    jcr->plugin_ctx = (void *)malloc(sizeof(bpContext) * num);
163
164    bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
165    Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
166    foreach_alist(plugin, plugin_list) {
167       /* Start a new instance of each plugin */
168       plugin_ctx[i].bContext = (void *)jcr;
169       plugin_ctx[i].pContext = NULL;
170       plug_func(plugin)->newPlugin(&plugin_ctx[i++]);
171    }
172 }
173
174 /*
175  * Free the plugin instances for this Job
176  */
177 void free_plugins(JCR *jcr)
178 {
179    Plugin *plugin;
180    int i = 0;
181
182    if (!plugin_list) {
183       return;
184    }
185
186    bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
187    Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
188    foreach_alist(plugin, plugin_list) {
189       /* Free the plugin instance */
190       plug_func(plugin)->freePlugin(&plugin_ctx[i++]);
191    }
192    free(plugin_ctx);
193    jcr->plugin_ctx = NULL;
194 }
195
196 static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
197 {
198    struct io_pkt io;
199    Dmsg0(000, "plugin_bopen\n");
200    io.func = IO_OPEN;
201    io.count = 0;
202    io.buf = NULL;
203
204    return 0;
205 }
206
207 static int my_plugin_bclose(JCR *jcr)
208 {
209    struct io_pkt io;
210    Dmsg0(000, "plugin_bclose\n");
211    io.func = IO_CLOSE;
212    io.count = 0;
213    io.buf = NULL;
214    return 0;
215 }
216
217 static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
218 {
219    struct io_pkt io;
220    Dmsg0(000, "plugin_bread\n");
221    io.func = IO_READ;
222    io.count = count;
223    io.buf = (char *)buf;
224    return 0;
225 }
226
227 static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
228 {
229    struct io_pkt io;
230    Dmsg0(000, "plugin_bwrite\n");
231    io.func = IO_WRITE;
232    io.count = count;
233    io.buf = (char *)buf;
234    return 0;
235 }
236
237 /* ==============================================================
238  *
239  * Callbacks from the plugin
240  *
241  * ==============================================================
242  */
243 static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
244 {
245    JCR *jcr = (JCR *)(ctx->bContext);
246 // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
247    if (!value) {
248       return bRC_Error;
249    }
250 // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); 
251    switch (var) {
252    case bVarJobId:
253       *((int *)value) = jcr->JobId;
254       Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
255       break;
256    case bVarFDName:
257       *((char **)value) = my_name;
258       Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name);
259       break;
260    case bVarLevel:
261    case bVarType:
262    case bVarClient:
263    case bVarJobName:
264    case bVarJobStatus:
265    case bVarSinceTime:
266       break;
267    }
268    return bRC_OK;
269 }
270
271 static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value)
272 {
273    Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
274    return bRC_OK;
275 }
276
277 static bRC baculaRegisterEvents(bpContext *ctx, ...)
278 {
279    va_list args;
280    uint32_t event;
281
282    va_start(args, ctx);
283    while ((event = va_arg(args, uint32_t))) {
284       Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
285    }
286    va_end(args);
287    return bRC_OK;
288 }
289
290 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
291   int type, time_t mtime, const char *msg)
292 {
293    Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n",
294       file, line, type, mtime, msg);
295    return bRC_OK;
296 }
297
298 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
299   int level, const char *msg)
300 {
301    Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n",
302       file, line, level, msg);
303    return bRC_OK;
304 }
305
306 #ifdef TEST_PROGRAM
307
308 int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
309 int     (*plugin_bclose)(JCR *jcr) = NULL;
310 ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
311 ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
312
313
314 int main(int argc, char *argv[])
315 {
316    char plugin_dir[1000];
317    JCR mjcr1, mjcr2;
318    JCR *jcr1 = &mjcr1;
319    JCR *jcr2 = &mjcr2;
320
321    strcpy(my_name, "test-fd");
322     
323    getcwd(plugin_dir, sizeof(plugin_dir)-1);
324    load_fd_plugins(plugin_dir);
325
326    jcr1->JobId = 111;
327    new_plugins(jcr1);
328
329    jcr2->JobId = 222;
330    new_plugins(jcr2);
331
332    generate_plugin_event(jcr1, bEventJobStart);
333    generate_plugin_event(jcr1, bEventJobEnd);
334    generate_plugin_event(jcr2, bEventJobStart);
335    free_plugins(jcr1);
336    generate_plugin_event(jcr2, bEventJobEnd);
337    free_plugins(jcr2);
338
339    unload_plugins();
340
341    Dmsg0(dbglvl, "bacula: OK ...\n");
342    close_memory_pool();
343    sm_dump(false);
344    return 0;
345 }
346
347 #endif /* TEST_PROGRAM */