Thanks for all that, any suggestions why the file gets wiped out every so
often?

-----Original Message-----
From: Jenda Krynicky [mailto:[EMAIL PROTECTED]
Sent: 14 July 2004 21:06
To: [EMAIL PROTECTED]
Subject: Re: Data File getting set to an empty file


From: "Nigel Peck" <[EMAIL PROTECTED]>
> I have a (possible) problem with a script that records the number of
> page views for various pages on a site (full script below).
>
> Every so often (60 days or more) the data file (data.xml) loses all
> it's data and is still there but empty.

Waitasecond ... all your CGI scripts try to edit a potentially huge
XML file? I must be missing something here!

XML might be a fine format for exchanging information, but as an
editable database it's almost the worst thing you could get.

No matter how good is the XML parser it takes ages to find the
information and even longer to change the XML.

You should be using a database for this.

If you do not want to install any "real" one try DBD::SQLite. You'll
find out the modifications are much much quicker.

Jenda
P.S.: Guess what happens if two instances of your script are started
at the same time, both read the same XML, both make some changes and
both write their changes to the file? Yes the write is "atomic", but
there is nothing in the script preventing one instance from reading
the XML between the other reads it and writes it!


> Any suggestions greatly appreciated.
>
> Cheers,
> Nigel
>
> -=-=-=-=-=Script Follows=-=-=-=-=-
>
> use strict;
> use XML::LibXML;
> use CGI;
> use IO::AtomicFile;
>
> sub build_dom (\$\$\$);
> sub commit_changes ($$\$);
> sub error ($);
>
> my $query = new CGI;
> $CGI::DISABLE_UPLOADS = 1;
>
> print "Content-type: text/html\n\n";
>
> my $lasterror;
> my $data_file = "/home/sebs/pageviews/data.xml";
> my $error_file = "/home/sebs/pageviews/errors.txt";
>
> my $location = $query->param("location") ||
>  error ('Required variable location was not sent');
>
> my $data;
>
> build_dom($data, $data_file, $lasterror)
>  || error($lasterror);
>
> my $views;
> my $node = (($data->findnodes('//[EMAIL PROTECTED]"' . $location .
> '"]'))?($data->findnodes('//[EMAIL PROTECTED]"' . $location .
> '"]')->[0]):'');
>
> if ( not $node ) {
> # It's a new page, not seen before, create a page element for it
>  $node = XML::LibXML::Element->new('page');
>  $node->setAttribute('location', $location);
>  $node->setAttribute('views', 0);
>  $node->setAttribute('starttime', time);
>  $data->getDocumentElement->appendChild($node);
> }
>
> my $views = $node->getAttribute('views');
>
> if ( $query->param("average") == 1 ) {
> # Send the average and die if average was set
>  my $starttime = $node->getAttribute('starttime');
>  my $timediff = time - $starttime;
>  # Seconds in a 30 day month
>  # 2592000
>  my $months = int($timediff / 2592000) + 1;
>  my $average = $views / $months;
>  print int($average);
>  die;
> }
>
> unless ($query->param("noview") == 1) {
> # Increase views unless noview was set
>  $views++;
>  $node->setAttribute('views', $views);
>
>  commit_changes($data, $data_file, $lasterror)
>   || error($lasterror);
> }
>
> print $views;
>
> ##########################
> #      COMMON SUBS       #
> ##########################
>
> sub error ($) {
>  my ($errormsg) = @_;
>  print "<h2>Error</h2>\n";
>  print "<p>Please note the information below, this was the cause of
>  the
> error.</p>\n";
>  print "<p>" . $errormsg . "</p>\n";
>  open ( ERRORS, ">>$error_file" );
>  print ERRORS $errormsg . "\n";
>  close ( ERRORS );
>  die;
> }
>
> ##########################
> #       DOM STUFF        #
> ##########################
>
> sub build_dom (\$\$\$) {
>  my ($doc, $config, $errormsg) = @_;
>
>  my $parser = XML::LibXML->new();
>  $parser->validation(0);
>  $parser->expand_entities(1);
>  $parser->keep_blanks(0);
>  $parser->pedantic_parser(0);
>  $parser->load_ext_dtd(0);
>  $parser->complete_attributes(1);
>
>  eval { $$doc = $parser->parse_file( $$config ) };
>  if ($@) { $$errormsg = "build_dom error: " . $@ . "\n"; return 0; }
>  else { return 1; }
> }
>
> sub commit_changes ($$\$) {
>  my ($doc, $file, $errormsg) = @_;
>  my $fh;
>  unless ($fh = IO::AtomicFile->open($file,"w"))       { $$errormsg =
>  "Couldn't
> open filehandle to $file : $!";
>          return 0; }
>
>  eval { $doc->toFH($fh, 1) };
>  if ($@) { $fh->delete();
>     $$errormsg = "commit_changes error with $file : " . $@ . "\n";
>     return 0;
>  } elsif ( not $fh->close() ) { $$errormsg = "Couldn't write file
>  $file"; } else { return 1 }
> }
>
> -=-=-=-=-=Script Ends=-=-=-=-=-
>
>
> --
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>


===== [EMAIL PROTECTED] === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
        -- Terry Pratchett in Sourcery


--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to