[prev in list] [next in list] [prev in thread] [next in thread] 

List:       bacula-commits
Subject:    [Bacula-commits] SF.net SVN: bacula:[7650]
From:       kerns () users ! sourceforge ! net
Date:       2008-09-26 12:14:30
Message-ID: E1KjCDO-0005H5-JR () dn4whf1 ! ch3 ! sourceforge ! com
[Download RAW message or body]

Revision: 7650
          http://bacula.svn.sourceforge.net/bacula/?rev=7650&view=rev
Author:   kerns
Date:     2008-09-26 12:14:29 +0000 (Fri, 26 Sep 2008)

Log Message:
-----------
Update plugin API documentation

Modified Paths:
--------------
    trunk/docs/manuals/en/concepts/concepts.kilepr
    trunk/docs/manuals/en/concepts/newfeatures.tex

Modified: trunk/docs/manuals/en/concepts/concepts.kilepr
===================================================================
--- trunk/docs/manuals/en/concepts/concepts.kilepr	2008-09-26 08:17:54 UTC (rev 7649)
+++ trunk/docs/manuals/en/concepts/concepts.kilepr	2008-09-26 12:14:29 UTC (rev 7650)
@@ -161,10 +161,10 @@
 
 [item:newfeatures.tex]
 archive=true
-column=28
+column=0
 encoding=UTF-8
 highlight=LaTeX
-line=509
+line=1188
 open=true
 order=0
 

Modified: trunk/docs/manuals/en/concepts/newfeatures.tex
===================================================================
--- trunk/docs/manuals/en/concepts/newfeatures.tex	2008-09-26 08:17:54 UTC (rev 7649)
+++ trunk/docs/manuals/en/concepts/newfeatures.tex	2008-09-26 12:14:29 UTC (rev 7650)
@@ -682,7 +682,7 @@
 is a very useful and working program.
 
 The {\bf make test} command will build the {\bf example-plugin-fd.so}
-plugin and a binary named main, which is build from the source
+plugin and a binary named {\bf main}, which is build from the source
 code located in {\bf src/filed/fd\_plugins.c}. 
 
 If you execute {\bf ./main}, it will load and run the example-plugin-fd
@@ -703,13 +703,23 @@
 %%
 
 \chapter{Bacula FD Plugin API}
-To write a Bacula plugin, you cread a dynamic shared object
+To write a Bacula plugin, you create a dynamic shared object
 program (or dll on Win32) with a particular name and two 
-entry points, place it in the {\bf Plugins Directory}, and when the FD
-starts, it will load all the plugins found in that directory.
-Once it loads them, it calls the {\bf loadPlugin} entry point (see below)
-then later, it will call particular functions that are defined by the
-{\bf loadPlugin} interface.  When Bacula is finished with the plugin 
+exported entry points, place it in the {\bf Plugins Directory}, which is defined in \
the +{\bf bacula-fd.conf} file in the {\bf Client} resource, and when the FD
+starts, it will load all the plugins that end with {\bf -fd.so} (or {\bf -fd.dll}
+on Win32) found in that directory.
+
+Once the File daemon loads the plugins, it asks the OS for the
+two entry points (loadPlugin and unloadPlugin) then calls the
+{\bf loadPlugin} entry point (see below).
+
+Bacula passes information to the plugin through this call and it gets
+back information that it needs to use the plugin.  Later, Bacula
+ will call particular functions that are defined by the
+{\bf loadPlugin} interface.  
+
+When Bacula is finished with the plugin 
 (when Bacula is going to exit), it will call the {\bf unloadPlugin}
 entry point.
 
@@ -723,14 +733,15 @@
 bRC unloadPlugin()
 \end{verbatim}
 
-both these entry points to the shared object are defined as C entry points
+both these external entry points to the shared object are defined as C entry points
 to avoid name mangling complications with C++.  However, the shared object
-can actually be written in any language.
+can actually be written in any language (preferrably C or C++) providing that it
+follows C language calling conventions.
 
 The definitions for {\bf bRC} and the arguments are {\bf
 src/filed/fd-plugins.h} and so this header file needs to be included in
-your plug.  It along with {\bf lib/plugins.h} define basically the whole
-plugin interface.  Within this header file, it includes the fillowing
+your plugin.  It along with {\bf src/lib/plugins.h} define basically the whole
+plugin interface.  Within this header file, it includes the following
 files:
 
 \begin{verbatim}
