From: Kern Sibbald Date: Thu, 9 Oct 2008 20:55:50 +0000 (+0000) Subject: kes Add malloc and free Bacula entry points for plugins. Increment X-Git-Tag: Release-7.0.0~3996 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7794252be65a4b27778e83db32c9cd088c2de929;p=bacula%2Fbacula kes Add malloc and free Bacula entry points for plugins. Increment FD plugin interface version. Create a bacula plugin context structure to keep track of whether or not the plugin is disabled. kes Apply FileIndex fix for plugin name stream suggested by James. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@7741 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/AUTHORS b/bacula/AUTHORS index 34607fe655..e2b696d26f 100644 --- a/bacula/AUTHORS +++ b/bacula/AUTHORS @@ -12,6 +12,7 @@ Adam Thorton Adrew J. Millar Adrian Close Aitor Matilla +Alan Brown Aleksandar Milivojevic Alexander Bergolth Alexandre Baron diff --git a/bacula/kernstodo b/bacula/kernstodo index 0b290f351d..967a215fe7 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -71,12 +71,26 @@ Professional Needs: Priority: ================ +- Detect deadlocks in reservations. +- Plugins: + - add malloc/restore + - Add list during dump + - Add in plugin code flag + - Add bRC_EndJob -- stops more calls to plugin this job + - Add bRC_Term (unload plugin) + - remove time_t from Jmsg and use utime_t? + - add more doc + - distinguish two types of plugins +- Extended ACLs - Deadlock detection, watchdog sees if counter advances when jobs are running. With debug on, can do a "status" command. - User options for plugins. +- Pool Storage override precidence over command line. - Autolabel only if Volume catalog information indicates tape not written. This will avoid overwriting a tape that gets an I/O error on reading the volume label. +- I/O error, SD thinks it is not the right Volume, should check slot + then disable volume, but Asks for mount. - Can be posible modify package to create and use configuration files in the Debian manner? diff --git a/bacula/patches/2.4.2-migration-deadlock.patch b/bacula/patches/2.4.2-migration-deadlock.patch new file mode 100644 index 0000000000..ba43d2fee5 --- /dev/null +++ b/bacula/patches/2.4.2-migration-deadlock.patch @@ -0,0 +1,47 @@ + + This patch fixes migration SQL not to migrate a job that has not + terminated, or in otherwords do not migrate a running job. + This is a partial fix to bug #1164. + + Any prior patches to src/dird/migration must already be applied. + Apply it to 2.4.2 with: + + cd + patch -p0 <2.4.2-migration-deadlock.patch + ./configure + make + ... + make install + + +Index: src/dird/migrate.c +=================================================================== +--- src/dird/migrate.c (revision 7729) ++++ src/dird/migrate.c (working copy) +@@ -554,7 +554,7 @@ + const char *sql_jobids_from_mediaid = + "SELECT DISTINCT Job.JobId,Job.StartTime FROM JobMedia,Job" + " WHERE JobMedia.JobId=Job.JobId AND JobMedia.MediaId IN (%s)" +- " AND Job.Type='B'" ++ " AND Job.Type='B' AND Job.JobStatus = 'T'" + " ORDER by Job.StartTime"; + + /* Get the number of bytes in the pool */ +@@ -563,7 +563,7 @@ + " (SELECT DISTINCT Job.JobId from Pool,Job,Media,JobMedia WHERE" + " Pool.Name='%s' AND Media.PoolId=Pool.PoolId AND" + " VolStatus in ('Full','Used','Error','Append') AND Media.Enabled=1 AND" +- " Job.Type='B' AND" ++ " Job.Type='B' AND Job.JobStatus = 'T' AND" + " JobMedia.JobId=Job.JobId AND Job.PoolId=Media.PoolId)"; + + /* Get the number of bytes in the Jobs */ +@@ -582,7 +582,7 @@ + "SELECT DISTINCT Job.JobId from Pool,Job,Media,JobMedia WHERE" + " Pool.Name='%s' AND Media.PoolId=Pool.PoolId AND" + " VolStatus in ('Full','Used','Error') AND Media.Enabled=1 AND" +- " Job.Type='B' AND" ++ " Job.Type='B' AND Job.JobStatus = 'T' AND" + " JobMedia.JobId=Job.JobId AND Job.PoolId=Media.PoolId" + " AND Job.RealEndTime<='%s'"; + diff --git a/bacula/src/filed/fd_plugins.c b/bacula/src/filed/fd_plugins.c index db73eae976..beae72f474 100644 --- a/bacula/src/filed/fd_plugins.c +++ b/bacula/src/filed/fd_plugins.c @@ -59,7 +59,14 @@ static bRC baculaJobMsg(bpContext *ctx, const char *file, int line, int type, time_t mtime, const char *fmt, ...); static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line, int level, const char *fmt, ...); +static void *baculaMalloc(bpContext *ctx, const char *file, int line, + size_t size); +static void baculaFree(bpContext *ctx, const char *file, int line, void *mem); +/* + * These will be plugged into the global pointer structure for + * the findlib. + */ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode); static int my_plugin_bclose(BFILE *bfd); static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count); @@ -81,9 +88,20 @@ static bFuncs bfuncs = { baculaGetValue, baculaSetValue, baculaJobMsg, - baculaDebugMsg + baculaDebugMsg, + baculaMalloc, + baculaFree }; +/* + * Bacula private context + */ +struct bacula_ctx { + JCR *jcr; /* jcr for plugin */ + bRC rc; /* last return code */ + bool in_plugin; /* in plugin code */ + bool disabled; /* set if plugin disabled */ +}; /* * Create a plugin event @@ -218,11 +236,15 @@ bail_out: bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) { int stat; + int index = jcr->JobFiles; struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp; + if (start) { + index++; /* JobFiles not incremented yet */ + } Dmsg1(dbglvl, "send_plugin_name=%s\n", sp->cmd); /* Send stream header */ - if (!sd->fsend("%ld %d 0", jcr->JobFiles+1, STREAM_PLUGIN_NAME)) { + if (!sd->fsend("%ld %d 0", index, STREAM_PLUGIN_NAME)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); return false; @@ -231,7 +253,7 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) if (start) { /* Send data -- not much */ - stat = sd->fsend("%ld 1 %d %s%c", jcr->JobFiles+1, sp->portable, sp->cmd, 0); + stat = sd->fsend("%ld 1 %d %s%c", index, sp->portable, sp->cmd, 0); } else { /* Send end of data */ stat = sd->fsend("0 0"); @@ -484,7 +506,10 @@ void new_plugins(JCR *jcr) Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId); foreach_alist(plugin, plugin_list) { /* Start a new instance of each plugin */ - plugin_ctx_list[i].bContext = (void *)jcr; + bacula_ctx *b_ctx = (bacula_ctx *)malloc(sizeof(bacula_ctx)); + memset(b_ctx, 0, sizeof(bacula_ctx)); + b_ctx->jcr = jcr; + plugin_ctx_list[i].bContext = (void *)b_ctx; /* Bacula private context */ plugin_ctx_list[i].pContext = NULL; plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]); } @@ -504,7 +529,8 @@ void free_plugins(JCR *jcr) bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId); - foreach_alist(plugin, plugin_list) { + foreach_alist(plugin, plugin_list) { + free(plugin_ctx_list[i].bContext); /* free Bacula private context */ /* Free the plugin instance */ plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]); } @@ -650,7 +676,7 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence) */ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value) { - JCR *jcr = (JCR *)(ctx->bContext); + JCR *jcr = ((bacula_ctx *)ctx->bContext)->jcr; // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); if (!value) { return bRC_Error; @@ -700,7 +726,7 @@ static bRC baculaJobMsg(bpContext *ctx, const char *file, int line, { va_list arg_ptr; char buf[2000]; - JCR *jcr = (JCR *)(ctx->bContext); + JCR *jcr = ((bacula_ctx *)ctx->bContext)->jcr; va_start(arg_ptr, fmt); bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); @@ -722,6 +748,27 @@ static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line, return bRC_OK; } +static void *baculaMalloc(bpContext *ctx, const char *file, int line, + size_t size) +{ +#ifdef SMARTALLOC + return sm_malloc(file, line, size); +#else + return malloc(size); +#endif +} + +static void baculaFree(bpContext *ctx, const char *file, int line, void *mem) +{ +#ifdef SMARTALLOC + sm_free(file, line, mem); +#else + free(mem); +#endif +} + + + #ifdef TEST_PROGRAM int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL; diff --git a/bacula/src/filed/fd_plugins.h b/bacula/src/filed/fd_plugins.h index 35a5378e86..302ebb2346 100644 --- a/bacula/src/filed/fd_plugins.h +++ b/bacula/src/filed/fd_plugins.h @@ -147,6 +147,7 @@ typedef enum { bVarSinceTime = 8 } bVariable; +/* Events that are passed to plugin */ typedef enum { bEventJobStart = 1, bEventJobEnd = 2, @@ -205,6 +206,9 @@ typedef struct s_baculaFuncs { int type, time_t mtime, const char *fmt, ...); bRC (*DebugMessage)(bpContext *ctx, const char *file, int line, int level, const char *fmt, ...); + void *(*malloc)(bpContext *ctx, const char *file, int line, + size_t size); + void (*free)(bpContext *ctx, const char *file, int line, void *mem); } bFuncs; @@ -223,7 +227,7 @@ typedef enum { #define FD_PLUGIN_MAGIC "*FDPluginData*" -#define FD_PLUGIN_INTERFACE_VERSION 1 +#define FD_PLUGIN_INTERFACE_VERSION 2 typedef struct s_pluginInfo { uint32_t size; diff --git a/bacula/src/filed/status.c b/bacula/src/filed/status.c index 4461a66f57..7b646476e6 100644 --- a/bacula/src/filed/status.c +++ b/bacula/src/filed/status.c @@ -143,6 +143,21 @@ static void list_status_header(STATUS_PKT *sp) len = Mmsg(msg, _(" Sizeof: boffset_t=%d size_t=%d debug=%d trace=%d\n"), sizeof(boffset_t), sizeof(size_t), debug_level, get_trace()); sendit(msg.c_str(), len, sp); + if (debug_level > 0 && plugin_list->size() > 0) { + Plugin *plugin; + int len; + pm_strcpy(msg, "Plugin="); + foreach_alist(plugin, plugin_list) { + len = pm_strcat(msg, plugin->file); + if (len > 80) { + pm_strcat(msg, "\n "); + } else { + pm_strcat(msg, " "); + } + } + len = pm_strcat(msg, "\n"); + sendit(msg.c_str(), len, sp); + } } static void list_running_jobs(STATUS_PKT *sp) diff --git a/bacula/src/lib/plugins.h b/bacula/src/lib/plugins.h index be08be9659..787b2ca226 100644 --- a/bacula/src/lib/plugins.h +++ b/bacula/src/lib/plugins.h @@ -55,12 +55,13 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); extern DLL_IMP_EXP alist *plugin_list; -/* Universal return codes from all functions */ +/* Universal return codes from all plugin functions */ typedef enum { - bRC_OK = 0, /* OK */ - bRC_Stop = 1, /* Stop calling other plugins */ - bRC_Error = 2, /* Some kind of error */ - bRC_More = 3, /* More files to backup */ + bRC_OK = 0, /* OK */ + bRC_Stop = 1, /* Stop calling other plugins */ + bRC_Error = 2, /* Some kind of error */ + bRC_More = 3, /* More files to backup */ + bRC_Term = 4 /* Unload me */ } bRC; /* Context packet as first argument of all functions */ diff --git a/bacula/technotes-2.5 b/bacula/technotes-2.5 index 5a1d7701cd..33e2ca5aa7 100644 --- a/bacula/technotes-2.5 +++ b/bacula/technotes-2.5 @@ -17,6 +17,12 @@ dbdriver remove reader/writer in FOPTS???? General: +09Oct08 +kes Add malloc and free Bacula entry points for plugins. Increment + FD plugin interface version. Create a bacula plugin context + structure to keep track of whether or not the plugin is disabled. +kes Apply FileIndex fix for plugin name stream suggested by James. +kes List plugins in FD status report when debug > 0. 08Oct08 ebl Add a new VerId variable that is printed in version command. kes Fix migration SQL not to migrate a job that has not terminated.