## UDisksModuleManager

UDisksModuleManager — Manages daemon modules

## Functions

gboolean | ( *UDisksObjectHasInterfaceFunc ) ()
void | ( *UDisksObjectConnectInterfaceFunc ) ()
gboolean | ( *UDisksObjectUpdateInterfaceFunc ) ()
GDBusObjectSkeleton * | ( *UDisksModuleObjectNewFunc ) ()
GDBusInterfaceSkeleton * | ( *UDisksModuleNewManagerIfaceFunc ) ()
gpointer | ( *UDisksModuleInitFunc ) ()
UDisksModuleInterfaceInfo ** | ( *UDisksModuleIfaceSetupFunc ) ()
UDisksModuleObjectNewFunc * | ( *UDisksModuleObjectNewSetupFunc ) ()
UDisksModuleNewManagerIfaceFunc * | ( *UDisksModuleNewManagerIfaceSetupFunc ) ()
UDisksModuleManager * | udisks_module_manager_new ()
gboolean | udisks_module_manager_get_modules_available ()
void | udisks_module_manager_load_modules ()
gpointer | udisks_module_manager_get_module_state_pointer ()
void | udisks_module_manager_set_module_state_pointer ()
GList * | udisks_module_manager_get_block_object_iface_infos ()
GList * | udisks_module_manager_get_drive_object_iface_infos ()
GList * | udisks_module_manager_get_module_object_new_funcs ()
GList * | udisks_module_manager_get_new_manager_iface_funcs ()
gboolean | udisks_module_object_process_uevent ()
gboolean | udisks_module_object_housekeeping ()

## Types and Values

| UDisksModuleManager
| UDisksModuleInterfaceInfo
| UDisksModuleObject
struct | UDisksModuleObjectIface

## Description

#### UDisks modular approach

UDisks functionality can be extended by modules. It's not a fully pluggable system as we know it, in this case modules are almost integral parts of the source tree. Meaning that modules are free to use whatever internal objects they need as there is no universal module API (or a translation layer).

This fact allows us to stay code-wise simple and transparent. It also means that there's no support for out-of-the-tree modules and care must be taken when changing UDisks internals. As a design decision, for sake of simplicity, once modules are loaded they stay active until the daemon exits (this may be a subject to change in the future).

The primary motivation for this was to keep the daemon low on resource footprint for basic usage (typically desktop environments) and only activating the extended functionality when needed (e.g. enterprise storage applications). As the extra information comes in form of additional D-Bus objects and interfaces, no difference should be observed by legacy clients.

#### D-Bus interface extensibility

The modular approach is fairly simple, there are basically two primary ways of extending the D-Bus API:

- by attaching custom interfaces to existing objects (limited to block and drive objects for the moment)

- by exporting objects of its own type directly in the object manager root

Besides that there are several other ways of extensibility such as attaching custom interfaces on the master /org/freedesktop/UDisks2/Manager object.

#### Modules activation

The UDisks daemon constructs a UDisksModuleManager singleton acting as a manager. This object tracks module usage and takes care of its activation.

By default, module manager is constructed on daemon startup but module loading is delayed until requested. This can be overriden by the --force-load-modules and --disable-modules commandline switches that makes modules loaded right on startup or never loaded respectively.

Upon successful activation, the "modules-ready" property on the UDisksModuleManager instance is set to `TRUE`. Any daemon objects watching this property are responsible for performing "coldplug" on their exported objects to assure modules would pick up the devices they're interested in. See e.g. `UDisksModuleObjectNewFunc()` to see how device binding works for UDisksModuleObject.

Modules are in fact separate shared objects (.so) that are loaded from the "$(libdir)/udisks2/modules" path (usually "/usr/lib/udisks2/modules"). No extra or service files are needed, the directory is enumerated and all files are attempted to be loaded.

Clients are supposed to call the org.freedesktop.UDisks2.Manager.EnableModules() D-Bus method as a "greeter" call. Please note that from asynchronous nature of uevents and the way modules are processing them the extra D-Bus interfaces may not be available right after this method call returns.

#### Module API

