19 #include <sys/types.h> 27 static GHashTable *cib_op_callback_table = NULL;
30 ciblib_GCompareFunc(gconstpointer a, gconstpointer b)
42 crm_trace(
"callbacks for %s are not equal: %p < %p",
46 crm_trace(
"callbacks for %s are not equal: %p > %p",
54 cib_client_add_notify_callback(
cib_t * cib,
const char *event,
55 void (*callback) (
const char *event,
58 GList *list_item = NULL;
62 return -EPROTONOSUPPORT;
65 crm_trace(
"Adding callback for %s events (%d)",
69 new_client->
event = event;
72 list_item = g_list_find_custom(cib->
notify_list, new_client,
75 if (list_item != NULL) {
76 crm_warn(
"Callback already present");
91 get_notify_list_event_count(
cib_t *cib,
const char *event)
95 for (GList *iter = g_list_first(cib->
notify_list); iter != NULL;
99 if (strcmp(client->
event, event) == 0) {
103 crm_trace(
"event(%s) count : %d", event, count);
108 cib_client_del_notify_callback(
cib_t *cib,
const char *event,
109 void (*callback) (
const char *event,
112 GList *list_item = NULL;
116 return -EPROTONOSUPPORT;
119 if (get_notify_list_event_count(cib, event) == 0) {
120 crm_debug(
"The callback of the event does not exist(%s)", event);
124 crm_debug(
"Removing callback for %s events", event);
127 new_client->
event = event;
130 list_item = g_list_find_custom(cib->
notify_list, new_client, ciblib_GCompareFunc);
132 if (list_item != NULL) {
144 if (get_notify_list_event_count(cib, event) == 0) {
154 cib_async_timeout_handler(gpointer
data)
158 crm_debug(
"Async call %d timed out after %ds",
163 return G_SOURCE_CONTINUE;
168 gboolean only_success,
void *user_data,
169 const char *callback_name,
170 void (*callback)(xmlNode *,
int,
int,
172 void (*free_func)(
void *))
177 if (only_success == FALSE) {
182 if (user_data && free_func) {
183 free_func(user_data);
189 blob->
id = callback_name;
199 blob->
timer = async_timer;
205 cib_async_timeout_handler,
210 pcmk__intkey_table_insert(cib_op_callback_table,
call_id, blob);
217 gboolean only_success,
void *user_data,
218 const char *callback_name,
219 void (*callback) (xmlNode *,
int,
int, xmlNode *,
223 only_success, user_data,
224 callback_name, callback, NULL);
228 cib_client_noop(
cib_t *
cib,
int call_options)
235 cib_client_ping(
cib_t *
cib, xmlNode ** output_data,
int call_options)
242 cib_client_query(
cib_t *
cib,
const char *section, xmlNode ** output_data,
int call_options)
248 cib_client_query_from(
cib_t *
cib,
const char *
host,
const char *section,
249 xmlNode ** output_data,
int call_options)
252 output_data, call_options,
cib->
user);
256 set_secondary(
cib_t *
cib,
int call_options)
259 NULL, call_options,
cib->
user);
263 set_primary(
cib_t *
cib,
int call_options)
266 NULL, call_options,
cib->
user);
270 cib_client_bump_epoch(
cib_t *
cib,
int call_options)
277 cib_client_upgrade(
cib_t *
cib,
int call_options)
280 NULL, call_options,
cib->
user);
284 cib_client_sync(
cib_t *
cib,
const char *section,
int call_options)
290 cib_client_sync_from(
cib_t *
cib,
const char *
host,
const char *section,
int call_options)
293 NULL, NULL, call_options,
cib->
user);
297 cib_client_create(
cib_t *
cib,
const char *section, xmlNode *
data,
int call_options)
300 NULL, call_options,
cib->
user);
304 cib_client_modify(
cib_t *
cib,
const char *section, xmlNode *
data,
int call_options)
307 NULL, call_options,
cib->
user);
311 cib_client_replace(
cib_t *
cib,
const char *section, xmlNode *
data,
int call_options)
314 NULL, call_options,
cib->
user);
318 cib_client_delete(
cib_t *
cib,
const char *section, xmlNode *
data,
int call_options)
321 NULL, call_options,
cib->
user);
325 cib_client_erase(
cib_t *
cib, xmlNode ** output_data,
int call_options)
328 output_data, call_options,
cib->
user);
332 cib_client_init_transaction(
cib_t *
cib)
350 const char *client_id = NULL;
353 crm_err(
"Failed to initialize CIB transaction for client %s: %s",
360 cib_client_end_transaction(
cib_t *
cib,
bool commit,
int call_options)
362 const char *client_id = NULL;
370 client_id = pcmk__s(client_id,
"(unidentified)");
376 crm_err(
"Failed to commit transaction for CIB client %s: %s",
386 crm_trace(
"Discarded transaction for CIB client %s", client_id);
388 crm_trace(
"No transaction found for CIB client %s", client_id);
397 cib_client_fetch_schemas(
cib_t *
cib, xmlNode **output_data,
const char *after_ver,
406 output_data, call_options, NULL);
412 cib_client_set_user(
cib_t *
cib,
const char *user)
418 cib_destroy_op_callback(gpointer
data)
435 destroy_op_callback_table(
void)
437 if (cib_op_callback_table != NULL) {
438 g_hash_table_destroy(cib_op_callback_table);
439 cib_op_callback_table = NULL;
446 char *cib_home = NULL;
447 char *fullname = NULL;
449 const char *dir = getenv(
"CIB_shadow_dir");
452 uid_t uid = geteuid();
453 struct passwd *pwent = getpwuid(uid);
454 const char *user = NULL;
457 user = pwent->pw_name;
459 user = getenv(
"USER");
461 "Assuming %s because cannot get user details for user ID %d",
462 (user? user :
"unprivileged user"), uid);
469 const char *home = NULL;
471 if ((home = getenv(
"HOME")) == NULL) {
473 home = pwent->pw_dir;
478 if (home && home[0] ==
'/') {
483 rc = mkdir(cib_home, 0700);
484 if (rc < 0 && errno != EEXIST) {
485 crm_perror(LOG_ERR,
"Couldn't create user-specific shadow directory: %s",
506 cib_t *new_cib = NULL;
507 char *shadow_file = NULL;
533 const char *shadow = getenv(
"CIB_shadow");
536 unsetenv(
"CIB_shadow");
539 if (shadow != NULL) {
540 setenv(
"CIB_shadow", shadow, 1);
564 const char *value = getenv(
"CIB_shadow");
565 const char *server = NULL;
566 const char *user = NULL;
567 const char *pass = NULL;
568 gboolean encrypted = TRUE;
571 if (!pcmk__str_empty(value)) {
575 value = getenv(
"CIB_file");
576 if (!pcmk__str_empty(value)) {
580 value = getenv(
"CIB_port");
581 if (pcmk__str_empty(value)) {
595 server = getenv(
"CIB_server");
596 user = getenv(
"CIB_user");
597 pass = getenv(
"CIB_passwd");
599 if (pcmk__str_empty(user)) {
603 if (pcmk__str_empty(server)) {
604 server =
"localhost";
607 crm_debug(
"Initializing %s remote CIB access to %s:%d as user %s",
608 (encrypted?
"encrypted" :
"plain-text"), server, port, user);
624 cib_t *new_cib = NULL;
626 new_cib = calloc(1,
sizeof(
cib_t));
628 if (new_cib == NULL) {
645 if (new_cib->
cmds == NULL) {
655 new_cib->
cmds->
noop = cib_client_noop;
656 new_cib->
cmds->
ping = cib_client_ping;
658 new_cib->
cmds->
sync = cib_client_sync;
692 while (list != NULL) {
695 list = g_list_remove(list, client);
712 destroy_op_callback_table();
733 destroy_op_callback_table();
734 cib_op_callback_table = pcmk__intkey_table(cib_destroy_op_callback);
736 pcmk__intkey_table_remove(cib_op_callback_table, call_id);
743 if (cib_op_callback_table == NULL) {
746 return g_hash_table_size(cib_op_callback_table);
750 cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data)
752 int call = GPOINTER_TO_INT(key);
755 crm_debug(
"Call %d (%s): pending", call, pcmk__s(blob->
id,
"without ID"));
761 if (cib_op_callback_table == NULL) {
764 return g_hash_table_foreach(cib_op_callback_table, cib_dump_pending_op, NULL);
770 return pcmk__intkey_table_lookup(cib_op_callback_table, call_id);
#define CRM_CHECK(expr, failure_action)
const char * pcmk_strerror(int rc)
gboolean(* register_callback)(cib_t *cib, int call_id, int timeout, gboolean only_success, void *user_data, const char *callback_name, void(*callback)(xmlNode *, int, int, xmlNode *, void *))
cib_t * cib_remote_new(const char *server, const char *user, const char *passwd, int port, gboolean encrypted)
int pcmk_rc2legacy(int rc)
#define PCMK__CIB_REQUEST_PRIMARY
void cib_dump_pending_callbacks(void)
#define PCMK__CIB_REQUEST_CREATE
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
gboolean(* register_callback_full)(cib_t *cib, int call_id, int timeout, gboolean only_success, void *user_data, const char *callback_name, void(*callback)(xmlNode *, int, int, xmlNode *, void *), void(*free_func)(void *))
void(* callback)(const char *event, xmlNode *msg)
#define PCMK__CIB_REQUEST_QUERY
#define PCMK__CIB_REQUEST_COMMIT_TRANSACT
void cib_free_callbacks(cib_t *cib)
Free all callbacks for a CIB connection.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
int(* fetch_schemas)(cib_t *cib, xmlNode **output_data, const char *after_ver, int call_options)
cib_t * cib_new(void)
Create a new CIB connection object.
cib_t * cib_shadow_new(const char *shadow)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
int(* set_secondary)(cib_t *cib, int call_options)
Set the local CIB manager as a secondary instance.
#define PCMK__CIB_REQUEST_ERASE
int(* sync)(cib_t *cib, const char *section, int call_options)
void pcmk__xml_free(xmlNode *xml)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
#define crm_warn(fmt, args...)
struct timer_rec_s * timer
int(* query_from)(cib_t *cib, const char *host, const char *section, xmlNode **output_data, int call_options)
int pcmk__scan_port(const char *text, int *port)
cib_api_operations_t * cmds
#define crm_debug(fmt, args...)
int num_cib_op_callbacks(void)
guint pcmk__create_timer(guint interval_ms, GSourceFunc fn, gpointer data)
void(* callback)(xmlNode *, int, int, xmlNode *, void *)
#define crm_trace(fmt, args...)
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
char * get_shadow_file(const char *suffix)
int(* create)(cib_t *cib, const char *section, xmlNode *data, int call_options)
void pcmk__str_update(char **str, const char *value)
Wrappers for and extensions to libxml2.
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
cib_t * cib_new_no_shadow(void)
Create a new CIB connection object, ignoring any active shadow CIB.
cib_t * cib_native_new(void)
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
int(* add_notify_callback)(cib_t *cib, const char *event, void(*callback)(const char *event, xmlNode *msg))
int(* sync_from)(cib_t *cib, const char *host, const char *section, int call_options)
int(* register_notification)(cib_t *cib, const char *callback, int enabled)
int(* ping)(cib_t *cib, xmlNode **output_data, int call_options)
#define PCMK__CIB_REQUEST_UPGRADE
cib_t * cib_file_new(const char *filename)
cib_callback_client_t * cib__lookup_id(int call_id)
#define PCMK__CIB_REQUEST_BUMP
int(* set_primary)(cib_t *cib, int call_options)
Set the local CIB manager as the cluster's primary instance.
int(* noop)(cib_t *cib, int call_options)
const char * pcmk__get_tmpdir(void)
int(* end_transaction)(cib_t *cib, bool commit, int call_options)
End and optionally commit this client's CIB transaction.
int(* del_notify_callback)(cib_t *cib, const char *event, void(*callback)(const char *event, xmlNode *msg))
#define PCMK__CIB_REQUEST_SCHEMAS
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
void cib_free_notify(cib_t *cib)
#define crm_err(fmt, args...)
#define PCMK__CIB_REQUEST_REPLACE
#define PCMK__CIB_REQUEST_SYNC_TO_ALL
#define PCMK__CIB_REQUEST_SECONDARY
#define PCMK__CIB_REQUEST_NOOP
gboolean crm_is_true(const char *s)
void cib_native_callback(cib_t *cib, xmlNode *msg, int call_id, int rc)
void(* set_user)(cib_t *cib, const char *user)
Set the user as whom all CIB requests via methods will be executed.
cib_t * cib_new_variant(void)
int(* bump_epoch)(cib_t *cib, int call_options)
#define PCMK__CIB_REQUEST_MODIFY
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
int cib_internal_op(cib_t *cib, const char *op, const char *host, const char *section, xmlNode *data, xmlNode **output_data, int call_options, const char *user_name)
int(* init_transaction)(cib_t *cib)
Initiate an atomic CIB transaction for this client.
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
#define pcmk__assert_alloc(nmemb, size)
#define PCMK__XE_CIB_TRANSACTION
void(* free_func)(void *)
int(* client_id)(const cib_t *cib, const char **async_id, const char **sync_id)
Get the given CIB connection's unique client identifier(s)
int(* upgrade)(cib_t *cib, int call_options)
int(* erase)(cib_t *cib, xmlNode **output_data, int call_options)
void remove_cib_op_callback(int call_id, gboolean all_callbacks)
#define PCMK__CIB_REQUEST_DELETE
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1