Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b806477
Doc: based, libcrmcluster: Drop gpointer from include comments
nrwahl2 Jul 6, 2026
13dbe8b
Feature: libcrmcommon: Drop support for PCMK_ipc_type env variable
nrwahl2 Jan 7, 2026
941f397
Refactor: libcrmcommon: Use QB_IPC_SHM in pcmk__serve_DAEMON_ipc()
nrwahl2 Jan 8, 2026
dda959f
Feature: libcrmcommon: mainloop_add_ipc_server{,_with_prio} ignore type
nrwahl2 Jan 8, 2026
9e6f028
API: libcib: Deprecate cib_command_nonblocking
nrwahl2 Jan 11, 2026
d206be5
Refactor: various: Drop PCMK__SERVER_BASED_SHM
nrwahl2 Jan 11, 2026
b3c1bc2
Refactor: libcrmcommon: Drop pcmk__stop_based_ipc()
nrwahl2 Jan 11, 2026
f4c3b9d
Refactor: libcrmcommon: Assert for arguments in pcmk__serve_DAEMON_ipc()
nrwahl2 Jan 11, 2026
891a7f5
Refactor: based: New based_{callbacks,io}_cleanup()
nrwahl2 Jan 8, 2026
2efa004
Refactor: based: Move based_terminate() to pacemaker-based.c
nrwahl2 Jan 8, 2026
5e6bb01
Refactor: based: New based_cleanup()
nrwahl2 Jan 8, 2026
b1e23ca
Refactor: based: Assume main loop is running in based_terminate()
nrwahl2 Jan 8, 2026
8c90b73
Doc: based: Add notes to based_terminate()
nrwahl2 Jan 8, 2026
0674c2c
Refactor: based: Set shutting_down to true in based_terminate()
nrwahl2 Jan 8, 2026
d95a597
Low: based: Fix memory leak in remote listeners
nrwahl2 Jan 9, 2026
c58ff59
Refactor: libcrmcommon: Expose struct mainloop_io_s internally
nrwahl2 Jan 9, 2026
c1baa15
Low: based: Destroy remote listeners in based_remote_cleanup()
nrwahl2 Jan 9, 2026
098641f
Refactor: libcrmcommon: Free mainloop child list at exit
nrwahl2 Jan 10, 2026
551ae76
Refactor: libcrmcommon: Drop callback_needed variable
nrwahl2 Jan 10, 2026
6a03bf5
Refactor: libcrmcommon: child_kill_helper() returns standard code
nrwahl2 Jan 10, 2026
f7019de
Refactor: libcrmcommon: Track mainloop children in a hash table
nrwahl2 Jan 10, 2026
552e2ce
Refactor: based: Add missing include to pacemaker-based.c
nrwahl2 Jan 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 80 additions & 93 deletions daemons/based/based_callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <crm/common/ipc.h> // crm_ipc_*, pcmk_ipc_*
#include <crm/common/logging.h> // CRM_LOG_ASSERT, CRM_CHECK
#include <crm/common/mainloop.h> // mainloop_*
#include <crm/common/results.h> // CRM_EX_OK, crm_exit_t, pcmk_rc_*
#include <crm/common/results.h> // pcmk_rc_*
#include <crm/common/xml.h> // PCMK_XA_*, PCMK_XE_*
#include <crm/crm.h> // CRM_OP_*

Expand All @@ -39,6 +39,85 @@ static long long ping_seq = 0;
static char *ping_digest = NULL;
static bool ping_modified_since = false;

/*!
* \internal
* \brief Request CIB digests from all peer nodes
*
* This is used as a callback that runs 5 seconds after we modify the CIB on the
* DC. It sends a ping request to all cluster nodes. They will respond by
* sending their current digests and version info, which we will validate in
* process_ping_reply(). If their digest doesn't match, we'll sync our own CIB
* to them. This helps ensure consistency across the cluster after a CIB update.
*
* \param[in] data Ignored
*
* \return \c G_SOURCE_REMOVE (to destroy the timeout)
*
* \note It's not clear why we wait 5 seconds rather than sending the ping
* request immediately after a performing a modifying op. Perhaps it's to
* avoid overwhelming other nodes with ping requests when there are a lot
* of modifying requests in a short period. The timer restarts after
* every successful modifying op, so we send ping requests **at most**
* every 5 seconds. Or perhaps it's a remnant of legacy mode (pre-1.1.12).
* In any case, the other nodes shouldn't need time to process the
* modifying op before responding to the ping request. The ping request is
* sent after the op is sent, so it should also be received after the op
* is received.
*/
static gboolean
digest_timer_cb(void *data)
{
xmlNode *ping = NULL;

if (!based_get_local_node_dc()) {
// Only the DC sends a ping
return G_SOURCE_REMOVE;
}

if (++ping_seq < 0) {
ping_seq = 0;
}

g_clear_pointer(&ping_digest, free);
ping_modified_since = false;

ping = pcmk__xe_create(NULL, PCMK__XE_PING);
pcmk__xe_set(ping, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(ping, PCMK__XA_CIB_OP, CRM_OP_PING);
pcmk__xe_set_ll(ping, PCMK__XA_CIB_PING_ID, ping_seq);
pcmk__xe_set(ping, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET);

pcmk__trace("Requesting peer digests (%lld)", ping_seq);
pcmk__cluster_send_message(NULL, pcmk_ipc_based, ping);

pcmk__xml_free(ping);
return G_SOURCE_REMOVE;
}

/*!
* \internal
* \brief Initialize data structures used for CIB manager callbacks
*/
void
based_callbacks_init(void)
{
if (digest_timer == NULL) {
digest_timer = mainloop_timer_add("based_digest_timer", 5000, false,
digest_timer_cb, NULL);
}
}

/*!
* \internal
* \brief Free data structures used for CIB manager callbacks
*/
void
based_callbacks_cleanup(void)
{
g_clear_pointer(&digest_timer, mainloop_timer_del);
g_clear_pointer(&ping_digest, free);
}

/*!
* \internal
* \brief Create reply XML for a CIB request
Expand Down Expand Up @@ -148,61 +227,6 @@ do_local_notify(const xmlNode *xml, const char *client_id, bool sync_reply,
}
}

/*!
* \internal
* \brief Request CIB digests from all peer nodes
*
* This is used as a callback that runs 5 seconds after we modify the CIB on the
* DC. It sends a ping request to all cluster nodes. They will respond by
* sending their current digests and version info, which we will validate in
* process_ping_reply(). If their digest doesn't match, we'll sync our own CIB
* to them. This helps ensure consistency across the cluster after a CIB update.
*
* \param[in] data Ignored
*
* \return \c G_SOURCE_REMOVE (to destroy the timeout)
*
* \note It's not clear why we wait 5 seconds rather than sending the ping
* request immediately after a performing a modifying op. Perhaps it's to
* avoid overwhelming other nodes with ping requests when there are a lot
* of modifying requests in a short period. The timer restarts after
* every successful modifying op, so we send ping requests **at most**
* every 5 seconds. Or perhaps it's a remnant of legacy mode (pre-1.1.12).
* In any case, the other nodes shouldn't need time to process the
* modifying op before responding to the ping request. The ping request is
* sent after the op is sent, so it should also be received after the op
* is received.
*/
static gboolean
digest_timer_cb(void *data)
{
xmlNode *ping = NULL;

if (!based_get_local_node_dc()) {
// Only the DC sends a ping
return G_SOURCE_REMOVE;
}

if (++ping_seq < 0) {
ping_seq = 0;
}

g_clear_pointer(&ping_digest, free);
ping_modified_since = false;

ping = pcmk__xe_create(NULL, PCMK__XE_PING);
pcmk__xe_set(ping, PCMK__XA_T, PCMK__VALUE_CIB);
pcmk__xe_set(ping, PCMK__XA_CIB_OP, CRM_OP_PING);
pcmk__xe_set_ll(ping, PCMK__XA_CIB_PING_ID, ping_seq);
pcmk__xe_set(ping, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET);

pcmk__trace("Requesting peer digests (%lld)", ping_seq);
pcmk__cluster_send_message(NULL, pcmk_ipc_based, ping);

pcmk__xml_free(ping);
return G_SOURCE_REMOVE;
}

/*!
* \internal
* \brief Process a reply to a \c CRM_OP_PING request
Expand Down Expand Up @@ -542,11 +566,6 @@ based_perform_op_rw(xmlNode *request, const cib__operation_t *operation,
ping_modified_since = true;
}

if (digest_timer == NULL) {
digest_timer = mainloop_timer_add("based_digest_timer", 5000, false,
digest_timer_cb, NULL);
}

mainloop_timer_start(digest_timer);

done:
Expand Down Expand Up @@ -812,35 +831,3 @@ based_process_request(xmlNode *request, bool privileged,
pcmk__xml_free(reply);
return rc;
}

/*!
* \internal
* \brief Close remote sockets, free the global CIB and quit
*
* \param[in] exit_status Exit code
*/
void
based_terminate(crm_exit_t exit_status)
{
based_ipc_cleanup();
based_remote_cleanup();

g_clear_pointer(&digest_timer, mainloop_timer_del);
g_clear_pointer(&ping_digest, free);
g_clear_pointer(&based_cib, pcmk__xml_free);

// Exit immediately on error
if (exit_status != CRM_EX_OK) {
crm_exit(exit_status);
return;
}

based_cluster_disconnect();

if ((mainloop != NULL) && g_main_loop_is_running(mainloop)) {
g_main_loop_quit(mainloop);
return;
}

crm_exit(CRM_EX_OK);
}
5 changes: 3 additions & 2 deletions daemons/based/based_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
#include <libxml/tree.h> // xmlNode

#include <crm/common/internal.h> // pcmk__client_t
#include <crm/common/results.h> // crm_exit_t

void based_callbacks_init(void);
void based_callbacks_cleanup(void);

int based_process_request(xmlNode *request, bool privileged,
const pcmk__client_t *client);
void based_terminate(crm_exit_t exit_status);

#endif // BASED_CALLBACKS__H
2 changes: 1 addition & 1 deletion daemons/based/based_corosync.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <stdlib.h> // free

#include <corosync/cpg.h> // cpg_*
#include <glib.h> // gpointer
#include <glib.h> // g_clear_pointer
#include <libxml/tree.h> // xmlNode

#include <crm_config.h> // SUPPORT_COROSYNC
Expand Down
14 changes: 12 additions & 2 deletions daemons/based/based_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <crm/cib/util.h> // createEmptyCib
#include <crm/common/internal.h> // pcmk__assert_asprintf, PCMK__XE_*, etc.
#include <crm/common/logging.h> // CRM_CHECK
#include <crm/common/mainloop.h> // mainloop_add_signal
#include <crm/common/mainloop.h> // mainloop_*
#include <crm/common/results.h> // pcmk_legacy2rc, pcmk_rc_*
#include <crm/common/util.h> // pcmk_common_cleanup
#include <crm/common/xml.h> // PCMK_XA_*, PCMK_XE_*
Expand Down Expand Up @@ -176,7 +176,7 @@ based_enable_writes(int nsig)

/*!
* \internal
* \brief Initialize data structures for \c pacemaker-based I/O
* \brief Initialize data structures used for CIB manager I/O
*/
void
based_io_init(void)
Expand All @@ -198,6 +198,16 @@ based_io_init(void)
write_trigger = mainloop_add_trigger(G_PRIORITY_LOW, write_cib_async, NULL);
}

/*!
* \internal
* \brief Free data structures used for CIB manager I/O
*/
void
based_io_cleanup(void)
{
g_clear_pointer(&write_trigger, mainloop_destroy_trigger);
}

/*!
* \internal
* \brief Rename a CIB or digest file after digest mismatch
Expand Down
2 changes: 2 additions & 0 deletions daemons/based/based_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <libxml/tree.h> // xmlNode

void based_io_init(void);
void based_io_cleanup(void);

void based_enable_writes(int nsig);
xmlNode *based_read_cib(void);
int based_activate_cib(xmlNode *new_cib, bool to_disk, const char *op);
Expand Down
6 changes: 1 addition & 5 deletions daemons/based/based_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

static qb_ipcs_service_t *ipcs_ro = NULL;
static qb_ipcs_service_t *ipcs_rw = NULL;
static qb_ipcs_service_t *ipcs_shm = NULL;

/*!
* \internal
Expand Down Expand Up @@ -305,7 +304,7 @@ static struct qb_ipcs_service_handlers ipc_rw_callbacks = {
void
based_ipc_init(void)
{
pcmk__serve_based_ipc(&ipcs_ro, &ipcs_rw, &ipcs_shm, &ipc_ro_callbacks,
pcmk__serve_based_ipc(&ipcs_ro, &ipcs_rw, &ipc_ro_callbacks,
&ipc_rw_callbacks);
}

Expand All @@ -322,9 +321,6 @@ based_ipc_cleanup(void)
pcmk__drop_all_clients(ipcs_rw);
g_clear_pointer(&ipcs_rw, qb_ipcs_destroy);

pcmk__drop_all_clients(ipcs_shm);
g_clear_pointer(&ipcs_shm, qb_ipcs_destroy);

/* Drop remote clients here because they're part of the IPC client table and
* must be dropped before \c pcmk__client_cleanup()
*/
Expand Down
Loading