Steven Dake bb42020f9a Use qb_hdb instead of mutex based hdb code 14 yıl önce
..
.gitignore f0104b6d31 Add .gitignore files. 15 yıl önce
Makefile.am bb42020f9a Use qb_hdb instead of mutex based hdb code 14 yıl önce
README.lcr 904a10ed38 remove all trailing blanks 17 yıl önce
lcr_ifact.c 37e17e7a94 libqb: logging & trace 14 yıl önce
libtest_a.c d86737ac9c remove empty lines at end-of-file 17 yıl önce
libtest_b.c 904a10ed38 remove all trailing blanks 17 yıl önce
test.c 904a10ed38 remove all trailing blanks 17 yıl önce
uic.c 1f40a10983 don't include <signal.h> when it's not used 16 yıl önce
uis.c 00434a4f10 Fix usage of strerror_r()/perror() 14 yıl önce

README.lcr

Live Component Replacement
--------------------------
All software is composed of components, which contain multiple software classes.
Components generally depend upon other components and sometimes classes from
other components.

Some components of corosync are the evt service, the ckpt service, the clm
service, the totem protocol, and others. If a defect is found in any of
these components, the entire ais executive must be stopped, replaced, and
restarted.

The lcr code formalizes the concept of components into dynamic libraries. A
component may have multiple classes. Each class (the lcr code uses the word
interface) may have multiple functions within the class. Each interface may
depend upon other interfaces, and those interfaces are then loaded prior to the
requested interface being referenced.

Note that with recent changes, the lcr interface factory can be used when
statically linking without additional steps. The interface for notifying
lcr of a component has changed.

A list of shared objects is scanned each time an interface is requested to
load via the following interface:

int lcr_ifact_reference (
void **handle,
char *iface_name,
int version,
void **interface,
void *context);

The iface_name is the name of the interface, the version is the version,
the void **interface is the list of functions returned once the interface
has been dynamically loaded and referenced, and context is passed to the
constructor and destructor.

The interface is loaded, the interface constructor is called, and the list
of interfaces is returned back to the caller.

First the list of interfaces is described in an iface_list data structure:
struct iface_list iface_list = {
.iface1_func1 = iface1_func1,
.iface1_func2 = iface1_func2,
.iface1_func3 = iface1_func3,
};
iface1_func1 is a simple function call.

Then the lcr_iface data structure is defined for the c file:

struct lcr_iface iface1_ver0 = {
.name = "iface1",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_constructor,
.destructor = iface1_destructor,
.interfaces = (void **)&iface_list,
};

The name and version fields provide naming and versioning. The constructor
and destructor functions execute at reference and release times. Finally
the .interfaces type describes the list of functions used for the interface.

Next, an lcr_comp must be described:

struct lcr_comp test_comp = {
.iface_count = 2,
.ifaces = lcr_ifaces
};

the iface count describes the number of interfaces within the component,
and lcr_ifaces is an array of pointers to lcr_iface data types.

The lcr_comp_get method has been replaced. The final step is to setup a
constructor that is started when the task is started. This ctor will
register the component with the lcr framework.

static void register_this_component (void) {
lcr_component_register (&test_comp);
}

static void (*const __init_this_component[1]) (void) __attribute__ ((section(".ctors"))) = { register_this_component };


Now the component can be referenced and used in another application.
int main ()
{

.....

lcr_ifact_reference (
&ifact_handle_ver0,
"iface1",
0, /* version 0 */
(void **)&iface_ver0,
(void *)0xdeadbeef);

iface_ver0->func1();
iface_ver0->func2();
iface_ver0->func3();
}


See libtest_a and libtest_b for two sample components. The test program
demonstrates usage. The test_static demonstrates operation when statically
linked. Note the dynamic inteface factory is still available for use when
statically linking components.

On startup, a thread is created which listens for requests from the "uic"
application. These requests are then processed by the lcr service which
would execute a live replacement.