On Sat, 17 Mar 2007, Steve Singer wrote:

The attached patch replaces the one I sent last week. This version has the only_on execute script executed directly against the subscriber node by slonik as discussed on slony1-general.

Also per the discussion on general this patch also includes a fix so that subscribers that do not subscribe to the set a script is submitted against do not receive the script (As was the behaviour in the 1.1 series)

These patches are all against the 1.2 branch.


Steve

On Sat, 17 Mar 2007, Steve Singer wrote:

The attached patch against 1.2 should fix this bug by not
executing your DDL on the event node.

If your DDL has errors then you won't find out about it until slon tries to execute it on the other node (slonik won't give you an error but making changes just on your subscribers can have the potential for all sorts of trouble if your not careful)



On Sat, 17 Mar 2007, Mikko Partio wrote:

Your getting this because your EVENT_NODE is 1 but you only want to execute the script on 2.

Slonik probably should have a check to see if you have specified an only excecute different than your event node and just submit the script into the queue at that stage.

Another option is to require the event node be equal to the only execute node.



Hi,

slonik's EXECUTE SCRIPT -documentation says that:

EXECUTE ONLY ON = ival

  (Optional) The ID of the only node to actually execute the script.
  This option causes the script to be propagated by all nodes but
  executed only by one. The default is to execute the script on all
  nodes that are subscribed to the set.


In my experience this property is not working correctly, and here's the proof ("tiuhti" is origin and "viuhti" subscriber):

[EMAIL PROTECTED]:~$ psql -d cldb -c "CREATE TABLE testtable (id int)" -h tiuhti
CREATE TABLE
[EMAIL PROTECTED]:~$ psql -d cldb -c "CREATE TABLE testtable (id int)" -h viuhti
CREATE TABLE

[EMAIL PROTECTED]:~$ cat drop_table_testtable.sql
DROP TABLE testtable;

[EMAIL PROTECTED]:~$ cat droptest.slonik
#!/usr/bin/slonik

CLUSTER NAME=climate;

NODE 1 ADMIN CONNINFO = 'dbname=cldb host=tiuhti user=slony1';
NODE 2 ADMIN CONNINFO = 'dbname=cldb host=viuhti user=slony1';

EXECUTE SCRIPT (
      SET ID = 1,
      FILENAME = '/home/slony1/drop_table_testtable.sql',
      EVENT NODE = 1,
      EXECUTE ONLY ON = 2
);

[EMAIL PROTECTED]:~$ slonik droptest.slonik
DDL script consisting of 1 SQL statements
DDL Statement 0: (0,21) [DROP TABLE testtable;]
Submit DDL Event to subscribers...
DDL on origin - PGRES_TUPLES_OK

[EMAIL PROTECTED]:~$ psql -d cldb -c "\d testtable" -h viuhti
Did not find any relation named "testtable".

This is what I expected, but

[EMAIL PROTECTED]:~$ psql -d cldb -c "\d testtable" -h tiuhti
Did not find any relation named "testtable".

Wooah - the script dropped table testtable from both nodes although I specified the "execute only on" -option. Is there something I'm missing or is there a bug?

Regards

MP

_______________________________________________
Slony1-general mailing list
[email protected]
http://lists.slony.info/mailman/listinfo/slony1-general


_______________________________________________
Slony1-general mailing list
[email protected]
http://lists.slony.info/mailman/listinfo/slony1-general


Index: src/backend/slony1_funcs.sql
===================================================================
RCS file: /slony1/slony1-engine/src/backend/slony1_funcs.sql,v
retrieving revision 1.98.2.13
diff -c -r1.98.2.13 slony1_funcs.sql
*** src/backend/slony1_funcs.sql        22 Mar 2007 20:41:27 -0000      
1.98.2.13
--- src/backend/slony1_funcs.sql        24 Mar 2007 22:24:19 -0000
***************
*** 3683,3690 ****
--- 3683,3693 ----
        -- ----
        lock table @[EMAIL PROTECTED];
  
+       
        -- ----
        -- Check that the set exists and originates here
+       -- unless only_on_node was specified (then it can be applied to
+       -- that node because that is what the user wanted)
        -- ----
        select set_origin into v_set_origin
                        from @[EMAIL PROTECTED]
***************
*** 3693,3699 ****
        if not found then
                raise exception ''Slony-I: set % not found'', p_set_id;
        end if;
!       if v_set_origin <> @[EMAIL PROTECTED](''[EMAIL PROTECTED]@'') then
                raise exception ''Slony-I: set % does not originate on local 
node'',
                                p_set_id;
        end if;
--- 3696,3703 ----
        if not found then
                raise exception ''Slony-I: set % not found'', p_set_id;
        end if;
!       if v_set_origin <> @[EMAIL PROTECTED](''[EMAIL PROTECTED]@'') AND
!       p_only_on_node=-1 then
                raise exception ''Slony-I: set % does not originate on local 
node'',
                                p_set_id;
        end if;
***************
*** 5904,5907 ****
  to specify fields for the passed-in tab_id.  
  
  In PG versions > 7.3, this looks like (field1,field2,...fieldn)';
- 
--- 5908,5910 ----
Index: src/slon/remote_worker.c
===================================================================
RCS file: /slony1/slony1-engine/src/slon/remote_worker.c,v
retrieving revision 1.124.2.12
diff -c -r1.124.2.12 remote_worker.c
*** src/slon/remote_worker.c    6 Mar 2007 18:47:45 -0000       1.124.2.12
--- src/slon/remote_worker.c    24 Mar 2007 22:24:22 -0000
***************
*** 268,273 ****
--- 268,276 ----
  
  static void compress_actionseq(const char *ssy_actionseq, SlonDString * 
action_subquery);
  
+ static int process_ddl_script(SlonWorkMsg_event * event,SlonNode * node,
+                                                         PGconn * 
local_dbconn, char * seqbuf );
+ static int check_set_subscriber(int set_id, int node_id,PGconn * 
local_dbconn);
  
  /* ----------
   * slon_remoteWorkerThread
***************
*** 1339,1439 ****
                        }
                        else if (strcmp(event->ev_type, "DDL_SCRIPT") == 0)
                        {
!                               int                     ddl_setid = 
(int)strtol(event->ev_data1, NULL, 10);
!                               char       *ddl_script = event->ev_data2;
!                               int                     ddl_only_on_node = 
(int)strtol(event->ev_data3, NULL, 10);
!                               int num_statements = -1, stmtno;
! 
!                               PGresult *res;
!                               ExecStatusType rstat;
! 
! 
!                               slon_appendquery(&query1,
!                                                "select 
%s.ddlScript_prepare_int(%d, %d); ",
!                                                rtcfg_namespace,
!                                                ddl_setid, ddl_only_on_node);
! 
!                               if (query_execute(node, local_dbconn, &query1) 
< 0) {
!                                               slon_log(SLON_ERROR, 
"remoteWorkerThread_%d: DDL preparation failed - set %d - only on node %\n",
!                                                        node->no_id, 
ddl_setid, ddl_only_on_node);
!                                               slon_retry();
!                               }
! 
!                               num_statements = scan_for_statements 
(ddl_script);
!                               slon_log(SLON_CONFIG, "remoteWorkerThread_%d: 
DDL request with %d statements\n",
!                                        node->no_id, num_statements);
!                               if ((num_statements < 0) || (num_statements >= 
MAXSTATEMENTS)) {
!                                       slon_log(SLON_ERROR, 
"remoteWorkerThread_%d: DDL had invalid number of statements - %d\n", 
!                                                node->no_id, num_statements);
!                                       slon_retry();
!                               }
!                               
!                               for (stmtno=0; stmtno < num_statements;  
stmtno++) {
!                                       int startpos, endpos;
!                                       char *dest;
!                                       if (stmtno == 0)
!                                               startpos = 0;
!                                       else
!                                               startpos = STMTS[stmtno-1];
! 
!                                       endpos = STMTS[stmtno];
!                                       dest = (char *) malloc (endpos - 
startpos + 1);
!                                       if (dest == 0) {
!                                               slon_log(SLON_ERROR, 
"remoteWorkerThread_%d: malloc() failure in DDL_SCRIPT - could not allocate %d 
bytes of memory\n", 
!                                                        node->no_id, endpos - 
startpos + 1);
!                                               slon_retry();
!                                       }
!                                       strncpy(dest, ddl_script + startpos, 
endpos-startpos);
!                                       dest[STMTS[stmtno]-startpos] = 0;
!                                       slon_mkquery(&query1, dest);
!                                       slon_log(SLON_CONFIG, 
"remoteWorkerThread_%d: DDL Statement %d: [%s]\n", 
!                                                node->no_id, stmtno, dest);    
                                         
!                                       free(dest);
! 
!                                       res = PQexec(local_dbconn, 
dstring_data(&query1));
! 
!                                       if (PQresultStatus(res) != 
PGRES_COMMAND_OK && 
!                                           PQresultStatus(res) != 
PGRES_TUPLES_OK &&
!                                           PQresultStatus(res) != 
PGRES_EMPTY_QUERY)
!                                       {
!                                               rstat = PQresultStatus(res);
!                                               slon_log(SLON_ERROR, "DDL 
Statement failed - %s\n", PQresStatus(rstat));
!                                               dstring_free(&query1);
!                                               slon_retry();
!                                       }
!                                       rstat = PQresultStatus(res);
!                                       slon_log (SLON_CONFIG, "DDL success - 
%s\n", PQresStatus(rstat));
!                               }
!       
!                               slon_mkquery(&query1, "select 
%s.ddlScript_complete_int(%d, %d); ", 
!                                            rtcfg_namespace,
!                                            ddl_setid,
!                                            ddl_only_on_node);
! 
!                               /* DDL_SCRIPT needs to be turned into a log 
shipping script */
!                               /* Note that the issue about parsing that 
mandates breaking 
!                                  up compound statements into
!                                  individually-processed statements does not 
apply to log
!                                  shipping as psql parses and processes each 
statement
!                                  individually */
! 
!                               if (archive_dir)
!                               {
!                                       if ((ddl_only_on_node < 1) || 
(ddl_only_on_node == rtcfg_nodeid))
!                                       {
! 
!                                               if (archive_open(node, seqbuf) 
< 0)
!                                                       slon_retry();
!                                               if (archive_tracking(node, 
rtcfg_namespace, 
!                                                               ddl_setid, 
seqbuf, seqbuf, 
!                                                               
event->ev_timestamp_c) < 0)
!                                                       slon_retry();
!                                               if (archive_append_str(node, 
ddl_script) < 0)
!                                                       slon_retry();
!                                               if (archive_close(node) < 0)
!                                                       slon_retry();
!                                       }
!                               }
                        }
                        else if (strcmp(event->ev_type, "RESET_CONFIG") == 0)
                        {
--- 1342,1348 ----
                        }
                        else if (strcmp(event->ev_type, "DDL_SCRIPT") == 0)
                        {
!                               
process_ddl_script(event,node,local_dbconn,seqbuf);
                        }
                        else if (strcmp(event->ev_type, "RESET_CONFIG") == 0)
                        {
***************
*** 6097,6099 ****
--- 6006,6175 ----
        }
        slon_log(SLON_DEBUG4, " compressed actionseq subquery... %s\n", 
dstring_data(action_subquery));
  }
+ 
+ 
+ /**
+  *
+  * Process a ddl_script command.
+  */
+ static int process_ddl_script(SlonWorkMsg_event * event,SlonNode * node,
+                                                         PGconn * local_dbconn,
+                                                         char * seqbuf) 
+ {
+       int                     ddl_setid = (int)strtol(event->ev_data1, NULL, 
10);
+       char       *ddl_script = event->ev_data2;
+       int                     ddl_only_on_node = (int)strtol(event->ev_data3, 
NULL, 10);
+       int num_statements = -1, stmtno;
+       int node_in_set;
+       int localNodeId;
+       PGresult *res;
+       ExecStatusType rstat;
+       SlonDString query1;
+ 
+       
+ 
+       dstring_init(&query1);
+       /**
+        * Check to make sure this node is part of the set
+        */
+       slon_log(SLON_INFO, "Checking local node id");
+       localNodeId = db_getLocalNodeId(local_dbconn);
+       slon_log(SLON_INFO,"Found local node id");
+       node_in_set = check_set_subscriber(ddl_setid,localNodeId,local_dbconn);
+       
+       if(!node_in_set) {
+               /**
+                *
+                * Node is not part of the set.  
+                * Do not forward teh DDL to the node,
+                * nor should it be included in the log for log-shipping.
+                */
+               slon_log(SLON_INFO,"Not forwarding DDL to node %d for set %d\n",
+                                node->no_id,ddl_setid);
+               
+       }
+       else 
+       {
+               slon_appendquery(&query1,
+                                                "select 
%s.ddlScript_prepare_int(%d, %d); ",
+                                                rtcfg_namespace,
+                                                ddl_setid, ddl_only_on_node);
+               
+               if (query_execute(node, local_dbconn, &query1) < 0) {
+                       slon_log(SLON_ERROR, "remoteWorkerThread_%d: DDL 
preparation failed - set %d - only on node %\n",
+                                        node->no_id, ddl_setid, 
ddl_only_on_node);                     
+                       slon_retry();
+               }
+               
+               num_statements = scan_for_statements (ddl_script);
+               slon_log(SLON_CONFIG, "remoteWorkerThread_%d: DDL request with 
%d statements\n",
+                                node->no_id, num_statements);
+               if ((num_statements < 0) || (num_statements >= MAXSTATEMENTS)) {
+                       slon_log(SLON_ERROR, "remoteWorkerThread_%d: DDL had 
invalid number of statements - %d\n", 
+                                        node->no_id, num_statements);
+                       slon_retry();
+               }
+               
+               for (stmtno=0; stmtno < num_statements;  stmtno++) {
+                       int startpos, endpos;
+                       char *dest;
+                       if (stmtno == 0)
+                               startpos = 0;
+                       else
+                               startpos = STMTS[stmtno-1];
+                       
+                       endpos = STMTS[stmtno];
+                       dest = (char *) malloc (endpos - startpos + 1);
+                       if (dest == 0) {
+                               slon_log(SLON_ERROR, "remoteWorkerThread_%d: 
malloc() failure in DDL_SCRIPT - could not allocate %d bytes of memory\n", 
+                                                node->no_id, endpos - startpos 
+ 1);
+                               slon_retry();
+                       }
+                       strncpy(dest, ddl_script + startpos, endpos-startpos);
+                       dest[STMTS[stmtno]-startpos] = 0;
+                       slon_mkquery(&query1, dest);
+                       slon_log(SLON_CONFIG, "remoteWorkerThread_%d: DDL 
Statement %d: [%s]\n", 
+                                        node->no_id, stmtno, dest);            
                                 
+                       free(dest);
+                       
+                       res = PQexec(local_dbconn, dstring_data(&query1));
+                       
+                       if (PQresultStatus(res) != PGRES_COMMAND_OK && 
+                               PQresultStatus(res) != PGRES_TUPLES_OK &&
+                               PQresultStatus(res) != PGRES_EMPTY_QUERY)
+                               {
+                                       rstat = PQresultStatus(res);
+                                       slon_log(SLON_ERROR, "DDL Statement 
failed - %s\n", PQresStatus(rstat));
+                                       dstring_free(&query1);
+                                       slon_retry();
+                               }
+                       rstat = PQresultStatus(res);
+                       slon_log (SLON_CONFIG, "DDL success - %s\n", 
PQresStatus(rstat));
+               }
+               
+               slon_mkquery(&query1, "select %s.ddlScript_complete_int(%d, 
%d); ", 
+                                        rtcfg_namespace,
+                                        ddl_setid,
+                                        ddl_only_on_node);
+               
+               /* DDL_SCRIPT needs to be turned into a log shipping script */
+               /* Note that the issue about parsing that mandates breaking 
+                  up compound statements into
+                  individually-processed statements does not apply to log
+                  shipping as psql parses and processes each statement
+                  individually */
+               
+               if (archive_dir)
+                       {
+                               if ((ddl_only_on_node < 1) || (ddl_only_on_node 
== rtcfg_nodeid))
+                                       {
+                                               
+                                               if (archive_open(node, seqbuf) 
< 0)
+                                                       slon_retry();
+                                               if (archive_tracking(node, 
rtcfg_namespace, 
+                                                                               
         ddl_setid, seqbuf, seqbuf, 
+                                                                               
         event->ev_timestamp_c) < 0)
+                                                       slon_retry();
+                                               if (archive_append_str(node, 
ddl_script) < 0)
+                                                       slon_retry();
+                                               if (archive_close(node) < 0)
+                                                       slon_retry();
+                                       }
+                       }
+       }/*else node a subscriber */
+       
+       dstring_free(&query1);
+ 
+ }
+ 
+ /**
+  * Checks to see if the node specified is a member of the set.
+  *
+  */
+ static int check_set_subscriber(int set_id, int node_id,PGconn * 
local_dbconn) 
+ {
+   
+   
+   SlonDString query1;
+   PGresult* res;
+   dstring_init(&query1);
+ 
+   slon_appendquery(&query1,"select 1 from %s.sl_subscribe WHERE sub_set=%d 
AND sub_receiver=%d for update"
+              ,rtcfg_namespace,set_id,node_id);
+   res = PQexec(local_dbconn,dstring_data(&query1));
+   if(PQresultStatus(res)!=PGRES_TUPLES_OK) {
+     slon_log(SLON_ERROR,"remoteWorkerThread_%d: DDL preperation can not check 
set membership"
+            ,node_id);
+       dstring_free(&query1);
+     slon_retry();
+   }
+   dstring_free(&query1);
+   if(PQntuples(res)==0) {
+     PQclear(res);
+     return 0;
+   }
+   PQclear(res);
+   return 1;
+ 
+ 
+ }
Index: src/slonik/slonik.c
===================================================================
RCS file: /slony1/slony1-engine/src/slonik/slonik.c,v
retrieving revision 1.67.2.6
diff -c -r1.67.2.6 slonik.c
*** src/slonik/slonik.c 15 Mar 2007 18:52:02 -0000      1.67.2.6
--- src/slonik/slonik.c 24 Mar 2007 22:24:24 -0000
***************
*** 3849,3861 ****
        PGresult *res;
        ExecStatusType rstat;
  
  #define PARMCOUNT 1  
  
          const char *params[PARMCOUNT];
          int paramlens[PARMCOUNT];
          int paramfmts[PARMCOUNT];
  
!       adminfo1 = get_active_adminfo((SlonikStmt *) stmt, stmt->ev_origin);
        if (adminfo1 == NULL)
                return -1;
  
--- 3849,3865 ----
        PGresult *res;
        ExecStatusType rstat;
  
+ 
  #define PARMCOUNT 1  
  
          const char *params[PARMCOUNT];
          int paramlens[PARMCOUNT];
          int paramfmts[PARMCOUNT];
  
!       if(stmt->only_on_node>-1) {
!               adminfo1 = get_active_adminfo((SlonikStmt*) 
stmt,stmt->only_on_node);
!       }
!         adminfo1 = get_active_adminfo((SlonikStmt *) stmt, stmt->ev_origin);
        if (adminfo1 == NULL)
                return -1;
  
***************
*** 3935,3967 ****
                /* printf ("Success - %s\n", PQresStatus(rstat)); */
        }
        
!       printf("Submit DDL Event to subscribers...\n");
! 
!       slon_mkquery(&query, "select \"_%s\".ddlScript_complete(%d, $1::text, 
%d); ", 
!                    stmt->hdr.script->clustername,
!                    stmt->ddl_setid,  
!                    stmt->only_on_node);
! 
!       paramlens[PARMCOUNT-1] = 0;
!       paramfmts[PARMCOUNT-1] = 0;
!       params[PARMCOUNT-1] = dstring_data(&script);
! 
!       res = PQexecParams(adminfo1->dbconn, dstring_data(&query), PARMCOUNT,
!                          NULL, params, paramlens, paramfmts, 0);
!       
!       if (PQresultStatus(res) != PGRES_COMMAND_OK && 
!           PQresultStatus(res) != PGRES_TUPLES_OK &&
!           PQresultStatus(res) != PGRES_EMPTY_QUERY)
!       {
!               rstat = PQresultStatus(res);
!               printf("Event submission for DDL failed - %s\n", 
PQresStatus(rstat));
!               dstring_free(&query);
!               return -1;
!       } else {
!               rstat = PQresultStatus(res);
!               printf ("DDL on origin - %s\n", PQresStatus(rstat));
!       }
!       
        dstring_free(&script);
        dstring_free(&query);
        return 0;
