JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Remote Administration Daemon Developer Guide     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

1.  Introduction

2.  Concepts

3.  Abstract Data Representation

4.  libadr

5.  Client Libraries

6.  Module Development

API Definitions and Implementation

Entry Points and Generated Stubs

Global Variables

Module Registration

Instance Management

Container Interactions

Logging

Using Threads

Synchronization

Subprocesses

Utilities

Locales

Transactional Processing

Asynchronous Methods and Progress Reporting

rad Namespaces

Static Objects

rad Module Linkage

7.  rad Best Practices

A.  rad Binary Protocol

API Definitions and Implementation

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.

Entry Points and Generated Stubs

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.

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.

Global Variables

boolean_t rad_isproxy

A flag to determine if code is executing in the main or proxy rad daemon.

rad_container_t *rad_container

The rad container that contains the object instance.

Module Registration

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.

Instance Management

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.

Container Interactions

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.

Logging

Function
Description
void rad_log(rad_logtype_t type, 
const char * format, ...);
Log a message with type and format to the rad log. If the type is a lower level than the rad logging level, then the message is discarded.
void rad_log_alloc()
Log a memory allocation failure with log level RL_FATAL.
rad_logtype_t rad_get_loglevel()
Return the logging level.

Using Threads

Function
Description
void *rad_thread_arg(rad_thread_t *tp);
Return the arg referenced by the tp.
void rad_thread_ack(rad_thread_t *tp, 
rad_moderr_t error);
This function is intended to be used from a user function previously supplied as an argument to rad_thread_create. It should not be used in any other context.

Acknowledge the thread referenced by tp. This process enables the controlling thread, from which a new thread was created using rad_thread_create, to make progress. The error is used to update the return value from rad_thread_create and should return rm_ok for success.

rad_moderr_t rad_thread_create(rad_threadfp_t fp,
 void *arg);
Create a thread to run fp. This function will not return until the user function (fp) calls rad_thread_ack. arg is stored and passed into fp as a member of the rad_thread_t data. It can be accessed using rad_thread_arg.
rad_moderr_t rad_thread_create_async(
rad_thread_asyncfp_t fp, void *arg);
Create a thread to run fp. arg is stored and passed into fp.

Synchronization

Function
Description
void rad_mutex_init(pthread_mutex_t *mutex);
Initialize a mutex. abort() on failure.
void rad_mutex_enter(pthread_mutex_t *mutex);
Lock a mutex. abort() on failure.
void rad_mutex_exit(pthread_mutex_t *mutex);
Unlock a mutex. abort() on failure.
void rad_cond_init(pthread_cond_t *cond);
Initialize a condition variable, cond. abort(), on failure.

Subprocesses

Function
Description
exec_params_t *rad_exec_params_alloc
Allocate a control structure for executing a subprocess.
void rad_exec_params_free(exec_params_t *params);
Free a subprocess control structure, params.
void rad_exec_params_set_cwd(exec_params_t *params,
const char *cwd);
Set the current working directory, cwd, in a subprocess control structure, params.
void rad_exec_params_set_env(exec_params_t *params,
const char **envp);
Set the environment, envp, in a subprocess control structure, params.
void rad_exec_params_set_loglevel(
exec_params_t *params, rad_logtype_t loglevel);
Set the rad log level, loglevel, in a subprocess control structure, params.
int rad_exec_params_set_stdin(exec_params_t *params,
int fd);
Set the stdin file descriptor, fd, in a subprocess control structure, params.
int rad_exec_params_set_stdout(exec_params_t *params,
int fd);
Set the stdout file descriptor, fd, in a subprocess control structure, params.
int rad_exec_params_set_stderr(exec_params_t *params,
int fd);
Set the stderr file descriptor, fd, in a subprocess control structure, params.
int rad_forkexec(exec_params_t *params,
     const char **argv, exec_result_t *result);
Use the supplied subprocess control structure, params, to fork and execute (execv) the supplied args, argv. If result is not NULL, it is updated with the subprocess pid and file descriptor details.
int rad_forkexec_wait(exec_params_t *params,
     const char **argv, int *status);
Use the supplied subprocess control structure, params, to fork and execute (execv) the supplied args, argv. If status is not NULL, it is updated with the exit status of the subprocess. This function will wait for the subprocess to terminate before returning.
int rad_wait(exec_params_t *params,
     exec_result_t *result, int *status);
Use the supplied subprocess control structure, params, to wait for a previous invocation of rad_forkexe to complete. If result is not NULL, it is updated with the subprocess pid and file descriptor details. If status is not NULL, it is updated with the exit status of the subprocess. This function will wait for the subprocess to terminate before returning.

Utilities

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,
     ...);

Locales

Function
Description
int rad_locale_parse(const char *locale,
     rad_locale_t **rad_locale);
Update rad_locale with locale details based on locale. If locale is NULL, then attempt to retreive a locale based on the locale of the rad connection. Returns 0 on success.
void rad_locale_free(rad_locale_t *rad_locale);
Free a locale, rad_locale, previously obtained with rad_locale_parse.

Transactional Processing

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

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.