The (strictly internal) module API is simple - only a couple of functions are needed. The following text contains brief description of individual parts of the module API with further links to detailed description within this API reference book.

The UDisksModuleManager first loads all module entry functions, i.e. symbols defined in the public facing header "udisksmoduleiface.h". Only those symbols should be exported from each module. The header file is only meant to be compiled in modules, not the daemon. If any of the symbols is missing in the module library, the whole module is skipped.

Once module symbols are resolved, module manager activates each module by calling `udisks_module_init()` on it. The returned so-called "state" pointer is stored in the UDisksModuleManager and can be later retrieved by calling the `udisks_module_manager_get_module_state_pointer()` method. This is typically used further in the module code to retrieve and store module-specific runtime data.

Every one of the "udisksmoduleiface.h" header file symbols has its counterpart defined in the "udisksmoduleifacetypes.h" header file in form of function pointers. Those are used internally for symbol resolving purposes. However, they also carry detailed documentation. For illustration purposes, let's call these symbol pairs the "module setup entry functions". See UDisksModuleIfaceSetupFunc, UDisksModuleObjectNewSetupFunc and UDisksModuleNewManagerIfaceSetupFunc for reference. These however are essentially auxiliary symbols only described for demonstrating the big picture; for the useful part of the module API please read on.

Every module setup entry function (besides the very simple `udisks_module_init()`) returns an array of setup structures or functions, containing either none (NULL result), one or more elements. The result is then mixed by UDisksModuleManager from all modules and separate lists are created for each kind of UDisks way of extension. Such lists are then used in the daemon code at appropriate places, sequentially calling elements from the lists to obtain data or objects that are then typically exported on D-Bus.

In short, have a look at the UDisksModuleInterfaceInfo, UDisksModuleObjectNewFunc and UDisksModuleNewManagerIfaceFunc definitions to learn more about particular ways of extending UDisks.

## Functions

### UDisksObjectHasInterfaceFunc ()

    gboolean
    (*UDisksObjectHasInterfaceFunc) (UDisksObject *object);

Function prototype that is used to determine whether the `object` is applicable for carrying a particular D-Bus interface (determined by the callback function itself).

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects for checking specific feature that leads to exporting extra D-Bus interface on the object.

#### Parameters

object | A UDisksObject to consider. |

#### Returns

`TRUE` if the `object` is a valid candidate for the particular D-Bus interface, `FALSE` otherwise.

### UDisksObjectConnectInterfaceFunc ()

    void
    (*UDisksObjectConnectInterfaceFunc) (UDisksObject *object);

Function prototype that is used once a new D-Bus interface is created (meaning the UDisksObjectHasInterfaceFunc call was successful) to perform optional additional tasks before the interface is exported on the `object` .

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects.

#### Parameters

object | A UDisksObject to perform connection operation onto. |

### UDisksObjectUpdateInterfaceFunc ()

    gboolean
    (*UDisksObjectUpdateInterfaceFunc) (UDisksObject *object,
                                        const gchar *uevent_action,
                                        GDBusInterface *interface);

Function prototype that is used on existing `interface` on the `object` to process incoming uevents.

Used typically over UDisksLinuxBlockObject and UDisksLinuxDriveObject objects.

#### Parameters

object | A UDisksObject. |
uevent_action | An uevent action string. |
interface | Existing GDBusInterface exported on the `object` . |

#### Returns

`TRUE` if configuration (properties) on the interface have changed, `FALSE` otherwise.

### UDisksModuleObjectNewFunc ()

    GDBusObjectSkeleton *
    (*UDisksModuleObjectNewFunc) (UDisksDaemon *daemon,
                                  UDisksLinuxDevice *device);

Function prototype that creates new GDBusObjectSkeleton instance that implements the UDisksModuleObject interface.

This is an another way of extending UDisks functionality. Objects in this scope are meant to be of virtual kind and are pretty flexible - not necessarily bound to any block device or perhaps representing a group of resources. For illustration this kind of object may represent e.g. a RAID array comprised of several block devices, all devices of the same kind such as loop devices or any higher level representation of something else.

