2021-08-10 02:37:58 +02:00

884 lines
23 KiB
C

#include "topology.h"
/* two static data structures to hold the
* plugin configuration and the information
* stored in the shared tree.
* They will be initialized at plugin init/start,
* updated when the shared config is modified
* and accessed via set/get functions
*/
static TopoPluginConf topo_plugin_conf = {0};
static TopoReplicaConf topo_shared_conf = {0};
static int ipa_domain_level = 0;
static int topo_min_domain_level = 1;
char *ipa_topo_plugin_managed_attrs[] = {
"nsds5ReplicaStripAttrs",
"nsds5ReplicatedAttributeList",
"nsDS5ReplicatedAttributeListTotal",
"nsds5BeginReplicaRefresh",
"nsds5replicaTimeout",
"nsds5ReplicaEnabled",
"nsds5replicaSessionPauseTime",
"nsds5replicabinddn",
"nsds5replicacredentials",
"nsds5replicatransportinfo",
"nsds5replicabindmethod",
NULL };
/* subset of attrs which can only be modified via
* modification of segments in the shared tree.
* Other attributes still can be directly modified
* eg to reinit a replica or change bind method and
* credentials.
* This is currently needed to make ipa-replica-install work
*/
char *ipa_topo_plugin_restricted_attrs[] = {
"nsds5ReplicaStripAttrs",
"nsds5ReplicatedAttributeList",
"nsDS5ReplicatedAttributeListTotal",
"nsds5replicaTimeout",
"nsds5replicaSessionPauseTime",
NULL };
void *
ipa_topo_get_plugin_id(void)
{
return topo_plugin_conf.identity;
}
char *
ipa_topo_get_plugin_hostname(void)
{
return topo_plugin_conf.hostname;
}
char **
ipa_topo_get_plugin_managed_attrs(void)
{
return topo_plugin_conf.managed_attrs;
}
char **
ipa_topo_get_plugin_restricted_attrs(void)
{
return topo_plugin_conf.restricted_attrs;
}
char *
ipa_topo_get_plugin_shared_config(void)
{
return topo_plugin_conf.shared_config_base;
}
char *
ipa_topo_get_plugin_shared_topo(void)
{
return topo_plugin_conf.shared_topo;
}
Slapi_DN *
ipa_topo_get_plugin_shared_topo_dn(void)
{
return topo_plugin_conf.shared_topo_sdn;
}
char *
ipa_topo_get_domain_level_entry(void)
{
return topo_plugin_conf.domain_level;
}
Slapi_DN *
ipa_topo_get_domain_level_entry_dn(void)
{
return topo_plugin_conf.domain_level_sdn;
}
int
ipa_topo_get_min_domain_level(void)
{
return topo_min_domain_level;
}
int
ipa_topo_get_domain_level(void)
{
return ipa_domain_level;
}
char *
ipa_topo_get_plugin_shared_hosts(void)
{
return topo_plugin_conf.shared_hosts;
}
Slapi_DN *
ipa_topo_get_plugin_shared_hosts_dn(void)
{
return topo_plugin_conf.shared_hosts_sdn;
}
char *
ipa_topo_get_plugin_shared_bindgroup(void)
{
return topo_plugin_conf.shared_bindgroup;
}
Slapi_DN *
ipa_topo_get_plugin_shared_bindgroup_dn(void)
{
return topo_plugin_conf.shared_bindgroup_sdn;
}
char **
ipa_topo_get_plugin_replica_root(void)
{
return topo_plugin_conf.shared_replica_root;
}
int
ipa_topo_get_plugin_version_major(void)
{
return topo_plugin_conf.version_major;
}
int
ipa_topo_get_plugin_version_minor(void)
{
return topo_plugin_conf.version_minor;
}
int
ipa_topo_get_plugin_startup_delay(void)
{
return topo_plugin_conf.startup_delay;
}
void
ipa_topo_set_plugin_id(void *plg_id)
{
topo_plugin_conf.identity = plg_id;
}
void
ipa_topo_set_plugin_active(int state)
{
topo_plugin_conf.activated = state;
}
int
ipa_topo_get_plugin_active(void)
{
return topo_plugin_conf.activated;
}
void
ipa_topo_set_post_init(int state)
{
topo_plugin_conf.post_init = state;
}
int
ipa_topo_get_post_init(void)
{
return topo_plugin_conf.post_init;
}
void
ipa_topo_set_plugin_shared_config(char *cfg)
{
char *topo;
char *hosts;
char *domain_level;
topo_plugin_conf.shared_config_base = cfg;
topo = slapi_ch_smprintf("%s,%s","cn=topology",cfg);
hosts = slapi_ch_smprintf("%s,%s","cn=masters",cfg);
domain_level = slapi_ch_smprintf("%s,%s","cn=domain level",cfg);
topo_plugin_conf.shared_topo = topo;
topo_plugin_conf.shared_topo_sdn = slapi_sdn_new_normdn_byref(topo);
topo_plugin_conf.shared_hosts = hosts;
topo_plugin_conf.shared_hosts_sdn = slapi_sdn_new_normdn_byref(hosts);
topo_plugin_conf.domain_level = domain_level;
topo_plugin_conf.domain_level_sdn = slapi_sdn_new_normdn_byref(domain_level);
}
void
ipa_topo_set_plugin_shared_bindgroup(char *bindgroup)
{
topo_plugin_conf.shared_bindgroup = bindgroup;
topo_plugin_conf.shared_bindgroup_sdn = slapi_sdn_new_normdn_byref(bindgroup);
}
void
ipa_topo_set_domain_level(char *level)
{
if (level == NULL) {
ipa_domain_level = 0;
return;
}
ipa_domain_level = atoi(level);
}
void
ipa_topo_set_plugin_hostname(char *hostname)
{
topo_plugin_conf.hostname = hostname;
}
#define TOPO_PLUGIN_DEFAULT_STARTUP_DELAY 20
void
ipa_topo_set_plugin_startup_delay(char *delay)
{
if (delay) {
topo_plugin_conf.startup_delay = atoi(delay);
} else {
topo_plugin_conf.startup_delay = TOPO_PLUGIN_DEFAULT_STARTUP_DELAY;
}
}
void
ipa_topo_set_plugin_version(char *version)
{
char *minor;
if ( version == NULL) {
topo_plugin_conf.version_major = 0;
topo_plugin_conf.version_minor = 0;
return;
}
minor = strchr(version,'.');
if (minor) {
*minor = '\0';
topo_plugin_conf.version_minor = atoi(++minor);
} else {
topo_plugin_conf.version_minor = 0;
}
topo_plugin_conf.version_major = atoi(version);
}
void
ipa_topo_init_shared_config(void)
{
topo_shared_conf.allhosts = NULL;
topo_shared_conf.replicas = NULL;
topo_shared_conf.conf_lock = slapi_new_mutex();
}
void
ipa_topo_set_plugin_managed_attrs(char **attrs)
{
if (attrs) {
topo_plugin_conf.managed_attrs = attrs;
} else {
topo_plugin_conf.managed_attrs = ipa_topo_plugin_managed_attrs;
}
}
void
ipa_topo_set_plugin_restricted_attrs(char **attrs)
{
if (attrs) {
topo_plugin_conf.restricted_attrs = attrs;
} else {
topo_plugin_conf.restricted_attrs = ipa_topo_plugin_restricted_attrs;
}
}
int
ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix) {
int i = 0;
char **shared_replica_root = ipa_topo_get_plugin_replica_root();
while (shared_replica_root[i]) {
if (0 == strcasecmp(shared_replica_root[i], be_suffix)) return 1;
i++;
}
return 0;
}
int
ipa_topo_cfg_attr_is_restricted(char *type)
{
int i;
int rc = 0;
char **rattrs = ipa_topo_get_plugin_restricted_attrs();
for (i=0; rattrs[i]; i++) {
if(0 == strcasecmp(rattrs[i], type)) {
rc = 1;
break;
}
}
return rc;
}
void
ipa_topo_set_plugin_replica_root(char **root)
{
topo_plugin_conf.shared_replica_root = root;
}
int
ipa_topo_init_plugin_config(Slapi_PBlock * pb)
{
Slapi_Entry *plugin_entry = NULL;
char *hostname;
char *config_base;
char *startup_delay;
char *plugin_version;
char *bindgroup;
char **replica_root;
/* get the local hostname */
hostname = ipa_topo_util_get_pluginhost();
if (hostname == NULL) {
/* log error */
return -1;
} else {
ipa_topo_set_plugin_hostname(hostname);
}
/* get the args */
/* slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry); */
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry);
if(plugin_entry == NULL){
return -1;
}
ipa_topo_set_plugin_active(0);
config_base = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_SHARED_BASE);
if(config_base){
ipa_topo_set_plugin_shared_config(config_base);
}
replica_root = slapi_entry_attr_get_charray(plugin_entry,
CONFIG_ATTR_REPLICA_ROOT);
if(replica_root){
ipa_topo_set_plugin_replica_root(replica_root);
}
bindgroup = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_SHARED_BINDDNGROUP);
if(bindgroup){
ipa_topo_set_plugin_shared_bindgroup(bindgroup);
}
startup_delay = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_STARTUP_DELAY);
ipa_topo_set_plugin_startup_delay(startup_delay);
slapi_ch_free_string(&startup_delay);
plugin_version = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_PLUGIN_VERSION);
ipa_topo_set_plugin_version(plugin_version);
slapi_ch_free_string(&plugin_version);
ipa_topo_util_set_domain_level();
ipa_topo_util_check_plugin_active();
ipa_topo_set_plugin_managed_attrs(NULL); /* use defaults */
ipa_topo_set_plugin_restricted_attrs(NULL); /* use defaults */
return 0;
}
void
ipa_topo_free_plugin_config(void)
{
slapi_destroy_mutex(topo_plugin_conf.plg_lock);
slapi_ch_free((void **)topo_plugin_conf.identity);
slapi_ch_free_string(&topo_plugin_conf.hostname);
slapi_ch_free_string(&topo_plugin_conf.shared_config_base);
slapi_ch_free_string(&topo_plugin_conf.shared_topo);
slapi_sdn_free(&topo_plugin_conf.shared_topo_sdn);
slapi_ch_free_string(&topo_plugin_conf.shared_hosts);
slapi_sdn_free(&topo_plugin_conf.shared_hosts_sdn);
slapi_ch_free_string(&topo_plugin_conf.shared_bindgroup);
slapi_sdn_free(&topo_plugin_conf.shared_bindgroup_sdn);
slapi_ch_free_string(&topo_plugin_conf.domain_level);
slapi_sdn_free(&topo_plugin_conf.domain_level_sdn);
slapi_ch_array_free(topo_plugin_conf.shared_replica_root);
if (ipa_topo_plugin_managed_attrs != topo_plugin_conf.managed_attrs)
slapi_ch_array_free(topo_plugin_conf.managed_attrs);
if (ipa_topo_plugin_restricted_attrs != topo_plugin_conf.restricted_attrs)
slapi_ch_array_free(topo_plugin_conf.restricted_attrs);
}
void
ipa_topo_lock_conf(void)
{
slapi_lock_mutex(topo_shared_conf.conf_lock);
}
void
ipa_topo_unlock_conf(void)
{
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
int
ipa_topo_acquire_startup_inprogress(void)
{
int acquired = 0;
slapi_lock_mutex(topo_shared_conf.conf_lock);
if (topo_shared_conf.startup_inprogress == 0 ) {
topo_shared_conf.startup_inprogress = 1;
acquired = 1;
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return acquired;
}
void
ipa_topo_release_startup_inprogress(void)
{
slapi_lock_mutex(topo_shared_conf.conf_lock);
topo_shared_conf.startup_inprogress = 0;
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
TopoReplicaHost *
ipa_topo_cfg_host_find(TopoReplica *tconf, char *findhost, int lock)
{
TopoReplicaHost *host = NULL;
if (tconf->hosts == NULL) return NULL;
if (lock) slapi_lock_mutex(tconf->repl_lock);
for (host=tconf->hosts;host;host=host->next) {
if (!strcasecmp(host->hostname,findhost)) {
break;
}
}
if (lock) slapi_unlock_mutex(tconf->repl_lock);
return host;
}
TopoReplicaHost *
ipa_topo_cfg_host_new(char *newhost)
{
TopoReplicaHost *newnode;
newnode = (TopoReplicaHost *)slapi_ch_malloc(sizeof(TopoReplicaHost));
newnode->next = NULL;
newnode->hostname = newhost;
return newnode;
}
void
ipa_topo_cfg_host_add(TopoReplica *replica, char *newhost)
{
TopoReplicaHost *hostnode = NULL;
if (replica == NULL || newhost == NULL) return;
slapi_lock_mutex(replica->repl_lock);
if (ipa_topo_cfg_host_find(replica, newhost, 0)) {
/* host already added */
slapi_unlock_mutex(replica->repl_lock);
return;
}
hostnode = ipa_topo_cfg_host_new(slapi_ch_strdup(newhost));
hostnode->next = replica->hosts;
replica->hosts = hostnode;
slapi_unlock_mutex(replica->repl_lock);
return;
}
void
ipa_topo_cfg_host_free(TopoReplicaHost **node)
{
slapi_ch_free((void **)&((*node)->hostname));
slapi_ch_free((void **)node);
}
void
ipa_topo_cfg_host_del(Slapi_Entry *hostentry)
{
char *delhost;
TopoReplicaHost *hostnode = NULL;
TopoReplicaHost *prevnode = NULL;
char **repl_root = NULL;
TopoReplica *replica = NULL;
int i;
delhost = slapi_entry_attr_get_charptr(hostentry,"cn");
if (delhost == NULL) return;
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
if (repl_root == NULL || *repl_root == NULL) return;
for (i=0; repl_root[i];i++) {
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
if (replica == NULL) continue;
slapi_lock_mutex(replica->repl_lock);
hostnode = replica->hosts;
while (hostnode) {
if (!strcasecmp(hostnode->hostname,delhost)) {
/*remove from list and free*/
if (prevnode) {
prevnode->next = hostnode->next;
} else {
replica->hosts = hostnode->next;
}
ipa_topo_cfg_host_free(&hostnode);
break;
} else {
prevnode = hostnode;
hostnode = hostnode->next;
}
}
slapi_unlock_mutex(replica->repl_lock);
}
return;
}
TopoReplicaSegment *
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int dir, int lock)
{
TopoReplicaSegment *tsegm = NULL;
TopoReplicaSegmentList *segments = NULL;
int reverse_dir = SEGMENT_BIDIRECTIONAL;
if (dir == SEGMENT_LEFT_RIGHT) reverse_dir = SEGMENT_RIGHT_LEFT;
else if (dir == SEGMENT_RIGHT_LEFT) reverse_dir = SEGMENT_LEFT_RIGHT;
else reverse_dir = SEGMENT_BIDIRECTIONAL;
if (lock) slapi_lock_mutex(replica->repl_lock);
segments = replica->repl_segments;
while (segments) {
tsegm = segments->segm;
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
(tsegm->direct & dir)) ||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
(tsegm->direct & reverse_dir))) {
break;
}
tsegm = NULL;
segments = segments->next;
}
if (lock) slapi_unlock_mutex(replica->repl_lock);
return tsegm;
}
TopoReplicaAgmt *
ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt)
{
TopoReplicaAgmt *dup = NULL;
if (agmt == NULL) return NULL;
dup = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
dup->rdn = slapi_ch_strdup(agmt->rdn);
dup->origin = slapi_ch_strdup(agmt->origin);
dup->target = slapi_ch_strdup(agmt->target);
dup->enabled = slapi_ch_strdup(agmt->enabled);
dup->repl_root = slapi_ch_strdup(agmt->repl_root);
dup->strip_attrs = slapi_ch_strdup(agmt->strip_attrs);
dup->total_attrs = slapi_ch_strdup(agmt->total_attrs);
dup->repl_attrs = slapi_ch_strdup(agmt->repl_attrs);
dup->repl_pause = slapi_ch_strdup(agmt->repl_pause);
dup->repl_timeout = slapi_ch_strdup(agmt->repl_timeout);
dup->repl_refresh = slapi_ch_strdup(agmt->repl_refresh);
dup->repl_transport = slapi_ch_strdup(agmt->repl_transport);
dup->repl_bind_dn = slapi_ch_strdup(agmt->repl_bind_dn);
dup->repl_bind_cred = slapi_ch_strdup(agmt->repl_bind_cred);
dup->repl_bind_method = slapi_ch_strdup(agmt->repl_bind_method);
return dup;
}
TopoReplicaAgmt *
ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt)
{
char *tmp;
TopoReplicaAgmt *dup = NULL;
dup = ipa_topo_cfg_agmt_dup(agmt);
if (dup == NULL) return NULL;
tmp = dup->origin;
dup->origin = dup->target;
dup->target = tmp;
/* this is not enough, if a reverse agmt is
* created because segment becomes bidirectional
* we don't really know the rdn of the other direction
* As long as this info is not in the segment,
* assume std agmt naming and do best effort.
*/
slapi_ch_free_string(&dup->rdn);
dup->rdn = ipa_topo_agmt_std_rdn(dup->target);
return dup;
}
static void
ipa_topo_cfg_agmt_done(TopoReplicaAgmt *agmt)
{
if (agmt == NULL) return;
slapi_ch_free_string(&agmt->origin);
slapi_ch_free_string(&agmt->target);
slapi_ch_free_string(&agmt->enabled);
slapi_ch_free_string(&agmt->repl_root);
slapi_ch_free_string(&agmt->strip_attrs);
slapi_ch_free_string(&agmt->total_attrs);
slapi_ch_free_string(&agmt->repl_attrs);
slapi_ch_free_string(&agmt->repl_pause);
slapi_ch_free_string(&agmt->repl_timeout);
slapi_ch_free_string(&agmt->repl_refresh);
slapi_ch_free_string(&agmt->repl_transport);
slapi_ch_free_string(&agmt->repl_bind_dn);
slapi_ch_free_string(&agmt->repl_bind_cred);
slapi_ch_free_string(&agmt->repl_bind_method);
}
static void
ipa_topo_cfg_segment_done(TopoReplicaSegment *tsegm)
{
if (tsegm == NULL) return;
slapi_ch_free_string(&tsegm->name);
slapi_ch_free_string(&tsegm->from);
slapi_ch_free_string(&tsegm->to);
ipa_topo_cfg_agmt_done(tsegm->left);
ipa_topo_cfg_agmt_done(tsegm->right);
slapi_ch_free((void **)&tsegm->left);
slapi_ch_free((void **)&tsegm->right);
}
void
ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm)
{
ipa_topo_cfg_segment_done(tsegm);
slapi_ch_free((void **)&tsegm);
}
TopoReplicaSegment *
ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig)
{
TopoReplicaSegment *dup = NULL;
if (orig == NULL) return NULL;
dup = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
dup->name = slapi_ch_strdup(orig->name);
dup->from = slapi_ch_strdup(orig->from);
dup->to = slapi_ch_strdup(orig->to);
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
dup->direct = orig->direct;
dup->state = orig->state;
return dup;
}
TopoReplicaSegment *
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost, int dir)
{
TopoReplicaSegment *tsegm = NULL;
TopoReplica *replica = NULL;
slapi_lock_mutex(topo_shared_conf.conf_lock);
replica = ipa_topo_cfg_replica_find(repl_root, 0);
if (replica) {
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, dir, 1);
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return tsegm;
}
void
ipa_topo_cfg_segment_set_visited(TopoReplica *replica, TopoReplicaSegment *vsegm)
{
TopoReplicaSegmentList *segments = NULL;
TopoReplicaSegment *tsegm = NULL;
char *leftHost = vsegm->from;
char *rightHost = vsegm->to;
slapi_lock_mutex(replica->repl_lock);
segments = replica->repl_segments;
while (segments) {
tsegm = segments->segm;
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_LEFT_RIGHT)) ||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
segments->visited = 1;
break;
}
tsegm = NULL;
segments = segments->next;
}
slapi_unlock_mutex(replica->repl_lock);
}
void
ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm)
{
TopoReplicaSegmentList *seglist = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_add: %s\n", tsegm->name);
slapi_lock_mutex(replica->repl_lock);
if (ipa_topo_cfg_replica_segment_find(replica,
tsegm->from,
tsegm->to, tsegm->direct, 0)){
/* already exists: log error */
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_add: error: segment exists: %s\n",
tsegm->name);
goto done;
}
seglist = (TopoReplicaSegmentList *)
slapi_ch_calloc(1,sizeof(TopoReplicaSegmentList));
seglist->visited = 0;
seglist->segm = tsegm;
if (replica->repl_segments == NULL) {
replica->repl_segments = seglist;
} else {
seglist->next = replica->repl_segments;
replica->repl_segments = seglist;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_added: %s\n", tsegm->name);
done:
slapi_unlock_mutex(replica->repl_lock);
}
void
ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm)
{
TopoReplicaSegmentList *segment = NULL;
TopoReplicaSegmentList *prev = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_del: %s\n", tsegm->name);
slapi_lock_mutex(tconf->repl_lock);
segment = tconf->repl_segments;
while (segment) {
if (segment->segm == tsegm) {
if (prev == NULL) {
tconf->repl_segments = segment->next;
} else {
prev->next = segment->next;
}
/* free segment */
ipa_topo_cfg_segment_free(tsegm);
slapi_ch_free((void **)&segment);
break;
}
prev = segment;
segment = segment->next;
}
slapi_unlock_mutex(tconf->repl_lock);
}
TopoReplica *
ipa_topo_cfg_replica_new(void)
{
TopoReplica *topoRepl;
topoRepl = (TopoReplica *)slapi_ch_malloc(sizeof(TopoReplica));
if (topoRepl) {
topoRepl->next = NULL;
topoRepl->repl_segments = NULL;
topoRepl->repl_root = NULL;
topoRepl->strip_attrs = NULL;
topoRepl->total_attrs = NULL;
topoRepl->repl_attrs = NULL;
topoRepl->shared_config_base = NULL;
topoRepl->hosts = NULL;
topoRepl->repl_lock = slapi_new_mutex();
}
return topoRepl;
}
int
ipa_topo_cfg_replica_add(TopoReplica *tconf)
{
int rc = 0;
slapi_lock_mutex(topo_shared_conf.conf_lock);
if (topo_shared_conf.replicas == NULL) {
topo_shared_conf.replicas = tconf;
} else if (ipa_topo_cfg_replica_find(tconf->repl_root,0)) {
/* log error: already exists */
rc = -1;
} else {
tconf->next = topo_shared_conf.replicas;
topo_shared_conf.replicas = tconf;
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return rc;
}
void
ipa_topo_cfg_replica_del(TopoReplica *tconf)
{
/* TBD */
}
void
ipa_topo_cfg_replica_free(TopoReplica *tconf)
{
TopoReplicaSegmentList *seg, *seg_next;
TopoReplicaHost *host, *host_next;
if (tconf) {
slapi_destroy_mutex(tconf->repl_lock);
slapi_ch_free_string(&tconf->shared_config_base);
slapi_ch_free_string(&tconf->repl_root);
seg = tconf->repl_segments;
while (seg) {
seg_next = seg->next;
ipa_topo_cfg_segment_free(seg->segm);
slapi_ch_free((void **)&seg);
seg = seg_next;
}
host = tconf->hosts;
while (host) {
host_next = host->next;
slapi_ch_free_string(&host->hostname);
host = host_next;
slapi_ch_free((void **)&host);
}
slapi_ch_free((void **)&tconf);
}
}
TopoReplica *
ipa_topo_cfg_replica_find(char *repl_root, int lock)
{
TopoReplica *tconf = NULL;
if (lock) {
slapi_lock_mutex(topo_shared_conf.conf_lock);
}
if (topo_shared_conf.replicas == NULL) goto done;
tconf = topo_shared_conf.replicas;
while (tconf) {
if (!strcasecmp(repl_root,tconf->repl_root)) {
break;
}
tconf = tconf->next;
}
done:
if (lock) {
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
return tconf;
}