Sunday, 31 December 2006

RTFM - between the lines

Writing documentation sucks.

Sometimes it's next to impossible to convey all the information you need to help people understand your product. If something is large and complicated, the new user is likely going to miss things and there's nothing you can do to change that. We all learn differently, so regardless of how hard you try, some concept is going to slip through the cracks and be misunderstood by somebody.

I mention all this because I learned something fairly important about the MySQL C API today: the return value from most functions is fairly meaningless and should be treated as a boolean. Most functions return an int which a robust application should examine. What the robust application shouldn't do is assume that the return values means anything other than "zero good, non-zero bad", and that one needs to call mysql_errno() to retrieve the real error code.

At first I was a little pissed off that the manual wasn't more explicit about this; there are two sentences at the bottom of one page of the documentation that mention you should use mysql_errno() or mysql_error() to find out what went wrong. I felt that there should have been some large, obvious declaration somewhere stating "The Return Values Don't Mean Shit, Newbie. We've Provided You With The Means To Get The Information, So Use It".

Upon further reflection, it occurs to me that I'm full of shit. The manual does state in black and white that one should call mysql_errno() to find out what went wrong. The fact that I hadn't read that portion of the manual is nobody's fault but my own. Secondly (and probably more importantly), I'm a Win32 programmer; return values in that realm generally don't mean anything either, and you're obligated to call the ubiquitous GetLastError() to find out what happened.

I told you that story to tell you this one.

In my last two test runs with LokiJr, I discovered that he became unresponsive after a couple of days. The first time I wasn't sure why, because I wasn't capturing any debug information. The second time I did, and the problem revealed itself as a lost connection to the database. Not surprised that he lost his database connection; sooner or later the server is going to close an unused socket. However, I thought I'd provided for that case. I check for the corresponding error codes and reconnect if necessary, but Jr wasn't attempting to reconnect - he just failed to execute the query and reported that the server had gone away. Odd... why wouldn't he reconnect when he can plainly see that the server has gone away?

Finally occurs to me that I was checking the return value of mysql_real_query() instead of mysql_errno(), and that I was using mysql_error() to get an error string from the server, which is why he "knew" what the problem was, but didn't react properly. Inserting a call to mysql_errno() and checking that value gives us the correct behaviour, even if one restarts the MySQL server.

So remember kids, don't shoot the messenger; sometimes the designers of the software have told you what you need to know, they just didn't print it on a billboard.

Saturday, 23 December 2006

Building a bot, part deux

So I've got a preliminary bot running on #bottest at The Nibble. He's still kind of dumb, but I'm happy with how easy it was to get up and running. I think the toughest part was wading through the RFC to get all the protocol info I needed.

Here's the limited command set:

  • !greet - greet user with (one of) their tagline(s)

  • !joke - tell a random joke

  • !seen (nick) - print last time user was seen (if known by the bot)

  • !seen - print entire !seen list

  • !link or !url - print a random web link



If you whisper in his ear (via /msg or a query window) you can ident (password) (nick) yourself and claim the accounts I set up for you (and you know who you are). It's perfectly safe - he runs on SSL, too. Better instructions and a few nice operations net yet available via IRC are available at LokiJr's temporary home.

Basically, this is just proof-of-concept stuff, and some framework from which to build bigger and better ideas. The code is a bit of a snarl because I don't have a clue what I'm doing yet, but again, it's really just a prototype. I already have a whole bunch more ideas, and I'm sure you will after you've toyed around with the little bastard yourself.

What's to come:
Better integration with the database: currently there's some stuff that's hardcoded that should be coming out of tables. Ideally, the only items required outside of the database are the database parameters themselves. Once the bot connects to the database, he ought to be able to get everything he needs from there - including the queries he needs to do other things. Rather than message around with SQL statements in the C++ code, I could be debugging him on the fly - re-compiling for an SQL goof seems like a waste of time.

More commands: obvious, but required.

Script interpreters: I spent a little time today messing with perlembed; I'm pretty sure I can graft it on in a day or two. Python can't be far behind. And just because I'm very sick man, I'll probably add the little gem found here: CINT

In the end, you ought to be able to add functionality quite quickly by writing up a script in the language of your choice (no Tcl/Tk - don't even ask), and submitting it to a database table. The bots will occasionally check for updates - probably whenever the server issues a PING - or we'll have a !rehash command or some such.

Questions? Comments? Care hook into my SVN server and help?

Wednesday, 20 December 2006

More soon, but a few pleasantries first

First off, thanks to Dom for setting this up and allowing us to mess with the themes and stuff. I really will have something more interesting here soon, but Herself has beckoned me to go someplace and obey I must.

First post

That chippie thing? I took that out.