This function may be called quite often, for nearly any uevent received. It's done this way for broad flexibility and to give a chance to UDisksModuleObjectNewFunc functions to claim any device needed.

Every GDBusObjectSkeleton can claim one or more devices and UDisks automatically manages uevent routing and instance lifecycle. A hierarchy of claimed devices is maintained for the combination of particular module and every UDisksModuleObjectNewFunc - see below. This list lives in UDisksLinuxProvider and is strictly internal. Every module can provide multiple UDisksModuleObjectNewFunc functions for different kind of objects.

Two scenarios are distinguished:

1. The `device` is already claimed by existing GDBusObjectSkeleton instance for the current UDisksModuleObjectNewFunc, it is guaranteed that only that instance will receive further uevents for the particular `device` . This is done by calling the `udisks_module_object_process_uevent()` method of the UDisksModuleObject interface. Depending on the returning value the device is either kept claimed by the object or removed. When last claimed device has been removed from the instance, it is automatically destroyed. In either case no further processing is done at this cycle to prevent creating new bogus instances for a `device` that has just given up.

2. In case the `device` is not claimed by any existing GDBusObjectSkeleton instance for the current UDisksModuleObjectNewFunc. It now all depends on the return value of the function called. If it returns a new GDBusObjectSkeleton instance, it also indicates to UDisksLinuxProvider that it claims the device. The UDisksLinuxProvider then registers the value with the current function and keeps track of it. If it returns `NULL`, it inidcates that the current function is not interested in this kind of device.

It's guaranteed that existing GDBusObjectSkeleton instances will receive uevents for devices they took and creating a new instance will take place only if the event was not processed by any of them.

#### Parameters

daemon | A UDisksDaemon instance. |
device | A UDisksLinuxDevice device object. |

#### Returns

A new GDBusObjectSkeleton or `NULL` when the module doesn't handle the device specified. Free with `g_object_unref()`.

### UDisksModuleNewManagerIfaceFunc ()

    GDBusInterfaceSkeleton *
    (*UDisksModuleNewManagerIfaceFunc) (UDisksDaemon *daemon);

Function prototype that creates new GDBusInterfaceSkeleton instance carrying an additional D-Bus interface to be exported on the UDisks manager object (on the "/org/freedesktop/UDisks2/Manager" path). It is a fairly simple stateless object not related to any device and serves the purpose of performing general tasks or creating new resources.

#### Parameters

daemon | A UDisksDaemon instance. |

#### Returns

A new GDBusInterfaceSkeleton. Free with `g_object_unref()`.

### UDisksModuleInitFunc ()

    gpointer
    (*UDisksModuleInitFunc) (UDisksDaemon *daemon);

Function prototype that is called upon module initialization. Its purpose is to perform internal initialization and allocate memory that is then used e.g. for saving state. See the `udisks_module_manager_get_module_state_pointer()` method for how to work with state pointers.

Corresponds with the `udisks_module_init()` module symbol. Used internally by UDisksModuleManager.

#### Parameters

daemon | A UDisksDaemon instance. |

#### Returns

Pointer to an opaque memory or `NULL` when module doesn't need to save its state.

### UDisksModuleIfaceSetupFunc ()

    UDisksModuleInterfaceInfo **
    (*UDisksModuleIfaceSetupFunc) (void);

Type declaration of a module setup entry function.

Corresponds with the `udisks_module_get_block_object_iface_setup_entries()` and `udisks_module_get_drive_object_iface_setup_entries()` module symbols. Used internally by UDisksModuleManager.

#### Returns

An array of pointers to the UDisksModuleInterfaceInfo structs. Free with `g_free()`.

### UDisksModuleObjectNewSetupFunc ()

    UDisksModuleObjectNewFunc *
    (*UDisksModuleObjectNewSetupFunc) (void);

Type declaration of a module setup entry function.

Corresponds with the `udisks_module_get_object_new_funcs()` module symbol. Used internally by UDisksModuleManager.

#### Returns

An array of pointers to the UDisksModuleObjectNewFunc functions. Free with `g_free()`.

