OpenPKG CVS Repository http://cvs.openpkg.org/ ____________________________________________________________________________
Server: cvs.openpkg.org Name: Thomas Lotterer Root: /v/openpkg/cvs Email: [EMAIL PROTECTED] Module: openpkg-registry Date: 13-Jul-2006 09:32:41 Branch: HEAD Handle: 2006071308324100 Modified files: openpkg-registry registry-ui.pl Log: Fix transactional problems. When multiple XML requests are dropped for reregistration, "insert, on error update" logic breaks transaction and hearbeat is lost on all but the last request being processed (in perl random hash order). Reorganize to use "update or insert" (w/o error) logic; Defer result printing until transaction is completed. If transaction fails as a whole or because of one or more "ERROR" conditions are detected during processing, good requests are lost, too, so print "IGNORED" for them and do not mark them "DONE". Order response printing in processing order; Simplify user agent vs. HTML output formatting doing it in one place. Summary: Revision Changes Path 1.72 +75 -73 openpkg-registry/registry-ui.pl ____________________________________________________________________________ patch -p0 <<'@@ .' Index: openpkg-registry/registry-ui.pl ============================================================================ $ cvs diff -u -r1.71 -r1.72 registry-ui.pl --- openpkg-registry/registry-ui.pl 13 Jul 2006 07:14:13 -0000 1.71 +++ openpkg-registry/registry-ui.pl 13 Jul 2006 07:32:41 -0000 1.72 @@ -1601,12 +1601,10 @@ } return $html; } + my $res = {}; my $commit = 1; - - if (&uao()) { - $html .= "<registry>\n"; - } - foreach my $k (keys %{$ref->{request}}) { + my @keys = keys %{$ref->{request}}; + foreach my $k (@keys) { my $username; $username = $ref->{request}->{$k}->{registry_user}; @@ -1617,110 +1615,78 @@ if (not defined $rv) { $msg = $dbh->errstr; $msg =~ s/[ ]*ERROR:?[ ]*//; - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"no\">ERROR DataBase reports %s</response>\n", $k, $msg); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> ERROR DataBase reports %s\n", $k, $msg); - } + $res->{$k} = sprintf("ERROR DataBase reports %s", $msg); $commit = 0; next; } - if ($rv != 1) { - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"no\">ERROR username %s not found</response>\n", $k, $username); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> ERROR username <i>%s</i> not found\n", $k, $username); - } + elsif ($rv < 1) { + $res->{$k} = sprintf("ERROR username \"%s\" not found", $username); $commit = 0; next; } - # insert instance, possibly fall back to update + # update instance # + my $rowkey; + $rowkey = undef; my ($fields, $fieldlist, $fieldbind, $fieldvals, $sth); ($sql, $fields, $fieldlist, $fieldbind, $fieldvals, $sth) = undef; for my $field (sort keys %{$ref->{request}->{$k}}) { if (not ref($ref->{request}->{$k}->{$field})) { - $fieldlist = (defined $fieldlist ? $fieldlist . ", " : "") . $field; - $fieldbind = (defined $fieldbind ? $fieldbind . ", " : "") . "?"; - push @{$fieldvals}, $ref->{request}->{$k}->{$field}; - #FIXME here we could check the validity of all fields with string 'uuid' in their names + if ($field eq "uuid_registry") { + $rowkey = $ref->{request}->{$k}->{$field} + } + else { + $fieldlist = (defined $fieldlist ? $fieldlist . ", " : "") . $field . " = ?"; + push @{$fieldvals}, $ref->{request}->{$k}->{$field}; + } } else { ; # reserved for nested structures } } - $sql = sprintf("INSERT INTO reg_instance (%s) VALUES (%s);", $fieldlist, $fieldbind); + $sql = sprintf("UPDATE reg_instance SET registry_date = now(), %s WHERE ( uuid_registry = '%s' );", $fieldlist, $rowkey); $sth = $dbh->prepare($sql); $rv = $sth->execute(@{$fieldvals}); if (not defined $rv) { $msg = $dbh->errstr; $msg =~ s/[ ]*ERROR:?[ ]*//; - unless ($msg =~ m|duplicate key violates unique constraint|) { - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"no\">ERROR DataBase reports %s</response>\n", $k, $msg); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> ERROR DataBase reports %s\n", $k, $msg); - } - $commit = 0; - next; - } + $res->{$k} = sprintf("ERROR DataBase reports %s", $msg); + $commit = 0; + next; } - if ($rv != 1) { - my $rowkey; - $rowkey = undef; + elsif ($rv < 1) { + # insert instance + # ($sql, $fields, $fieldlist, $fieldbind, $fieldvals, $sth) = undef; - $fieldlist = 'registry_date = ?'; - push @{$fieldvals}, 'now()'; #FIXME this should read DEFAULT or COLUMN_DEF but does not work here for unknown reasons for my $field (sort keys %{$ref->{request}->{$k}}) { if (not ref($ref->{request}->{$k}->{$field})) { - if ($field eq "uuid_registry") { - $rowkey = $ref->{request}->{$k}->{$field} - } - else { - $fieldlist = (defined $fieldlist ? $fieldlist . ", " : "") . $field . " = ?"; - push @{$fieldvals}, $ref->{request}->{$k}->{$field}; - } + $fieldlist = (defined $fieldlist ? $fieldlist . ", " : "") . $field; + $fieldbind = (defined $fieldbind ? $fieldbind . ", " : "") . "?"; + push @{$fieldvals}, $ref->{request}->{$k}->{$field}; + #FIXME here we could check the validity of all fields with string 'uuid' in their names } else { ; # reserved for nested structures } } - $sql = sprintf("UPDATE reg_instance SET %s WHERE ( uuid_registry = ? );", $fieldlist); + $sql = sprintf("INSERT INTO reg_instance (%s) VALUES (%s);", $fieldlist, $fieldbind); $sth = $dbh->prepare($sql); - $rv = $sth->execute(@{$fieldvals}, $rowkey); + $rv = $sth->execute(@{$fieldvals}); if (not defined $rv) { $msg = $dbh->errstr; $msg =~ s/[ ]*ERROR:?[ ]*//; - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"no\">ERROR DataBase reports %s</response>\n", $k, $msg); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> ERROR DataBase reports %s\n", $k, $msg); - } - $commit = 0; - next; - } - if ($rv != 1) { - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"no\">ERROR update failed rv=%s</response>\n", $k, $msg); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> ERROR update failed rv=$rv\n", $k); - } + $res->{$k} = sprintf("ERROR DataBase reports %s", $msg); $commit = 0; next; } } - if (&uao()) { - $html .= sprintf(" <response id=\"%s\" done=\"yes\">%s</response>\n", $k, $ref->{request}->{$k}->{registry_desc}); - } - else { - $html .= sprintf("<br/><img src=\"?page=gif;name=icon-ok\"> <b>%s</b> %s\n", $k, $ref->{request}->{$k}->{registry_desc}); + if ($rv < 1) { + $res->{$k} = sprintf("ERROR update and insert failed"); + $commit = 0; + next; } + $res->{$k} = "DONE"; } if ($commit == 1) { @@ -1729,11 +1695,14 @@ $msg = $@; $msg =~ s/[ ]*ERROR:?[ ]*//; if (&uao()) { - $html .= sprintf(" <response id=\"FIXME\" done=\"no\">ERROR commit transaction failed, DataBase reports %s</response>\n", $msg); + $html .= "<registry>\n"; + $html .= sprintf("ERROR: commit transaction failed, DataBase reports %s\n", $msg); + $html .= "</registry>\n"; } else { $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> ERROR commit transaction failed, DataBase reports %s\n", $msg); } + return($html) } $cgi->delete(-name=>'data'); } @@ -1743,16 +1712,49 @@ $msg = $@; $msg =~ s/[ ]*ERROR:?[ ]*//; if (&uao()) { - $html .= sprintf(" <response id=\"FIXME\" done=\"no\">ERROR rollback transaction failed, DataBase reports %s</response>\n", $msg); + $html .= "<registry>\n"; + $html .= sprintf("ERROR: rollback transaction failed, DataBase reports %s\n", $msg); + $html .= "</registry>\n"; } else { $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> ERROR rollback transaction failed, DataBase reports %s\n", $msg); } + return($html) } } - if (&uao()) { - $html .= "</registry>\n"; + + $html .= "<registry>\n" if (&uao()); + foreach my $k (@keys) { + $msg = $res->{$k}; + if ($msg eq "DONE") { + $msg = $ref->{request}->{$k}->{registry_desc}; + if ($commit == 1) { + if (&uao()) { + $html .= sprintf(" <response id=\"%s\" done=\"yes\">%s</response>\n", $k, $msg); + } + else { + $html .= sprintf("<br/><img src=\"?page=gif;name=icon-ok\"> <b>%s</b> %s\n", $k, $msg); + } + } + else { + if (&uao()) { + $html .= sprintf(" <response id=\"%s\" done=\"no\">IGNORED: %s</response>\n", $k, $msg); + } + else { + $html .= sprintf("<br/><img src=\"?page=gif;name=icon-dot\"> <b>%s</b> IGNORED: %s\n", $k, $msg); + } + } + } + else { + if (&uao()) { + $html .= sprintf(" <response id=\"%s\" done=\"no\">%s</response>\n", $k, $msg); + } + else { + $html .= sprintf("<br/><img src=\"?page=gif;name=icon-x\"> <b>%s</b> %s\n", $k, $msg); + } + } } + $html .= "</registry>\n" if (&uao()); return($html); } @@ . ______________________________________________________________________ The OpenPKG Project www.openpkg.org CVS Repository Commit List openpkg-cvs@openpkg.org