--- 3939,3972 ----
                /* printf ("Success - %s\n", PQresStatus(rstat)); */
        }
        
!       if(stmt->only_on_node==-1) {
!               printf("Submit DDL Event to subscribers...\n");
!               
!               slon_mkquery(&query, "select \"_%s\".ddlScript_complete(%d, 
$1::text, %d); ", 
!                                        stmt->hdr.script->clustername,
!                                        stmt->ddl_setid,  
!                                        stmt->only_on_node);
!               
!               paramlens[PARMCOUNT-1] = 0;
!               paramfmts[PARMCOUNT-1] = 0;
!               params[PARMCOUNT-1] = dstring_data(&script);
!               
!               res = PQexecParams(adminfo1->dbconn, dstring_data(&query), 
PARMCOUNT,
!                                                  NULL, params, paramlens, 
paramfmts, 0);
!               
!               if (PQresultStatus(res) != PGRES_COMMAND_OK && 
!                       PQresultStatus(res) != PGRES_TUPLES_OK &&
!                       PQresultStatus(res) != PGRES_EMPTY_QUERY)
!                       {
!                               rstat = PQresultStatus(res);
!                               printf("Event submission for DDL failed - 
%s\n", PQresStatus(rstat));
!                               dstring_free(&query);
!                               return -1;
!                       } else {
!                               rstat = PQresultStatus(res);
!                               printf ("DDL on origin - %s\n", 
PQresStatus(rstat));
!                       }
!       }/*only on node*/
        dstring_free(&script);
        dstring_free(&query);
        return 0;
_______________________________________________
Slony1-general mailing list
[email protected]
http://lists.slony.info/mailman/listinfo/slony1-general

Reply via email to