Re: [PATCH] Support dynamic UDPU membership

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Steve, 

thanks for porting the patch.
i'm happy to make the suggested changes. I should be able to use git 
and work against the master. Will post the updated patch as soon
as i have all the corrections done.


Anton.


On Oct 21, 2011, at 2:53 PM, Steven Dake wrote:

> Anton,
> 
> I forward ported your patch to master and posted it to the mailing list
> via git send-email (we develop first in master, then backport to avoid
> regressions).
> 
> Really nice work!  There are a few issues that need addressing.  If you
> are unable to do the updates (against master), please let us know and
> someone from the community can pick up the patch.
> 
> Don't worry about backporting to a stable version - branch maintainer
> will take care of that work.
> 
> Patch review below
> 
> On 10/21/2011 02:38 PM, Steven Dake wrote:
>> From: Anton Jouline <anton.jouline@xxxxxxxxxxxxxxxxxx>
>> 
>> We are using a new db object to keep track of dynamic members, called
>> "totem.interface.dynamic". You create and delete child objects of that object,
>> using corosync-objctl utility:
>> 
>> to add new member:
>> corosync-objctl -c totem.interface.dynamic.10-211-55-12
>> 
>> to delete an existing member:
>> corosync-objctl -d totem.interface.dynamic.10-211-55-12
>> 
>> Then the logic in main.c reacts to those events accordingly, by adding a member
>> to the member list, or removing an existing one from it. (The object names are
>> basically IP addresses with dots replaced by dashes, because the dot is used as
>> separator in object hierarchy.)
>> 
>> The patch was successfully tested with Corosync versions 1.4.1 and 1.4.2.
>> 
>> Signed-off-by: Steven Dake <sdake@xxxxxxxxxx>
>> ---
>> exec/main.c      |  107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> exec/totempg.c   |   14 +++++++
>> exec/totemudpu.c |   53 +++++++++++++++++++++++++++
>> 3 files changed, 174 insertions(+), 0 deletions(-)
>> 
>> diff --git a/exec/main.c b/exec/main.c
>> index aacdc2f..3f40efc 100644
>> --- a/exec/main.c
>> +++ b/exec/main.c
>> @@ -680,6 +680,112 @@ static void corosync_totem_stats_updater (void *data)
>> 		&corosync_stats_timer_handle);
>> }
>> 
>> +
>> +static void totem_dynamic_create_notify_fn(hdb_handle_t parent_object_handle,
>> +	hdb_handle_t object_handle,
>> +	const void *name_pt, size_t name_len,
>> +	void *priv_data_pt)
>> +{
>> +	struct totem_ip_address member;
>> +	int ring_no; 
>> +	int numbers[4];
>> +	int i;
>> +	char *object_name;
>> +
>> +	object_name = strndup(name_pt, name_len);
> 
> should avoid memory allocation if possible.  A better choice here would
> be a variable on the stack.
> 
> 
>> +	log_printf(LOGSYS_LEVEL_DEBUG, 
>> +		"create_object: %s\n", object_name);
>> +
>> +	memset(numbers, 0, sizeof numbers);
>> +	if (sscanf(object_name, "%d-%d-%d-%d",
>> +		&numbers[0], &numbers[1], &numbers[2], &numbers[3]) == 4) {
> 
> sscanf is pretty evil...  We provide a parser helper in totemip.h called
> totemip_parse.
> 
> I saw in the patch message you mentioned the dots were parsed as
> separate objects.  This should be fixed if this is the case.
> 
>> +		/*
>> +		 * prepare totem_ip_address struct
>> +		 */
>> +		ring_no = 0;
>> +		member.family = AF_INET;
>> +		for (i=0;i<4;i++) {
>> +			member.addr[i] = numbers[i];
>> +		}
>> +
>> +		/*
>> +		 * add new member
>> +		 */
>> +		totempg_member_add (&member, ring_no);
>> +	}
>> +
>> +	free(object_name);
> 
> no alloc, no free.  totemip_parse is non-destructive.
> 
>> +}
>> +
>> +static void totem_dynamic_destroy_notify_fn(hdb_handle_t parent_object_handle,
>> +	const void *name_pt, size_t name_len,
>> +	void *priv_data_pt)
>> +{
>> +	struct totem_ip_address member;
>> +	int ring_no; 
>> +	int numbers[4];
>> +	int i;
>> +	char *object_name;
>> +
>> +	object_name = strndup(name_pt, name_len);
>> +	log_printf(LOGSYS_LEVEL_DEBUG, 
>> +		"destroy_object: %s\n", object_name);
> 
> same comments apply to destroy
> 
>> +
>> +	memset(numbers, 0, sizeof numbers);
>> +	if (sscanf(object_name, "%d-%d-%d-%d",
>> +			&numbers[0], &numbers[1], &numbers[2], &numbers[3]) == 4) {
>> +		/* prepare totem_ip_address struct */
>> +		ring_no = 0;
>> +		member.family = AF_INET;
>> +		for (i=0;i<4;i++) {
>> +			member.addr[i] = numbers[i];
>> +		}
>> +
>> +		/*
>> +		 * add new member
>> +		 */
>> +		totempg_member_remove(&member, ring_no);
>> +	}
>> +
>> +	free(object_name);
>> +
>> +}
>> +
>> +static void corosync_totem_dynamic_init (void)
>> +{
>> +	hdb_handle_t object_find_handle;
>> +	hdb_handle_t object_totem_handle;
>> +	hdb_handle_t object_interface_handle;
>> +
>> +	if (objdb->object_find_create(OBJECT_PARENT_HANDLE,
>> +			"totem", strlen("totem"), &object_find_handle) != 0) {
>> +		log_printf(LOGSYS_LEVEL_NOTICE, 
>> +			"corosync_totem_dynamic_init:: FAILED to find totem!\n");
>> +		return;
>> +	}
>> +	if (objdb->object_find_next (object_find_handle,
>> +			&object_totem_handle) != 0) {
>> +		return;
>> +	}
>> +
>> +	if (objdb->object_find_create(object_totem_handle,
>> +			"interface", strlen("interface"), &object_find_handle) != 0) {
>> +		log_printf(LOGSYS_LEVEL_NOTICE, 
>> +			"corosync_totem_dynamic_init:: FAILED to find totem.interface!\n");
> 
> The function name is logged as part of the logging infrastructure
> already - no need to log it again.  This should be LOGSYS_LEVEL_ERROR as
> well.
> 
>> +		return;
>> +	}
>> +	if (objdb->object_find_next (object_find_handle,
>> +			&object_interface_handle) != 0) {
>> +		return;
>> +	}
>> +
>> +	objdb->object_track_start (object_interface_handle,
>> +		OBJECT_TRACK_DEPTH_RECURSIVE,
>> +		NULL,
>> +		totem_dynamic_create_notify_fn,
>> +		totem_dynamic_destroy_notify_fn,
>> +		NULL, NULL);
>> +}
>> static void corosync_totem_stats_init (void)
>> {
>> 	totempg_stats_t * stats;
>> @@ -1128,6 +1234,7 @@ static void main_service_ready (void)
>> 	cs_ipcs_init();
>> 	corosync_totem_stats_init ();
>> 	corosync_fplay_control_init ();
>> +	corosync_totem_dynamic_init ();
>> 	if (minimum_sync_mode == CS_SYNC_V2) {
>> 		log_printf (LOGSYS_LEVEL_NOTICE, "Compatibility mode set to none.  Using V2 of the synchronization engine.\n");
>> 		sync_v2_init (
>> diff --git a/exec/totempg.c b/exec/totempg.c
>> index 9e88104..99a80e9 100644
>> --- a/exec/totempg.c
>> +++ b/exec/totempg.c
>> @@ -1444,6 +1444,20 @@ void totempg_queue_level_register_callback (totem_queue_level_changed_fn fn)
>> 	totem_queue_level_changed = fn;
>> }
>> 
>> + extern int totempg_member_add (
>> + 	const struct totem_ip_address *member,
>> +	int ring_no)
>> +{
>> +	return totemmrp_member_add (member, ring_no);
>> +}
>> + 
>> + extern int totempg_member_remove (
>> + 	const struct totem_ip_address *member,
>> +	int ring_no)
>> +{
>> +	return totemmrp_member_remove (member, ring_no);
>> +}
>> +
>> extern int totempg_member_add (
>> 	const struct totem_ip_address *member,
>> 	int ring_no);
>> diff --git a/exec/totemudpu.c b/exec/totemudpu.c
>> index 21e57c7..86e84e8 100644
>> --- a/exec/totemudpu.c
>> +++ b/exec/totemudpu.c
>> @@ -1677,6 +1677,9 @@ int totemudpu_member_add (
>> 	if (new_member == NULL) {
>> 		return (-1);
>> 	}
>> +	log_printf(LOGSYS_LEVEL_NOTICE, "totemudpu_member_add:: adding new member {%d.%d.%d.%d}\n", 
>> +		member->addr[0], member->addr[1], 
>> +		member->addr[2], member->addr[3]);
> 
> totemip_print() should be used here.
> 
>> 	list_init (&new_member->list);
>> 	list_add_tail (&new_member->list, &instance->member_list);
>> 	memcpy (&new_member->member, member, sizeof (struct totem_ip_address));
>> @@ -1708,12 +1711,62 @@ int totemudpu_member_add (
>> 	return (0);
>> }
>> 
>> +int _same_ip(const struct totem_ip_address *a, const struct totem_ip_address *b);
>> +
>> +int _same_ip(const struct totem_ip_address *a, const struct totem_ip_address *b)
>> +{
>> +	return a->addr[0] == b->addr[0]
>> +		&& a->addr[1] == b->addr[1]
>> +		&& a->addr[2] == b->addr[2]
>> +		&& a->addr[3] == b->addr[3];
>> +		
>> +}
>> +
> 
> We already have an equal comparitor function called totemip_equal().
> 
>> int totemudpu_member_remove (
>> 	void *udpu_context,
>> 	const struct totem_ip_address *token_target)
>> {
>> +	int found = 0;
>> +	struct list_head *list;
>> +	struct totemudpu_member *member;
>> +
>> 	struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
>> 
>> +	/*
>> +	 * Find the member to remove and close its socket
>> +	 */
>> +	for (list = instance->member_list.next;
>> +		list != &instance->member_list;
>> +		list = list->next) {
>> +
>> +		member = list_entry (list,
>> +			struct totemudpu_member,
>> +			list);
>> +
>> +		if (_same_ip(token_target, &member->member)) {
>> +			log_printf(LOGSYS_LEVEL_NOTICE, "totemudpu_member_remove:: removing member {%d.%d.%d.%d}\n", 
>> +				member->member.addr[0], member->member.addr[1], 
>> +				member->member.addr[2], member->member.addr[3]);
>> +
> 
> totemip_print should be used here
> 
>> +			if (member->fd > 0) {
>> +				log_printf(LOGSYS_LEVEL_NOTICE, "Closing socket to: {%d.%d.%d.%d}\n",
>> +					member->member.addr[0], member->member.addr[1],
>> +					member->member.addr[2], member->member.addr[3]);
>> +				close (member->fd);
>> +				cs_poll_dispatch_delete (instance->totemudpu_poll_handle,
>> +					member->fd);
>> +			}
>> +			found = 1;
>> +			break;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * Delete the member from the list
>> +	 */
>> +	if (found)
>> +		list_del(list);
>> +
> 
> { } should be used around all conditionals ie:
> if (found) {
> 	list_del (list)
> }
> 
>> 	instance = NULL;
>> 	return (0);
>> }
> 

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux