nbdkit-ocaml-plugin - Man Page

writing nbdkit plugins in OCaml

Synopsis

 nbdkit /path/to/plugin.so [arguments...]

 nbdkit plugin [arguments...]

Description

This manual page describes how to write nbdkit plugins in natively compiled OCaml code.

Note this requires OCaml ≥ 4.02.2, which has support for shared libraries.  See http://caml.inria.fr/mantis/view.php?id=6693

Writing an Ocaml Nbdkit Plugin

For an example plugin written in OCaml, see: https://gitlab.com/nbdkit/nbdkit/blob/master/plugins/ocaml/example.ml

Broadly speaking, OCaml nbdkit plugins work like C ones, so you should read nbdkit-plugin(3) first.

You should also look at NBDKit(3) which describes the plugin interface for OCaml plugins.

Your OCaml code should call NBDKit.register_plugin like this:

 let plugin = {
   NBDKit.default_callbacks with
     NBDKit.name     = "myplugin";
     version         = "1.0";
     open_connection = Some myplugin_open;
     get_size        = Some myplugin_get_size;
     pread           = Some myplugin_pread;
     thread_model    = Some (fun () -> NBDKit.THREAD_MODEL_SERIALIZE_CONNECTIONS);
     (* etc *)
 }
 
 let () = NBDKit.register_plugin plugin

Your plugin must call register_plugin exactly once when the plugin is loaded.

Compiling an OCaml nbdkit plugin

OCaml nbdkit plugins are natively compiled into shared object (*.so) files which nbdkit loads like regular C plugins.

After writing your OCaml plugin (myplugin.ml), compile and link it using this command:

 ocamlopt.opt -output-obj -runtime-variant _pic \
              -o nbdkit-myplugin-plugin.so \
              NBDKit.cmx myplugin.ml \
              -cclib -lnbdkitocaml

You can then use nbdkit-myplugin-plugin.so as an nbdkit plugin (see nbdkit(1), nbdkit-plugin(3)):

 nbdkit ./nbdkit-myplugin-plugin.so [args ...]

or if the .so file is installed in the $plugindir directory:

 nbdkit myplugin [args ...]

Handle

Your open_connection callback can return an OCaml value of any type.  The same value is passed back to the per-connection callbacks like get_size and pread.

Typically (although this is not a requirement) you define your own handle struct in your plugin:

 type handle = {
   (* any per-connection data you want to store goes here *)
   h_id : int; (* this is just an example field *)
   h_readonly : bool;
 }
 
 let id = ref 0
 let myplugin_open readonly =
   (* return a newly allocated handle *)
   incr id;
   { h_id = !id; h_readonly = readonly }
 
 let myplugin_get_size handle =
   printf "handle ID = %d\n" handle.h_id;
   (* ... *)

If you don't need to store per-connection data, open_connection can return ().

Errors

Plugins can return errors from methods by raising an exception.

If you need to control which errno is sent back to the client you have to call NBDKit.set_error before raising the exception.

Note if you call some function in the OCaml Unix module or another library which fails, then the errno of the failing system call will not be returned to the client.  You have to catch the exception and call NBDKit.set_error before re-raising the exception if you need to control this.

Threads

One of the members in the plugin record passed to NBDKit.register_plugin is thread model, which must return one of the values in the table below.  For more information on thread models, see “THREADS” in nbdkit-plugin(3).  If this optional function is not provided, the thread model defaults to THREAD_MODEL_PARALLEL.  Note that because of the garbage collector lock in OCaml, callbacks are never truly concurrent.

NBDKit.THREAD_MODEL_SERIALIZE_CONNECTIONS

NBDKit.THREAD_MODEL_SERIALIZE_ALL_REQUESTS

NBDKit.THREAD_MODEL_SERIALIZE_REQUESTS

NBDKit.THREAD_MODEL_PARALLEL

Debugging

You can add debugging messages which are printed only when nbdkit is in verbose mode by calling:

 NBDKit.debug fs [...]

This function works like Printf.printf.

OCaml scripts

Using nbdkit-cc-plugin(1) it is possible to write OCaml plugins which are compiled just before use, and so appear to work more like scripts.

Version

OCaml plugins first appeared in nbdkit 1.2.

See Also

NBDKit(3), nbdkit(1), nbdkit-plugin(3), ocamlopt(1).

Authors

Richard W.M. Jones

License

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Referenced By

nbdkit(1), NBDKit(3), nbdkit-cc-plugin(3), nbdkit-plugin(3), nbdkit-release-notes-1.10(1), nbdkit-release-notes-1.8(1).

2021-04-10 nbdkit-1.25.6