Wed Mar 1 12:18:47 PST 2006
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Log Message:
-----------
Automatically switch log tables every Sunday at 2am, if the admin
did not set up logtable switching via crontab.
Jan
Modified Files:
--------------
slony1-engine/src/backend:
slony1_base.sql (r1.29 -> r1.30)
slony1_funcs.c (r1.39 -> r1.40)
slony1_funcs.sql (r1.77 -> r1.78)
slony1-engine/src/parsestatements:
Makefile (r1.2 -> r1.3)
slony1-engine/src/slon:
cleanup_thread.c (r1.30 -> r1.31)
-------------- next part --------------
Index: slony1_base.sql
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_base.sql,v
retrieving revision 1.29
retrieving revision 1.30
diff -Lsrc/backend/slony1_base.sql -Lsrc/backend/slony1_base.sql -u -w -r1.29 -r1.30
--- src/backend/slony1_base.sql
+++ src/backend/slony1_base.sql
@@ -442,6 +442,22 @@
(log_xid @NAMESPACE at .xxid_ops);
+-- ----------------------------------------------------------------------
+-- TABLE sl_registry
+-- ----------------------------------------------------------------------
+create table @NAMESPACE at .sl_registry (
+ reg_key text primary key,
+ reg_int4 int4,
+ reg_text text,
+ reg_timestamp timestamp
+);
+comment on table @NAMESPACE at .sl_registry is 'Stores miscellaneous runtime data';
+comment on column @NAMESPACE at .sl_registry.reg_key is 'Unique key of the runtime option';
+comment on column @NAMESPACE at .sl_registry.reg_int4 is 'Option value if type int4';
+comment on column @NAMESPACE at .sl_registry.reg_text is 'Option value if type text';
+comment on column @NAMESPACE at .sl_registry.reg_timestamp is 'Option value if type timestamp';
+
+
-- **********************************************************************
-- * Views
-- **********************************************************************
Index: slony1_funcs.sql
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_funcs.sql,v
retrieving revision 1.77
retrieving revision 1.78
diff -Lsrc/backend/slony1_funcs.sql -Lsrc/backend/slony1_funcs.sql -u -w -r1.77 -r1.78
--- src/backend/slony1_funcs.sql
+++ src/backend/slony1_funcs.sql
@@ -451,6 +451,182 @@
-- ----------------------------------------------------------------------
+-- FUNCTION registry_set_int4(key, value);
+-- FUNCTION registry_get_int4(key, default);
+-- FUNCTION registry_set_text(key, value);
+-- FUNCTION registry_get_text(key, default);
+-- FUNCTION registry_set_timestamp(key, value);
+-- FUNCTION registry_get_timestamp(key, default);
+--
+-- Functions for accessing sl_registry
+-- ----------------------------------------------------------------------
+create or replace function @NAMESPACE at .registry_set_int4(text, int4)
+returns int4 as '
+DECLARE
+ p_key alias for $1;
+ p_value alias for $2;
+BEGIN
+ if p_value is null then
+ delete from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ else
+ lock table @NAMESPACE at .sl_registry;
+ update @NAMESPACE at .sl_registry
+ set reg_int4 = p_value
+ where reg_key = p_key;
+ if not found then
+ insert into @NAMESPACE at .sl_registry (reg_key, reg_int4)
+ values (p_key, p_value);
+ end if;
+ end if;
+ return p_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_set_int4(text, int4) is
+'registry_set_int4(key, value)
+
+Set or delete a registry value';
+
+create or replace function @NAMESPACE at .registry_get_int4(text, int4)
+returns int4 as '
+DECLARE
+ p_key alias for $1;
+ p_default alias for $2;
+ v_value int4;
+BEGIN
+ select reg_int4 into v_value from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ if not found then
+ v_value = p_default;
+ if p_default notnull then
+ perform @NAMESPACE at .registry_set_int4(p_key, p_default);
+ end if;
+ else
+ if v_value is null then
+ raise exception ''Slony-I: registry key % is not an int4 value'',
+ p_key;
+ end if;
+ end if;
+ return v_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_get_int4(text, int4) is
+'registry_get_int4(key, value)
+
+Get a registry value. If not present, set and return the default.';
+
+create or replace function @NAMESPACE at .registry_set_text(text, text)
+returns text as '
+DECLARE
+ p_key alias for $1;
+ p_value alias for $2;
+BEGIN
+ if p_value is null then
+ delete from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ else
+ lock table @NAMESPACE at .sl_registry;
+ update @NAMESPACE at .sl_registry
+ set reg_text = p_value
+ where reg_key = p_key;
+ if not found then
+ insert into @NAMESPACE at .sl_registry (reg_key, reg_text)
+ values (p_key, p_value);
+ end if;
+ end if;
+ return p_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_set_text(text, text) is
+'registry_set_text(key, value)
+
+Set or delete a registry value';
+
+create or replace function @NAMESPACE at .registry_get_text(text, text)
+returns text as '
+DECLARE
+ p_key alias for $1;
+ p_default alias for $2;
+ v_value text;
+BEGIN
+ select reg_text into v_value from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ if not found then
+ v_value = p_default;
+ if p_default notnull then
+ perform @NAMESPACE at .registry_set_text(p_key, p_default);
+ end if;
+ else
+ if v_value is null then
+ raise exception ''Slony-I: registry key % is not an text value'',
+ p_key;
+ end if;
+ end if;
+ return v_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_get_text(text, text) is
+'registry_get_text(key, value)
+
+Get a registry value. If not present, set and return the default.';
+
+create or replace function @NAMESPACE at .registry_set_timestamp(text, timestamp)
+returns timestamp as '
+DECLARE
+ p_key alias for $1;
+ p_value alias for $2;
+BEGIN
+ if p_value is null then
+ delete from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ else
+ lock table @NAMESPACE at .sl_registry;
+ update @NAMESPACE at .sl_registry
+ set reg_timestamp = p_value
+ where reg_key = p_key;
+ if not found then
+ insert into @NAMESPACE at .sl_registry (reg_key, reg_timestamp)
+ values (p_key, p_value);
+ end if;
+ end if;
+ return p_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_set_timestamp(text, timestamp) is
+'registry_set_timestamp(key, value)
+
+Set or delete a registry value';
+
+create or replace function @NAMESPACE at .registry_get_timestamp(text, timestamp)
+returns timestamp as '
+DECLARE
+ p_key alias for $1;
+ p_default alias for $2;
+ v_value timestamp;
+BEGIN
+ select reg_timestamp into v_value from @NAMESPACE at .sl_registry
+ where reg_key = p_key;
+ if not found then
+ v_value = p_default;
+ if p_default notnull then
+ perform @NAMESPACE at .registry_set_timestamp(p_key, p_default);
+ end if;
+ else
+ if v_value is null then
+ raise exception ''Slony-I: registry key % is not an timestamp value'',
+ p_key;
+ end if;
+ end if;
+ return v_value;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .registry_get_timestamp(text, timestamp) is
+'registry_get_timestamp(key, value)
+
+Get a registry value. If not present, set and return the default.';
+
+
+-- ----------------------------------------------------------------------
-- FUNCTION cleanupNodelock ()
--
-- Remove old entries from the nodelock table
@@ -5119,6 +5295,8 @@
-- ----
if v_current_status = 0 then
perform "pg_catalog".setval(''@NAMESPACE at .sl_log_status'', 3);
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch.laststart'', now()::timestamp);
raise notice ''Logswitch to sl_log_2 initiated'';
return 2;
end if;
@@ -5129,6 +5307,8 @@
-- ----
if v_current_status = 1 then
perform "pg_catalog".setval(''@NAMESPACE at .sl_log_status'', 2);
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch.laststart'', now()::timestamp);
raise notice ''Logswitch to sl_log_1 initiated'';
return 1;
end if;
@@ -5136,6 +5316,84 @@
raise exception ''Previous logswitch still in progress'';
END;
' language plpgsql;
+comment on function @NAMESPACE at .logswitch_start() is
+'logswitch_start()
+
+Initiate a log table switch if none is in progress';
+
+
+-- ----------------------------------------------------------------------
+-- FUNCTION logswitch_weekly()
+--
+-- Called by slonik to ensure that a logswitch is done at least
+-- once a week. The default time is Sunday 2am.
+-- ----------------------------------------------------------------------
+create or replace function @NAMESPACE at .logswitch_weekly()
+returns int4 as '
+DECLARE
+ v_now timestamp;
+ v_now_dow int4;
+ v_auto_dow int4;
+ v_auto_time time;
+ v_auto_ts timestamp;
+ v_lastrun timestamp;
+ v_laststart timestamp;
+ v_days_since int4;
+BEGIN
+ -- ----
+ -- Check that today is the day to run at all
+ -- ----
+ v_auto_dow := @NAMESPACE at .registry_get_int4(
+ ''logswitch_weekly.dow'', 0);
+ v_now := "pg_catalog".now();
+ v_now_dow := extract (DOW from v_now);
+ if v_now_dow <> v_auto_dow then
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch_weekly.lastrun'', v_now);
+ return 0;
+ end if;
+
+ -- ----
+ -- Check that the last run of this procedure was before and now is
+ -- after the time we should automatically switch logs.
+ -- ----
+ v_auto_time := @NAMESPACE at .registry_get_text(
+ ''logswitch_weekly.time'', ''02:00'');
+ v_auto_ts := current_date + v_auto_time;
+ v_lastrun := @NAMESPACE at .registry_get_timestamp(
+ ''logswitch_weekly.lastrun'', ''epoch'');
+ if v_lastrun >= v_auto_ts or v_now < v_auto_ts then
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch_weekly.lastrun'', v_now);
+ return 0;
+ end if;
+
+ -- ----
+ -- This is the moment configured in dow+time. Check that the
+ -- last logswitch was done more than 2 days ago.
+ -- ----
+ v_laststart := @NAMESPACE at .registry_get_timestamp(
+ ''logswitch.laststart'', ''epoch'');
+ v_days_since := extract (days from (v_now - v_laststart));
+ if v_days_since < 2 then
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch_weekly.lastrun'', v_now);
+ return 0;
+ end if;
+
+ -- ----
+ -- Fire off an automatic logswitch
+ -- ----
+ perform @NAMESPACE at .logswitch_start();
+ perform @NAMESPACE at .registry_set_timestamp(
+ ''logswitch_weekly.lastrun'', v_now);
+ return 1;
+END;
+' language plpgsql;
+comment on function @NAMESPACE at .logswitch_weekly() is
+'logswitch_weekly()
+
+Ensure a logswitch is done at least weekly';
-- ----------------------------------------------------------------------
@@ -5215,6 +5473,10 @@
end if;
END;
' language plpgsql;
+comment on function @NAMESPACE at .logswitch_finish() is
+'logswitch_finish()
+
+Attempt to finalize a log table switch in progress';
-- ----------------------------------------------------------------------
@@ -5324,6 +5586,19 @@
execute ''drop function @NAMESPACE at .truncateTable(text)'';
end if;
+ -- ----
+ -- Changes for 1.2
+ -- ----
+ if p_old IN (''1.0.2'', ''1.0.5'', ''1.0.6'', ''1.1.0'', ''1.1.1'', ''1.1.2'', ''1.1.3'') then
+ -- Add new table sl_registry
+ execute ''create table @NAMESPACE at .sl_registry (
+ reg_key text primay key,
+ reg_int4 int4,
+ reg_text text,
+ reg_timestamp timestamp
+ )'';
+ end if;
+
return p_old;
end;
' language plpgsql;
Index: slony1_funcs.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/backend/slony1_funcs.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -Lsrc/backend/slony1_funcs.c -Lsrc/backend/slony1_funcs.c -u -w -r1.39 -r1.40
--- src/backend/slony1_funcs.c
+++ src/backend/slony1_funcs.c
@@ -1449,6 +1449,9 @@
VARATT_SIZEP(cs->cmdtype_D) = VARHDRSZ + 1;
*VARDATA(cs->cmdtype_D) = 'D';
+ /*
+ * And the plan to read the current log_status.
+ */
sprintf(query, "SELECT last_value::int4 FROM %s.sl_log_status",
cs->clusterident);
cs->plan_get_logstatus = SPI_saveplan(SPI_prepare(query, 0, NULL));
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/parsestatements/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lsrc/parsestatements/Makefile -Lsrc/parsestatements/Makefile -u -w -r1.2 -r1.3
--- src/parsestatements/Makefile
+++ src/parsestatements/Makefile
@@ -17,3 +17,7 @@
cmp ./test_sql.log ./test_sql.expected
install:
+
+clean:
+ rm -f scanner.o test-scanner test-scanner.o
+ rm -f *.log
Index: cleanup_thread.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/cleanup_thread.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -Lsrc/slon/cleanup_thread.c -Lsrc/slon/cleanup_thread.c -u -w -r1.30 -r1.31
--- src/slon/cleanup_thread.c
+++ src/slon/cleanup_thread.c
@@ -123,8 +123,7 @@
* cluster will run into conflicts due to trying to vacuum pg_listener
* concurrently
*/
- // while (sched_wait_time(conn, SCHED_WAIT_SOCK_READ, SLON_CLEANUP_SLEEP * 1000 + vac_bias + (rand() % (SLON_CLEANUP_SLEEP * 166))) == SCHED_STATUS_OK)
- while (sched_wait_time(conn, SCHED_WAIT_SOCK_READ, 300 * 1000) == SCHED_STATUS_OK)
+ while (sched_wait_time(conn, SCHED_WAIT_SOCK_READ, SLON_CLEANUP_SLEEP * 1000 + vac_bias + (rand() % (SLON_CLEANUP_SLEEP * 166))) == SCHED_STATUS_OK)
{
/*
* Call the stored procedure cleanupEvent()
@@ -202,6 +201,23 @@
break;
}
PQclear(res2);
+
+ /*
+ * Eventually kick off a logswitch. This might fail,
+ * but this is not really slon's problem, so we just
+ * shrug and move on if it does.
+ */
+ slon_mkquery(&query2,
+ "select %s.logswitch_weekly(); ",
+ rtcfg_namespace);
+ res2 = PQexec(dbconn, dstring_data(&query2));
+ if (PQresultStatus(res2) != PGRES_TUPLES_OK)
+ {
+ slon_log(SLON_WARN,
+ "cleanupThread: \"%s\" - %s",
+ dstring_data(&query2), PQresultErrorMessage(res2));
+ }
+ PQclear(res2);
}
PQclear(res);
gettimeofday(&tv_end, NULL);
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list