declare
p_set_id alias for $1;
p_new_origin alias for $2;
v_local_node_id int4;
v_set_row record;
v_sub_row record;
v_sync_seqno int8;
v_lv_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that the set is locked and that this locking
-- happened long enough ago.
-- ----
v_local_node_id := getLocalNodeId('_schemadoc');
select * into v_set_row from sl_set
where set_id = p_set_id
for update;
if not found then
raise exception 'Slony-I: set % not found', p_set_id;
end if;
if v_set_row.set_origin <> v_local_node_id then
raise exception 'Slony-I: set % does not originate on local node',
p_set_id;
end if;
if v_set_row.set_locked isnull then
raise exception 'Slony-I: set % is not locked', p_set_id;
end if;
if v_set_row.set_locked > "pg_catalog".txid_snapshot_xmin("pg_catalog".txid_current_snapshot()) then
raise exception 'Slony-I: cannot move set % yet, transactions < % are still in progress',
p_set_id, v_set_row.set_locked;
end if;
-- ----
-- Unlock the set
-- ----
perform unlockSet(p_set_id);
-- ----
-- Check that the new_origin is an active subscriber of the set
-- ----
select * into v_sub_row from sl_subscribe
where sub_set = p_set_id
and sub_receiver = p_new_origin;
if not found then
raise exception 'Slony-I: set % is not subscribed by node %',
p_set_id, p_new_origin;
end if;
if not v_sub_row.sub_active then
raise exception 'Slony-I: subsctiption of node % for set % is inactive',
p_new_origin, p_set_id;
end if;
-- ----
-- Reconfigure everything
-- ----
perform moveSet_int(p_set_id, v_local_node_id,
p_new_origin, 0);
perform RebuildListenEntries();
-- ----
-- At this time we hold access exclusive locks for every table
-- in the set. But we did move the set to the new origin, so the
-- createEvent() we are doing now will not record the sequences.
-- ----
v_sync_seqno := createEvent('_schemadoc', 'SYNC');
insert into sl_seqlog
(seql_seqid, seql_origin, seql_ev_seqno, seql_last_value)
select seq_id, v_local_node_id, v_sync_seqno, seq_last_value
from sl_seqlastvalue
where seq_set = p_set_id;
-- ----
-- Finally we generate the real event
-- ----
return createEvent('_schemadoc', 'MOVE_SET',
p_set_id::text, v_local_node_id::text, p_new_origin::text);
end; |