From: Petr Jelinek Date: Tue, 30 Jun 2015 16:27:46 +0000 (+0200) Subject: Add function to clear sequence's amdata X-Git-Url: http://git.postgresql.org/gitweb/static/%7B%7Bpguslink%28?a=commitdiff_plain;h=f8bcb8aa3301e5a398d8189eff7d7d44e47c91a3;p=2ndquadrant_bdr.git Add function to clear sequence's amdata Function bdr.bdr_internal_sequence_reset_cache(regclass) sets the amdata of the sequence to NULL and schedules sequencer wakeup. This is first step for implementing GH #101. --- diff --git a/Makefile.in b/Makefile.in index 779ac14681..1bfc310803 100644 --- a/Makefile.in +++ b/Makefile.in @@ -34,7 +34,8 @@ DATA = \ extsql/bdr--0.10.0.1--0.10.0.2.sql \ extsql/bdr--0.10.0.2--0.10.0.3.sql \ extsql/bdr--0.10.0.3--0.10.0.4.sql \ - extsql/bdr--0.10.0.4--0.10.0.5.sql + extsql/bdr--0.10.0.4--0.10.0.5.sql \ + extsql/bdr--0.10.0.5--0.10.0.6.sql DATA_built = \ extsql/bdr--0.8.0.1.sql \ @@ -56,7 +57,8 @@ DATA_built = \ extsql/bdr--0.10.0.2.sql \ extsql/bdr--0.10.0.3.sql \ extsql/bdr--0.10.0.4.sql \ - extsql/bdr--0.10.0.5.sql + extsql/bdr--0.10.0.5.sql \ + extsql/bdr--0.10.0.6.sql DOCS = bdr.conf.sample README.bdr SCRIPTS = scripts/bdr_initial_load bdr_init_copy bdr_resetxlog bdr_dump @@ -217,6 +219,10 @@ extsql/bdr--0.10.0.5.sql: extsql/bdr--0.10.0.4.sql extsql/bdr--0.10.0.4--0.10.0. mkdir -p extsql cat $^ > $@ +extsql/bdr--0.10.0.6.sql: extsql/bdr--0.10.0.5.sql extsql/bdr--0.10.0.5--0.10.0.6.sql + mkdir -p extsql + cat $^ > $@ + bdr_resetxlog: pg_resetxlog.o $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(libpq_pgport) $(LIBS) -o $@$(X) @@ -266,11 +272,13 @@ check: regresscheck isolationcheck DDLREGRESSCHECKS=ddl/enable_ddl ddl/create ddl/alter_table ddl/extension ddl/function \ ddl/grant ddl/mixed ddl/namespace ddl/read_only ddl/replication_set \ ddl/sequence ddl/view ddl/disable_ddl +EXTRAREGRESSCHECKS=dml/sequence REGRESSINIT=init_bdr REGRESSTEARDOWN=part_bdr else check: regresscheck DDLREGRESSCHECKS= +EXTRAREGRESSCHECKS= REGRESSINIT=init_udr REGRESSTEARDOWN=part_udr endif @@ -287,6 +295,7 @@ REGRESSCHECKS= \ pause \ $(DDLREGRESSCHECKS) \ dml/basic dml/contrib dml/delete_pk dml/extended dml/missing_pk dml/toasted \ + $(EXTRAREGRESSCHECKS) \ $(REGRESSTEARDOWN) diff --git a/bdr.control b/bdr.control index f513dff24c..1ebfa15371 100644 --- a/bdr.control +++ b/bdr.control @@ -1,6 +1,6 @@ # bdr extension comment = 'Bi-directional replication for PostgreSQL' -default_version = '0.10.0.5' +default_version = '0.10.0.6' module_pathname = '$libdir/bdr' relocatable = false requires = btree_gist diff --git a/bdr.h b/bdr.h index 3ab46b203a..a096af7fd3 100644 --- a/bdr.h +++ b/bdr.h @@ -435,10 +435,6 @@ extern void bdr_sequencer_fill_sequences(void); extern void bdr_sequencer_wakeup(void); extern void bdr_schedule_eoxact_sequencer_wakeup(void); - -PGDLLEXPORT extern Datum bdr_sequence_alloc(PG_FUNCTION_ARGS); -PGDLLEXPORT extern Datum bdr_sequence_setval(PG_FUNCTION_ARGS); -PGDLLEXPORT extern Datum bdr_sequence_options(PG_FUNCTION_ARGS); #endif extern int bdr_sequencer_get_next_free_slot(void); //XXX PERDB temp diff --git a/bdr_seq.c b/bdr_seq.c index 69a8a778d4..344039ec67 100644 --- a/bdr_seq.c +++ b/bdr_seq.c @@ -32,6 +32,7 @@ #include "executor/spi.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/snapmgr.h" @@ -464,6 +465,10 @@ bdr_sequencer_shmem_init(int sequencers) prev_shmem_startup_hook = shmem_startup_hook; shmem_startup_hook = bdr_sequencer_shmem_startup; + /* + * We do the reloptions initialization here because this function is called + * at startup for every backend. + */ bdr_seq_relopt_kind = add_reloption_kind(); add_int_reloption(bdr_seq_relopt_kind, "cache_chunks", "Sets how many chunks shoult be cached on each node.", @@ -1322,3 +1327,86 @@ bdr_sequence_options(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } + + +/* + * Resets the sequence cache, needed for initialization from binary clone. + */ +PGDLLEXPORT Datum bdr_internal_sequence_reset_cache(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(bdr_internal_sequence_reset_cache); + +Datum +bdr_internal_sequence_reset_cache(PG_FUNCTION_ARGS) +{ + Oid seqoid = PG_GETARG_OID(0); + Buffer buf; + SeqTable elm; + Relation rel; + HeapTupleData seqtuple; + Datum values[SEQ_COL_LASTCOL]; + bool nulls[SEQ_COL_LASTCOL]; + HeapTuple newtup; + Page page, temppage; + + /* lock page, fill heaptup */ + init_sequence(seqoid, &elm, &rel); + (void) read_seq_tuple(elm, rel, &buf, &seqtuple); + + /* get values */ + heap_deform_tuple(&seqtuple, RelationGetDescr(rel), + values, nulls); + + /* if already null nothing needs to be done */ + if (nulls[SEQ_COL_AMDATA - 1]) + goto done_with_sequence; + + /* otherwise create new tuple with null amdata and save it */ + nulls[SEQ_COL_AMDATA - 1] = true; + newtup = heap_form_tuple(RelationGetDescr(rel), values, nulls); + + /* special requirements for sequence tuples */ + HeapTupleHeaderSetXmin(newtup->t_data, FrozenTransactionId); + HeapTupleHeaderSetXminFrozen(newtup->t_data); + HeapTupleHeaderSetCmin(newtup->t_data, FirstCommandId); + HeapTupleHeaderSetXmax(newtup->t_data, InvalidTransactionId); + newtup->t_data->t_infomask |= HEAP_XMAX_INVALID; + ItemPointerSet(&newtup->t_data->t_ctid, 0, FirstOffsetNumber); + + page = BufferGetPage(buf); + temppage = PageGetTempPage(page); + + /* replace page contents, the direct way */ + PageInit(temppage, BufferGetPageSize(buf), PageGetSpecialSize(page)); + memcpy(PageGetSpecialPointer(temppage), + PageGetSpecialPointer(page), + PageGetSpecialSize(page)); + + if (PageAddItem(temppage, (Item) newtup->t_data, newtup->t_len, + FirstOffsetNumber, false, false) == InvalidOffsetNumber) + elog(PANIC, "reset_sequence_cache: failed to add item to page"); + + PageSetLSN(temppage, PageGetLSN(page)); + + START_CRIT_SECTION(); + + MarkBufferDirty(buf); + + memcpy(page, temppage, BufferGetPageSize(buf)); + + seqtuple.t_len = newtup->t_len; + + log_sequence_tuple(rel, &seqtuple, page); + + END_CRIT_SECTION(); + +done_with_sequence: + + UnlockReleaseBuffer(buf); + heap_close(rel, NoLock); + + bdr_sequencer_wakeup(); + bdr_schedule_eoxact_sequencer_wakeup(); + + PG_RETURN_VOID(); +} diff --git a/expected/dml/sequence.out b/expected/dml/sequence.out new file mode 100644 index 0000000000..461e4f7600 --- /dev/null +++ b/expected/dml/sequence.out @@ -0,0 +1,45 @@ +CREATE SEQUENCE bdr_test_seq USING bdr; +SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0); + pg_xlog_wait_remote_apply +--------------------------- + +(1 row) + +DO $$ +BEGIN + LOOP + IF (SELECT amdata IS NOT NULL FROM bdr_test_seq) THEN + EXIT; + END IF; + PERFORM pg_sleep(0.1); + END LOOP; +END;$$; +CREATE TEMP TABLE bdr_test_seq_val AS SELECT nextval('bdr_test_seq') as last_val; +SELECT bdr.bdr_internal_sequence_reset_cache('bdr_test_seq'::regclass); + bdr_internal_sequence_reset_cache +----------------------------------- + +(1 row) + +SELECT amdata IS NULL FROM bdr_test_seq; + ?column? +---------- + t +(1 row) + +DO $$ +BEGIN + LOOP + IF (SELECT amdata IS NOT NULL FROM bdr_test_seq) THEN + EXIT; + END IF; + PERFORM pg_sleep(0.1); + END LOOP; +END;$$; +-- 10000 is maximum cache size in amdata +SELECT nextval('bdr_test_seq') >= last_val + 10000 FROM bdr_test_seq_val; + ?column? +---------- + t +(1 row) + diff --git a/expected/upgrade.out b/expected/upgrade.out index 44a91f70a5..b6375f05fc 100644 --- a/expected/upgrade.out +++ b/expected/upgrade.out @@ -49,6 +49,8 @@ CREATE EXTENSION bdr VERSION '0.10.0.4'; DROP EXTENSION bdr; CREATE EXTENSION bdr VERSION '0.10.0.5'; DROP EXTENSION bdr; +CREATE EXTENSION bdr VERSION '0.10.0.6'; +DROP EXTENSION bdr; -- evolve version one by one from the oldest to the newest one CREATE EXTENSION bdr VERSION '0.8.0'; ALTER EXTENSION bdr UPDATE TO '0.8.0.1'; @@ -71,14 +73,15 @@ ALTER EXTENSION bdr UPDATE TO '0.10.0.2'; ALTER EXTENSION bdr UPDATE TO '0.10.0.3'; ALTER EXTENSION bdr UPDATE TO '0.10.0.4'; ALTER EXTENSION bdr UPDATE TO '0.10.0.5'; +ALTER EXTENSION bdr UPDATE TO '0.10.0.6'; -- Should never have to do anything: You missed adding the new version above. ALTER EXTENSION bdr UPDATE; -NOTICE: version "0.10.0.5" of extension "bdr" is already installed +NOTICE: version "0.10.0.6" of extension "bdr" is already installed \dx bdr List of installed extensions Name | Version | Schema | Description ------+----------+------------+------------------------------------------- - bdr | 0.10.0.5 | pg_catalog | Bi-directional replication for PostgreSQL + bdr | 0.10.0.6 | pg_catalog | Bi-directional replication for PostgreSQL (1 row) \c postgres diff --git a/extsql/bdr--0.10.0.5--0.10.0.6.sql b/extsql/bdr--0.10.0.5--0.10.0.6.sql new file mode 100644 index 0000000000..3151695cee --- /dev/null +++ b/extsql/bdr--0.10.0.5--0.10.0.6.sql @@ -0,0 +1,10 @@ +SET LOCAL search_path = bdr; +SET bdr.permit_unsafe_ddl_commands = true; +SET bdr.skip_ddl_replication = true; + +CREATE OR REPLACE FUNCTION bdr.bdr_internal_sequence_reset_cache(seq regclass) +RETURNS void LANGUAGE c AS 'MODULE_PATHNAME' STRICT; + +RESET bdr.permit_unsafe_ddl_commands; +RESET bdr.skip_ddl_replication; +RESET search_path; diff --git a/sql/dml/sequence.sql b/sql/dml/sequence.sql new file mode 100644 index 0000000000..6084dd4514 --- /dev/null +++ b/sql/dml/sequence.sql @@ -0,0 +1,31 @@ +CREATE SEQUENCE bdr_test_seq USING bdr; + +SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0); + +DO $$ +BEGIN + LOOP + IF (SELECT amdata IS NOT NULL FROM bdr_test_seq) THEN + EXIT; + END IF; + PERFORM pg_sleep(0.1); + END LOOP; +END;$$; + +CREATE TEMP TABLE bdr_test_seq_val AS SELECT nextval('bdr_test_seq') as last_val; + +SELECT bdr.bdr_internal_sequence_reset_cache('bdr_test_seq'::regclass); +SELECT amdata IS NULL FROM bdr_test_seq; + +DO $$ +BEGIN + LOOP + IF (SELECT amdata IS NOT NULL FROM bdr_test_seq) THEN + EXIT; + END IF; + PERFORM pg_sleep(0.1); + END LOOP; +END;$$; + +-- 10000 is maximum cache size in amdata +SELECT nextval('bdr_test_seq') >= last_val + 10000 FROM bdr_test_seq_val; diff --git a/sql/upgrade.sql b/sql/upgrade.sql index 11b7cd180d..b8c37e7a7e 100644 --- a/sql/upgrade.sql +++ b/sql/upgrade.sql @@ -72,6 +72,9 @@ DROP EXTENSION bdr; CREATE EXTENSION bdr VERSION '0.10.0.5'; DROP EXTENSION bdr; +CREATE EXTENSION bdr VERSION '0.10.0.6'; +DROP EXTENSION bdr; + -- evolve version one by one from the oldest to the newest one CREATE EXTENSION bdr VERSION '0.8.0'; ALTER EXTENSION bdr UPDATE TO '0.8.0.1'; @@ -94,6 +97,7 @@ ALTER EXTENSION bdr UPDATE TO '0.10.0.2'; ALTER EXTENSION bdr UPDATE TO '0.10.0.3'; ALTER EXTENSION bdr UPDATE TO '0.10.0.4'; ALTER EXTENSION bdr UPDATE TO '0.10.0.5'; +ALTER EXTENSION bdr UPDATE TO '0.10.0.6'; -- Should never have to do anything: You missed adding the new version above. ALTER EXTENSION bdr UPDATE;