tag:blogger.com,1999:blog-11154769460168818892009-06-18T17:21:17.352-07:00Pulvis Et UmbraJayson Vantuyl's personal blog. Guaranteed to randomly and infrequently updated at my whim.Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-1115476946016881889.post-22191393466596769102009-06-18T15:17:00.000-07:002009-06-18T17:20:55.019-07:00A Quick Guide To TwitterIt seems like I have to explain Twitter every few days. While I think it's a wonderful service, I think everyone can agree that it's a bit obtuse. In order to save myself some trouble, I'm writing this post so that I can refer people to it. Call me lazy.<div><br /><div><b><span class="Apple-style-span" style="font-size:x-large;">What Is Twitter?</span></b></div><div><br /></div><div>This is a very good place to start. The easiest way to describe Twitter is:</div><div><blockquote></blockquote><blockquote>A little bird that tweets in all of your friends' ears.</blockquote></div><div>Basically, Twitter is a service to make communication easier. This is important to keep in mind. It is VERY easy to publicly humiliate yourself on Twitter. One wrong character can make a private Tweet very, very public.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">The Terminology of Twitter</span></b></div><div><br /></div><div>You've already probably noticed that I call a message sent via Twitter a "tweet". Here's the exhaustive list of terms you'll find useful:</div><div><ul><li>twitter: (n) a messaging service.</li><li>tweet: (n) a message sent via the Twitter messaging service.</li><li>(to) tweet: (v) the act of sending a message via Twitter</li><li>twitter client: (n) a program used to Tweet on Twitter</li><li>follow: (v) indicating that you are interested in a person's Tweets (often used to refer to your group of followers or the people that you follow)</li><li>at-reply: (n) a PUBLIC reply on the Twitter service, denoted by beginning with an @username</li><li>at-mentions: (n) a PUBLIC mention of someone on Twitter, denoted by having @username somewhere other than the beginning of a message</li><li>direct-reply: (n) a PRIVATE reply to someone on Twitter, sent by starting a message with "d username"</li><li>tweeple, tweeps: (n,pl) the group of people who follow you on Twitter</li><li>retweet: (v) the process of posting an interesting Tweet that you received from someone</li></ul><div><b><span class="Apple-style-span" style="font-size:x-large;">Strange Limitations</span></b></div><div><br /></div><div>Twitter, like MySpace before it, is a service that really "happened" more than it was "planned". Because of this, you may notice that it can be a bit rough around the edges. The factors that shaped it have given it some particular warts that I'll try to mention.</div><div><br /></div><div><i>Message Length</i>: Messages on Twitter can only be 140 characters. Longer messages are cut off.</div><div><i><br /></i></div><div><i>Cryptic Commands</i>: Private messages, at-replies, and at-mentions focus a rather crusty mix of single letters and symbols.</div><div><i><br /></i></div><div><i>Slowness</i>: At times, Twitter can be behind by hours.</div><div><i><br /></i></div><div><i>Link Mangling</i>: Web-links in messages are rewritten in a way that hides where they point.</div><div><br /></div><div>It turns out that every one of these limitations comes from one of Twitter's biggest strengths--SMS support. Twitter, from the beginning, has been made to be used on a simple, unadorned cellphone. While this undoubtedly has made it a success, we have to live with the above problems.</div><div><br /></div><div>Cell phone messages (so-called SMS messages) are limited to 160 characters. This means that messages from Twitter have to be shortened. This is where the length limitation comes from. It's worth noting that messages longer than 160 characters are supported by some phones, but the other phones hold us back. Some people feel that the brevity forced by this limitation is what makes Twitter enjoyable--it forces people to be succinct.</div><div><br /></div><div>The cryptic commands and link mangling are both ways to cope with the limited space. The commands have to be short, and the link mangling is done to make the web-link shorter.</div><div><br /></div><div>The slowness is just the nature of the beast. It turns out, that <a href="http://twitter.com/aplusk">some</a> <a href="http://twitter.com/barackobama">people</a> have lots of followers. When these people Tweet, every one of their followers must be notified. Today, those two users alone are responsible for over 15 million messages that must be sent. To put that in perspective, if they started at midnight (which they didn't), that would be 264 messages per second!</div><div><br /></div><div>Suddenly it makes sense why Twitter falls behind!</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">How To Use Twitter On The Phone</span></b></div><div><br /></div><div>There's a list of commands <a href="http://help.twitter.com/forums/10711/entries/14020">here</a>.</div><div><br /></div><div>To send a public message to all of your tweeps, just message the Twitter number (40404 in the US).</div><div><br /></div><div>To reply to a user named kagato, send a message like "@kagato I liked your omelet recipe.". This message will appear on your public profile as your Latest Tweet, appear in your public timeline, and generally be messaged to that user.</div><div><br /></div><div>To mention a user named kagato, send a message like "Omelets are AWESOME! Right @kagato?". In this case, the message will appear as your Latest Tweet, be messaged to all of your Tweeple, and generally be messaged to that user as well.</div><div><br /></div><div>You'll often see mentions like "Hanging at out an awesome Omelet Bar in Vegas with @kagato and @freeformz".</div><div><br /></div><div>To send a private reply to a user named kagato, send a message like "d kagato Pssst! Omelet's make me gassy.". Be <b><i>very careful</i></b> when sending private messages. It is very easy to accidentally type "dkagato ...". In that case, your message would go to all of your tweeple!</div><div><br /></div><div>To mark a user's last tweet as one of your favorites, send a message like "fav kagato". Note that this will sometimes mark a later tweet than the one that you intended when Twitter gets behind. You can also just send "fav" to mark the last tweet you received (from whoever) as a favorite. Again, this can suffer when Twitter gets behind.</div><div><br /></div><div>To follow a new user, send a message like "follow kagato".</div><div><br /></div><div>To nudge a user (silently indicating to them that they aren't talkative enough), just send a message like "nudge kagato". Not many people use this one.</div><div><br /></div><div>To disable all phone messages, send "off". To enable them, send "on". You can also put a user's name after them to just muzzle a specific person. That can be helpful when people are drunk-tweeting. Just don't forget to unmuzzle them when they sober up.</div><div><br /></div><div>To find out information about a user, send "whois kagato".</div><div><br /></div><div>To retrieve the latest tweet from someone, send "get kagato".</div><div><br /></div><div>To be vain and get information about yourself, send "stats".</div><div><br /></div><div>To invite someone to twitter by text-message, send "invite 415 555 1212" (substituting whatever their number is).</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">How To Use Twitter on the Web</span></b></div><div><br /></div><div>Just play around at <a href="http://twitter.com/">twitter.com</a>.</div><div><br /></div><div>Ironically, one you log in, just type a message like you would on your phone. There are buttons for most of the features (following people for instance), but messages, @replies, @mentions, and direct messages all work in the little box.</div><div><br /></div><div>The search functions here can be nice. The public timeline can be nice. Otherwise, it's about like your phone (at least in terms of functionality).</div><div><br /></div><div>The most useful feature that is on the website is the ability to control whether you get "mobile updates" for a user. This lets you get realtime updates for some people, while other people only appear on the web (or in your Twitter Client, if you use one).</div><div><br /></div><div>I mostly have close friends and coworkers enabled for mobile updates. This lets me catch messages like "Anybody up for dinner?". Setting dinner plans over Twitter can be a very cool pick-me-up at the end of the workday.</div><div><br /></div><div>On the other hand, I have many other people I follow. I occasionally (maybe once every other day) check my Twitter client. This lets me pull in the full volume of Twitter on my own time (instead of over my entire day).</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">Other Neat Stuff</span></b></div><div><br /></div><div>There are other services available over Twitter.</div><div><br /></div><div>You can use <a href="http://twitpic.com/">twitpic.com</a> to put links to pictures in your Twitter messages.</div><div><br /></div><div>People often put "tags" in their messages for people to search for. Whenever you see a message like "I love Chicken Tikka Masala #food", the #food part is a tag available for searching.</div><div><br /></div><div>Sometimes you'll see a message like "Just bought some $AAPL because $MSFT is down". These are used to indicate that a word is a stock symbol.</div><div><br /></div><div>Some people even put links to their location on a map. The possibilities are really endless.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">Twitter Clients</span></b></div><div><br /></div><div>If you become a "hardcore" Twitter user, you may download a special program just to access Twitter. If you're really into it, you might even get a special one for your iPhone or BlackBerry.</div><div><br /></div><div>Twitter Clients are where things get pretty crazy. The functionality like stock symbols, location links, @replies, TwitPics are all integrated into various Twitter clients. From my phone, I can take a picture of something and Tweet about it with a link to the location on a map. It's surreal.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">Other Twitter Quirks</span></b></div><div><br /></div><div>The one other thing that always seems to trip people up is retweets. Let's say that you hear about some new thing you like. For example, you might receive a message like "freeformz: A bank car overturned at 4th and King, free money!". You, understandably, might want to send this to all of your friends so they can become wealthy with you.</div><div><br /></div><div>However, knowing that freeformz will soon be a rich man, you don't want to offend him by implicitly claiming that you are the source of this blessed information. This seemingly simple scenario can be confusing.</div><div><br /></div><div>Many people re-tweet with a message like "RT @freeformz: A bank car overturned at 4th and King, free money!". The RT indicates that it is a retweet. Some people will do it like this: "A bank car overturned at 4th and King, free money! (via @freeformz)". In either case, it does the same thing.</div><div><br /></div><div>To complicate things, sometimes people want to add some more to the message. This makes it <i>really</i> confusing. For example, you might see this "RT @freeformz: A bank car overturned at 4th and King, free money!-- I'm RICH!". In this case, it's easy to miss that @freeformz was the one with the initial message and that the re-tweeter added "I'm RICH!".</div><div><br /></div><div>In other words, read carefully, and watch for signs that someone added a message to the end of a re-tweet.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:x-large;">Conclusion</span></b></div><div><br /></div><div>Twitter is a powerful and useful tool for forcing people to effectively communicate through cryptic abbreviations and haikus. Hopefully it can be as transformative for your time-wasting as it has been for mine.</div><div><br /></div><div>Good luck, and have a lot of fun!</div></div></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-2219139346659676910?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-41369287036750921192009-06-02T17:47:00.000-07:002009-06-02T18:02:20.254-07:00Interpreting The Evidence on Human ReasoningI recently read two largely unrelated articles. Much like french fries and milkshakes, they go together well even though you might not expect it.<br /><br />If you have a technical bent, read <a href="http://discovermagazine.com/2009/feb/16-what-makes-you-uniquely-you/article_view?b_start:int=0&-C=">this</a> whole article. It's about a guy building electronic brains, and it's fascinating. If you just want the salty-sweet juxtaposition, just read the first question on the third page <a href="http://discovermagazine.com/2009/feb/16-what-makes-you-uniquely-you/article_view?b_start:int=2&-C=">here</a>.<div><br /></div><div>Now read <a href="http://www.juliansanchez.com/2009/04/06/climate-change-and-argumentative-fallacies/">this article</a> on the recent friction between science and politics.</div><div><br /></div><div>What's interesting is the fact that the observations of the first article cast the second article in a disturbing but understandable light. As thinking creatures in what some assume is an age of reason, it's comforting to think of reason as being somehow inherent in ourselves. In a democracy, it's most depressing to conceive that your voting peers might lack that spark of reason that we've hoped drives a democracy towards informed legislation.</div><div><br /></div><div>The sad truth appears to be that the brain is really just a powerful, dynamic pattern-matching system. While this makes it very generally applicable, it also means that it's possible to train it to match in a way that is wholly incompatible with logic and reason. I guess nurture wins out of nature on this one.</div><div><br /></div><div>What I find to be most interesting is that this is a clue that many AI researchers are focusing in the wrong places. It's pretty clear that achieving intelligence in a human sense will have to be highly statistical in implementation. While I do sincerely hope that we can someday build a logic processor that is based entirely on semantically-infused logic, I wonder at how such a machine would contrast with humanity.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-4136928703675092119?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-9103653801172276372009-04-27T11:59:00.000-07:002009-04-27T11:59:32.868-07:00What Java Should Learn From Ruby and RailsI hate to say this, but Java has gotten a bad rap among some programmers. It's deserved at times, but it's worth noting that it's often more about the people behind Java than the technology itself.<br /><br />Here's an example. Clearly, <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4273532">this is horribly wrong</a>. Sun refuses to fix a bug because people have worked around it, thus it must be maintained--to the detriment of all programmers to follow. This gradual growth of cruft is one thing that has driven people away from Java.<br /><br />Why is this important to me? Well, it's mostly important because I think that it prevents good comparisons of technologies. It sends the wrong message when people move to Rails because Java is riddled with unnecessary complexity and buggy libraries. While it is some compliment that it says that Ruby is easy to use compared to Java, it doesn't emphasize what makes Ruby such a different way of doing things.<br /><br />Real improvements like reduction in code through expressiveness, flexible extension of types, the block syntax, et cetera get lost in the shuffle. What's worse, it doesn't send the message that Ruby can be used to solve industrial problems. The eternal mantra of the Ruby naysayers--that it doesn't scale--is at least partially reinforced when people flock to it for simple projects.<br /><br />For those who have built scalable applications on top of Ruby, this is laughable. Yet the point remains that dynamic languages in general and Ruby in particular have a great deal of value to deliver to real, serious software development. Even though it's fun to play with, it's not just a toy.<br /><br />Similarly, when people legitimately work on projects like JRuby that work gets ignored by people who just don't want to deal with the cruft. While that's a great reason to avoid a class-library, it's a horrible way to allocate our resources as an industry. In a world where languages live or die by their "standard libraries", this just makes people's lives harder and guarantees that we spend more energy to move the same distance.<br /><br />I can only hope that Oracle's recent acquisition of Sun might change this attitude and position Java as a more useful technology. It's a shame to see all of the hard work people have put into the JVM be squandered because some people are afraid to break an API. If anything, this could have been turned into an opportunity for Java to offer versioned APIs, but instead it was met with duplication of functionality and degradation of the clarity of their class library.<br /><br />I feel that this puts work on Rails 3 in an important light. The Merb project was about a lot of things, but one of its most important aspects was that the people behind it continued the march towards a better product. The Rails core team did a great thing by welcoming the best of Merb into Rails. It's letting us build a better future, and it's showing that we can maintain compatibility and still move forward.<br /><br /> We just need to always be mindful that the day that we stop improving Rails is the day that someone starts writing its replacement. More than anything, we need to insist that there is no excuse for not fixing a bug.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-910365380117227637?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-49039523611488284292009-04-25T19:41:00.000-07:002009-04-25T19:59:08.023-07:00Random MacOSX TCP BehaviorTCP is an interesting protocol. It's interesting mostly because it is less a specification of bytes and more a specification of behavior. Most TCP implementations have developed from the sort of arcane knowledge that you can only amass after trying to implement such a basic protocol over a long period of time.<br /><br />By the time TCP (and indeed the whole IP stack) has made it to my desktop, it had been on a long journey. MacOSX's network has a storied pedigree that goes back deep into the iterations of the original BSD Unix. There is, as they say, heavy voodoo.<br /><br />Today I hit a corner case that only made sense after some pretty serious debugging. I'm sharing it here with the hopes that it may save you the headache.<br /><br />The backbone of the Internet is designed to just have these routes disappear for a while. You get a few ICMP messages back if you're very lucky. Otherwise, your packets might just disappear.<br /><br />One of the nice features of TCP is that it's incredibly resilient to network links just disappearing. This is no problem for it. In fact, if you're not sending any traffic, you may not even notice that you're down. Failures being invisible is a nice feature when you're not doing anything.<br /><br />That said, there are protocols that really want to know when they're down. XMPP is one of them. For protocols like XMPP, there is a pretty standard procedure of having some sort of "keep-alive" data that you occasionally send. Since XMPP data streams are just XML documents, most XMPP implementations just send a few whitespace bytes in between stanzas when idle.<br /><br />Today, I was debugging an XMPP connection over a 3G modem. This manifests itself under a ppp0 link in MacOSX. While I wasn't thinking about it, I walked around with my laptop. One spot caused the phone connection to lose signal and it failed. When I noticed, I reconnected the modem. This provoked some very interesting behavior (or rather lack of behavior) from the BSD IP stack.<br /><br />Normally, when some fundamental aspect of network changes, there is some device that will interrupt your connection. For example, if my XMPP server had lost power, when it recovered the keepalive packets would have triggered a TCP reset, which breaks the connection. Similarly, if I remove an IP address from a Linux machine, connections on that IP are interrupted. It just so happens that in this case, the IP stack did NOT break the connections.<br /><br />In fact, it just silently ate any data that the connections attempted to send. So the keepalives completely failed to kill the dead connection. It took almost fifteen minutes until some sort of behavior that caused the IP stack to notice that the connection should be killed.<br /><br />It took a while to track down what was happening, but apparently the connections were maintained (so says netstat) and the sent packets just disappeared without any sort of sending error! Very weird behavior triggered by an odd corner case. I've also discovered that this appears to also happen when you close your laptop and go to another wireless access point. This is ugly for my use-case, as I want the agent on the laptop to reconnect when it has a new address. If anyone has a good way to detect this in a portable way (i.e. not plugging into Apple's NetKit watchers), please let me know.<br /><br />While I find this mildly annoying, I have to admit that I can't fault TCP. If the packets are just disappearing, the best behavior is to just resend and keep waiting for the connection to come back up for a reasonably long time out. This is exactly what happened. Instead, I hope that Apple will eventually do what Linux does and push an error into the socket when it tries to send from an address that isn't valid for that machine anymore.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-4903952361148828429?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-54025607879903933072009-04-23T08:40:00.000-07:002009-04-23T08:45:24.545-07:00One Year Update<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/P4110359-711276.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://souja.net/uploaded_images/P4110359-711264.jpg" border="0" alt="" /></a><br />Who gave this guy permission to grow? I sure didn't! I guess it's okay, though... :)<div><br /></div><div>Here are some good pics grandma Vantuyl got of the birthday boy:</div><div><br /></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/P4110355-711249.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://souja.net/uploaded_images/P4110355-711235.jpg" border="0" alt="" /></a><br /><div><br /></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/P4110370-767407.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://souja.net/uploaded_images/P4110370-767390.jpg" border="0" alt="" /></a><br /><div><br /></div><div>One down, seventeen to go. ;P</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-5402560787990393307?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-16566448799608677542009-04-23T06:36:00.000-07:002009-04-23T08:33:04.815-07:00On Tail Recursion Elimination<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/f/fa/Ouroboros.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 358px; height: 380px;" src="http://upload.wikimedia.org/wikipedia/commons/f/fa/Ouroboros.png" border="0" alt="" /></a><br />There was a bit of <a href="http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html">a controversial post</a> on Guido van Rossum's blog that I thought deserved a little comment.<div><br /></div><div>To sum up Guido's argument, he doesn't feel like implementing <a href="http://www.itl.nist.gov/div897/sqg/dads/HTML/tailRecursion.html">Tail Recursion Elimination</a> (henceforth referred to as TRE) in Python because:</div><div><br /></div><div><ol><li>Stack traces help debug, TRE makes them useless</li><li>TRE Is Not An Optimization (it creates a class of code that explodes without it)</li><li>Guido does not subscribe to the "Recursion is the basis of all programming" idea</li><li>Due to Python's highly dynamic namespaces, it's very nontrivial to know if a call is a recursion.</li></ol><div>The funny thing is that, even though I am a big supporter of TRE, I actually agree with all of these points. Taking them in turn:</div><div><br /></div><div>Stack traces are critical to debugging code. Ruby and Erlang both started out with uglier stack traces than they have today. They were adjusted because they are important. Similarly, the most difficult Python frameworks have always been that way due to their affect on stack traces. Zope and Twisted--I mean you. Zope would create absolutely titanic stack traces. Twisted, on the other hand, creates virtually no useful stack traces (as a consequence of the deferred model).</div><div><br /></div><div>While I find this to be telling, I would caution against considering this in the context of TRE. Why? Simple. Some styles of programming don't generate good stack traces. As an example, consider the construct of a loop. Loops don't generate stack traces. When code explodes in a loop, you have no idea what state led-up to that explosion. Does that mean that loops are "bad"? No. It simply means that what we want is not a stack-trace, but rather information about what led up to the failure.</div><div><br /></div><div>For some classes of code, stack-traces provide that fairly economically. The catch is that other types of code don't benefit from them at all. Guido's statement that you can trivially rewrite any TRE function as a loop is very practical, but it actually detracts from his point. It's pretty clear that the type of code that benefits from tail recursion doesn't benefit from stack-traces. This means that effectively he's deciding that Python just doesn't tailor to a certain type of code. I'm mildly opposed to this and I think there's a good case for a type of TRE in Python.</div><div><br /></div><div>Taking the second point, Guido has this right. The fact that there is code that would explode without TRE is a good reason not to just add it to the language. That said, it doesn't mean that we shouldn't do it. In fact, it is largely an argument to do so in the main Python runtime. If anything, fragmenting the Python codebase is negative. However, TRE tailors to a certain type of code, and the fragmenting effect of that reality means that he is really choosing between fragmenting the Python codebase and driving people to other languages that handle the use-case better. He might be okay with that, but I don't really believe it to be necessary.</div><div><br /></div><div>Taking the third point, talking about the "basis of all programming" is a little tough. From a very high level, design a language without recursion. What's left that defines programming? In all seriousness, I think that the statement that "recursion" is the basis for all programming has a strong case assuming that you mean "recursion" in terms of the function call (or subroutine, or whatever you call it).</div><div><br /></div><div>Without functions, you don't really have anything but a long list of instructions. All control statements are pretty much functions or branches. Branches without the concept of subroutine are effectively <span class="Apple-style-span" style="font-family:'courier new';">goto</span> statements, which have always been as controversial as they can be useful. The point being that TRE allows you to turn one of the most fundamental constructs of programming and use it in a way that increases its utility. If recursion isn't the basis of all programming, it's still pretty fundamental.</div><div><br /></div><div>Addressing the final point, I recall part of the Zen of Python, "Explicit is better than implicit." The statement that Python has difficulty (at compile time) determining whether a call is recursion is a good one. There's a really simple solution to this. Add a keyword to make tail-recursion explicit. Perhaps we could propose abusing the pass keyword. Basically, where <span class="Apple-style-span" style="font-family:'courier new';">pass</span> is used now, consider it to mean "<span class="Apple-style-span" style="font-family:'courier new';">pass None</span>". The idea is that it is either passed a function call or None to indicate tail recursion. The nice bit of magic here is that it reuses an existing keyword compatibly, clearly indicates what's happening, easily translates to bytecode, and works really well for TRE's most powerful use-case (coroutines).</div><div><br /></div><div>So, as an example, consider the following code:</div><div><br /></div><div></div><blockquote><div><span class="Apple-style-span" style="font-family:'courier new';"><span class="Apple-style-span" style=" ;font-family:Georgia;"><div><span class="Apple-style-span" style="font-family:'courier new';">class <span class="Apple-style-span" style="font-weight: bold;">cli</span>:</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> def <span class="Apple-style-span" style="font-weight: bold;">start</span>(self):</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> print "Welcome to the CLI"</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> pass <span class="Apple-style-span" style="font-style: italic;">self</span>.loop()</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> def <span class="Apple-style-span" style="font-weight: bold;">main</span>(self):</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> print_prompt()</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> cmd,args = parse_line()</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> cmd = getattr(self,'cmd_' + cmd,None)</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> if cmd is not None and callable(cmd):</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> pass cmd(*args)</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> else:</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> print "Command not found"</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> pass self.start()</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> def <span class="Apple-style-span" style="font-weight: bold;">cmd_help</span>(self):</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> ...</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> pass self.main()</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></div><div><span class="Apple-style-span" style="font-family:'courier new';">...</span></div></span></span></div></blockquote><div></div><div><br /></div><div>The above code may seem slightly convoluted, but it's actually interesting because it tackles one use-case that Python is bad at. Admittedly, the above could have been factored as a loop, but the more steps you insert into the process, the uglier it gets. What is the purpose of continually having to implement some sort of mini-scheduler in a loop? Why have all this convoluted logic that has to handle a random series of states and detect an "end-state". This is just simpler, and more importantly "Beautiful is better than ugly."</div><div><br /></div><div>Critics might say that loops give you an easier understanding of the top-level flow of the program. I would contend that any problem that needs the above technique would instead result in a loop so complex that it would generally serve to reduce the understanding of the problem--replete with various <span class="Apple-style-span" style="font-family:'courier new';">if</span>s, <span class="Apple-style-span" style="font-family:'courier new';">return</span>s, <span class="Apple-style-span" style="font-family:'courier new';">while</span>s, and <span class="Apple-style-span" style="font-family:'courier new';">break</span>s.</div><div><br /></div><div>In assembly, C, or any number of other systems, this would have been implemented with <span class="Apple-style-span" style="font-family:'courier new';">goto</span> statements. The problem with <span class="Apple-style-span" style="font-family:'courier new';">goto</span> statements is that they very easily obscure the boundaries of single bits of code and can poorly document the intent of the <span class="Apple-style-span" style="font-family:'courier new';">goto</span>. This is a nice abstraction that allows the use of <span class="Apple-style-span" style="font-family:'courier new';">goto</span>-like functionality without losing information about what's supposed to be going on. There comes a point where the above would get factored into a general state machine implementation, but it's not really necessary.</div><div><br /></div><div>Another thing to notice about the above is that it gives you a really good point for debugging. Any Python implementation of the above type of problem would not have stack-traces to debug. However, the <span class="Apple-style-span" style="font-family:'courier new';">pass</span> statement gives you a place to track behavior. In a debugger it's pretty clear what's going on. At the beginning of each iteration, the function arguments clearly define the state of execution.</div><div><br /></div><div>This is something that is much more useful that implementing this with a loop. With a loop, the state is invisibly contained in the current binding namespace. Temporary values easily leak. There's not a clear point where the state of the iteration is distilled. This is why people want TRE.</div><div><br /></div><div>There are just a lot of situations where people would benefit from greater control over the constructs of flow control. Right now we've already abrogated the model of nested-call-return with generators. Most control structures that are difficult in Python could benefit from further disentangling the assumptions of function calls.</div><div><br /></div><div>Someday, I would love to see the work that was started with generators end with easy coroutines, promises / lazy evaluation, message passing, and smarter code replacement. Every language has idioms for what a recursion or evaluation means. We have the opportunity to make this handling explicit, and I suspect that we would benefit from it.</div></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-1656644879960867754?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com12tag:blogger.com,1999:blog-1115476946016881889.post-2295741493147170382009-04-18T06:01:00.000-07:002009-04-23T08:33:32.004-07:00Making Sense of Erlang's Event Tracer<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/Coffee-Order-Trace-718852.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 311px;" src="http://souja.net/uploaded_images/Coffee-Order-Trace-718850.png" border="0" alt="" /></a><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/Coffee-Order-Trace-777248.png"></a>Let's face it people, while Erlang is wonderful in a number of ways documentation is not one of them. I mean, it's there, and it's better than some other projects. However, there are incredibly useful things staring you in the face that are just impenetrably difficult. The <span class="Apple-style-span" style="font-family:'courier new';">et</span> module is one of those.<div><br /></div><div>Fear not, gentle reader. After more time than I'd care to admit, I've managed to figure out roughly how the pieces fit together. As usual, they exhibit the combination of weirdness and inspiration that have driven us to embrace Erlang. Without futher ado, let me take a stab at laying out exactly how to actually use it.</div><div><br /></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-weight: bold;">Four Modules</span></span></span></div><div><br /></div><div>The event tracer framework is made up of four modules:</div><div><ul><li><span class="Apple-style-span" style="font-family:'courier new';">et</span></li><li><span class="Apple-style-span" style="font-family:'courier new';">et_collector</span></li><li><span class="Apple-style-span" style="font-family:'courier new';">et_viewer</span></li><li><span class="Apple-style-span" style="font-family:'courier new';">et_selector</span></li></ul>In addition, you'll probably want to familiarize yourself with the <span class="Apple-style-span" style="font-family:'courier new';">dbg</span> module and possibly <span class="Apple-style-span" style="font-family:'courier new';">seq_trace</span> module as well.</div><div><br /></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-weight: bold;">The Event Tracer Interface</span></span></span></div><div><br /></div><div>This is perhaps the most confusing module. It contains a function that you call to report arbitrary events to the tracing interface. The method is named <span class="Apple-style-span" style="font-family:'courier new';">report_event</span>. There is also a humorous alias named <span class="Apple-style-span" style="font-family:'courier new';">phone_home</span>. Get it? <span class="Apple-style-span" style="font-family:'courier new';">et:phone_home</span>? Yeah, it makes me sad, too.</div><div><br /></div><div>Ostensibly, they're supposed to be called with options something like:</div><div><blockquote><span class="Apple-style-span" style="font-family:'courier new';">report_event(85,from,to,message,extra_stuff)</span></blockquote></div><div>The number (in this case 85) is an integer from 1 to 100 that specifies the "detail level" of the message. The higher the number, the more important it is. This provides a crude form of priority filtering. Avoid using 100, since it seems to disagree with being displayed in the viewer.</div><div><br /></div><div>The <span class="Apple-style-span" style="font-family:'courier new';">from</span>, <span class="Apple-style-span" style="font-family:'courier new';">to</span>, and <span class="Apple-style-span" style="font-family:'courier new';">message</span> variables are exactly what they sound like. From and To are visualized as "lifelines", with the message passing from one to the other. If from and to are the same value, then it is displayed next to the lifeline as an "action". The extra_stuff value is simply data that you can attach that will be displayed with someone actually clicks on the action or message.</div><div><br /></div><div>In a perfect world, this would be enough to start to get your hands direty. We do not live in that perfect world. Oddly enough, these functions do absolutely nothing. Let me repeat that. They do <span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-style: italic;">nothing</span></span>, except return an ominous atom <span class="Apple-style-span" style="font-family:'courier new';">hopefully_traced</span>. This confused me at first, and let me down the long rabbit hole that is the event tracer.</div><div><br /></div><div>Their purpose is to be traced. Rather than having them do something, they're just there so that the system can notice when you call them (via tracing) and use the data accordingly. While this is a great idea it has three faults. The first is that it makes the process rather magical. The second is that Erlang tracing is a seething pile of pain that involves reasonably complex knowledge of clever ports, tracing return formats, and specialized tracing <span class="Apple-style-span" style="font-family:'courier new';">MatchSpec</span>s (which are really their own special kind of hell). The third problem is that this conspires to make an incredibly useful and reasonably flashy feature inaccessible to users.</div><div><br /></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-weight: bold;">The Collector and Viewer</span></span></span></div><div><br /></div><div>These two pieces work in concert. Basically, the collector receives trace events and processes them. The viewer interrogates the collector and displays a relatively nice, interactive representation of them. As usual, it's in TK, which is a shame.</div><div><br /></div><div>You might wonder why these aren't just one module. It turns out that, in typical Erlang style, the collector is a generic full-fledged framework that allows processes to "subscribe" to the events that it collects. This would probably be really useful if there were any other subscribers. Someday I may write one to help debug some code, but for now just trust that it really is a pretty interesting architecture.</div><div><br /></div><div>You also have the advantage that the viewer creates a collector for you. With a few options and some debugging settings you can start collecting events.</div><div><br /></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-weight: bold;">The Selector</span></span></span></div><div><br /></div><div>This is perhaps the most useful and frustrating module in the entirety of the <span class="Apple-style-span" style="font-family:'courier new';">et</span> suite. This is mostly because it isn't really mentioned in the User's Guide. It turns out that the collector needs "filters" to convert the raw trace data into "events" that it can display. The et_selector module provides the default filter and some API calls to manage the filter pattern. Due to the architecture of the collector, this module is quite a bit of a bear.</div><div><br /></div><div>Effectively, it's a mishmash of functions that achieve the following:</div><div><ul><li>Convert Any Trace Message Into An Appropriate Event</li><li>Magically Notice Traces of the <span class="Apple-style-span" style="font-family:'courier new';">et</span> Module and Make Appropriate Events</li><li>Carefully Prevent Translating A Message Twice</li><li>Manage A "Trace Pattern"</li></ul><div>It turns out the there are a few strange interactions. First of all, you still have to tell the system to trace the right things. Secondly, without the correct incantation you will get infuriatingly strange "trace" events instead of the nice events you're reporting with<span class="Apple-style-span" style="font-family:'courier new';"> et:report_event/5</span>. Finally, the documentation doesn't do a decent job of telling you what the trace pattern even is.</div><div><br /></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-size:large;">How To Put It Together</span></span></span></div><div><br /></div><div>It turns out that the collector automatically registers itself to listen for debugging events, so all you have to do is enable them.</div><div><br /></div><div>For those people who want to do general tracing, consult the <span class="Apple-style-span" style="font-family:'courier new';">dbg</span> module on how to trace whatever you're interested in and let it work its magic. In my case, I just wanted <span class="Apple-style-span" style="font-family:'courier new';">et:report_event/5</span> to work, so that's what I'll illustrate here. I did the following:</div><div><ol><li>Create A Collector</li><li>Create A Viewer (this can do step #1 for you)</li><li>Turn On and Pare Down Debugging</li></ol><div>The following module achieves this.</div><div><div></div><blockquote><div><span class="Apple-style-span" style="font-family:'courier new';">-module(trace_test).</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></div><div><span class="Apple-style-span" style="font-family:'courier new';">-export([test/0]).</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></div><div><span class="Apple-style-span" style="font-family:'courier new';">test() -></span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et_viewer:start([</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> {title,"Coffee Order"},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> {trace_global,true},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> {trace_pattern,{et,max}},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> {max_actors,10}</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> ]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> dbg:p(all,call),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> dbg:tpl(et, report_event, 5, []),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> Drink = {drink,iced_chai_latte},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> Size = {size,grande},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> Milk = {milk,whole},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> Flavor = {flavor,vanilla},</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista1,register,enter_order,[Drink,Size,Flavor]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,register,barrista1,give_total,"$5"),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista1,barrista1,get_cup,[Drink,Size]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista1,barrista2,give_cup,[]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(90,barrista1,customer,request_money,"$5"),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(90,customer,barrista1,pay_money,"$5"),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,barrista2,get_chai_mix,[]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,barrista2,add_flavor,[Flavor]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,barrista2,add_milk,[Milk]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,barrista2,add_ice,[]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,barrista2,swirl,[]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> et:report_event(80,barrista2,customer,give_tasty_beverage,[Drink,Size]),</span></div><div><span class="Apple-style-span" style="font-family:'courier new';"> ok.</span></div></blockquote><div>Running through the above, the most important points are:</div><div><br /></div><div><ul><li>Turn On Global Tracing (it doesn't work for me if I don't)</li><li>Set a Trace Pattern</li><li>Tell The Debugger to Trace Function Calls</li><li>Tell It Specifically To Trace The <span class="Apple-style-span" style="font-family:'courier new';">et:report_event/5</span> Function</li></ul><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-weight: bold;">The Aftermath</span></span></span></div><div><br /></div><div>The most vexing part of figuring this out was the trace pattern of <span class="Apple-style-span" style="font-family:'courier new';">{et,max}</span>. The trace pattern is basically a tuple of a module and a detail level (either an integer or the atom <span class="Apple-style-span" style="font-family:'courier new';">max</span> for full detail).</div><div><br /></div><div><div><div>The specified module flows from your instantiation of the viewer, to the collector that it automatically creates, gets stashed in as the trace pattern, and eventually goes down into the bowels of the selector. Tracking this down sucked.</div></div></div><div><br /></div><div>This fact is documented basically nowhere. It also doesn't make a lot of sense, either. The module that you specify gets passed down (eventually) into <span class="Apple-style-span" style="font-family:'courier new';">et_selector</span>'s default filter. The format of the report_event/5 function call is hardcoded in that filter. That makes it very hard for me to imagine why you would ever specify another module. I suppose you could replace the default filter, but it turns out that doing so is pretty obtuse to do even if you wanted to. At any rate, just pass it through and it works.</div><div><br /></div><div>That said, I think it was worth it. If you compile the above example code and execute <span class="Apple-style-span" style="font-family:'courier new';">trace_test:test()</span>, you'll see something like the following screenshot. Source code <a href="http://souja.net/static/trace_test.erl">here</a>, screenshot <a href="http://souja.net/static/Coffee%20Order%20Trace.png">here</a>.</div><div><br /></div></div></div><div><div>Beautiful. I think I'm going to get a cup of coffee now.</div><div><br /></div><div><br /></div></div></div></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-229574149314717038?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-72474778028853251812009-03-10T02:36:00.000-07:002009-04-23T08:34:19.876-07:00Reigning In LVM pvmove Memory Leakage<div>If you use the Linux Logical Volume Manager, <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> can be a wonderful utility. It lets you move a logical volume (or many, in parallel) from one physical volume to another. Engine Yard was recently <a href="http://xn--hgi.ws/raptorattack">attacked by raptors</a>. To help deal with this, we needed to move off of the disks before they exploded. <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> to the rescue.</div><div><br /></div><div>It turns out that we hit a few bumps. The biggest was that the <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> command would slowly consume massive quantities of memory until a node would run out. This was both vexing and confusing, as we were pretty sure that the <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> command wasn't really doing any of the actual moving work.</div><div><br /></div><div>Some digging in the source code indicated that the <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> command utilized some sort of generic polling daemon implemented within LVM. A little more inspection showed that this daemon would scan the volume groups for an in-progress move, then would check on the progress of the move. This was done on some interval (15 seconds by default).</div><div><br /></div><div>It turns out that the functions that scan the volume groups don't really release memory properly (at least not the way they are currently used). In most LVM invocations, this is fine. The data is only loaded once each invocation. For <span class="Apple-style-span" style="font-weight: bold;">pvmove</span>, this caused a leak of memory every interval.</div><div><br /></div><div>While some deep work on the source code could eventually fix this memory leak, we took the easy out. We realized that you can just crank up the polling interval and it cuts the rate of leak to an acceptable level. On our test server, we show the leak around of 120MB per hour at the default 15-second polling interval. Increasing the polling interval to five minutes reduces the leak to less than 10MB per hour, at the expense of an average of 2.5 minutes of "wasted" time between <span class="Apple-style-span" style="font-weight: bold;">pvmove</span> invocations. Not too shabby.</div><div><br /></div><div>Changing "<span class="Apple-style-span" style="font-style: italic;">pvmove /dev/a /dev/b</span>" to "<span class="Apple-style-span" style="font-style: italic;">pvmove -i 300 /dev/a /dev/b</span>" makes a big difference.</div><div><br /></div><div>Hopefully this can help out some other people. Enjoy.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-7247477802885325181?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-40377075206302753152009-02-08T19:13:00.001-08:002009-04-23T08:35:19.391-07:00Maildirs, Timestamps, and Metadata IndexesEvery once in a while, you have a problem that has an approachable solution, but you just don't want to tackle. This weekend, I took a brief break from a more significant problem to attack one that I've had since February 20, 2008 at about 12:35pm.<div><br /></div><div>You might ask, how do I know the date so precisely. Well, it's been staring at me from my e-mail Inbox. Essentially, around that time I was getting ready to shut down my e-mail server I had run out of my cybercafe for a while. In doing so, I had to choose to move somewhere. I tried GMail. While GMail is a great webmail client, it's IMAP implementation leaves something to be desired, so I quickly decided to move somewhere else. Being short on time and not having good luck with the three other people I checked out, I settled on running my own on a small VPS at a <a href="http://www.grokthis.net/">decent provider</a>.</div><div><br /></div><div>In order to get the mail back out of GMail, I used imapsync, a script that will dump an IMAP mailbox into a Maildir. At the same time, I switched to the Dovecot IMAP server. I had previously used it, but had never wanted to fight with Cyrus IMAP, which I had been using before GMail. I figured, what could possibly go wrong?</div><div><br /></div><div>Well, what went wrong was fairly understandable. Dovecot decided that it would use the filesystem timestamp on the files instead of their Date header. This created the interesting situation where all of my imported mail showed the time that it was downloaded from GMail, but paradoxically showed a different Date header.</div><div><br /></div><div>This has been more than a minor nuisance. Essentially, when I have wanted to read an old conversation thread, it's all out of order. Messages downloaded in a strange order that didn't exactly match the receive order, so threads were often a challenge to read. Additionally, any really old mail couldn't be found by sorting by Date, so I was also challenged when finding messages that I can't remember their exact content, but I can remember when they were received.</div><div><br /></div><div>This was an entirely ignorable problem, with a reasonably tractable solution. I just never really wanted to tackle it.</div><div><br /></div><div>While my parents were here for my birthday, Mom (who also hosts her e-mail with me) remembered that she was having a similar problem. Since I got stuck on a different problem, decided to tackle this.</div><div><br /></div><div>If anybody ever has a problem where the IMAP server dates their e-mail by stat (i.e. mtime) instead of RFC822-style date, here's a script for you. Should work in Python 2.5.</div><div><br /></div><a href="http://souja.net/static/fixdate.py">fixdate.py</a><div><br /></div><div>UPDATE: Added fix so that Ctrl-C actually stops the script. Thanks to Noah Kantrowitz for that one.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-4037707520630275315?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com2tag:blogger.com,1999:blog-1115476946016881889.post-78898342834659869392008-10-26T22:18:00.000-07:002009-04-23T08:36:41.054-07:00What If There Were No CDs?I was just retagging some of my music. I ran across an interesting set of unexpected issues with <a href="http://en.wikipedia.org/wiki/Sgt._Pepper">Sgt. Pepper's Lonely Hearts Club Band</a> (by the Beatles, duh!). The end was cut off of some of the song names, so I wanted to fix it up. I looked up the album on the Internet and began fixing song names. Immediately, I noticed that the number of tracks in my list didn't match the number of songs on the record.<div><br /></div><div>After some headscratching I realized that the songs were listed by side of the record. After smacking my forehead, I started thinking about how iTunes indexes songs. It has metadata for multiple discs, but not different sides. My immediate thought was, "What if there had never been CDs? Would there be extra data for which side of the disk the song was on?"</div><div><br /></div><div>After pondering this deeply philosophical alternate history, I noticed on the above Wikipedia article that the original release had some interesting quirks. Specifically, after the last song was a 15 kilohertz tone designed by John Lennon to annoy people's dogs, followed by some jibberish studio noise put into the gutter track. So, the original record would end by annoying your dog and then playing gibberish endlessly.</div><div><br /></div><div>Apparently the CD re-release only repeats the noise eight or nine times and then fades out, since CDs can't really simulate an infinite loop like you get out of the gutter track. Similarly, I'd imagine that the 15 kilohertz tone might not survive the MP3 encoding process. Even though the tone and gutter track magic are really just tricks of the vinyl, it's interesting to think that these aspects of that album are effectively forever lost on future generations of Beatles fans.</div><div><br /></div><div>Oh, well. Endlessly repeating gibberish probably doesn't have much of a place in the world of iPod playlists. Still, I can't help but feel that a little something is missing...</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-7889834283465986939?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-2264705712386216882008-10-14T20:10:00.000-07:002008-10-14T20:19:31.425-07:00Erlang Error: {open_error, -12}This error happens when you have old or missing .so libraries for your Erlang app. It is rarely mentioned on the Internet and can consume hours of wasted debugging time. Now you know. :(<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-226470571238621688?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-10319584626047154052008-10-04T00:26:00.000-07:002009-04-23T08:36:41.055-07:00No to Bail-Out; Yes to Buy-OutLeave it up to <a href="http://www.bloomberg.com/apps/news?pid=20601039&refer=columnist_weil&sid=aMaWyNFImi4o">an opinion column in Bloomberg</a> to perfectly articulate what I've had brewing in my head.<div><br /></div><div>I kept thinking, "How does putting money into the banks fix the problem that these assets are overvalued?" Unless we are buying these securities, and then writing them down to a corrected value, nothing is fixed. It's quintessentially anti-market. The properties aren't allowed to go down in value.</div><div><br /></div><div>Ron Paul <a href="http://www.dailyreckoning.com.au/federal-reserve-system-credit/2008/10/03/">hit it on the head</a>, it's <a href="http://www.youtube.com/watch?v=dv6rQ0U01Yc">price-fixing</a>. As with most of Ron Paul's theories, I don't completely agree with his solution (i.e. the Federal Reserve and paper currency is the root of all evil). I think that there's a balance to be struck between letting banks set prudent interest rates and preventing <a href="http://books.google.com/books?id=bbw3AAAAMAAJ">a predatory banker's trust</a> to form again. Pure-free-market types often forget that freedom, liberty, and justice are rarely selected by the market.</div><div><br /></div><div>At any rate, it appears that this has been solved before by buying an interest in the bad securities, rather than just extending the failing banks more credit (i.e. letting them dig the hole deeper). Despite a deep understanding of all of the issues, this solution already is a favorite on Main Street.</div><div><br /></div><div>The right solution seems to <a href="http://www.canada.com/vancouversun/news/business/story.html?id=a7ea7cd2-bd9e-497c-a05d-d6caab422605">have worked for other people before</a>, where the wrong solution <a href="http://en.wikipedia.org/wiki/Japanese_asset_price_bubble">didn't work so well</a>. Of course, they eventually <a href="http://www.nytimes.com/2008/09/20/business/worldbusiness/20yen.html">figured it out</a> and appear to have learned something in the process.</div><div><br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-1031958462604715405?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-65626861600287400812008-10-02T02:28:00.000-07:002008-10-02T02:30:37.221-07:00iCal and Automator<span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px; ">Recently discovered something kind of cool. Apparently, you can save an automator workflow as a "iCal Alarm Plug-In". Then you can select it as the "alarm" for a message. Depending on your bent, this makes either a very elaborate alarm or a poor man's crond.<br /></span><div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;"><br /></span></div><div><span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;">Rather skimpy details <a href="http://www.macosxhints.com/article.php?story=20050504105901868">here</a>.</span></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-6562686160028740081?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-86800130377368175682008-09-28T04:57:00.000-07:002009-04-23T08:37:31.988-07:00Sidestep The Little Bits of History Repeating<span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px; ">Is it just me, or does this make anyone else nervous.<div><br /></div><div>Read <span class="Apple-style-span" style="text-decoration: underline; color: rgb(85, 26, 139); -webkit-text-decorations-in-effect: underline; "><a href="http://online.wsj.com/article/SB122256539004883001.html?mod=special_page_campaign2008_mostpop">this</a><span class="Apple-style-span" style="color: rgb(0, 0, 0); ">.</span></span></div><div><br /></div><div>Then read <a href="http://en.wikipedia.org/wiki/Japanese_asset_price_bubble">this</a>.</div><div><br /></div><div>Deja vu? Is it just me, or is this exactly history repeating itself. The most disturbing confluence is:</div><div><ul><li>Cheap Credit</li><li>Bad Loans</li><li>Reinvestment in Real Estate</li></ul></div><div>Basically, credit gets cheap. Banks compete too much because of the cheap credit. Bad loans are made because of the competition. Given the cheap credit, people reinvest in the real-estate, essentially refinancing themselves so it is never paid off.</div><div><br /></div><div>In that environment, it was just a matter of time until bad loans creeped unacceptably high. Even worse, naive interpretation of loan failure statistics gave a false sense of security. When times are good, the bad loans look okay because they aren't failing. As soon as the economy contracts, everything goes down like a house of cards.<br /></div><div><br /></div><div>The crazy bit is that the issuing of bad loans is incentivized. It's a Loan Officer's job to make loans, under-producers are fired, banks compete, and the process of elimination wipes out any Loan Officers with restraint. As the banks each try to get an edge, they find ways to creatively relax loan requirements. When all is done, whoever loosened the loan requirements is at fault, leaving the investors in the bank, possibly the depositors, and the loan-holder picking up the pieces.</div><div><br /></div><div>While it would be nice to point the finger at the Loan Officers, company boards, or some middle management, I bet that most of the time it wasn't even a single person, but a group of people working uncoordinated. Sometimes it would have been a large investor who was overly pushy trying to squeeze out some more stock value. Other times it would be a loan officer struggling to cram in a deal that was already borderline. Maybe it was a bank manager trying not to come up on the bottom of the list.</div><div><br /></div><div>As usual, the wisdom of the market can make major things happen, but it doesn't prevent abuse. It's a raging inferno that's just as content to power our economic engine as it is to blow the engine apart.</div><div><br /></div><div>At some point all of Wall Street was silently overrun with people who's predictions, worse-cases, and guarantees weren't based in reality. They should have been the last line of defense. Some auditors or fund managers should have raised a flag--and their management should have taken them seriously. I have a hunch that nothing currently being considered can really address that--the human tendency to avoid bad news runs deep.<br /></div></span><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-8680013037736817568?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-65354509969649188042008-09-25T04:04:00.000-07:002009-04-23T08:39:17.562-07:00The Nikon D700 Rocks!So, I picked up a Nikon (a <a href="http://www.nikonusa.com/Find-Your-Nikon/Product/Digital-SLR/25444/D700.html">D700</a> specifically). It was pricey, but I figured that David would only be tiny once, so I should get quality pictures. After a deep breath, I signed the check and went home with my equipment.<div><br /></div><div>I don't regret it. See my <a href="http://flickr.com/photos/kagato/">photostream on Flickr</a> for the goods.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-6535450996964918804?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-63837782740410493642008-07-13T16:34:00.000-07:002008-07-13T16:59:27.644-07:00Useful Mac ScriptWhen I used to use Windows more regularly (i.e. Windows NT), one of the most useful commands was the "start" command. It would behave much like the "Run" dialog. The number one thing I used it for was to open the current directory (or another directory) in the Explorer.<div><br /></div><div>When I moved to Linux, this was still relatively possible (using konqueror or gmc from the terminal).</div><div><br /></div><div>Upon moving to the Mac, I've never found anything that does it very well. I googled around for something today, and still found nothing. So I thought a little bit and wrote one.</div><div><br /></div><div>You can download it <a href="http://souja.net/static/reveal">here</a>. I called it "reveal". It does some very simple (by no means comprehensive) URL escaping on the specified path (or current directory if none is given) to create a file URL. Then it uses osascript to tell Finder to open that location. Simple.</div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">UPDATE: I added a line to bring Finder into the foreground.</span></div><div><span class="Apple-style-span" style="font-weight: bold;">UPDATE++: Apparently there's already a command to do this (open). Appeared in NextStep. Curse you Google!</span></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-6383778274041049364?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-19568370992993272572008-07-05T21:52:00.000-07:002009-04-23T08:36:41.055-07:00Preying On Youth?Being fairly unconventional in my youth, I have some exciting stories. One time I spent my birthday money on "Subliminal Tapes". The theory was that they had hidden recordings that played directly into your subconscious.<div><br /></div><div>That sounded like it made sense to me (being about 12), so I purchased a few. Two that I recall were one to improve my bowling game (I was in a kid's league at the time), and one titled "Do It Now!". Even at 12, I knew I was a procrastinator. It was a harmless purchase, even if a naive one.</div><div><br /></div><div>At that point I clearly had the idea that <span class="Apple-style-span" style="font-weight: bold;">I</span> was spending <span class="Apple-style-span" style="font-weight: bold;">my</span> money, and what it meant. A few years earlier, not so much. I had previously fallen victim to a much more insidious scheme. In the later case, "Subliminal Tapes" were intended to play upon the naivety or curiosity of adults--people who should know better. People who would know to read the fine print.</div><div><br /></div><div>Here's the scenario. Being a 10-year-old, I heard a commercial on the radio for a phone number that would get me a message from Santa Claus. How could I resist? I mean, I wasn't so certain about his existence at the time, but I thought it sounded like it was worth calling. Of course, there was some boilerplate about having your parents' permission, but it obviously didn't (and wouldn't) have a huge impact on a 10-year-old. So I called this number. I'll give you a hint, it started with 900.</div><div><br /></div><div>That's right, instead of a 900 number being used as God intended, for audio porn and hookup lines, it was instead being used to drain the wallets of unsuspecting parents. So, after about ten calls to a repeating automated message, my parents figured it out, talked to me about it, and I learned that I had been a party to their fleecing; and that Santa Claus doesn't have a phone.</div><div><br /></div><div>Not cool. In fact, later, these people were pretty much categorically sued into the ground by various States' Attorneys General. It stands under the some very old, and very sound, <a href="http://en.wikipedia.org/wiki/Attractive_nuisance_doctrine">legal reasoning</a>--i.e. if you put a cookie in a bear trap in your front lawn, you are liable when a child gets caught in it.</div><div><br /></div><div>These days, I'm a recent parent. I think it's important to supervise my son and my step-daughter. A kid can't raise itself. Television is not a substitute for supervision. That said, I don't need some greedy schmuck making parenting more difficult either. As an analogy, just because I don't let my kids smoke doesn't mean that I'd be thrilled about Mickey-Mouse-themed cigarettes (note, Mickey Mouse is wholly owned by the Disney Military-Industrial Complex).</div><div><br /></div><div>You can imagine my dismay when I saw a certain commercial on television. Was what I saw an attractive nuisance? No. Was it designed to prey upon parents who raise their children with a television? Yes, it was. In fact, being shown on the "Teen Network" was direct, if brazen, targeting.</div><div><br /></div><div>What was it, you ask? It was so simple, and yet unoriginal, that it must be the work of some sort of greedy idiot savant. Imagine <a href="http://en.wikipedia.org/wiki/Magic_8-ball">the Magic 8-Ball</a> accessed via a cellphone text message. That's right, you text your "question" to "Ask The Phone", and you get cryptic, generic responses back.</div><div><br /></div><div>If you read the fine print, it says you must be 18+, or 13+ with the "wireless subscriber's permission". Oh, and it's $9 per month for 5 questions, plus $2 each additional question (with varying differences for different carriers). Wow.</div><div><br /></div><div>Should this be outlawed? No. Should these people be shut down? Not directly. Should it be possible for a small, determined group of parents to make these people suffer in court until they closed down? Very probably.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-1956837099299327257?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-49350304541349004752008-06-27T21:16:00.000-07:002008-06-27T21:25:00.605-07:00Genius Speaks For Itself<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Jesus_is_coming.._Look_Busy_%28George_Carlin%29.jpg/200px-Jesus_is_coming.._Look_Busy_%28George_Carlin%29.jpg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Jesus_is_coming.._Look_Busy_%28George_Carlin%29.jpg/200px-Jesus_is_coming.._Look_Busy_%28George_Carlin%29.jpg" border="0" alt="" /></a><br />As I'm sure everyone has heard already, <a href="http://en.wikipedia.org/wiki/George_Carlin">George Carlin</a> died this week (picture kindly borrowed from Wikipedia).<div><br /></div><div>We all choose to remember the people that influence us in different ways. George is easy to memorialize because so much of his work is so faithfully recorded.</div><div><br /></div><div>I was able to find my favorite one of his routines on YouTube. I've included it here for your viewing.</div><div><br /></div><div>Make sure you listen all the way through. He insults a lot of people early on, but if you listen to his message, you'll see that his message, while dark, actually transcends most of the rhetoric on the subject.</div><div><br /></div><div><br /></div><br /><div><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/eScDfYzMEEw&hl=en"></param><embed src="http://www.youtube.com/v/eScDfYzMEEw&hl=en" type="application/x-shockwave-flash" width="425" height="344"></embed></object></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-4935030454134900475?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-54457705594946354472008-06-16T14:15:00.000-07:002008-06-16T14:26:36.000-07:00Crash!<div><div><a href="http://abclocal.go.com/kgo/story?section=news/local&id=6206150">Saturday was eventful.</a> A <a href="http://sfmuni.com">MUNI</a> train rear-ended another one in front of the apartment. It was before a game, so there were tons of people around and it was a bit crazy. There were 6 ambulances at one point. The track was running later that day.</div><div><br /></div><div>It's hard to appreciate the damage from the pictures. Keep in mind that these trains have a giant steel connector that sticks out of each end about a foot or two. For these trains to be that close, it means that two of these assemblies have met and crumpled enough to shorten the whole thing by four or five feet. Two giant steel assemblies that are each hefty enough to hold multiple cars together--CRUNCH!</div><div><span class="Apple-style-span" style="color: rgb(0, 0, 238);"><br /></span></div><div><span class="Apple-style-span" style="color: rgb(0, 0, 0); "><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/IMG_0897-745420.JPG" style="text-decoration: none;"> </a></span><div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/IMG_0897-745420.JPG" style="text-decoration: none;"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "></span><img style="float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 10px; cursor: pointer; " src="http://souja.net/uploaded_images/IMG_0897-745396.JPG" border="0" alt="" /></a><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/IMG_0899-745523.JPG"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://souja.net/uploaded_images/IMG_0899-745504.JPG" border="0" alt="" /></a><br /><div><br /></div><div><br /></div></div></div></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-5445770559494635447?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-52029956265688200292008-06-02T00:54:00.000-07:002009-04-23T08:38:23.253-07:00Random Erlang ArticleWe really should have tried harder to hire Yariv. He's an awesome guy. I recently found <a href="http://yarivsblog.com/articles/2008/05/18/erlang-vs-scala/">this</a> on his blog.<div><br /></div><div>It's an excellent comparison of Erlang and Scala. However, it's even better as a very concise, succinct explanation of how the pieces of Erlang fit together to make it so useful.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-5202995626568820029?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-83261136935933984962008-05-03T15:19:00.000-07:002008-05-03T15:39:16.459-07:00A Sad Goodbye<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://souja.net/uploaded_images/08-06-06_1419-725710.jpg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px;" src="http://souja.net/uploaded_images/08-06-06_1419-725710.jpg" border="0" alt="" /></a><br />For those of you who haven't heard, Daniel Joseph Dougherty died Friday from complications from his cancer. The specifics probably don't matter. For those who want to know, his heart was stopped by a blood clot, possibly from bleeding within his heart. The story I got was muddled.<div><br /></div><div>Ironically, I was actually looking at plane tickets to go see him shortly before he died. He had requested that we make it out so that he could see us and his namesake, David Joseph, before things got any worse. As you might imagine, this has hit Alicia and I pretty hard.</div><div><br /></div><div>Before we moved out here, he actually intended to come out with us. It seems like only a month ago--actually it was only a month ago--that he was dreamily thinking of starting an exciting new chapter of his life in San Francisco.</div><div><br /></div><div>He actually sent out his bicycles and his most prized possessions with us when we came out. Being Joey, it was mostly antiquated but somehow unique old computer hardware.</div><div><br /></div><div>He will be missed.</div><div><br /></div><div>I am currently unclear as to exactly where the funeral and visitation will be held, as I've alternately heard it would be at (I think) the First Christian Church or at Waters Funeral Home, in Vandalia, Missouri. The visitation will be from 5pm to 8pm on Wednesday, May 7th, 2008. The funeral will be the following morning at 10am on Thursday, May 8th, 2008. I am currently assuming that the visitation will be at Waters and the funeral will be at the Church.</div><div><br /></div><div>Funeral home is at 500 Main St in Vandalia. Here's a (hopefully accurate) map:</div><br /><iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&hl=en&geocode=&q=500+S+Main+St+Vandalia,+MO&sll=39.32726,-91.481524&sspn=0.052849,0.10231&ie=UTF8&ll=39.315043,-91.48118&spn=0.052865,0.10231&z=14&iwloc=addr&output=embed&s=AARTsJp8h58T4HdTfZVkZlpLAqBxGSsteA"></iframe><br /><small><a href="http://maps.google.com/maps?f=q&hl=en&geocode=&q=500+S+Main+St+Vandalia,+MO&sll=39.32726,-91.481524&sspn=0.052849,0.10231&ie=UTF8&ll=39.315043,-91.48118&spn=0.052865,0.10231&z=14&iwloc=addr&source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small><div><br /></div><div>The church (assuming I have the right one) is at 205 W Park Street, also in Vandalia, Missouri. Here's another (also hopefully accurate) map:</div><iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&hl=en&geocode=&q=205+W+Park+St+Vandalia,+MO&sll=39.307,-91.48567&sspn=0.026432,0.051155&ie=UTF8&ll=39.316172,-91.48324&spn=0.026432,0.051155&z=14&iwloc=addr&output=embed&s=AARTsJpmRUphrkgs1I7UY10amjI4A5KObA"></iframe><br /><small><a href="http://maps.google.com/maps?f=q&hl=en&geocode=&q=205+W+Park+St+Vandalia,+MO&sll=39.307,-91.48567&sspn=0.026432,0.051155&ie=UTF8&ll=39.316172,-91.48324&spn=0.026432,0.051155&z=14&iwloc=addr&source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small><div><br /></div><div>I'll edit this post with updates as I get more information.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-8326113693593398496?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com0tag:blogger.com,1999:blog-1115476946016881889.post-4239271456865259772008-04-16T21:21:00.000-07:002009-04-23T08:38:44.401-07:00A Warm Welcome<div><img src="http://lh5.ggpht.com/jvantuyl/SAZgBo8kf-I/AAAAAAAAAz4/YuyKnPDPcyY/s144/IMG_0701.JPG" alt="David" style="float: right" /><br />I'd like to introduce you to David Joseph Vantuyl. He was born April 15, 2008 at 8:39 PM PST. It was a warm spring day in San Francisco, California. He weighs in at 6 lbs 5 oz and is 19 inches long. He is also disarmingly cute, as can be seen in the pictures <a href="http://picasaweb.google.com/jvantuyl/DavidSDebut">here</a>.<br /></div><br /><div><br />He's healthy and is generally happy (unless tickled).<br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-423927145686525977?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1tag:blogger.com,1999:blog-1115476946016881889.post-67872650224898936572008-04-02T20:42:00.000-07:002008-04-02T20:52:32.276-07:00First Post, AgainWell, my old blog is effectively gone. I could recover it, but I don't have the time. Wasn't that much on it anyways.<div><br /></div><div>Let's see how well blogger handles remote blogs. I'm kind of curious actually.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1115476946016881889-6787265022489893657?l=souja.net'/></div>Jayson Vantuylhttp://www.blogger.com/profile/12699845108719516586noreply@blogger.com1