From ff1d843a7bc33c8fa81223b54795bc388d3b28f3 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 5 Dec 2013 11:58:56 -0500
Subject: [PATCH] Ticket 47587 - hard coded limit of 64 masters in agreement and changelog code

Bug Description:  Need to remove hardcoded limit of 64 masters.

Fix Description:  Changed the default limit to 256, and then we resize the array
                  as needed.

https://fedorahosted.org/389/ticket/47587

Reviewed by: ?
---
 ldap/servers/plugins/replication/cl5_clcache.c |   22 +++++++++++++++++-----
 ldap/servers/plugins/replication/repl5.h       |    4 ++--
 ldap/servers/plugins/replication/repl5_agmt.c  |   18 ++++++++++++++----
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
index 8218312..d86620f 100644
--- a/ldap/servers/plugins/replication/cl5_clcache.c
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
@@ -113,8 +113,9 @@ struct clc_buffer {
 	CSN			*buf_missing_csn;	/* used to detect persistent missing of CSN */
 
 	/* fields for control the CSN sequence sent to the consumer */
-	struct csn_seq_ctrl_block *buf_cscbs [MAX_NUM_OF_MASTERS];
+	struct csn_seq_ctrl_block **buf_cscbs;
 	int			 buf_num_cscbs;		/* number of csn sequence ctrl blocks */
+	int			 buf_max_cscbs;
 
 	/* fields for debugging stat */
 	int		 	 buf_load_cnt;		/* number of loads for session */
@@ -256,12 +257,15 @@ clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV
 		(*buf)->buf_record_cnt = 0;
 		(*buf)->buf_record_skipped = 0;
 		(*buf)->buf_cursor = NULL;
-		(*buf)->buf_num_cscbs = 0;
 		(*buf)->buf_skipped_new_rid = 0;
 		(*buf)->buf_skipped_csn_gt_cons_maxcsn = 0;
 		(*buf)->buf_skipped_up_to_date = 0;
 		(*buf)->buf_skipped_csn_gt_ruv = 0;
 		(*buf)->buf_skipped_csn_covered = 0;
+		(*buf)->buf_cscbs  = (struct csn_seq_ctrl_block **) slapi_ch_calloc(MAX_NUM_OF_MASTERS + 1,
+			                 sizeof(struct csn_seq_ctrl_block *));
+		(*buf)->buf_num_cscbs = 0;
+		(*buf)->buf_max_cscbs = MAX_NUM_OF_MASTERS;
 	}
 	else {
 		*buf = clcache_new_buffer ( consumer_rid );
@@ -311,7 +315,7 @@ clcache_return_buffer ( CLC_Buffer **buf )
 	for ( i = 0; i < (*buf)->buf_num_cscbs; i++ ) {
 		clcache_free_cscb ( &(*buf)->buf_cscbs[i] );
 	}
-	(*buf)->buf_num_cscbs = 0;
+	slapi_ch_free((void **)&(*buf)->buf_cscbs);
 
 	if ( (*buf)->buf_cursor ) {
 
@@ -554,7 +558,7 @@ clcache_refresh_consumer_maxcsns ( CLC_Buffer *buf )
 static int
 clcache_refresh_local_maxcsn ( const ruv_enum_data *rid_data, void *data )
 {
-	CLC_Buffer *buf = (CLC_Buffer*) data;
+	struct clc_buffer *buf = (struct clc_buffer*) data;
 	ReplicaId rid;
 	int rc = 0;
 	int i;
@@ -575,7 +579,12 @@ clcache_refresh_local_maxcsn ( const ruv_enum_data *rid_data, void *data )
 			break;
 	}
 	if ( i >= buf->buf_num_cscbs ) {
-		buf->buf_cscbs[i] = clcache_new_cscb ();
+		if( i + 1 > buf->buf_max_cscbs){
+			buf->buf_cscbs = (struct csn_seq_ctrl_block **) slapi_ch_realloc((char *)buf->buf_cscbs,
+							 (i + 2) * sizeof(struct csn_seq_ctrl_block *));
+			buf->buf_max_cscbs = i + 1;
+		}
+		buf->buf_cscbs[i] = clcache_new_cscb();
 		if ( buf->buf_cscbs[i] == NULL ) {
 			return -1;
 		}
@@ -878,6 +887,9 @@ clcache_new_buffer ( ReplicaId consumer_rid )
 		buf->buf_agmt_name = get_thread_private_agmtname();
 		buf->buf_consumer_rid = consumer_rid;
 		buf->buf_num_cscbs = 0;
+		buf->buf_max_cscbs = MAX_NUM_OF_MASTERS;
+		buf->buf_cscbs  = (struct csn_seq_ctrl_block **) slapi_ch_calloc(MAX_NUM_OF_MASTERS + 1,
+					sizeof(struct csn_seq_ctrl_block *));
 
 		welldone = 1;
 
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index eb646e3..9bed558 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -140,11 +140,11 @@
 
 #define DEFAULT_PROTOCOL_TIMEOUT 120
 
-/* To Allow Consumer Initialisation when adding an agreement - */
+/* To Allow Consumer Initialization when adding an agreement - */
 #define STATE_PERFORMING_TOTAL_UPDATE 501
 #define STATE_PERFORMING_INCREMENTAL_UPDATE 502
 
-#define MAX_NUM_OF_MASTERS		64
+#define MAX_NUM_OF_MASTERS		256
 #define REPL_SESSION_ID_SIZE	64
 
 #define REPL_GET_DN(addrp) slapi_sdn_get_dn((addrp)->sdn)
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 6a9f8ad..55a74c8 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -111,8 +111,9 @@ typedef struct repl5agmt {
 	const Slapi_RDN *rdn; /* RDN of replication agreement entry */
 	char *long_name; /* Long name (rdn + host, port) of entry, for logging */
 	Repl_Protocol *protocol; /* Protocol object - manages protocol */
-	struct changecounter *changecounters[MAX_NUM_OF_MASTERS]; /* changes sent/skipped since server start up */
+	struct changecounter **changecounters; /* changes sent/skipped since server start up */
 	int num_changecounters;
+	int max_changecounters;
 	time_t last_update_start_time; /* Local start time of last update session */
 	time_t last_update_end_time; /* Local end time of last update session */
 	char last_update_status[STATUS_LEN]; /* Status of last update. Format = numeric code <space> textual description */
@@ -455,14 +456,17 @@ agmt_new_from_entry(Slapi_Entry *e)
 	/* Initialize status information */
 	ra->last_update_start_time = 0UL;
 	ra->last_update_end_time = 0UL;
-	ra->num_changecounters = 0;
 	ra->last_update_status[0] = '\0';
 	ra->update_in_progress = PR_FALSE;
 	ra->stop_in_progress = PR_FALSE;
 	ra->last_init_end_time = 0UL;
 	ra->last_init_start_time = 0UL;
 	ra->last_init_status[0] = '\0';
-	
+	ra->changecounters = (struct changecounter**) slapi_ch_calloc(MAX_NUM_OF_MASTERS + 1,
+	                     sizeof(struct changecounter *));
+	ra->num_changecounters = 0;
+	ra->max_changecounters = MAX_NUM_OF_MASTERS;
+
 	/* Fractional attributes */
 	slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr);
 
@@ -629,6 +633,7 @@ agmt_delete(void **rap)
 	{
 		slapi_ch_free((void **)&ra->changecounters[ra->num_changecounters]);
 	}
+	slapi_ch_free((void **)&ra->changecounters);
 
 	if (ra->agreement_type == REPLICA_TYPE_WINDOWS)
 	{
@@ -2345,7 +2350,12 @@ agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped)
 		}
 		else
 		{
-			ra->num_changecounters ++;
+			ra->num_changecounters++;
+			if(ra->num_changecounters > ra->max_changecounters){
+				ra->changecounters = (struct changecounter**) slapi_ch_realloc((char *)ra->changecounters,
+				                     (ra->num_changecounters + 1) * sizeof(struct changecounter*));
+				ra->max_changecounters = ra->num_changecounters;
+			}
 			ra->changecounters[i] = (struct changecounter*) slapi_ch_calloc(1, sizeof(struct changecounter));
 			ra->changecounters[i]->rid = rid;
 			if ( skipped )
-- 
1.7.1