### UDisksModuleNewManagerIfaceSetupFunc ()

    UDisksModuleNewManagerIfaceFunc *
    (*UDisksModuleNewManagerIfaceSetupFunc)
                                   (void);

Type declaration of a module setup entry function.

Corresponds with the `udisks_module_get_new_manager_iface_funcs()` module symbol. Used internally by UDisksModuleManager.

#### Returns

An array of pointers to the UDisksModuleNewManagerIfaceFunc functions. Free with `g_free()`.

### udisks_module_manager_new ()

    UDisksModuleManager *
    udisks_module_manager_new (UDisksDaemon *daemon);

Creates a new UDisksModuleManager object.

#### Parameters

daemon | A UDisksDaemon instance. |

#### Returns

A UDisksModuleManager. Free with `g_object_unref()`.

### udisks_module_manager_get_modules_available ()

    gboolean
    udisks_module_manager_get_modules_available
                                   (UDisksModuleManager *manager);

Indicates whether modules have been loaded.

#### Parameters

manager | A UDisksModuleManager instance. |

#### Returns

`TRUE` if modules have been loaded, `FALSE` otherwise.

### udisks_module_manager_load_modules ()

    void
    udisks_module_manager_load_modules (UDisksModuleManager *manager);

Loads all modules at a time and emits the "modules-ready" signal. Does nothing when called multiple times.

#### Parameters

manager | A UDisksModuleManager instance. |

### udisks_module_manager_get_module_state_pointer ()

    gpointer
    udisks_module_manager_get_module_state_pointer
                                   (UDisksModuleManager *manager,
                                    const gchar *module_name);

Retrieves the stored module state pointer for the given `module_name` .

#### Parameters

manager | A UDisksModuleManager instance. |
module_name | A module name. |

#### Returns

A stored pointer to the private data or `NULL` if there is no state pointer for the given `module_name` .

### udisks_module_manager_set_module_state_pointer ()

    void
    udisks_module_manager_set_module_state_pointer
                                   (UDisksModuleManager *manager,
                                    const gchar *module_name,
                                    gpointer state);

Stores the `state` pointer for the given `module_name` .

#### Parameters

manager | A UDisksModuleManager instance. |
module_name | A module name. |
state | Pointer to a private data. |

### udisks_module_manager_get_block_object_iface_infos ()

    GList *
    udisks_module_manager_get_block_object_iface_infos
                                   (UDisksModuleManager *manager);

Returns a list of block object interface info structs that can be plugged in UDisksLinuxBlockObject instances. See UDisksModuleIfaceSetupFunc for details.

#### Parameters

manager | A UDisksModuleManager instance. |

#### Returns

A list of UDisksModuleIfaceSetupFunc structs that belongs to the manager and must not be freed.

[element-type UDisksModuleIfaceSetupFunc][transfer full]

### udisks_module_manager_get_drive_object_iface_infos ()

    GList *
    udisks_module_manager_get_drive_object_iface_infos
                                   (UDisksModuleManager *manager);

Returns a list of drive object interface info structs that can be plugged in UDisksLinuxDriveObject instances. See UDisksModuleIfaceSetupFunc for details.

#### Parameters

manager | A UDisksModuleManager instance. |

#### Returns

A list of UDisksModuleIfaceSetupFunc structs that belongs to the manager and must not be freed.

[element-type UDisksModuleIfaceSetupFunc][transfer full]

### udisks_module_manager_get_module_object_new_funcs ()

    GList *
    udisks_module_manager_get_module_object_new_funcs
                                   (UDisksModuleManager *manager);

Returns a list of all module object new functions. See UDisksModuleObjectNewFunc for details.

#### Parameters

manager | A UDisksModuleManager instance. |

#### Returns

A list of UDisksModuleObjectNewFunc function pointers that belongs to the manager and must not be freed.

[element-type UDisksModuleObjectNewFunc][transfer full]

### udisks_module_manager_get_new_manager_iface_funcs ()

    GList *
    udisks_module_manager_get_new_manager_iface_funcs
                                   (UDisksModuleManager *manager);

