Jan Wieck wieck at lists.slony.info
Sun Jul 29 13:15:43 PDT 2007
Update of /home/cvsd/slony1/slony1-engine/src/backend
In directory main.slony.info:/tmp/cvs-serv8012/src/backend

Modified Files:
	slony1_funcs.sql 
Log Message:
Rewrote rebuildListenEntries() from scratch. The goal here is to suppress
listen entries that would cause events to arrive on cascaded subscribers
on a different path around the data provider for the subscription. 


Jan


Index: slony1_funcs.sql
===================================================================
RCS file: /home/cvsd/slony1/slony1-engine/src/backend/slony1_funcs.sql,v
retrieving revision 1.116
retrieving revision 1.117
diff -C2 -d -r1.116 -r1.117
*** slony1_funcs.sql	29 Jul 2007 17:37:34 -0000	1.116
--- slony1_funcs.sql	29 Jul 2007 20:15:41 -0000	1.117
***************
*** 4675,4710 ****
  as '
  declare
! 	v_receiver record ;
! 	v_provider record ;
! 	v_origin record ;
! 	v_reachable int4[] ;
  begin
  	-- First remove the entire configuration
  	delete from @NAMESPACE at .sl_listen;
  
! 	-- Loop over every possible pair of receiver and provider
! 	for v_receiver in select no_id from @NAMESPACE at .sl_node loop
! 		for v_provider in select pa_server as no_id from @NAMESPACE at .sl_path where pa_client = v_receiver.no_id loop
  
! 			-- Find all nodes that v_provider.no_id can receiver events from without using v_receiver.no_id			
! 			for v_origin in select * from @NAMESPACE at .ReachableFromNode(v_provider.no_id, array[v_receiver.no_id]) as r(no_id) loop
  
! 				-- If v_receiver.no_id subscribes a set from v_provider.no_id, events have to travel the same
! 				-- path as the data. Ignore possible sl_listen that would break that rule.
! 				perform 1 from @NAMESPACE at .sl_subscribe
! 					join @NAMESPACE at .sl_set on sl_set.set_id = sl_subscribe.sub_set
! 		 			where
! 						sub_receiver = v_receiver.no_id and
! 						sub_provider != v_provider.no_id and
! 						set_origin = v_origin.no_id ;
! 				if not found then
! 					insert into @NAMESPACE at .sl_listen (li_receiver, li_provider, li_origin)
! 						values (v_receiver.no_id, v_provider.no_id, v_origin.no_id) ;
! 				end if ;
  
  
! 			end loop ;
  
- 		end loop ;
  	end loop ;
  
--- 4675,4756 ----
  as '
  declare
! 	v_row	record;
  begin
  	-- First remove the entire configuration
  	delete from @NAMESPACE at .sl_listen;
  
! 	-- Second populate the sl_listen configuration with a full
! 	-- network of all possible paths.
! 	insert into @NAMESPACE at .sl_listen
! 				(li_origin, li_provider, li_receiver)
! 			select pa_server, pa_server, pa_client from @NAMESPACE at .sl_path;
! 	while true loop
! 		insert into @NAMESPACE at .sl_listen
! 					(li_origin, li_provider, li_receiver)
! 			select distinct li_origin, pa_server, pa_client
! 				from @NAMESPACE at .sl_listen, @NAMESPACE at .sl_path
! 				where li_receiver = pa_server
! 				  and li_origin <> pa_client
! 			except
! 			select li_origin, li_provider, li_receiver
! 				from @NAMESPACE at .sl_listen;
  
! 		if not found then
! 			exit;
! 		end if;
! 	end loop;
  
! 	-- We now replace specific event-origin,receiver combinations
! 	-- with a configuration that tries to avoid events arriving at
! 	-- a node before the data provider actually has the data ready.
  
