Tue Feb 22 04:14:07 PST 2005
- Previous message: [Slony1-commit] By cbbrowne: Fix typo in filelist.sgml - missing quote
- Next message: [Slony1-commit] By xfade: Check for real net-snmp headers instead of the wrapper
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Log Message:
-----------
Purge out slonspool area that is obsolete
Removed Files:
-------------
slony1-engine/src/slonspool:
NOTES
README
Tasks
gen_output.pm
init.pm
slonspool.pl
subscribe.pm
-------------- next part --------------
--- src/slonspool/Tasks
+++ /dev/null
@@ -1,45 +0,0 @@
-1. Modifications to DB Schema
-
-sl_node needs a new boolean field, no_spool
-
- alter table @NAMESPACE at .sl_node add column no_spool boolean default 'f';
-
- comment on column @NAMESPACE at .sl_node.no_spool is
- 'Value is t if this node is a Log Shipping/Spooling node which does not communicate with other nodes.';
-
-2. Modifications to stored functions
-
- Numerous functions that do node-based things need to reject updates on nodes where no_spool = 't':
-
- - moveset() and moveset_int() cannot move set to a node where no_spool = 't'
-
- - storepath() and storepath_int() must fail when given a node where
- no_spool = 't'; there is no path to that node
-
- - storeset() and storeset_int() must reject an origin where no_spool = 't'
-
- - subscribeset(set,provider,receiver,forward) and subscribeset_int(set,provider,receiver,forward)
- should reject both provider and receiver where no_spool = 't'
-
- - unsubscribeset() and unsubscribeset_int() rejects where receiver has no_spool = 't'
-
- Add in function nodespool(node) and nodespool_int(node):
-
- - These verify that the node hasn't got any subscribers or paths or
- listens, and then modify sl_node.no_spool to 't'.
-
-3. Slonik
-
- Need an extra boolean option, "spooler", which, if set to 'TRUE'
- causes slonik to call nodespool(node).
-
-4. slon
-
- Should be pretty oblivious of "log shipping."
-
-5. slon_spool
-
- This is an alternative to slon, which gets used to generate "log shipper" output
-
- It's a script/program that is passed information allowing it to
- connect to Slony-I, along with a node number.
--- src/slonspool/subscribe.pm
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/perl
-# $Id: subscribe.pm,v 1.1 2004/11/30 23:38:41 cbbrowne Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-sub subscribe_to_node {
- open(SUBSCRIBE, ">$spoolpath/subscription.log");
- foreach $set (@SETS) {
-
- # Create namespaces
- print SUBSCRIBE "-- Subscribing node $node to set $set on $host - $port/$database/$user\n";
- my $sth = $dbh->exec("select distinct nspname from pg_class p, pg_namespace n, _oxrsorg.sl_table t where t.tab_reloid = p.oid and p.relnamespace = n.oid and tab_set = $set;");
- while ( @row = $sth->fetchrow ) {
- my ($namespace) = @row;
- print SUBSCRIBE "create schema $namespace;\n";
- }
- close(SUBSCRIBE);
-
- # Create tables
- $sth = $dbh->exec("select nspname || '.' || relname from pg_class p, pg_namespace n, _oxrsorg.sl_table t where t.tab_reloid = p.oid and p.relnamespace = n.oid and tab_set = $set;");
- while ( @row = $sth->fetchrow ) {
- my ($table) = @row;
- `$pgbins/pg_dump -p $port -h $host -U $user -t $table -s $database >> $spoolpath/subscription.log`;
- }
- open(SUBSCRIBE, ">>$spoolpath/subscription.log");
-
- # Pull data, as in copy_set (remote_worker.c)
- my $query = "begin transaction; set transaction isolation level serializable;";
- $sth = $dbh->exec($query);
- my $tquery = qq{
- select T.tab_id,
- "pg_catalog".quote_ident(PGN.nspname) || '.' ||
- "pg_catalog".quote_ident(PGC.relname) as tab_fqname,
- T.tab_idxname, T.tab_comment
- from "$cluster".sl_table T,
- "pg_catalog".pg_class PGC,
- "pg_catalog".pg_namespace PGN
- where T.tab_set = $set
- and T.tab_reloid = PGC.oid
- and PGC.relnamespace = PGN.oid
- order by tab_id;
- };
- }
- $sth=$dbh->exec($tquery);
- while (@row=$sth->fetchrow) {
- my ($table) = @row;
- print SUBSCRIBE qq{copy "$table" from stdin;\n};
- my $query = qq{copy "$table" to stdout;};
- $res = $dbh->exec($query);
- my $line = "*" x 16384;
- $ret = $dbh->getline($line, 16384);
- while ($line ne "\\.") {
- print SUBSCRIBE line, "\n";
- $ret = $dbh->getline($line, 16384);
- }
- print SUBSCRIBE "\.\n";
- }
- close SUBSCRIBE;
- my $seqquery = qq{
- select n.nspname, c.relname
- from "pg_catalog".pg_class c, "pg_catalog".pg_namespace, "$cluster".sl_sequence s
- where
- n.oid = c.relnamespace and
- c.oid = s.seq_reloid and
- s.seq_set = $set;};
- $sth=$dbh->exec($seqquery);
- while (my @row=$sth->fetchrow) {
- my ($nsp, $seqname) = @row;
- `$pgbins/pg_dump -p $port -h $host -U $user -n $nsp -t $seqname $database >> $spoolpath/subscription.log`;
- }
- # Next, populate Sync information
- # Use the last SYNC's snapshot information and set
- # the action sequence list to all actions after
- # that.
-
- my $squery = qq{
- select ssy_seqno, ssy_minxid, ssy_maxxid,
- ssy_xip, ssy_action_list
- from "$cluster".sl_setsync
- where ssy_setid = $set; };
- $sth=$dbh->exec($squery);
- while (my @row=$sth->fetchrow) {
- my ($seqno, $minxid, $maxxid, $xip, $actionlist) = @row;
- }
- my $createsync = qq{
- insert into "_$cluster".sl_setsync
- (ssy_setid, ssy_origin, ssy_seqno, ssy_minxid, ssy_maxxid, ssy_xip, ssy_action_list)
- values ($set, $node, $seqno, $minxid, $maxxid, '$xip', '$actionlist');};
- print SUBSCRIBE $createsync, "\n";
-}
-
-1;
--- src/slonspool/slonspool.pl
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/perl
-# $Id: slonspool.pl,v 1.1 2004/11/30 23:38:41 cbbrowne Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Pg;
-use Getopt::Long;
-require "subscribe.pm";
-require "gen_output.pm";
-require "init.pm";
-
-my($database,$user, $host, $cluster, $password, $port, $spoolpath, $spoolname,
- $maxsize, $maxage, $subnode, $node);
-
-my @SETS;
-my $dbh;
-process_options();
-initialize_configuration();
-#subscribe_to_node();
-
-while (1) {
- listen_to_node();
-}
-
-sub listen_to_node {
- while (1) {
- process_event();
- die -1;
- }
-}
-
-sub process_event {
- my $dsn = "dbname=$database host=$host port=$port user=$user";
- if ($password) {
- $dsn .= " password=$password";
- }
- print "DSN: $dsn\n";
- my $dbh = Pg::connectdb($dsn);
- print "Last err:", $dbh->errorMessage, "\n";
- my $sync_event;
- my $last_seq = qq{select con_seqno from "_$cluster".sl_confirm
- where con_origin = $node order by con_seqno desc limit 1;};
- print $last_seq, "\n";
- my $res = $dbh->exec($last_seq);
- while (my @row = $res->fetchrow) {
- ($sync_event) = @row;
- print "Last sync: $sync_event\n";
- }
- print "Last err:", $dbh->errorMessage, "\n";
- $sync_event++;
- print "Next sync: $sync_event\n";
-
- my @ORIGINS;
- my $origin_query = qq{ select set_origin from "_$cluster".sl_set where set_id in ($opt_sets); };
- $res = $dbh->exec($origin_query);
- while (my @row = $res->fetchrow) {
- my ($origin) = @row;
- push @ORIGINS, $origin;
- }
- $origin_qualification = " (log_origin in (" . join(',', @ORIGINS) . ")) ";
-
-
- my $table_qualification = " (log_tableid in (" . join(',', @TABLES) . ")) ";
-
- print "Table qualification: $table_qualification\n";
- my $qualification .= " $origin_qualification and $table_qualification ";
-
- my $cursor_query = qq{
- declare LOG cursor for
- select log_origin, log_xid, log_tableid, log_actionseq, log_cmdtype, log_cmddata
- from "_$cluster".sl_log_1
- where $origin_qualification and $table_qualification
- order by log_xid, log_actionseq;};
-
- print "Cursor query: $cursor_query\n";
-
- my $lastxid = "";
- my $syncname=sprintf("log-%08d", $sync);
- open(LOGOUTPUT, ">$spoolpath/$syncname");
- print LOGOUTPUT "-- Data for sync $sync_event\n";
- print LOGOUTPUT "-- ", `date`;
- my $begin = $dbh->exec("begin;");
- my $cursorexec = $dbh->exec($cursor_query);
- print "Last err:", $dbh->errorMessage, "\n";
- my $foundsome = "YES";
- while ($foundsome eq "YES") {
- $foundsome = "NO";
- my $res = $dbh->exec("fetch forward 100 in LOG;");
- while (my @row = $res->fetchrow) {
- $foundsome = "YES";
- my ($origin, $xid, $tableid, $actionseq, $cmdtype, $cmddata) = @row;
- if ($xid ne $lastxid) { # changed xid - report that...
- if ($lastxid ne "") { # Do nothing first time around...
- printf LOGOUTPUT "COMMIT; -- Done xid $lastxid\n";
- }
- print LOGOUTPUT "BEGIN;\nselect fail_if_xid_applied($xid);\n";
- $lastxid = $xid;
- }
- if ($cmdtype eq "I") {
- printf LOGOUTPUT "insert into %s %s;\n", $TABLENAME[$tableid], $cmddata;
- } elsif ($cmdtype eq "U") {
- printf LOGOUTPUT "update only %s set %s;\n", $TABLENAME[$tableid], $cmddata;
- } elsif ($cmdtype eq "D") {
- printf LOGOUTPUT "delete from only %s where %s;\n", $TABLENAME[$tableid], $cmddata;
- } else {
- print LOGOUTPUT "problem: cmddata not in (I,U,D) = [$cmdtype]\n";
- }
- }
- }
- if ($lastxid ne "") {
- print LOGOUTPUT "COMMIT; -- Done xid $lastxid\n";
- }
- close LOGOUTPUT;
- $dbh->exec("rollback;");
- my $confirmation = qq{ insert into "_$cluster".sl_confirm (con_origin,con_received,con_seqno,con_timestamp)
- values ($node, $subnode, $sync_event, CURRENT_TIMESTAMP); };
- print "Confirm: $confirmation\n";
- my $cursorexec = $dbh->exec($confirmation);
-}
-
-sub connect_to_node {
- my $dsn = "dbname=$database host=$host port=$port user=$user";
- if ($password) {
- $dsn .= " password=$password";
- }
- $dbh = Pg::connectdb($dsn);
-}
-
-sub process_options {
-
- $goodopts = GetOptions("help", "database=s", "host=s", "user=s",
- "cluster=s", "password=s", "port=s", "sets=s",
- "spoolpath=s", "spoolname=s", "pgbins=s",
- "maxsize=i", "maxage=i", "node=i", "subnode=i");
-
- if (defined ($opt_help)) {
- show_usage();
- }
-
- $cluster=$opt_cluster if (defined($opt_cluster));
- $subnode = $opt_subnode if (defined ($opt_subnode));
- $node = $opt_node if (defined($opt_node));
- $database=$opt_database if (defined ($opt_database));
- $user = $opt_user if (defined ($opt_user));
- $host = $opt_host if (defined($opt_host));
- $password = $opt_password if (defined($opt_password));
- $port = $opt_port if (defined($opt_port));
- $pgbins = $opt_pgbins if (defined($opt_pgbins));
- $spoolpath = $opt_spoolpath if (defined($opt_spoolpath));
- $spoolname = $opt_spoolname if (defined($opt_spoolname));
- if (defined($opt_sets)) {
- @SETS=split (/,/, $opt_sets);
- }
- if (defined($opt_maxsize)){
- $maxsize = $opt_maxsize;
- } else {
- $maxsize = 10000;
- }
- if (defined($opt_maxage)){
- $maxsize = $opt_maxage;
- } else {
- $maxage = 300;
- }
-}
-
-sub show_usage {
- print qq{slonspool:
- --help get help
- --cluster=s Slony-I cluster name
- --subnode=s Node number subscribed through
- --node=i Node number to use to request
- --pgbins=s Location of PostgreSQL binaries including slonik and pg_dump
- --database=s database to connect to
- --host=s host for database
- --user=s user for database
- --password=s password for database (you should probably use .pgpass instead)
- --port=i port number to connect to
- --sets=s Sets to replicate (comma-delimited) - e.g --sets=1,2,4
- --spoolpath=s directory in which to spool output
- --spoolname=s naming convention for spoolfiles
- --maxsize=i maximum size of spool files, in kB - default =10000KB
- --maxage=i maximum age of spool files in seconds - default 300
-};
- die -1;
-}
--- src/slonspool/gen_output.pm
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/perl
-
-1;
--- src/slonspool/init.pm
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/perl
-# $Id: init.pm,v 1.1 2004/11/30 23:38:40 cbbrowne Exp $
-
-# Data structures...
-# %NODES{}{}
-# Fields:
-# $NODE{$i}{last_event} - Last event processed for node
-#
-# %SET{}{}
-# Fields:
-# $SET{$i}{origin} - origin node
-# $SET{$i}{comment} - Comment about set
-# $SET{$i}{provider} - node that provides data to our favorite node
-#
-# %TABLES
-# $TABLES{$i}{name}
-# $TABLES{$i}{namespace}
-# $TABLES{$i}{set}
-
-# Populate latest information about subscription providers and such...
-sub load_configuration {
- my $dsn = "dbname=$database host=$host port=$port user=$user";
- if ($password) {
- $dsn .= " password=$password";
- }
- $dbh = Pg::connectdb($dsn);
-
- # Populate %NODE with confirmation information
- my $confirm_query = qq{ select con_origin, con_seqno from "_$cluster".sl_confirm where received = $node; };
- my $res = $dbh->exec($confirm_query);
- while (my @row = $res->fetchrow) {
- my ($origin, $sync) = @row;
- if ($NODE{$origin}{last_event} < $sync) {
- $NODE{$origin}{last_event} = $sync;
- }
- }
-
- # Populate %SET with set info for the sets being handled
- my $sub_set_query = qq{ select set_id, set_origin from "_$cluster".sl_set where set_id in ($opt_sets);};
- my $res = $dbh->exec($confirm_query);
- while (my @row = $res->fetchrow) {
- my ($set, $origin) = @row;
- $SET{$set}{origin} = $origin;
- }
-
- my $tables_query = qq{select t.tab_id, t.tab_set, n.nspname, r.relname from "_$cluster".sl_table t, pg_catalog.pg_namespace n, pg_catalog.pg_class r where r.oid = t.tab_reloid and n.oid = r.relnamespace and tab_set in ($opt_sets) ;};
- $res = $dbh->exec($tables_query);
- while (my @row = $res->fetchrow) {
- my ($id, $set, $namespace, $tname) = @row;
- $TABLES{$id}{name} = $tname;
- $TABLES{$id}{namespace} = $namespace;
- $TABLES{$id}{set} = $set;
- }
-}
-
-sub storeNode {
- my ($id, $comment) = @_;
- $NODES[$id] = $comment;
-}
-
-1;
--- src/slonspool/NOTES
+++ /dev/null
@@ -1,153 +0,0 @@
-Slony-I Log Shipping
-==========================================
-
-One of the features intended for 1.1 is the ability to serialize the
-updates to go out into files that can be kept in a spool directory.
-
-The spool files could then be transferred via whatever means was
-desired to a "slave system," whether that be via FTP, rsync, or
-perhaps even by pushing them onto a 1GB "USB key" to be sent to the
-destination by clipping it to the ankle of some sort of "avian
-transport" system ;-) .
-
-There are plenty of neat things you can do with a data stream in this
-form, including:
-
- -> Using it to replicate to nodes that _aren't_ securable
- -> Supporting a different form of PITR
- -> If disaster strikes, you can look at the logs of queries
- themselves
- -> This is a neat scheme for building load for tests...
- -> We have a data "escrow" system that would become incredibly
- cheaper given 'log shipping'
-
-But we need to start thinking about how to implement it to be usable.
-I'm at the stage of starting to think about questions; this will be
-WAY richer on questions than on answers...
-
-Q1: Where should the "spool files" for a subscription set be generated?
-
- Several thoughts come to mind:
-
- A1 -> The slon for the origin node generates them
-
- A2 -> Any slon node participating in the subscription set can generate
- them
-
- A3 -> A special "pseudo-node" generates spool files rather than applying
- changes to a database
-
- Answer tentatively seems to be A3.
-
-Q2: What takes place when a failover/MOVE SET takes place?
-
- -> If we picked, for Q1, A2 or A3, then the answer is "nothing."
-
- -> If Q1's answer was A1, then it becomes necessary for the new
- origin to start generating spool files.
-
- What do we do if it that slon hasn't got suitable configuration?
- Simply stop spooling?
-
- Given Q1:A3, nothing special happens when failover/MOVE SET takes
- place, except that if the "spool node" is subscribed to a node that
- is somehow orphaned, it might get disconnected :-(.
-
-Q3: What if we run out of "spool space"?
-
- -> It's forced to stop writing out logs; this should _prevent_
- purging sl_log_1/sl_log_2 entries in the affected range so
- that "log shipping" isn't corrupted.
-
- In effect, "log shipping" is a sort of 'virtual destination'
- that Slony-I's existing data structures need to know something
- about. It's not a "true" node, but it needs to have a
- subscription and set up
- sl_confirm entries.
-
-Q4: How do we configure it?
-
- Things that need to be configured include:
-
- a) Path in which to put "spool files"
-
- SPOOLPATH
-
- -p "/var/spool/slony1/something"
-
- b) Naming convention for the spool files, likely using a
- strftime()-conformant name string, also with the option of
- having it use the starting and/or ending SYNC ids.
-
- -n "something"
-
- c) There needs to be some sort of "subscribe" notion...
-
- This is implemented _inside_ the spooler.
-
- --> For each table, run pg_dump -s -t on the table
-
- --> Then do a "copy from" on each table
-
- d) How often to split between files???
-
- --> Combo of time, number of syncs, size
-
-Q5: What should the logs consist of?
-
- -> Should they simply consist of the updates on the tables Slony-I
- is to replicate?
-
- -> Should there also be some information stored concerning what
- SYNCS are processed?
-
- Yes, there should be. There shouldn't merely be comments; the
- structure should be something like:
-
- BEGIN;
- @NAMESPACE at .start_spool(23451); -- SYNC 23451
- insert this
- delete that
- update other thing
- @NAMESPACE at .end_spool(23451); -- SYNC 23451
- COMMIT;
- BEGIN;
- @NAMESPACE at .start_spool(23452); -- SYNC 23452
- insert this
- delete that
- update other thing
- @NAMESPACE at .end_spool(23452);
- COMMIT;
- BEGIN;
- @NAMESPACE at .start_spool(23454); -- SYNC 23454
- insert this
- delete that
- update other thing
- @NAMESPACE at .end_spool(23454);
- COMMIT;
- BEGIN;
- @NAMESPACE at .start_spool(23453); -- SYNC 23453
- insert this
- delete that
- update other thing
- @NAMESPACE at .end_spool(23453);
- COMMIT;
-
- -> Would the log-shipped-subscribers also operate in a
- "mostly-read-only" mode as is the case for 'direct' subscribers?
-
- start_spool() could alter tables to turn on and off the
- ability to update the data...
-
- -> How much metadata should get added in? E.g. - comments about
- SYNCs, when data was added in, data about events that aren't
- directly updating data
-
- For this to be overly voluminous would be irritating, but having
- some metadata to search through would be handy...
-
- -> Would it be a useful notion to try to make it possible for a
- resulting "node" to join a replication set?
-
-I'm sure there are some "oughtn't try to do that" answers to be had
-here, but we might as well start somewhere...
\ No newline at end of file
--- src/slonspool/README
+++ /dev/null
@@ -1,2 +0,0 @@
-Here begins the code for a "log shipping" slon...
-
- Previous message: [Slony1-commit] By cbbrowne: Fix typo in filelist.sgml - missing quote
- Next message: [Slony1-commit] By xfade: Check for real net-snmp headers instead of the wrapper
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list