Returns a list of all module new manager interface functions. See UDisksModuleNewManagerIfaceFunc for details.

#### Parameters

manager | A UDisksModuleManager instance. |

#### Returns

A list of UDisksModuleNewManagerIfaceFunc function pointers that belongs to the manager and must not be freed.

[element-type UDisksModuleNewManagerIfaceFunc][transfer full]

### udisks_module_object_process_uevent ()

    gboolean
    udisks_module_object_process_uevent (UDisksModuleObject *object,
                                         const gchar *action,
                                         UDisksLinuxDevice *device);

Virtual method that processes the uevent and updates all information on interfaces on `object` .

See UDisksModuleObjectNewFunc for detailed information on how to work with the events.

#### Parameters

object | A UDisksModuleObject. |
action | Uevent action, common values are "add", "changed" and "removed" or `NULL` |
device | A UDisksLinuxDevice device object or `NULL` if the device hasn't changed. |

#### Returns

`FALSE` if the object should be unexported and removed, `TRUE` if the object has processed the information successfully and should be kept around.

### udisks_module_object_housekeeping ()

    gboolean
    udisks_module_object_housekeeping (UDisksModuleObject *object,
                                       guint secs_since_last,
                                       GCancellable *cancellable,
                                       GError **error);

Virtual method that is called periodically (every ten minutes or so) to perform housekeeping tasks such as refreshing ATA SMART data.

The function runs in a dedicated thread and is allowed to perform blocking I/O.

Long-running tasks should periodically check `cancellable` to see if they have been cancelled.

#### Parameters

object | A UDisksModuleObject. |
secs_since_last | Number of seconds since the last housekeeping or 0 if the first housekeeping ever. |
cancellable | A `GCancellable` or `NULL`. |
error | Return location for error or `NULL`. |

#### Returns

`TRUE` if the operation succeeded, `FALSE` if `error` is set.

## Types and Values

### UDisksModuleManager

    typedef struct _UDisksModuleManager UDisksModuleManager;

The UDisksModuleManager structure contains only private data and should only be accessed using the provided API.

### UDisksModuleInterfaceInfo

    typedef struct {
      UDisksObjectHasInterfaceFunc has_func;
      UDisksObjectConnectInterfaceFunc connect_func;
      UDisksObjectUpdateInterfaceFunc update_func;
      GType skeleton_type;
    } UDisksModuleInterfaceInfo;

Structure containing interface setup functions used by modules for exporting custom interfaces on existing block and drive objects.

Event processing is solely done by UDisksLinuxBlockObject and UDisksLinuxDriveObject themselves whose call the `has_func` , `connect_func` and `update_func` respectively as needed. Purpose of these member functions is to check whether the particular UDisksModuleInterfaceInfo record is applicable to the current device and construct a new GDBusInterface if so.

See UDisksObjectHasInterfaceFunc, UDisksObjectConnectInterfaceFunc and UDisksObjectUpdateInterfaceFunc for detailed description and return values.

#### Members

UDisksObjectHasInterfaceFunc `has_func`; | A UDisksObjectHasInterfaceFunc |
UDisksObjectConnectInterfaceFunc `connect_func`; | A UDisksObjectConnectInterfaceFunc |
UDisksObjectUpdateInterfaceFunc `update_func`; | A UDisksObjectUpdateInterfaceFunc |
GType `skeleton_type`; | A GType of the instance that is created once `has_func` succeeds. |

### UDisksModuleObject

    typedef struct _UDisksModuleObject UDisksModuleObject;

The UDisksModuleObject structure contains only private data and should only be accessed using the provided API.

### struct UDisksModuleObjectIface

    struct UDisksModuleObjectIface {
      GTypeInterface parent_iface;

      gboolean (*process_uevent) (UDisksModuleObject  *object,
                                  const gchar         *action,
                                  UDisksLinuxDevice   *device);

      gboolean (*housekeeping) (UDisksModuleObject  *object,
                                guint                secs_since_last,
                                GCancellable        *cancellable,
                                GError             **error);
    };