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