Fairly straightforward. A user can supply { "name"; None } or {
"name"; Some "description" } as desired.Signed-off-by: Eric Blake <[email protected]> --- plugins/ocaml/NBDKit.mli | 9 ++++ plugins/ocaml/NBDKit.ml | 17 ++++++++ plugins/ocaml/example.ml | 33 +++++++++----- plugins/ocaml/ocaml.c | 92 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 140 insertions(+), 11 deletions(-) diff --git a/plugins/ocaml/NBDKit.mli b/plugins/ocaml/NBDKit.mli index 3ebbf18f..aaec519c 100644 --- a/plugins/ocaml/NBDKit.mli +++ b/plugins/ocaml/NBDKit.mli @@ -51,6 +51,12 @@ type extent = { } (** The type of the extent list returned by [.extents]. *) +type export = { + name : string; + description : string option; +} +(** The type of the export list returned by [.list_exports]. *) + type thread_model = | THREAD_MODEL_SERIALIZE_CONNECTIONS | THREAD_MODEL_SERIALIZE_ALL_REQUESTS @@ -78,10 +84,13 @@ type 'a plugin = { after_fork : (unit -> unit) option; preconnect : (bool -> unit) option; + list_exports : (bool -> bool -> export list) option; + default_export : (bool -> bool -> string) option; open_connection : (bool -> 'a) option; (* required *) close : ('a -> unit) option; get_size : ('a -> int64) option; (* required *) + export_description : ('a -> string) option; can_cache : ('a -> cache_flag) option; can_extents : ('a -> bool) option; diff --git a/plugins/ocaml/NBDKit.ml b/plugins/ocaml/NBDKit.ml index 9ce3bf3e..1823fc71 100644 --- a/plugins/ocaml/NBDKit.ml +++ b/plugins/ocaml/NBDKit.ml @@ -53,6 +53,11 @@ type extent = { is_zero : bool; } +type export = { + name : string; + description : string option; +} + type 'a plugin = { name : string; longname : string; @@ -73,10 +78,13 @@ type 'a plugin = { after_fork : (unit -> unit) option; preconnect : (bool -> unit) option; + list_exports : (bool -> bool -> export list) option; + default_export : (bool -> bool -> string) option; open_connection : (bool -> 'a) option; close : ('a -> unit) option; get_size : ('a -> int64) option; + export_description : ('a -> string) option; can_cache : ('a -> cache_flag) option; can_extents : ('a -> bool) option; @@ -118,10 +126,13 @@ let default_callbacks = { after_fork = None; preconnect = None; + list_exports = None; + default_export = None; open_connection = None; close = None; get_size = None; + export_description = None; can_cache = None; can_extents = None; @@ -162,10 +173,13 @@ external set_get_ready : (unit -> unit) -> unit = "ocaml_nbdkit_set_get_ready" external set_after_fork : (unit -> unit) -> unit = "ocaml_nbdkit_set_after_fork" external set_preconnect : (bool -> unit) -> unit = "ocaml_nbdkit_set_preconnect" +external set_list_exports : (bool -> bool -> export list) -> unit = "ocaml_nbdkit_set_list_exports" +external set_default_export : (bool -> bool -> string) -> unit = "ocaml_nbdkit_set_default_export" external set_open : (bool -> 'a) -> unit = "ocaml_nbdkit_set_open" external set_close : ('a -> unit) -> unit = "ocaml_nbdkit_set_close" external set_get_size : ('a -> int64) -> unit = "ocaml_nbdkit_set_get_size" +external set_export_description : ('a -> string) -> unit = "ocaml_nbdkit_set_export_description" external set_can_cache : ('a -> cache_flag) -> unit = "ocaml_nbdkit_set_can_cache" external set_can_extents : ('a -> bool) -> unit = "ocaml_nbdkit_set_can_extents" @@ -225,10 +239,13 @@ let register_plugin plugin = may set_after_fork plugin.after_fork; may set_preconnect plugin.preconnect; + may set_list_exports plugin.list_exports; + may set_default_export plugin.default_export; may set_open plugin.open_connection; may set_close plugin.close; may set_get_size plugin.get_size; + may set_export_description plugin.export_description; may set_can_cache plugin.can_cache; may set_can_extents plugin.can_extents; diff --git a/plugins/ocaml/example.ml b/plugins/ocaml/example.ml index 448de8c4..de493bf2 100644 --- a/plugins/ocaml/example.ml +++ b/plugins/ocaml/example.ml @@ -41,6 +41,13 @@ let ocamlexample_config key value = | _ -> failwith (Printf.sprintf "unknown parameter: %s" key) +let ocamlexample_list_exports ro tls : NBDKit.export list = + [ { name = "name1"; description = Some "desc1" }; + { name = "name2"; description = None } ] + +let ocamlexample_default_export ro tls = + "name1" + (* Any type (even unit) can be used as a per-connection handle. * This is just an example. The same value that you return from * your [open_connection] function is passed back as the first @@ -58,6 +65,9 @@ let ocamlexample_open readonly = incr id; { h_id = !id } +let ocamlexample_export_description h = + "some description" + let ocamlexample_get_size h = Int64.of_int (Bytes.length !disk) @@ -80,20 +90,23 @@ let plugin = { (* name, open_connection, get_size and pread are required, * everything else is optional. *) - NBDKit.name = "ocamlexample"; - version = "1.0"; + NBDKit.name = "ocamlexample"; + version = "1.0"; - load = Some ocamlexample_load; - unload = Some ocamlexample_unload; + load = Some ocamlexample_load; + unload = Some ocamlexample_unload; - config = Some ocamlexample_config; + config = Some ocamlexample_config; - open_connection = Some ocamlexample_open; - get_size = Some ocamlexample_get_size; - pread = Some ocamlexample_pread; - pwrite = Some ocamlexample_pwrite; + list_exports = Some ocamlexample_list_exports; + default_export = Some ocamlexample_default_export; + open_connection = Some ocamlexample_open; + export_description = Some ocamlexample_export_description; + get_size = Some ocamlexample_get_size; + pread = Some ocamlexample_pread; + pwrite = Some ocamlexample_pwrite; - thread_model = Some ocamlexample_thread_model; + thread_model = Some ocamlexample_thread_model; } let () = NBDKit.register_plugin plugin diff --git a/plugins/ocaml/ocaml.c b/plugins/ocaml/ocaml.c index d8b61108..8fb73755 100644 --- a/plugins/ocaml/ocaml.c +++ b/plugins/ocaml/ocaml.c @@ -123,10 +123,13 @@ static value get_ready_fn; static value after_fork_fn; static value preconnect_fn; +static value list_exports_fn; +static value default_export_fn; static value open_fn; static value close_fn; static value get_size_fn; +static value export_description_fn; static value can_cache_fn; static value can_extents_fn; @@ -311,6 +314,65 @@ preconnect_wrapper (int readonly) CAMLreturnT (int, 0); } +static int +list_exports_wrapper (int readonly, int is_tls, struct nbdkit_exports *exports) +{ + CAMLparam0 (); + CAMLlocal2 (rv, v); + + caml_leave_blocking_section (); + + rv = caml_callback2_exn (list_exports_fn, Val_bool (readonly), + Val_bool (is_tls)); + if (Is_exception_result (rv)) { + nbdkit_error ("%s", caml_format_exception (Extract_exception (rv))); + caml_enter_blocking_section (); + CAMLreturnT (int, -1); + } + + /* Convert exports list into calls to nbdkit_add_export. */ + while (rv != Val_emptylist) { + const char *name, *desc = NULL; + + v = Field (rv, 0); /* export struct */ + name = String_val (Field (v, 0)); + if (Is_block (Field (v, 1))) + desc = String_val (Field (Field (v, 1), 0)); + if (nbdkit_add_export (exports, name, desc) == -1) { + caml_enter_blocking_section (); + CAMLreturnT (int, -1); + } + + rv = Field (rv, 1); + } + + caml_enter_blocking_section (); + CAMLreturnT (int, 0); +} + +static const char * +default_export_wrapper (int readonly, int is_tls) +{ + const char *name; + CAMLparam0 (); + CAMLlocal1 (rv); + + caml_leave_blocking_section (); + + rv = caml_callback2_exn (default_export_fn, Val_bool (readonly), + Val_bool (is_tls)); + if (Is_exception_result (rv)) { + nbdkit_error ("%s", caml_format_exception (Extract_exception (rv))); + caml_enter_blocking_section (); + CAMLreturnT (const char *, NULL); + } + + name = nbdkit_strdup_intern (String_val (rv)); + + caml_enter_blocking_section (); + CAMLreturnT (const char *, name); +} + static void * open_wrapper (int readonly) { @@ -358,6 +420,28 @@ close_wrapper (void *h) CAMLreturn0; } +static const char * +export_description_wrapper (void *h) +{ + const char *desc; + CAMLparam0 (); + CAMLlocal1 (rv); + + caml_leave_blocking_section (); + + rv = caml_callback_exn (export_description_fn, *(value *) h); + if (Is_exception_result (rv)) { + nbdkit_error ("%s", caml_format_exception (Extract_exception (rv))); + caml_enter_blocking_section (); + CAMLreturnT (const char *, NULL); + } + + desc = nbdkit_strdup_intern (String_val (rv)); + + caml_enter_blocking_section (); + CAMLreturnT (const char *, desc); +} + static int64_t get_size_wrapper (void *h) { @@ -747,7 +831,7 @@ extents_wrapper (void *h, uint32_t count, uint64_t offset, uint32_t flags, } /* Convert extents list into calls to nbdkit_add_extent. */ - while (rv != Val_int (0)) { + while (rv != Val_emptylist) { uint64_t length; uint32_t type = 0; @@ -856,10 +940,13 @@ SET(get_ready) SET(after_fork) SET(preconnect) +SET(list_exports) +SET(default_export) SET(open) SET(close) SET(get_size) +SET(export_description) SET(can_write) SET(can_flush) @@ -900,10 +987,13 @@ remove_roots (void) REMOVE (after_fork); REMOVE (preconnect); + REMOVE (list_exports); + REMOVE (default_export); REMOVE (open); REMOVE (close); REMOVE (get_size); + REMOVE (export_description); REMOVE (can_cache); REMOVE (can_extents); -- 2.28.0 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