@@ -741,7 +752,7 @@
 #include <sys/stat.h>
 \end{verbatim}
 
-Aside from the {\bf bc\_types.h} header, the plugin definition uses the
+Aside from the {\bf bc\_types.h} and {\bf confit.h} headers, the plugin definition \
uses the  minimum code from Bacula.  The bc\_types.h file is required to ensure that
 the data type defintions in arguments correspond to the Bacula core code.
 
@@ -763,10 +774,12 @@
 
 \section{loadPlugin}
 As previously mentioned, the {\bf loadPlugin} entry point in the plugin
-is called immediately after Bacula loads the plugin.  In calling the
+is called immediately after Bacula loads the plugin when the File daemon
+itself is first starting.  This entry point is only called once during the
+execution of the File daemon.  In calling the
 plugin, the first two arguments are information from Bacula that
 is passed to the plugin, and the last two arguments are information
-about the plugin that is returned to Bacula.  The call is:
+about the plugin that the plugin must return to Bacula.  The call is:
 
 \begin{verbatim}
 bRC loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
@@ -777,9 +790,10 @@
 \begin{description}
 \item [lbinfo]
 This is information about Bacula in general. Currently, the only value
-defined in the bInfo structure is version, which is the Bacula plugin 
-interface version, currently defined as 1.
-The exact definition as of this writing is: 
+defined in the bInfo structure is the version, which is the Bacula plugin 
+interface version, currently defined as 1.  The {\bf size} is set to the
+byte size of the structure. The exact definition of the bInfo structure
+as of this writing is: 
 
 \begin{verbatim}
 typedef struct s_baculaInfo {
@@ -791,12 +805,11 @@
 \item [lbfuncs]
 The bFuncs structure defines the callback entry points within Bacula
 that the plugin can use register events, get Bacula values, set
-Bacula values, and send messages to the Job output.
+Bacula values, and send messages to the Job output or debug output.
 
 The exact definition as of this writing is:
-
 \begin{verbatim}
-ypedef struct s_baculaFuncs {
+typedef struct s_baculaFuncs {
    uint32_t size;
    uint32_t version;
    bRC (*registerBaculaEvents)(bpContext *ctx, ...);
@@ -812,6 +825,7 @@
 We will discuss these entry points and how to use them a bit later when
 describing the plugin code.
 
+
 \item [pInfo]
 When the loadPlugin entry point is called, the plugin must initialize
 an information structure about the plugin and return a pointer to
@@ -834,23 +848,31 @@
 
 Where:
  \begin{description}
- \item [version] is the current plugin interface version, currently
-   set to 1.
- \item [plugin\_magic] is a pointer to the string "*FDPluginData*", a
-   sort of sanity check.
- \item [plugin\_license] is a pointer to a string that describes the
-   plugin license. 
- \item [plugin\_author] is a pointer to the name of the author of the program.
- \item [plugin\_date] is the pointer string containing the date of the plugin.
- \item [plugin\_version] is a pointer to a string containing the version of
-   the plugin.
+ \item [version] is the current Bacula defined plugin interface version, currently
+   set to 1. If the interface version differs from the current version of 
+   Bacula, the plugin will not be run (not yet implemented).
+ \item [plugin\_magic] is a pointer to the text string "*FDPluginData*", a
+   sort of sanity check.  If this value is not specified, the plugin
+   will not be run (not yet implemented).
+ \item [plugin\_license] is a pointer to a text string that describes the
+   plugin license. Bacula will only accept compatible licenses (not yet
+   implemented).
+ \item [plugin\_author] is a pointer to the text name of the author of the program.
+   This string can be anything but is generally the author's name.
+ \item [plugin\_date] is the pointer text string containing the date of the plugin.
+   This string can be anything but is generally some human readable form of 
+   the date.
+ \item [plugin\_version] is a pointer to a text string containing the version of
+   the plugin.  The contents are determined by the plugin writer.
  \item [plugin\_description] is a pointer to a string describing what the
-   plugin does.
+   plugin does. The contents are determined by the plugin writer.
  \end{description}
 
 The pInfo structure must be defined in static memory because Bacula does not
 copy it and may refer to the values at any time while the plugin is
-loaded.
+loaded. All values must be supplied or the plugin will not run (not yet
+implemented).  All text strings must be either ASCII or UTF-8 strings that
+are terminated with a zero byte.
 
 \item [pFuncs]
 When the loadPlugin entry point is called, the plugin must initialize
@@ -864,7 +886,6 @@
 copy it and may refer to the values at any time while the plugin is
 loaded.
 
-
 The exact definition as of this writing is:
 
 \begin{verbatim}
@@ -891,30 +912,56 @@
 
 Where:
  \begin{description}
- \item [size] is the size of the structure.
- \item [version] is the plugin interface version.
+ \item [size] is the byte size of the structure.
+ \item [version] is the plugin interface version currently set to 1.
  \end{description}
 
+Sample code for loadPlugin:
+\begin{verbatim}
+  bfuncs = lbfuncs;                  /* set Bacula funct pointers */
+  binfo  = lbinfo;
+  *pinfo  = &pluginInfo;             /* return pointer to our info */
+  *pfuncs = &pluginFuncs;            /* return pointer to our functions */
+
+   return bRC_OK;
+\end{verbatim}
+
+where pluginInfo and pluginFuncs are statically defined structures. 
+See bpipe-fd.c for details.
+
+
+
 \end{description}
 
 \section{Plugin Entry Points}
-This section will describe each of the entry points that
-the plugin must provide for Bacula, when they are called
-and their arguments.
+This section will describe each of the entry points (subroutines) within
+the plugin that the plugin must provide for Bacula, when they are called
+and their arguments. As noted above, pointers to these subroutines are
+passed back to Bacula in the pFuncs structure when Bacula calls the 
+loadPlugin() externally defined entry point.
 
 \subsection{newPlugin(bpContext *ctx)}
   This is the entry point that Bacula will call
-   when a new instance of the plugin is created. This typically
-   happens at the beginning of a Job.  If 10 Jobs are running
-   simultaneously, there will be at least 10 instances of the
-   plugin.
+  when a new "instance" of the plugin is created. This typically
+  happens at the beginning of a Job.  If 10 Jobs are running
+  simultaneously, there will be at least 10 instances of the
+  plugin.
 
-   The bpContext structure will be passed to the plugin, and
-   during this call, if the plugin needs to have its private
-   working storage that is associated with the particular
-   instance of the plugin, it should create it from the heap
-   (malloc the memory) and store a pointer to
-   its private working storage in the {\bf pContext} variable.
+  The bpContext structure will be passed to the plugin, and
+  during this call, if the plugin needs to have its private
+  working storage that is associated with the particular
+  instance of the plugin, it should create it from the heap
+  (malloc the memory) and store a pointer to
+  its private working storage in the {\bf pContext} variable.
+  Note: since Bacula is a multi-threaded program, you must not
+  keep any variable data in your plugin unless it is truely meant
+  to apply globally to the whole plugin.  In addition, you must
+  be aware that except the first and last call to the plugin
+  (loadPlugin and unloadPlugin) all the other calls will be 
+  made by threads that correspond to a Bacula job.  The 
+  bpContext that will be passed for each thread will remain the
+  same throughout the Job thus you can keep your privat Job specific
+  data in it ({\bf bContext}).
 
 \begin{verbatim}
 typedef struct s_bpContext {
@@ -927,14 +974,19 @@
   This context pointer will be passed as the first argument to all
   the entry points that Bacula calls within the plugin.  Needless
   to say, the plugin should not change the bContext variable, which
-  is Bacula's private context pointer for this instance of this
+  is Bacula's private context pointer for this instance (Job) of this
   plugin.
 
 \subsection{freePlugin(bpContext *ctx)}
 This entry point is called when the
 this instance of the plugin is no longer needed (the Job is
 ending), and the plugin should release all memory it may
-have allocated for the pContext.
+have allocated for this particular instance (Job) i.e. the pContext.  
+This is not the final termination
+of the plugin signaled by a call to {\bf unloadPlugin}. 
+Any other instances (Job) will
+continue to run, and the entry point {\bf newPlugin} may be called
+again if other jobs start.
 
 \subsection{getPluginValue(bpContext *ctx, pVariable var, void *value)} 
 Bacula will call this entry point to get
@@ -946,7 +998,12 @@
  
 \subsection{handlePluginEvent(bpContext *ctx, bEvent *event, void *value)}
 This entry point is called when Bacula
-encounters certain events (discussed below). Bacula passes the pointer to an event
+encounters certain events (discussed below). This is, in fact, the 
+main way that most plugins get control when a Job runs and how
+they know what is happening in the job. It can be likened to the
+{\bf RunScript} feature that calls external programs and scripts,
+and is very similar to the Bacula Python interface.
+When the plugin is called, Bacula passes it the pointer to an event
 structure (bEvent), which currently has one item, the eventType:
 
 \begin{verbatim}
@@ -958,7 +1015,8 @@
   which defines what event has been triggered, and for each event,
   Bacula will pass a pointer to a value associated with that event.
   If no value is associated with a particular event, Bacula will 
-  pass a NULL pointer, so you must always check for it.
+  pass a NULL pointer, so the plugin must be careful to always check
+  value pointer prior to dereferencing it.
   
   The current list of events are:
 
@@ -980,7 +1038,7 @@
 
 \end{verbatim}
  
-Most of which are pretty explanatory.
+Most of the above are self-explanatory.
 
 \begin{description}
  \item [bEventJobStart] is called whenever a Job starts. The value
@@ -988,33 +1046,64 @@
    Job=job-name". Where nnn will be replaced by the JobId and job-name
    will be replaced by the Job name. The variable is temporary so if you
    need the values, you must copy them.
+
  \item [bEventJobEnd] is called whenever a Job ends. No value is passed.
+
  \item [bEventStartBackupJob] is called when a Backup Job begins. No value
    is passed.
+
  \item [bEventEndBackupJob] is called when a Backup Job ends. No value is 
    passed.
+
  \item [bEventStartRestoreJob] is called when a Restore Job starts. No value
    is passed.
+
  \item [bEventEndRestoreJob] is called when a Restore Job ends. No value is
    passed.
+
  \item [bEventStartVerifyJob] is called when a Verify Job starts. No value
    is passed.
+
  \item [bEventEndVerifyJob] is called when a Verify Job ends. No value
    is passed.
+
  \item [bEventBackupCommand] is called prior to the bEventStartBackupJob and
    the plugin is passed the command string (everything after the equal sign
    in "Plugin =" as the value.
+
+   Note, if you intend to backup a file, this is an important first point to
+   write code that copies the command string passed into your pContext area
+   so that you will know that a backup is being performed and you will know
+   the full contents of the "Plugin =" command (i.e. what to backup and
+   what virtual filename the user wants to call it.
+
  \item [bEventRestoreCommand] is called prior to the bEventStartRestoreJob and
    the plugin is passed the command string (everything after the equal sign
    in "Plugin =" as the value.
+
+   See the notes above concerning backup and the command string. This is the
+   point at which Bacula passes you the original command string that was
+   specified during the backup, so you will want to save it in your pContext
+   area for later use when Bacula calls the plugin again.
+
  \item [bEventLevel] is called when the level is set for a new Job. The value
    is a 32 bit integer stored in the void*, which represents the Job Level code.
+
  \item [bEventSince] is called when the since time is set for a new Job. The 
    value is a time\_t time at which the last job was run.
 \end{description}
 
+During each of the above calls, the plugin receives either no specific value or
+only one value, which in some cases may not be sufficient.  However, knowing the
+context of the event, the plugin can call back to the Bacula entry points it
+was passed during the {\bf loadPlugin} call and get to a number of Bacula variables.
+(at the current time few Bacula variables are implemented, but it easily extended
+at a future time and as needs require).
+
 \subsection{startBackupFile(bpContext *ctx, struct save\_pkt *sp)}
-Called when beginning the backup of a file.
+Called when beginning the backup of a file. Here Bacula provides you
+with a pointer to the {\bf save\_pkt} structure and you must fill in 
+this packet with the "attribute" data of the file.
 
 \begin{verbatim}
  struct save_pkt {
@@ -1030,19 +1119,79 @@
 
 The second argument is a pointer to the {\bf save\_pkt} structure for the file
 to be backed up.  The plugin is responsible for filling in all the fields 
-of the {\bf save\_pkt}.  The values in the {\bf save\_pkt} are used to create a \
                virtual file
-entry in the Bacula catalog database. The full path and filename should be
-unique on the system to avoid conflicts with real files. Example programs such
-as {\bf bpipe.c} show how to set these fields.
+of the {\bf save\_pkt}. If you are backing up
+a real file, then generally, the statp structure can be filled in by doing
+a {\bf stat} system call on the file.  
 
+If you are backing up a database or
+something that is more complex, you might want to create a virtual file.
+That is a file that does not actually exist on the filesystem, but represents 
+say an object that you are backing up.  In that case, you need to ensure
+that the {\bf fname} string that you pass back is unique so that it
+does not conflict with a real file on the system, and you need to 
+artifically create values in the statp packet.
+
+Example programs such as {\bf bpipe-fd.c} show how to set these fields.
+You must take care not to store pointers the stack in the pointer fields such
+as fname and link, because when you return from your function, your stack entries
+will be destroyed. The solution in that case is to malloc() and return the pointer
+to it. In order to not have memory leaks, you should store a pointer to all memory
+allocated in your pContext structure so that in subsequent calls or at termination,
+you can release it back to the system.
+
 Once the backup has begun, Bacula will call your plugin at the {\bf pluginIO}
-entry point to "read" the data to be backed up.  Please see the {\bf bpipe.c}
+entry point to "read" the data to be backed up.  Please see the {\bf bpipe-fd.c}
 plugin for how to do I/O.
 
+Example of filling in the save\_pkt as used in bpipe-fd.c:
+
+\begin{verbatim}
+   struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
+   time_t now = time(NULL);
+   sp->fname = p_ctx->fname;
+   sp->statp.st_mode = 0700 | S_IFREG;
+   sp->statp.st_ctime = now;
+   sp->statp.st_mtime = now;
+   sp->statp.st_atime = now;
+   sp->statp.st_size = -1;
+   sp->statp.st_blksize = 4096;
+   sp->statp.st_blocks = 1;
+   p_ctx->backup = true;
+   return bRC_OK; 
+\end{verbatim}
+
+Note: the filename to be created has already been created from the 
+command string previously sent to the plugin and is in the plugin 
+context (p\_ctx->fname) and is a malloc()ed string.  This example
+creates a regular file (S\_IFREG), with various fields being created.
+
+In general, the sequence of commands issued from Bacula to the plugin
+to do a backup while processing the "Plugin = " directive are:
+
+\begin{enumerate}
+ \item generate a bEventBackupCommand event to the specified plugin
+       and pass it the command string.
+ \item make a startPluginBackup call to the plugin, which
+       fills in the data needed in save\_pkt to save as the file
+       attributes and to put on the Volume and in the catalog.
+ \item call Bacula's internal save\_file() subroutine to save the specified
+       file.  The plugin will then be called at pluginIO() to "open"
+       the file, and then to read the file data.
+       Note, if you are dealing with a virtual file, the "open" operation
+       is something the plugin does internally and it doesn't necessarily
+       mean opening a file on the filesystem.  For example in the case of
+       the bpipe-fd.c program, it initiates a pipe to the requested program.
+       Finally when the plugin signals to Bacula that all the data was read,
+       Bacula will call the plugin with the "close" pluginIO() function.
+\end{enumerate}
+
+
 \subsection{endBackupFile(bpContext *ctx)}
 Called at the end of backing up a file.  If the plugin's work
 is done, it should return bRC\_OK.  If the plugin wishes to create another
 file and back it up, then it must return bRC\_More (not yet implemented).
+This is probably a good time to release any malloc()ed memory you used to
+pass back filenames.
 
 \subsection{startRestoreFile(bpContext *ctx, const char *cmd)}
 Not implemented.
@@ -1079,7 +1228,7 @@
 
 
 \subsection{createFile(bpContext *ctx, struct restore\_pkt *rp)}
-Called to create a file before restoring the data. The data in the 
+Called to create a file during a Restore job before restoring the data. The data in \
the   restore\_pkt is passed to the plugin and is based on the data that was
 originally given by the plugin during the backup and the current user
 restore settings (e.g. where, RegexWhere, replace).  This allows the


This was sent by the SourceForge.net collaborative development platform, the world's \
largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Bacula-commits mailing list
Bacula-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic