Skip to content

Commit

Permalink
Introduce hooks to implement refreshing the otherNodes array. (#740)
Browse files Browse the repository at this point in the history
This way we allow extensions to pg_auto_failover to implement specific
processing when the otherNodes array changes, when that's needed.
  • Loading branch information
DimCitus committed Jun 25, 2021
1 parent 99ae2b8 commit 7a878a4
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 12 deletions.
70 changes: 58 additions & 12 deletions src/bin/pg_autoctl/keeper.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,9 +2039,7 @@ keeper_refresh_other_nodes(Keeper *keeper, bool forceCacheInvalidation)
Monitor *monitor = &(keeper->monitor);
KeeperConfig *config = &(keeper->config);

NodeAddressArray *otherNodesArray = &(keeper->otherNodes);
NodeAddressArray newNodesArray = { 0 };
NodeAddressArray diffNodesArray = { 0 };

int64_t nodeId = keeper->state.current_node_id;

Expand All @@ -2064,30 +2062,83 @@ keeper_refresh_other_nodes(Keeper *keeper, bool forceCacheInvalidation)
}
}

/*
* In case of success, copy the current nodes array to the keeper's cache.
*/
bool success =
keeper_call_refresh_hooks(keeper, &newNodesArray, forceCacheInvalidation);

if (success)
{
keeper->otherNodes = newNodesArray;
}

return success;
}


/*
* keeper_call_refresh_hooks loops over the KeeperNodesArrayRefreshArray and
* calls each hook in turn. It returns true when all the hooks have returned
* true.
*/
bool
keeper_call_refresh_hooks(Keeper *keeper,
NodeAddressArray *newNodesArray,
bool forceCacheInvalidation)
{
bool success = true;

for (int index = 0; KeeperRefreshHooks[index]; index++)
{
KeeperNodesArrayRefreshFunction hookFun = KeeperRefreshHooks[index];

bool ret = (*hookFun)(keeper, newNodesArray, forceCacheInvalidation);

success = success && ret;
}

return success;
}


/*
* keeper_refresh_hba is a KeeperNodesArrayRefreshFunction that adds new
* entries in the Postgres HBA file for new nodes that have been added to our
* group.
*/
bool
keeper_refresh_hba(Keeper *keeper,
NodeAddressArray *newNodesArray,
bool forceCacheInvalidation)
{
NodeAddressArray *otherNodesArray = &(keeper->otherNodes);
NodeAddressArray diffNodesArray = { 0 };

/* compute nodes that need an HBA change (new ones, new hostnames) */
if (forceCacheInvalidation)
{
diffNodesArray = newNodesArray;
diffNodesArray = *newNodesArray;
}
else
{
(void) diff_nodesArray(otherNodesArray, &newNodesArray, &diffNodesArray);
(void) diff_nodesArray(otherNodesArray, newNodesArray, &diffNodesArray);
}

/*
* When we're alone in the group, and also when there's no change, then we
* are done here already.
*/
if (newNodesArray.count == 0 || diffNodesArray.count == 0)
if (newNodesArray->count == 0 || diffNodesArray.count == 0)
{
/* refresh the keeper's cache with the current other nodes array */
keeper->otherNodes = newNodesArray;
keeper->otherNodes = *newNodesArray;
return true;
}

log_info("Fetched current list of %d other nodes from the monitor "
"to update HBA rules, including %d changes.",
newNodesArray.count, diffNodesArray.count);
newNodesArray->count, diffNodesArray.count);

/*
* We have a new list of other nodes, update the HBA file. We only update
Expand All @@ -2103,11 +2154,6 @@ keeper_refresh_other_nodes(Keeper *keeper, bool forceCacheInvalidation)
return false;
}

/*
* In case of success, copy the current nodes array to the keeper's cache.
*/
keeper->otherNodes = newNodesArray;

return true;
}

Expand Down
18 changes: 18 additions & 0 deletions src/bin/pg_autoctl/keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,32 @@ bool keeper_config_accept_new(Keeper *keeper, KeeperConfig *newConfig);
*/
typedef bool (*KeeperReloadFunction)(Keeper *keeper, bool firstLoop, bool doInit);

/*
* When updating the list of other nodes (a NodesArray) after calling
* node_active, the keeper needs to implement specific actions such as editing
* the HBA rules to allow new nodes to connect.
*/
typedef bool (*KeeperNodesArrayRefreshFunction)(Keeper *keeper,
NodeAddressArray *newNodesArray,
bool forceCacheInvalidation);

/* src/bin/pg_autoctl/service_keeper.c */
extern KeeperReloadFunction *KeeperReloadHooks;
extern KeeperNodesArrayRefreshFunction *KeeperRefreshHooks;

void keeper_call_reload_hooks(Keeper *keeper, bool firstLoop, bool doInit);
bool keeper_reload_configuration(Keeper *keeper, bool firstLoop, bool doInit);

bool keeper_call_refresh_hooks(Keeper *keeper,
NodeAddressArray *newNodesArray,
bool forceCacheInvalidation);
bool keeper_refresh_hba(Keeper *keeper,
NodeAddressArray *newNodesArray,
bool forceCacheInvalidation);

bool keeper_read_nodes_from_file(Keeper *keeper, NodeAddressArray *nodesArray);
bool keeper_get_primary(Keeper *keeper, NodeAddress *primaryNode);
bool keeper_get_most_advanced_standby(Keeper *keeper, NodeAddress *primaryNode);


#endif /* KEEPER_H */
10 changes: 10 additions & 0 deletions src/bin/pg_autoctl/service_keeper.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ KeeperReloadFunction KeeperReloadHooksArray[] = {

KeeperReloadFunction *KeeperReloadHooks = KeeperReloadHooksArray;

/* list of hooks to run to update a list of nodes, at node active time */
KeeperNodesArrayRefreshFunction KeeperNodesArrayRefreshArray[] = {
&keeper_refresh_hba,
NULL
};

KeeperNodesArrayRefreshFunction *KeeperRefreshHooks =
KeeperNodesArrayRefreshArray;


static bool service_keeper_node_active(Keeper *keeper, bool doInit);
static void check_for_network_partitions(Keeper *keeper);
static bool is_network_healthy(Keeper *keeper);
Expand Down

0 comments on commit 7a878a4

Please sign in to comment.