Slony-I 2.2.11 Documentation
Prev | Fast Backward | Chapter 8. Schema schemadoc | Fast Forward | Next

# 8.83. rebuildlistenentries()

Function Properties

Language: PLPGSQL

Return Type: integer

RebuildListenEntries() Invoked by various subscription and path modifying functions, this rewrites the sl_listen entries, adding in all the ones required to allow communications between nodes in the Slony-I cluster.

    declare
    	v_row	record;
            v_cnt  integer;
    begin
    	-- ----
    	-- Grab the central configuration lock
    	-- ----
    	lock table sl_config_lock;

    	-- First remove the entire configuration
    	delete from sl_listen;

    	-- Second populate the sl_listen configuration with a full
    	-- network of all possible paths.
    	insert into sl_listen
    				(li_origin, li_provider, li_receiver)
    			select pa_server, pa_server, pa_client from sl_path;
    	while true loop
    		insert into sl_listen
    					(li_origin, li_provider, li_receiver)
    			select distinct li_origin, pa_server, pa_client
    				from sl_listen, sl_path
    				where li_receiver = pa_server
    				  and li_origin <> pa_client
    				  and pa_conninfo<>'<event pending>'
    			except
    			select li_origin, li_provider, li_receiver
    				from 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,
    			  N2.no_failed as failed
    			from sl_node as N1, 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 sl_set, sl_subscribe				, sl_node p
    				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
    				  and p.no_active
    				  and p.no_id=sub_provider
    				  )
    		then
    			delete from sl_listen
    				where li_origin = v_row.origin
    				  and li_receiver = v_row.receiver;
    			insert into sl_listen (li_origin, li_provider, li_receiver)
    				values (v_row.origin, v_row.origin, v_row.receiver);

    		-- 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.
    		else
    				if exists (select true from sl_set, sl_subscribe,
    				   	  	       sl_node provider
    						where set_origin = v_row.origin
    						  and sub_set = set_id
    						  and sub_provider=provider.no_id
    						  and provider.no_failed = false
    						  and sub_receiver = v_row.receiver
    						  and sub_active)
    				then
    						delete from sl_listen
    							   where li_origin = v_row.origin
    					  		   and li_receiver = v_row.receiver;
    						insert into sl_listen (li_origin, li_provider, li_receiver)
    						select distinct set_origin, sub_provider, v_row.receiver
    							   from sl_set, sl_subscribe
    						where set_origin = v_row.origin
    						  and sub_set = set_id
    						  and sub_receiver = v_row.receiver
    						  and sub_active;
    				end if;
    		end if;

    		if v_row.failed then

    		--for every failed node we delete all sl_listen entries
    		--except via providers (listed in sl_subscribe)
    		--or failover candidates (sl_failover_targets)
    		--we do this to prevent a non-failover candidate
    		--that is more ahead of the failover candidate from
    		--sending events to the failover candidate that
    		--are 'too far ahead'

    		--if the failed node is not an origin for any
                    --node then we don't delete all listen paths
    		--for events from it.  Instead we leave
                    --the listen network alone.

    		select count(*) into v_cnt from sl_subscribe sub,
    		       sl_set s
                           where s.set_origin=v_row.origin and s.set_id=sub.sub_set;
                    if v_cnt > 0 then
    		    delete from sl_listen where
    			   li_origin=v_row.origin and
    			   li_receiver=v_row.receiver
    			   and li_provider not in
    			       (select sub_provider from
    			       sl_subscribe,
    			       sl_set where
    			       sub_set=set_id
    			       and set_origin=v_row.origin);
    		    end if;
                   end if;
    --		   insert into sl_listen
    --		   		  (li_origin,li_provider,li_receiver)
    --				  SELECT v_row.origin, pa_server
    --				  ,v_row.receiver
    --				  FROM sl_path where
    --				  	   pa_client=v_row.receiver
    --				  and (v_row.origin,pa_server,v_row.receiver) not in
    --				  	  		(select li_origin,li_provider,li_receiver
    --					  		from sl_listen);
    --		end if;
    	end loop ;

    	return null ;
    end ;

Prev | Home | Next
preparetableforcopy(p_tab_id integer) | Up | recreate_log_trigger(p_tab_attkind text, p_tab_id oid, p_fq_table_name text)