Skip Navigation Links | |
Exit Print View | |
Remote Administration Daemon Developer Guide Oracle Solaris 11.1 Information Library |
Although an API can be constructed manually, using radadrgen to generate the necessary type definitions is much simpler . If requested, radadrgen can also generate stubs for the entry points referenced by the generated types.
All entry points take a pointer to the object instance and a pointer to the internal structure for the method or attribute. The object instance pointer is essential for distinguishing different objects that implement the same interface. The internal structure pointer is theoretically useful for sharing the same implementation across multiple methods or attributes, but isn't used and may be removed.
Additionally, all entry reports return a conerr_t. If the access is successful, they should return ce_ok. If the access fails due to a system error, they should return ce_system. If the access fails due to an expected error which should be noted in the API definition, they should return ce_object. If an expected error occurs and an error payload is defined, it may be set in *error. The caller will unref the error object when it is done with it.
A method entry point has the type meth_invoke_f:
typedef conerr_t (meth_invoke_f)(struct rad_instance *i, struct adr_method *m, adr_data_t **result, adr_data_t **args, int count, adr_data_t **error);
args is an array of count arguments.
Upon successful return, *result should contain the return value of the method, if any.
The entry point for a method named METHOD in interface INTERFACE is named interface_INTERFACE_invoke_METHOD.
An attribute read entry point has the type attr_read_f:
typedef conerr_t (attr_read_f)(struct rad_instance *i, struct adr_attribute *a, adr_data_t **value, adr_data_t **error);
Upon successful return, *value should contain the value of the attribute, if any.
The read entry point for an attribute named ATTR in interface INTERFACE is named interface_INTERFACE_read_ATTR.
An attribute write entry point has the type attr_write_f:
typedef conerr_t (attr_write_f)(struct rad_instance *i, struct adr_attribute *a, adr_data_t *newvalue, adr_data_t **error);
newvalue points to the new value. If the attribute is nullable, newvalue can be NULL.
The write entry point for an attribute named ATTR in interface INTERFACE is named interface_INTERFACE_write_ATTR.
rad explicitly checks the types of all arguments passed to methods and all values written to attributes. Stub implementations can assume that all data provided is of the correct type. Stub implementations are responsible for returning valid data. Returning invalid data results in an undefined behavior.
A flag to determine if code is executing in the main or proxy rad daemon.
The rad container that contains the object instance.
int _rad_init(void *handle); int rad_module_register(void *handle, int version, rad_modinfo_t *modinfo);
A module must provide a _rad_init. This is called by the rad daemon when the module is loaded and is a convenient point for module initialization including registration. Return 0 to indicate that the module successfully initialized.
rad_module_register provides a handle, which is the handle provided to the module in the call to _rad_init. This handle is used by the rad daemon to maintain the private list of loaded modules. The version indicates which version of the rad module interface the module is using. modinfo contains information used to identify the module.
rad_instance_t *instance_create(adr_name_t *name, rad_object_type *type, void *data, void (*)(void *)freef);
instance_create uses the supplied parameters to create a new instance, with name, of an object of type. data is the user data to store with the instance the freef function is a callback which will be called with the user data when the instance is removed. If the function fails, it returns NULL. Otherwise, a valid instance reference is returned. Note that you do not have to call instance_hold on a newly created instance, because the reference count is initialized to 1.
rad_instance_t *instance_hold(rad_instance_t *instance);
instance_hold increments the reference count on instance.
void instance_rele(rad_instance_t *instance);
instance_rele decrements the reference count on instance. If the count reaches 0, then the instance is destroyed.
adr_data_t *instance_getname(rad_instance_t *instance);
instance_getname returns a adr_data_t * containing the name of the instance.
void * instance_getdata(rad_instance_t *instance);
instance_getdata returns the user data (supplied in instance_create) of the instance.
void instance_notify (rad_instance_t *instance, const char *event, long sequence, adr_data_t *data);
instance_notify generates an event on the supplied instance. The seq is supplied in the event as the sequence number and the payload of the event is provided in data.
conerr_t cont_insert(rad_container_t *container, rad_instance_t *instance, long long id); conerr_t cont_insert_singleton(rad_container_t *container, adr_name_t *name, rad_object_t *object);
Create a instance, rad_instance_t, using the supplied name and object and then insert into container. If the operation succeeds, ce_ok is returned.
conerr_t cont_insert_singleton_id(rad_container_t *container, adr_name_t *name, rad_object_t *object, long long id);
As cont_insert_singleton_id but with the ability to specify an id for the created instance. Returns ce_ok on success.
void cont_remove(rad_container_t *container, rad_instance_t *instance);
Remove the instance from the container.
conerr_t cont_register_dynamic(rad_container_t *container, adr_name_t *pattern, rad_dyn_list_t listf, rad_dyn_lookup_t lookupf, void *arg);
Register a dynamic container instance manager. The container defines the container in which the instances will be managed. The pattern defines the name filter for which this instance manager is responsible.
A typical pattern would define the type of the instance which are managed. For example, zpat = adr_name_vcreate (DOMAIN, 1, "type", "Zone") would be responsible for managing all instances with a type of "Zone". listf is a user-supplied function which is invoked when objects with the matching pattern are listed. lookupf is a user-supplied function which is invoked when objects with the matching pattern are looked up. arg is stored and provided in the callback to the user functions.
|
|
|
|
void *rad_zalloc(size_t size); Return a pointer to a zero-allocated block of size bytes. char *rad_strndup(char *string, size_t length); int rad_strccmp(const char * zstring, const char * cstring, size_t length); int rad_openf(const char *format, int oflag, mode_tmode, ...); FILE *rad_fopenf(const char *format, mode_tmode, ...);
|
There is no direct support for transactional processing within a module. If a transactional model is desirable, then it is the responsibility of the module creator to provide the required building blocks, start_transaction, commit, rollback, and other related processes.
Asynchronous methods and progress reporting is achieved using threads and events. The pattern is to return a token from a synchronous method invocation which spawns a thread to do work asynchronously. This worker thread is then responsible for providing notifications to interested parties events.
Example:
An interface has a method which returns a Task object. The method is called installpkg and takes one argument, the name of the package to install.
Task installpkg(string pkgname);
The Task instance returned by the method, contains enough information to identify a task. Prior to invoking installpkg, the client subscribes to a task-update event. The worker thread is responsible for issuing events about the progress of the work. These events contain information about the progress of the task.
In a minimal implementation, the worker thread would issue one event to notify the client that the task was complete and what the outcome of the task was. A more complex implementation would provide multiple events documenting progress and possibly also provide an additional method that a client could invoke to interrogate the server for a progress report.