http://qs321.pair.com?node_id=271216

sulfericacid has asked for the wisdom of the Perl Monks concerning the following question:

Still working on the same problem, I'm making this question really short with as few codes as possible hoping more people will read it.

You can send as many plain text messages of around 500 or so characters and the script will purr if you ask it to. But if you add an emoticon ( :), :( ) ... the script will crash anywhere between 10 and 15 messages from the first time you used it. All it takes is one smiley face for the database to lose it's insertion order and stop posting messages correctly. (oddly enough the swear filter doesn't affect anything).

Can someone please take a look at the snippet below to see what's making the database crash on me?

use Tie::IxHash; my $columns = 50; use Text::Wrap qw( wrap $columns ); require SDBM_File; my %chat; my %chatorder; my @words = (); my $chat = "list.dbm"; # location of database my $imagedir = "http://sulfericacid.perlmonk.org/chat/images"; + # location of image directory (emoticons) tie %chat, "Tie::IxHash"; tie %chatorder, "Tie::IxHash"; tie (%chat, 'SDBM_File', $chat, O_CREAT | O_RDWR, 0644) or die "Couldn’t tie SDBM file '$chat' $!; aborting";; foreach (reverse keys (%chatorder)) { my ( $name, $message, $time ) = split /::/, $chatorder{$_}; $name =~ s/$_/****/g for @words; # say goodbye to swear words $message =~ s/$_/****/g for @words; # say goodbye to swear words $message =~ s/:\)/\<img src=\"$imagedir\/smiley.gif\"\>/g; # happy emo +ticon $message =~ s/:\(/\<img src=\"$imagedir\/sad.gif\"\>/g; # sad emoti +con $message =~ s/:p/\<img src=\"$imagedir\/tongue.gif\"\>/g; # tongue em +oticon $message =~ s/:P/\<img src=\"$imagedir\/tongue.gif\"\>/g; # tongue1 e +moticon $message =~ s/:o/\<img src=\"$imagedir\/oh.gif\"\>/g; # oh emotic +on $message = wrap('', '', $message); print Tr(td({-width=>'700'},"<font color=blue>&lt;$name @ $time&gt +;</font>$message")), }


"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: same database problem
by bobn (Chaplain) on Jul 03, 2003 at 17:04 UTC

    Not to be meaner than needed, but, (since this is the third time you've posted this), which part of "post a small snippet of code which demonstrates the problem" do you not understand?

    update:What's meant by a small snippet that demonstrates the problem: get rid of everything except a loop that inserts the string you think is the problem into the db file, via the tied hash. If you're really using the string that causes the problem (which you should verify by some print messages in your regular program, as another poster below mentions), then the problem really is the db file or the module that ties it. And the program that demonstrates this should be about 5-10 lines long. But if youcan't reproduce it that way, then your problem is elsewhere.

    Your code has the foillowing problems:

    • foreach (reverse keys (%chatorder))iterates zero times because %chatorder is empty. In your actual code there may be something there, but in the code you posted, there is not.
    • The code iterated wouldn't do anythng anyhow (except genrate a Undefined subroutine &main::td error due to no use CGI), because it contains no references to %chat or $chat{some_key}
    • On my system, the tie (%chat, , 'SDBM_File', fails without a use Fcntl;
    • The tie %chat, "Tie::IxHash"; is almost certainly meaningless due to the subsequent tie (%chat, , 'SDBM_File',
    Once again, create a snippet of code that runs from the command line, and demonstrates the problem, and you have an actual chance of someone helping you.

    --Bob Niederman, http://bob-n.com
Re: same database problem
by Tomte (Priest) on Jul 03, 2003 at 17:45 UTC

    Learn to debug!
    sprinkle 'print STDERR's through the execution-path and see what data you really have on each step, for a start, to see if it does what you think it's doing, try to isolate the problem in your code, if you wouldn't understand the why and therefore ask why something happens, instead of asking what actually happens, that would be a real progress.

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.

Re: same database problem
by pfaut (Priest) on Jul 04, 2003 at 13:53 UTC

    One thing that might help you when debugging web applications is to make your code more modular. Create packages to handle different aspects of the program. Your entire database interface, for example, ought to be written as a separate module. And don't think being a separate module means writing OO code - it just means separating out a related set of subroutines into its own source.

    If you do this, you will have a defined set of subroutines to talk to your database - this is the database interface. You will then be able to write test programs to call this interface and make sure it works before you try calling it from your web pages (which are extremely hard to debug).

    Figure out what transactions you are performing against your database and write subroutines to perform those transactions. It sounds like you might need routines to add new messages, list messages, get a specific message, etc. Then, remove all database handling code from your web apps. They should collect submitted information, determine what needs to be done, and pass some or all of that collected information to one or more database routines to do the actual work.

    90% of every Perl application is already written.
    dragonchild
Re: same database problem
by Cody Pendant (Prior) on Jul 04, 2003 at 01:17 UTC
    While we're here, sulferic, you might want to note that you can use other characters than / when doing "$x =~ s///" -- you can use # or ! or | and so on, which makes it a lot easier when replacing involves HTML. Also you seem to be under the impression that you need to escape HTML brackets and quotes with preceding slashes, but you don't. Your line:
    $message =~ s/:\)/\<img src=\"$imagedir\/smiley.gif\"\>/g;
    could just be
    $message =~ s#:\)#<img src="$imagedir/smiley.gif">#g;
    or
    $message =~ s{:\)} {<img src="$imagedir/smiley.gif">}g;


    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
    M-J D
      I wasn't aware you could use different characters during a substitution, thanks for that bit of info. You're right, that would make life a lot easier to read using # instead of slashes in situations like this. Your first solution is easy to read, I'll have to admit when using curlies confuses me.

      This problem was bugging me for a few weeks now so I was throwing in anything I thought the problem could be (escaping every non-letter character). Also, I make a habit of escaping pretty much everything because I don't quite understand when things need to be escaped and when they're ok.

      Thanks for the suggestion, that's really going to clean up my code :)

      "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

      sulfericacid