From 39af2e9e98c895c5145090865d5ab7cde6cc12fd Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 6 Dec 2013 16:57:41 -0500
Subject: [PATCH 65/65] Ticket 47620 - 389-ds rejects
nsds5ReplicaProtocolTimeout attribute
Bug Description: Attempting to add/modify/delete nsds5ReplicaProtocolTimeout
results in an error 53 (unwilling to perform).
Fix Description: Allow nsds5ReplicaProtocolTimeout to be updated in agreements
and the replica configuration. Also, made the config timeout
setting dynamic.
https://fedorahosted.org/389/ticket/47620
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 58fca2c4e4f2120cb6e5fb249008be8f551e944c)
(cherry picked from commit 490360fd96121d06fa8813e182b44d045257be98)
---
ldap/servers/plugins/replication/repl5.h | 12 +++--
ldap/servers/plugins/replication/repl5_agmt.c | 54 ++++++++++++++++------
ldap/servers/plugins/replication/repl5_agmtlist.c | 27 +++++++++--
.../plugins/replication/repl5_inc_protocol.c | 23 +++++++--
.../plugins/replication/repl5_prot_private.h | 1 -
ldap/servers/plugins/replication/repl5_protocol.c | 13 ++----
ldap/servers/plugins/replication/repl5_replica.c | 54 ++++++++++++++--------
.../plugins/replication/repl5_replica_config.c | 25 +++++++++-
.../plugins/replication/repl5_tot_protocol.c | 17 +++++--
9 files changed, 169 insertions(+), 57 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 92a9229..321a285 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -386,9 +386,15 @@ char **agmt_get_attrs_to_strip(Repl_Agmt *ra);
int agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e);
int agmt_set_timeout(Repl_Agmt *ra, long timeout);
void agmt_update_done(Repl_Agmt *ra, int is_total);
-int agmt_get_protocol_timeout(Repl_Agmt *agmt);
typedef struct replica Replica;
+PRUint64 agmt_get_protocol_timeout(Repl_Agmt *agmt);
+void agmt_set_protocol_timeout(Repl_Agmt *agmt, PRUint64 timeout);
+void agmt_update_maxcsn(Replica *r, Slapi_DN *sdn, int op, LDAPMod **mods, CSN *csn);
+void add_agmt_maxcsns(Slapi_Entry *e, Replica *r);
+void agmt_set_maxcsn(Repl_Agmt *ra);
+void agmt_remove_maxcsn(Repl_Agmt *ra);
+int agmt_maxcsn_to_smod (Replica *r, Slapi_Mod *smod);
/* In repl5_agmtlist.c */
int agmtlist_config_init();
@@ -494,7 +500,6 @@ void prot_notify_window_opened (Repl_Protocol *rp);
void prot_notify_window_closed (Repl_Protocol *rp);
Object *prot_get_replica_object(Repl_Protocol *rp);
void prot_replicate_now(Repl_Protocol *rp);
-int prot_get_timeout(Repl_Protocol *rp);
Repl_Protocol *agmt_get_protocol(Repl_Agmt *ra);
@@ -591,7 +596,8 @@ char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
void replica_update_state (time_t when, void *arg);
void replica_reset_csn_pl(Replica *r);
-int replica_get_protocol_timeout(Replica *r);
+PRUint64 replica_get_protocol_timeout(Replica *r);
+void replica_set_protocol_timeout(Replica *r, PRUint64 timeout);
int replica_get_backoff_min(Replica *r);
int replica_get_backoff_max(Replica *r);
void replica_set_backoff_min(Replica *r, int min);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 90d94f8..b0da172 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -142,7 +142,9 @@ typedef struct repl5agmt {
char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes:
* modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */
int agreement_type;
- PRUint64 protocol_timeout;
+ Slapi_Counter *protocol_timeout;
+ char *maxcsn; /* agmt max csn */
+ Slapi_RWLock *attr_lock; /* RW lock for all the stripped attrs */
} repl5agmt;
/* Forward declarations */
@@ -265,6 +267,14 @@ agmt_new_from_entry(Slapi_Entry *e)
slapi_entry_get_dn_const(e));
goto loser;
}
+ if ((ra->attr_lock = slapi_new_rwlock()) == NULL)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Unable to create new attr lock "
+ "for replication agreement \"%s\" - agreement ignored.\n",
+ slapi_entry_get_dn_const(e));
+ goto loser;
+ }
+ ra->protocol_timeout = slapi_counter_new();
/* Find all the stuff we need for the agreement */
@@ -338,19 +348,14 @@ agmt_new_from_entry(Slapi_Entry *e)
tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot);
if (NULL != tmpstr)
{
+ PRUint64 ptimeout = 0;
+
ra->replarea = slapi_sdn_new_dn_passin(tmpstr);
/* If this agmt has its own timeout, grab it, otherwise use the replica's protocol timeout */
- ra->protocol_timeout = slapi_entry_attr_get_int(e, type_replicaProtocolTimeout);
- if(ra->protocol_timeout == 0){
- /* grab the replica protocol timeout */
- Object *replobj = replica_get_replica_from_dn(ra->replarea);
- if(replobj){
- Replica *replica =(Replica*)object_get_data (replobj);
- ra->protocol_timeout = replica_get_protocol_timeout(replica);
- } else {
- ra->protocol_timeout = DEFAULT_PROTOCOL_TIMEOUT;
- }
+ ptimeout = slapi_entry_attr_get_int(e, type_replicaProtocolTimeout);
+ if(ptimeout){
+ slapi_counter_set_value(ra->protocol_timeout, ptimeout);
}
}
@@ -613,6 +618,17 @@ agmt_delete(void **rap)
if(ra->attrs_to_strip){
slapi_ch_array_free(ra->attrs_to_strip);
}
+ if(ra->maxcsn){
+ slapi_ch_free_string(&ra->maxcsn);
+ }
+ schedule_destroy(ra->schedule);
+ slapi_ch_free_string(&ra->long_name);
+
+ slapi_counter_destroy(&ra->protocol_timeout);
+
+ /* free the locks */
+ PR_DestroyLock(ra->lock);
+ slapi_destroy_rwlock(ra->attr_lock);
schedule_destroy(ra->schedule);
slapi_ch_free((void **)&ra->long_name);
@@ -2663,9 +2679,21 @@ agmt_update_done(Repl_Agmt *agmt, int is_total)
windows_update_done(agmt, is_total);
}
-int
+PRUint64
agmt_get_protocol_timeout(Repl_Agmt *agmt)
{
- return (int)agmt->protocol_timeout;
+ if(agmt){
+ return slapi_counter_get_value(agmt->protocol_timeout);
+ } else {
+ return 0;
+ }
+}
+
+void
+agmt_set_protocol_timeout(Repl_Agmt *agmt, PRUint64 timeout)
+{
+ if(agmt){
+ slapi_counter_set_value(agmt->protocol_timeout, timeout);
+ }
}
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 1167b0c..04891b7 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -209,6 +209,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
LDAPMod **mods;
char buff [SLAPI_DSE_RETURNTEXT_SIZE];
char *errortext = returntext ? returntext : buff;
+ char *val = NULL;
int rc = SLAPI_DSE_CALLBACK_OK;
Slapi_Operation *op;
void *identity;
@@ -243,16 +244,21 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
for (i = 0; NULL != mods && NULL != mods[i]; i++)
{
+ slapi_ch_free_string(&val);
if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaInitialize))
{
/* we don't allow delete attribute operations unless it was issued by
the replication plugin - handled above */
if (mods[i]->mod_op & LDAP_MOD_DELETE)
{
- if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0){
+ if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0 ){
/* allow the deletion of cleanallruv agmt attr */
continue;
}
+ if(strcasecmp (mods[i]->mod_type, type_replicaProtocolTimeout) == 0){
+ agmt_set_protocol_timeout(agmt, 0);
+ continue;
+ }
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
"deletion of %s attribute is not allowed\n", type_nsds5ReplicaInitialize);
@@ -262,8 +268,6 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
}
else
{
- char *val;
-
if (mods[i]->mod_bvalues && mods[i]->mod_bvalues[0])
val = slapi_berval_get_string_copy (mods[i]->mod_bvalues[0]);
else
@@ -304,7 +308,6 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
val, mods[i]->mod_type);
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: %s\n", errortext);
}
- slapi_ch_free ((void**)&val);
}
}
else if (slapi_attr_types_equivalent(mods[i]->mod_type,
@@ -511,6 +514,21 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
rc = SLAPI_DSE_CALLBACK_ERROR;
}
}
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_replicaProtocolTimeout)){
+ if (val){
+ long ptimeout = atol(val);
+
+ if(ptimeout <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "attribute %s value (%s) is invalid, "
+ "must be a number greater than zero.\n",
+ type_replicaProtocolTimeout, val);
+ rc = SLAPI_DSE_CALLBACK_ERROR;
+ break;
+ }
+ agmt_set_protocol_timeout(agmt, ptimeout);
+ }
+ }
else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e))
{
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
@@ -561,6 +579,7 @@ done:
{
agmtlist_release_agmt(agmt);
}
+ slapi_ch_free_string(&val);
return rc;
}
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
index 612fe46..05074b0 100644
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
@@ -1921,10 +1921,24 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
static int
repl5_inc_stop(Private_Repl_Protocol *prp)
{
- int return_value;
PRIntervalTime start, maxwait, now;
+ Replica *replica = NULL;
+ PRUint64 timeout;
+ int return_value;
+
+ if((timeout = agmt_get_protocol_timeout(prp->agmt)) == 0){
+ timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ if(prp->replica_object){
+ object_acquire(prp->replica_object);
+ replica = object_get_data(prp->replica_object);
+ if((timeout = replica_get_protocol_timeout(replica)) == 0){
+ timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ }
+ object_release(prp->replica_object);
+ }
+ }
- maxwait = PR_SecondsToInterval(prp->timeout);
+ maxwait = PR_SecondsToInterval(timeout);
prp->terminate = 1;
event_notify(prp, EVENT_PROTOCOL_SHUTDOWN);
start = PR_IntervalNow();
@@ -1939,8 +1953,8 @@ repl5_inc_stop(Private_Repl_Protocol *prp)
/* Isn't listening. Do something drastic. */
return_value = -1;
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "%s: repl5_inc_stop: protocol does not stop after %d seconds\n",
- agmt_get_long_name(prp->agmt), (int)prp->timeout);
+ "%s: repl5_inc_stop: protocol does not stop after %llu seconds\n",
+ agmt_get_long_name(prp->agmt), (long long unsigned int)timeout);
}
else
{
@@ -2044,7 +2058,6 @@ Repl_5_Inc_Protocol_new(Repl_Protocol *rp)
prp->notify_window_closed = repl5_inc_notify_window_closed;
prp->update_now = repl5_inc_update_now;
prp->replica_object = prot_get_replica_object(rp);
- prp->timeout = prot_get_timeout(rp);
if ((prp->lock = PR_NewLock()) == NULL)
{
goto loser;
diff --git a/ldap/servers/plugins/replication/repl5_prot_private.h b/ldap/servers/plugins/replication/repl5_prot_private.h
index 37072ee..586e1eb 100644
--- a/ldap/servers/plugins/replication/repl5_prot_private.h
+++ b/ldap/servers/plugins/replication/repl5_prot_private.h
@@ -75,7 +75,6 @@ typedef struct private_repl_protocol
int repl50consumer; /* Flag to tell us if this is a 5.0-style consumer we're talking to */
int repl71consumer; /* Flag to tell us if this is a 7.1-style consumer we're talking to */
int repl90consumer; /* Flag to tell us if this is a 9.0-style consumer we're talking to */
- PRUint64 timeout;
} Private_Repl_Protocol;
extern Private_Repl_Protocol *Repl_5_Inc_Protocol_new();
diff --git a/ldap/servers/plugins/replication/repl5_protocol.c b/ldap/servers/plugins/replication/repl5_protocol.c
index 34fe8a0..0e9668d 100644
--- a/ldap/servers/plugins/replication/repl5_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_protocol.c
@@ -71,8 +71,7 @@ typedef struct repl_protocol
Object *replica_object; /* Local replica. If non-NULL, replica object is acquired */
int state;
int next_state;
- PRUint64 protocol_timeout;
- PRThread *agmt_thread;
+ PRThread *agmt_thread;
PRLock *lock;
} repl_protocol;
@@ -134,16 +133,17 @@ prot_new(Repl_Agmt *agmt, int protocol_state)
rp->prp_total = private_protocol_factory(rp, PROTOCOL_WINDOWS_TOTAL);
rp->delete_conn = windows_conn_delete;
}
- rp->protocol_timeout = agmt_get_protocol_timeout(agmt);
-
/* XXXggood register callback handlers for entries updated, and
schedule window enter/leave. */
goto done;
+
loser:
prot_delete(&rp);
+
done:
slapi_sdn_free(&replarea_sdn);
+
return rp;
}
@@ -593,8 +593,3 @@ private_protocol_factory(Repl_Protocol *rp, int type)
return prp;
}
-int
-prot_get_timeout(Repl_Protocol *rp)
-{
- return (int)rp->protocol_timeout;
-}
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 8a1c590..02d4e74 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -87,7 +87,7 @@ struct replica {
PRBool state_update_inprogress; /* replica state is being updated */
PRLock *agmt_lock; /* protects agreement creation, start and stop */
char *locking_purl; /* supplier who has exclusive access */
- PRUint64 protocol_timeout; /* protocol shutdown timeout */
+ Slapi_Counter *protocol_timeout; /* protocol shutdown timeout */
PRUint64 backoff_min; /* backoff retry minimum */
PRUint64 backoff_max; /* backoff retry maximum */
};
@@ -164,26 +164,26 @@ replica_new(const Slapi_DN *root)
Replica *
replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation)
{
- int rc = 0;
- Replica *r;
+ int rc = 0;
+ Replica *r;
char *repl_name = NULL;
- if (e == NULL)
- {
- if (NULL != errortext)
+ if (e == NULL)
+ {
+ if (NULL != errortext)
{
- PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE, "NULL entry");
+ PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE, "NULL entry");
}
- return NULL;
- }
+ return NULL;
+ }
- r = (Replica *)slapi_ch_calloc(1, sizeof(Replica));
+ r = (Replica *)slapi_ch_calloc(1, sizeof(Replica));
- if (!r)
+ if (!r)
{
- if (NULL != errortext)
+ if (NULL != errortext)
{
- PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE, "Out of memory");
+ PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE, "Out of memory");
}
rc = -1;
goto done;
@@ -208,6 +208,7 @@ replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation
rc = -1;
goto done;
}
+ r->protocol_timeout = slapi_counter_new();
/* read parameters from the replica config entry */
rc = _replica_init_from_config (r, e, errortext);
@@ -403,6 +404,8 @@ replica_destroy(void **arg)
csnplFree(&r->min_csn_pl);;
}
+ slapi_counter_destroy(&r->protocol_timeout);
+
slapi_ch_free((void **)arg);
}
@@ -796,10 +799,22 @@ replica_get_type (const Replica *r)
return r->repl_type;
}
-int
+PRUint64
replica_get_protocol_timeout(Replica *r)
{
- return (int)r->protocol_timeout;
+ if(r){
+ return slapi_counter_get_value(r->protocol_timeout);
+ } else {
+ return 0;
+ }
+}
+
+void
+replica_set_protocol_timeout(Replica *r, PRUint64 timeout)
+{
+ if(r){
+ slapi_counter_set_value(r->protocol_timeout, timeout);
+ }
}
/*
@@ -1659,6 +1674,7 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
char *val;
int backoff_min;
int backoff_max;
+ int ptimeout = 0;
int rc;
PR_ASSERT (r && e);
@@ -1731,9 +1747,11 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
}
/* get the protocol timeout */
- r->protocol_timeout = slapi_entry_attr_get_int(e, type_replicaProtocolTimeout);
- if(r->protocol_timeout == 0){
- r->protocol_timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ ptimeout = slapi_entry_attr_get_int(e, type_replicaProtocolTimeout);
+ if(ptimeout <= 0){
+ slapi_counter_set_value(r->protocol_timeout, DEFAULT_PROTOCOL_TIMEOUT);
+ } else {
+ slapi_counter_set_value(r->protocol_timeout, ptimeout);
}
/* get replica flags */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 94c23c0..9452d51 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -396,9 +396,16 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
else if (strcasecmp (config_attr, type_replicaCleanRUV) == 0 ||
strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
{
- /* only allow the deletion of the cleanAllRUV config attributes */
+ /*
+ * Only allow the deletion of the cleanAllRUV config attributes, and the
+ * protocol timeout.
+ */
continue;
}
+ else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 )
+ {
+ replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+ }
else
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
@@ -487,6 +494,22 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
{
*returncode = LDAP_SUCCESS;
}
+ else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 ){
+ if (apply_mods && config_attr_value && config_attr_value[0])
+ {
+ long ptimeout = atol(config_attr_value);
+
+ if(ptimeout <= 0){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+ config_attr, config_attr_value);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+ } else {
+ replica_set_protocol_timeout(r, ptimeout);
+ }
+ }
+ }
else
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c
index 5bb203a..a241128 100644
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
@@ -505,11 +505,22 @@ static int
repl5_tot_stop(Private_Repl_Protocol *prp)
{
int return_value;
- int seconds = 600;
PRIntervalTime start, maxwait, now;
+ PRUint64 timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ Replica *replica = NULL;
+
+ if((timeout = agmt_get_protocol_timeout(prp->agmt)) == 0){
+ timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ if(prp->replica_object){
+ replica = object_get_data(prp->replica_object);
+ if((timeout = replica_get_protocol_timeout(replica)) == 0){
+ timeout = DEFAULT_PROTOCOL_TIMEOUT;
+ }
+ }
+ }
prp->terminate = 1;
- maxwait = PR_SecondsToInterval(seconds);
+ maxwait = PR_SecondsToInterval(timeout);
start = PR_IntervalNow();
now = start;
while (!prp->stopped && ((now - start) < maxwait))
@@ -567,7 +578,6 @@ Repl_5_Tot_Protocol_new(Repl_Protocol *rp)
prp->notify_window_opened = repl5_tot_noop;
prp->notify_window_closed = repl5_tot_noop;
prp->update_now = repl5_tot_noop;
- prp->timeout = DEFAULT_PROTOCOL_TIMEOUT;
if ((prp->lock = PR_NewLock()) == NULL)
{
goto loser;
@@ -588,6 +598,7 @@ Repl_5_Tot_Protocol_new(Repl_Protocol *rp)
prp->repl50consumer = 0;
prp->repl71consumer = 0;
prp->repl90consumer = 0;
+ prp->replica_object = prot_get_replica_object(rp);
return prp;
loser:
repl5_tot_delete(&prp);
--
1.8.1.4