While we were watching a ball in a TV adaptation of Northanger Abbey last night, Elyn hit upon a genius idea: DDR Georgian Edition. Just the thing for those Austen revival parties!
Despite my lackluster performance at a talk last month (about Emacs, what else?) the Boulder LUG let me attend another meeting. Thanks!
I was fascinated by this talk — I know little about databases and enjoy hearing about them. Although it ranged strangely between the very generic (high-level comparison of MySQL and PostgreSQL) and the incredibly specific (rundown of command line options to psql), Kevin’s depth of knowledge and cool stories made this well worth attending.
Postgres is a good product. My impression, overall, is that while it is missing some gloss that Oracle has, it is basically “enterprise-ready”. Kevin has a project now that gets one terabyte of new data per day, and Postgres handles that fine. Refreshingly, Kevin did not spend much time defending the choice of an open source product over a proprietary one. I guess at a LUG that would seem unnecessary — I thought so, too, until somebody asked why bother.
A database is a big programming environment in its own right. One take away for me was: learn something before starting. Kevin said he’s run across projects that did not vacuum regularly and were running with a lot of bloat — basic stuff. Based on his talk and the questions, some of which I did not understand at all, I would say that if I were running a company I would just hire a DBA and move on.
Kevin is a fan of Slony-I for replication. This came up over and over through the talk, as did table partitioning (which I had never heard of before).
One goal I have for integrating Python scripting into gdb is to be able to fully control gdb from Python. I’ve made a few steps toward this recently. Today I can do:
#! /home/tromey/gnu/python-gdb/build/gdb/gdb --python import sys, gdb from hack import inferior child = inferior(sys.argv) if not child.run(): gdb.execute("bt 5") gdb.cli()
This is a short script that is marked executable. With this, I can invoke “
stop-if-broken my-program arguments“. This will run the program; if it dies for some reason, it will print a stack trace and bring up the gdb command line. Otherwise, it exits.
I like to think you can already see the future of gdb here, though. And although this is pretty young, you can easily extend it a bit — for instance, you could add breakpoints between creating the inferior and starting it. Still, don’t be totally fooled; this is still a toy and there is a lot to do on the gdb side.
hack” stuff is because I have no clue about intelligently managing Python packages. I’m looking for a good guide here. What I really want to do, I think, is have classes like
Breakpoint, etc, directly in the gdb namespace, but I don’t want everything in one huge file. Or is this javathink? Writing “
import gdb.inferior.Inferior” feels weird. (If you’re going to give me advice — which I really want — there is an added wrinkle, which is that the
gdb module is created directly in the C code in gdb.)
Yesterday I set up a new blog aggregator for Elyn. It is called “All About Psychotherapy and Counseling“, and aggregates blogs from various therapists, including her.
Setting this stuff up is pretty easy — I used WordPress, because the hosting service makes it very, very easy to install, and because Elyn already knows how to use it. Then she found a WordPress theme she liked; I installed that and tweaked it a bit with some newfound PHP knowledge. And finally, I installed the excellent FeedWordPress plugin to handle the actual aggregation. There were a couple tricky bits — I had to use a trick to get the author attribution to work properly (I don’t know yet if this is a FeedWordPress problem or a blogspot problem) — but nothing too extreme.
I’m a fan of WordPress.
Go read the new planet.
This weekend our wireless router went on the fritz, so I replaced it. Naturally, this turned into a multi-day, hair-pulling ordeal.
First, the new wireless box did not play well with the DSL router. For some reason, it was apparently programmed with an extra error check, so I couldn’t get its built-in DHCP server to hand out addresses on the same network as the DSL server, even though I configured them to handle different ranges. The old wireless handled this just fine… grrr.
So, I subnetted, using 192.168.0.0/7. Great! Everything is working. Except…
Elyn couldn’t print any more. Looking in the logs I saw the dreaded
client-error-not-found. My searches yielded nothing worthwhile — am I unusually bad at searching, or is there just little information out there?
First, I changed the machine attached to the printer to have a (local) static IP. It’s been a long time since I did this kind of thing (I switched to NetworkManager as early as possible), and so this took a while. (I didn’t find a man page describing the ifcfg files — is there one?) A static IP let me hard-code the IP address on Elyn’s Mac without worrying that a reboot would invalidate her configuration.
Oh, BTW — setting up a new printer is a great example of a place where the Mac’s vaunted GUI is not so hot. For one thing, as far as I can tell, you can’t edit an existing printer — you have to delete it and start over. I got really good at typing “192.168.0.50″.
It turns out that having a default printer configured in CUPS was not enough to let the Mac print properly. I don’t know whether this is a bug on the Mac or a bug in the CUPS in F8 — I saw requests in the log for “
ipp://192.168.0.50:631/“, but then CUPS would return the not-found error, and the print job would fail.
In the end I hit upon telling the Mac that the printer queue name was “printers/Name” (“Name” being the name of the printer), and this worked… I think this is amazingly obscure.
Due to my recent hacking on gdb, I’ve been thinking recently about patch review. Mostly, I seem to be interested the social aspects of review; though there’s also a lot to discuss concerning the mechanics, and that would probably be a useful area for a tutorial of some kind.
Here are a few guidelines I came up with, based on what I think I do when I review a patch:
- Don’t hold a patch to a higher standard than the code it modifies. I think it is pretty tempting to try to get patch submitters to do cleanups that you, the maintainer, have been putting off. My view is that it is more important to encourage part-time patch contributors than it is to try to achieve perfection in the code. Yes, the existing code may have some problem that the new patch perpetuates. But, one more instance of that is not going to severely disable a cleanup effort.
- Keep your standards up. While you can’t expect a patch to solve unrelated existing problems, it is also important not to let your standards drop. This is easy to do — for example, a big, useful feature might be written by someone who is unwilling to write documentation. One thing to remember is that every time you give in to something like this, it is harder to resist the next time. And, it gets harder to enforce the rule for the rest of the community. One solution is to try to work with the submitter to find someone willing to help him. With new contributors it is sometimes handy to temporarily break this rule — fix up their first patch, send it back so they can see it, and then tell them that this is how it ought to be done in the future. This can avoid the slippery slope problem, as long as you are clear that it is a one-time-only event.
- Review the patch, not the context. This is related to the first point. Sometimes the context of a diff will have an obvious problem; it can be tempting to ask the patch submitter to fix this as well. In the worst cases, this will snowball into a generic cleanup. Resist this temptation! Instead, fix the context yourself; or at worst ask if the submitter would be willing to submit a separate cleanup patch. I think that, ordinarily, this temptation arises when patch-writing barriers are too high — rather than try to push things off on volunteers, look at lowering these barriers so you don’t shy away from quickly cleaning up small messes.
- Keep independent disputes independent. When I am triggered by someone, it is easy to want to hold a grudge and to review their other patches more harshly. This is a huge mistake. A dispute about one change need imply nothing about another; mixing them together will just cause confusion and distrust. This does not mean you ought to ignore bad behavior — it is very important to set boundaries and raise communication standards as early as possible. Instead, you can reply to a “bad” note twice, once to start a sub-thread discussing the content of the patch, and a second response to address the tone of the message.
- Enforce your standards on yourself. Or, if you can do it, have higher standards for yourself than for others. Either way, this is hard to do — I find it easy to cut myself some slack, knowing I will be around to clean things up later. Likewise it is easy for me to go with the first fix I think of, or to give a new function the first name that comes to mind. Similarly, hold your logic and standards up to the same scrutiny. It is community-destroying when a maintainer says one thing, but then does another himself.
- Ignore patches you don’t care about. A large project will get many patches. Think about what areas you are interested in, or know about, or want to influence; and then ignore the rest. I sometimes see attacks on patches from otherwise disinterested parties. I’m not sure what is going on here — maybe just the occasionally irresistible urge to appear smart — but it is counterproductive. If someone’s patch fixes their problem, and doesn’t affect you, get out of the way.
- Be generous. Remember what your goals are when reviewing. Mine are to get quality patches into the tree, and to gain new contributors. So, I try to be polite when responding and I try to give only constructive criticism. If I make pedantic comments on a patch, I usually explain that they are just nits to fix; but more importantly, I just try to avoid being overly pedantic.