+ 	-- Loop over every possible pair of receiver and event origin
+ 	for v_row in select N1.no_id as receiver, N2.no_id as origin
+ 			from @NAMESPACE at .sl_node as N1, @NAMESPACE at .sl_node as N2
+ 			where N1.no_id <> N2.no_id
+ 	loop
+ 		-- 1st choice:
+ 		-- If we use the event origin as a data provider for any
+ 		-- set that originates on that very node, we are a direct
+ 		-- subscriber to that origin and listen there only.
+ 		if exists (select true from @NAMESPACE at .sl_set, @NAMESPACE at .sl_subscribe
+ 				where set_origin = v_row.origin
+ 				  and sub_set = set_id
+ 				  and sub_provider = v_row.origin
+ 				  and sub_receiver = v_row.receiver
+ 				  and sub_active)
+ 		then
+ 			delete from @NAMESPACE at .sl_listen
+ 				where li_origin = v_row.origin
+ 				  and li_receiver = v_row.receiver;
+ 			insert into @NAMESPACE at .sl_listen (li_origin, li_provider, li_receiver)
+ 				values (v_row.origin, v_row.origin, v_row.receiver);
+ 			continue;
+ 		end if;
  
! 		-- 2nd choice:
! 		-- If we are subscribed to any set originating on this
! 		-- event origin, we want to listen on all data providers
! 		-- we use for this origin. We are a cascaded subscriber
! 		-- for sets from this node.
! 		if exists (select true from @NAMESPACE at .sl_set, @NAMESPACE at .sl_subscribe
! 						where set_origin = v_row.origin
! 						  and sub_set = set_id
! 						  and sub_receiver = v_row.receiver
! 						  and sub_active)
! 		then
! 			delete from @NAMESPACE at .sl_listen
! 					where li_origin = v_row.origin
! 					  and li_receiver = v_row.receiver;
! 			insert into @NAMESPACE at .sl_listen (li_origin, li_provider, li_receiver)
! 					select distinct set_origin, sub_provider, v_row.receiver
! 						from @NAMESPACE at .sl_set, @NAMESPACE at .sl_subscribe
! 						where set_origin = v_row.origin
! 						  and sub_set = set_id
! 						  and sub_receiver = v_row.receiver
! 						  and sub_active;
! 			continue;
! 		end if;
  
  	end loop ;
  
***************
*** 4722,4766 ****
  
  -- ----------------------------------------------------------------------
- -- FUNCTION ReachableFromNode (receiver, blacklist)
- --
- -- ----------------------------------------------------------------------
- create or replace function @NAMESPACE at .ReachableFromNode(int4, int4[]) returns setof int4 as '
- declare
- 	v_node alias for $1 ;
- 	v_blacklist alias for $2 ;
- 	v_ignore int4[] ;
- 	v_reachable_edge_last int4[] ;
- 	v_reachable_edge_new int4[] default ''{}'' ;
- 	v_server record ;
- begin
- 	v_reachable_edge_last := array[v_node] ;
- 	v_ignore := v_blacklist || array[v_node] ;
- 	return next v_node ;
- 	while v_reachable_edge_last != ''{}'' loop
- 		v_reachable_edge_new := ''{}'' ;
- 		for v_server in select pa_server as no_id
- 			from @NAMESPACE at .sl_path
- 			where pa_client = ANY(v_reachable_edge_last) and pa_server != ALL(v_ignore)
- 		loop
- 			if v_server.no_id != ALL(v_ignore) then
- 				v_ignore := v_ignore || array[v_server.no_id] ;
- 				v_reachable_edge_new := v_reachable_edge_new || array[v_server.no_id] ;
- 				return next v_server.no_id ;
- 			end if ;
- 		end loop ;
- 		v_reachable_edge_last := v_reachable_edge_new ;
- 	end loop ;
- 	return ;
- end ;
- ' language 'plpgsql';
- 
- comment on function @NAMESPACE at .ReachableFromNode(int4, int4[]) is
- 'ReachableFromNode(receiver, blacklist)
- 
- Find all nodes that <receiver> can receive events from without
- using nodes in <blacklist> as a relay.';
- 
- 
- -- ----------------------------------------------------------------------
  -- FUNCTION generate_sync_event (interval)
  --
--- 4768,4771 ----



More information about the Slony1-commit mailing list