tag:blogger.com,1999:blog-83774247207320222662024-02-08T09:15:31.402-08:00grotrandom walk through fields of musingsUnknownnoreply@blogger.comBlogger27125tag:blogger.com,1999:blog-8377424720732022266.post-86921649079889536712013-10-09T10:51:00.001-07:002013-10-10T17:25:42.292-07:00auto-generating IPv6 PTR DNS records with PowerDNS recursor in Lua<div dir="ltr" style="text-align: left;" trbidi="on">
Pre-generating PTR records for dynamically-assigned SLAAC IPv6 is fairly
unreasonable and silly because most of the time there won't be a
match. However, if you do want to do that, and you run<a href="http://www.powerdns.com/" target="_blank">PowerDNS</a> (which you should pick
because it has working Lua scripting support to do this), you can
generate them when the query hits quite easily:
<br />
<pre>function preresolve ( remoteip, domain, qtype )
-- for a v6 only connected site, don't resolve A records
if matchnetmask( remoteip, "2000::/3") then
-- only rewrite PTR requests
if (qtype == pdns.PTR) then
-- and then only in our block(s)
qv6 = string.find(domain, "d.f.8.6.8.a.8.3.0.0.2.ip6.arpa")
if not qv6 then return -1, {} end
ret={}
revdom="reverse-ip.mylab.tld.";
rev= string.reverse( string.gsub( string.gsub(domain, "%.ip6%.arpa", ""), "%.", "") ) .. "." .. revdom;
-- pdnslog("returning " .. rev .. " for " .. domain);
ret[1]= {qtype=pdns.PTR, content=rev, ttl=86400}
return 0, ret
end
end
end
</pre>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-33841136713773141982012-10-04T18:53:00.001-07:002012-10-04T18:53:03.678-07:00I give up. and so I get more done.My kids won't listen. I get angry and yell. They still won't listen, but
<br>now they feel I'm mean. I'm frustrated. So I give up. I can't make them
<br>do anything.
<br>
<br>I tell them they can do what they want and don't have to listen to me
<br>and that they are responsible for themselves this evening.
<br>
<br>Or they could make a deal to do what I ask and then I'd tell them what
<br>to do -- no whining, no pouting, no argument even if you disagree.
<br>
<br>That whiff of anarchy is all it took.
<br>
<br>They both chose structure and that was that.
<br>
<br>We made up, they went to sleep tired and calm.
<br>
<br>We'll see what tomorrow brings.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-76761061013300352232011-08-15T20:05:00.001-07:002011-08-15T20:05:07.044-07:00so what do I do? teach him about congestion control?I was walking home from my office staff picnic, when I prepared to be<br>solicited by a young, disheveled man selling some newspapers at the<br>corner. To my surprise he looked away and while I was starting to wonder<br>why, he muttered loud enough that I know it was intended for me, "Thank<br>you for coming to MY country and f**in it up." Not one to normally want<br>to pick on the down and out, I started to ignore it, but then felt<br>compelled to turn around and ask directly, "what was that?". I was<br>impressed by the fluid save, "I said Corporations are f**ing this<br>country up."<p>So I'm the wrong color? not knowing enough English to evesdrop?<br>spineless enough to not object? what? I wish I could read minds -- the<br>words are far too filtered to know what is really the case.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-22036589284483644422010-04-09T03:58:00.001-07:002010-04-09T03:58:47.824-07:00ahead of my time in Berkeley and Palo Alto, maybe A2 is the 3rd time charm?<div xmlns='http://www.w3.org/1999/xhtml'>I've wanted to build a community <a href='http://en.wikipedia.org/wiki/Peering' target='_blank'>Internet exchange point</a> ever since I knew how to technically do it (for over 10 years), but my efforts in Berkeley and then in Palo Alto ran into institutions that were pennywise and pound foolish or just waiting for the right time. Given Google's success in pointing out that that time is now, maybe I'll have <a href='http://www.annarbor.com/community/news/opinion/who_needs_google_to_fiber_anyway_community_networks_should_be_community_built/#' target='_blank'>more luck in A2 this time</a>?<br/></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-72443134627549858202010-04-01T20:29:00.001-07:002010-04-01T20:29:24.980-07:00more of the same: last.fm scrobbles to iCalendar format<div xmlns='http://www.w3.org/1999/xhtml'>This is getting to be a lame habit, but it makes me slightly happy, so here's another Yahoo! pipe that makes an iCalendar feed out of your last.fm scrobbles feed:<br/><a href='http://pipes.yahoo.com/rpaditya/lastfm2ical'>Pipes: last.fm scrobble</a><br/><blockquote/></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-1130109827392209812010-03-24T18:18:00.001-07:002010-03-24T18:18:39.968-07:00it's old-fashioned to swap to disk...<div xmlns='http://www.w3.org/1999/xhtml'>or not only is swapping to disk harmful, it's downright silly on webservers (conditions apply and exceptions are many).<br/><br/>Back when the OS on your webserver was 32-bit and 512MB was a lot, arguments like <a href='http://kerneltrap.org/node/3660' target='_blank'>this </a>might have been germane, but I'll just claim to have been a decade ahead of my time when I wanted my FreeBSD 2.1 webservers (behind a load-balancer with shared nothing) configured without swap so that they would just panic and reboot if they ran out of memory rather than suffer the slow death of context switches and disk IO (we'd end up rebooting them anyway).<br/><br/>Now with 64-bit OSes and less-than-expensive multi Gigabyte RAM, plus effective ways to cap memory usage of JVM and VMs, there is little use for disk swap on clusters of machines which are identical and data-less. Even on large DB servers with 30+ GB of RAM it is silly to consider swapping to be okay unless it's for long-running queries that can tolerate large latency. OLTP type DBs should just have the DB process restarted if it gets too big.<br/><br/>I'm sure there are lots of cases where you don't want to lose data and can tolerate the latency, but it certainly seems for all the low-latency "social web" sorts of applications, a load-balancer that sends new sessions to real servers based on least-response-time plus a quick reboot are going to be better remedies than the slow-death of disk swapping.<br/><br/>So unless you can come up with a compelling argument other than "it's always been done that way", I'm going to practice not recommending or building "clustered", web servers for interactive applications with disk swap until experience or overwhelming evidence suggests otherwise. So there.<br/></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8377424720732022266.post-91294061022754577172010-03-21T18:52:00.001-07:002010-03-22T08:21:48.118-07:00implementing high-volume queues cheaply<div xmlns='http://www.w3.org/1999/xhtml'>Implementing write-heavy queues is hard to do in a technically "inexpensive" way -- RDBMS' are typically read-optimized and too heavy for the task of a simple queue, dedicated queuing packages require frameworks to run in etc., so the most simple queue that is "web-writable" I could come up with, which is chronologically ordered is to simply use the webserver logs as a queue. Serving static files, as simple as a text file that contains a simple string such as "ok" and named "ok.txt", is efficient in most webservers, and a small file is easily cached, so physical disk IO would be limited to writing the webserver access logs. To add items to the queue you can just use query parameters that will get recorded in the weblogs and then can be parsed out, ie.:<br /><code><br />http://my_example_server.com/some_path/ok.txt?key=addme&value=withThisVal&whereAmI=London&why=toTrack<br /></code><br />and the query params won't be "interpreted" by the static file, just show up in the weblogs as long as GET query params are set to be logged.<br /><p><br />Most webservers allow writing the timestamp in a format that is easily machine readable (milliseconds since the epoch in UTC is probably a good choice). Using <a target='_blank' href='http://spread.org'>spread</a> to write the logfile in realtime to the network would reduce the disk IO on the local webserver but a spread listener would have to write it somewhere, though the ability to add multiple listeners could spread the load.<br /></p></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-30861889319745883112010-03-10T11:44:00.001-08:002010-03-11T10:03:52.413-08:00album of my family (ala rattlesnake)<div xmlns='http://www.w3.org/1999/xhtml'>Courtesy of an IR camera, you can now <a target='_blank' href='http://en.wikipedia.org/wiki/Infrared_sensing_in_snakes'>"see" what some snakes can</a> without such a camera.<br/><a title='IR 0126' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0126.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:17' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0126' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0126.jpg'/> </a><a title='IR 0220 Jai under a blanket' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0220.jpg'> </a><a title='IR 0202 Divya' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0202.jpg'><img border='0' title='received from aditya on 03/08/2010 15:55:29' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0202 Divya' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0202.jpg'/></a><a title='IR 0205 Jai' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0205.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:30' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0205 Jai' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0205.jpg'/></a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/640x480/IR_1462.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 1462'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/tn_IR_1462.jpg' alt='IR 1462' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/11/2010 14:30:06'/> </a><br/>kid hiding under a blanket:<br/><a title='IR 0220 Jai under a blanket' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0220.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:32' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0220 Jai under a blanket' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0220.jpg'/> </a><br/>a family pet in a few poses:<br/><a title='IR 0127' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0127.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:17' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0127' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0127.jpg'/> </a><a title='IR 0193 bunny' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0193.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:28' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0193 bunny' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0193.jpg'/></a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/640x480/IR_1464.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 1464'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/tn_IR_1464.jpg' alt='IR 1464' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/11/2010 14:30:07'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/640x480/IR_1465.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 1465'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100311142550/tn_IR_1465.jpg' alt='IR 1465' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/11/2010 14:30:07'/> </a><br/>and the kids asleep:<br/><a title='IR 0835 Divya sleeping' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0835.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:58' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0835 Divya sleeping' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0835.jpg'/> </a><a title='IR 0836 Jai sleeping' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0836.jpg'> <img border='0' title='received from aditya on 03/08/2010 15:55:58' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' alt='IR 0836 Jai sleeping' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0836.jpg'/> </a><br/><br/><a title='IR 0205 Jai' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0205.jpg'> </a><a title='IR 0202 Divya' rel='lightbox[album:|GO 24 IR study 2010|]' class='lightwindow' href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0202.jpg'> </a><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=aaf102e2-cb2d-86ea-bacd-33474534f7b8' alt='' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-65165521073339581282010-03-10T11:15:00.001-08:002010-03-10T11:15:40.405-08:00seeing things in a different light<div xmlns='http://www.w3.org/1999/xhtml'>Not being able to justify purchasing an IR ("Thermal imaging") camera and not finding one nearby for as good a price, I <a href='http://www.flir.com/thermography/americas/us/content/?id=18978' target='_blank'>rented</a> a <a href='http://www.flir.com/thermography/americas/us/content/?id=23106' target='_blank'>FLIR b50</a> from flir.com for $425 per week ($25 sales tax plus I pay overnight shipping both ways) for the past week. The main purpose of the rental was to take followup pictures of our community's common house to see if the added insulation in the attic really made a difference but comparing the before and after IR pictures was complicated by the fact that the before pictures, taken by an "Energy Audit" firm, didn't have the temperature to color legend embedded.<br/><br/>In any case, I took pictures in my own unit, and the results mostly confirmed what I already knew.<br/> <a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0124.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0124 lens cap'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0124.jpg' alt='IR 0124 lens cap' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:16'/></a><br/>don't take pictures with the lens cap on!<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0125.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0125 skylight'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0125.jpg' alt='IR 0125 skylight' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:17'/> </a><br/>the skylight leaks heat like crazy -- 15 degree F difference between inside and skylight is more than the 10 degrees F a regular window typically has:<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0128.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0128 front door'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0128.jpg' alt='IR 0128 front door' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:17'/> </a><br/>blinds and most types of shades really do work well to keep the heat from leaking out windows -- here's the gap between shade and window and another one looking at an upstairs window which also has a thin curtain in front:<br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0194.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0194 leakage around a honeycomb blind'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0194.jpg' alt='IR 0194 leakage around a honeycomb blind' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:28'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0200.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0200 MBR upstairs window with shade'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0200.jpg' alt='IR 0200 MBR upstairs window with shade' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:29'/> </a><br/>one of our upstairs windows was broken by a small rock a few years ago and replaced, however the replacement definitely isn't as well sealed as the original:<br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0833.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0833 MBR S windows no drapes, right is Diamond glass replacement'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0833.jpg' alt='IR 0833 MBR S windows no drapes, right is Diamond glass replacement' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:58'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0834.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0834 MBR S windows, right is Diamond glass replacement'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0834.jpg' alt='IR 0834 MBR S windows, right is Diamond glass replacement' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:58'/> </a><br/>(hint: replacement is on the right in both pictures -- I took two just to show that reflection works in all spectra) - that shoddy replacement is almost 10 degress F worse it seems...<br/><br/>Finally, our upstairs Master bedroom is always colder in winter than either the downstairs (where the thermostat is) or even the other bedrooms on the same floor. Originally we thought it was a lack of insulation in the attic above the master bedroom (which wouldn't account for it retaining heat well when heated by sunlight, but anything else seemed remote and unlikely), so we added insulation to the attic to no avail. An HVAC person confirmed that the room seemed pretty tight, but noted that the two ducts leading to that room were each less than half the size of the ducts to any other part of the house and so he posited that sufficient warm air, especially on the long run to that room, was just not making it to that room. To fix that, he'd have to replace the ducts which would have involved tearing open the walls etc., so might just be cheaper to put in booster vents in that room. With the IR camera I have proof that he was right:<br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0195.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0195 vent while furnace is on'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0195.jpg' alt='IR 0195 vent while furnace is on' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:28'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0196.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0196 cold air return'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0196.jpg' alt='IR 0196 cold air return' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:28'/> </a><br/>that's a downstairs vent while the furnace is running -- around 114 degress F coming out (even if the numbers are uncalibrated, we hope that in relative terms they are pretty accurate) and a vent in the bathroom on the same floor, at an oblique angle and farther from the furnace. Next, we look upstairs:<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0201.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0201 guest room vent (compare with MBR vents)'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0201.jpg' alt='IR 0201 guest room vent (compare with MBR vents)' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:29'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0198.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0198 upstairs bedroom E vent (about 8 degress cooler than downstairs vent)'/><br/>in the guest room upstairs, it's about 104 degress, pretty good and that bedroom gets sufficiently warn by our experience. Now the kicker:<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0198.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0198 upstairs bedroom E vent (about 8 degress cooler than downstairs vent)'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0198.jpg' alt='IR 0198 upstairs bedroom E vent (about 8 degress cooler than downstairs vent)' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:29'/> </a><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0199.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0199 upstairs MBR SE vent (12 degress cooler than downstairs vent)'> <img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/tn_IR_0199.jpg' alt='IR 0199 upstairs MBR SE vent (12 degress cooler than downstairs vent)' onerror='this.onerror=null; this.src = 'http://images.grot.org/clipart/photo.jpg'' title='received from aditya on 03/08/2010 15:55:29'/> </a><br/>Those are the two vents in the master bedroom, anywhere from 8 to 12 degrees cooler than the vent in the guest room. Clearly, not enough warm air is making it up into that room, and part of what does make it into that larger room probably escapes into the landing and up via the skylight due to a chimmney effect.<br/><br/>All these photos were taken at night to minimize sun glare/reflection effects.<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2010/aditya/20100308155200/640x480/IR_0124.jpg' class='lightwindow' rel='lightbox[album:|GO 24 IR study 2010|]' title='IR 0124 lens cap'> </a><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=51adc5a8-d2d3-8b91-82fc-35ced1ea7267' alt='' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-78465093259672733482010-03-04T20:48:00.001-08:002010-03-04T20:48:44.787-08:00(mostly) machine readable event info<div xmlns='http://www.w3.org/1999/xhtml'>Being a geek means I cringe when easily parseable data isn't. The <a href='http://aadl.org' target='_blank'>AADL</a> is a fine public library and offers pretty cool online tools, but they only give us a RSS feed of checkouts with the due dates in the "summary" stanza. Although they send us an email reminder 2 days before the item is due, that doesn't fit into my iCal feed grokking calendar. There are a few other such RSS feeds that hide the event data within and being sure that I'm not the only one facing this problem I looked around for a generic solution and finally hit upon a few others using Yahoo Pipes!. It took far too long to get it just right (and even then timezone parsing is still off) but I made my first publically somewhat useful pipe, described as <a href='http://www.aadl.org/node/9928#comment-18434' target='_blank'>part of a thread on the AADL forums</a>. If you want to see the source for the pipe or use it, read the forum post and then click on <a href='http://pipes.yahoo.com/rpaditya/aadlduedates' target='_blank'>http://pipes.yahoo.com/rpaditya/aadlduedates</a>.<br/></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-63346123626693105462009-04-27T14:10:00.001-07:002009-04-27T17:35:34.965-07:00monitoring core/vcpu usage on Sun CMT machines<div xmlns='http://www.w3.org/1999/xhtml'>Sun provides the <code>/usr/local/bin/corestat</code> CLI tool for their CMT (T1 and T2 Ultrasparc) machines which outputs in a loop with a line per core, however the output isn't suitable for long-term monitoring and trending.<br/><br/>Here's my approach to monitoring core (really vcpu or hardware thread) usage, divided into usr and sys. Add <br/><code>exec vcpuidl /bin/sh /etc/snmp/conf/vcpuidl.sh</code> to <code>/etc/snmp/conf/snmpd.conf</code> and the script <code>/etc/snmp/conf/vcpuidl.sh</code> is simply (mpstat is what corestat calls):<br/><br/><code><br/>#!/bin/sh<br/>/usr/bin/mpstat 1 2 | /usr/bin/awk 'BEGIN {RS="\n"; ORS="|"; } (NR>33) {print $13 "|" $14} END {print "\n"}'<br/></code><br/><br/>which shows % usage per vcpu (or hardware thread) and it can be read via SNMP:<br/><br/><code><br/>UCD-SNMP-MIB::extOutput.1 = STRING: usr|sys|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|1|1|1|0|0|0|0|5|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|<br/></code><br/><br/>the above is from a Sun T2000 which has a Ultrasparc T1 with 8 cores and 4 hardware threads per core or 32 vcpus -- graphing then looks like this (alternate red and yellow bands for 32 x sys usage, green and yellow x 32 bands for usr usage):<br/><br/><a href='http://www.flickr.com/photos/adram/3480540957/' title='cmt_core_utilization_week by adramblah, on Flickr'><img height='244' width='591' src='http://farm4.static.flickr.com/3625/3480540957_51e26eec8f_o.png' alt='cmt_core_utilization_week'/></a><br/><br/>note the peak over 3200 (8 cores x 4 threads per core x 100%) is due to the addition of max peaks of both usr and cpu (so a little misleading).<br/><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=80bd87b5-0bbd-869e-b593-b371d27aaa24' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-41322821832142572092009-04-07T18:27:00.001-07:002009-04-07T18:27:24.602-07:00monitoring webapplication activity<div xmlns='http://www.w3.org/1999/xhtml'>Monitoring webapplications, gathering statistics and graphing them for trending visualization is a well-known and common practice. Gross bandwidth, disk space usage, possibly hits per second based on mod_status output in Apache, free heap, user sessions from a servlet engine (like Tomcat) are all frequent measures of activity. However to get more complete timeseries data for custom or not so commonly monitored variables that are in a webserver access log in near-realtime requires some extra effort.<br/><br/>Timeseries graphing and data collection and consolidation is trivially done with a Round-robin Database, the most mature and useful, not to mention open-source of these is RRDTool. RRDTool consolidates the data over uniform time periods and so "bin-ing" the data is crucial. Out-of-the-box, webservers do not bin accesslogs, or at most at daily or hourly intervals. With cronolog on Apache, you can bin easily down to the minute (and perhaps even the second, though that is sort of silly in the cases I care about). With CTools, all the webserver traffic flows through a Netscaler load-balancer, which emits weblogs and rotates them up to once a minute. We use that to bin the data in 1 minute intervals and run a script out of cron (which doesn't have to parse timestamps making it much faster) to consolidate the data and slice and dice it into RRDs to produce graphs like these:<br/><br/><a title='ctools_hits_by_http_status by adramblah, on Flickr' href='http://www.flickr.com/photos/adram/3422057429/'><img width='491' height='387' alt='ctools_hits_by_http_status' src='http://farm4.static.flickr.com/3398/3422057429_fbab4c0828_o.png'/></a><br/><br/>showing hits by http status stacked -- glitches in the application show up very quickly in this<br/><br/><a title='ctools_bandwidth_by_tool by adramblah, on Flickr' href='http://www.flickr.com/photos/adram/3422866222/'><img width='591' height='751' alt='ctools_bandwidth_by_tool' src='http://farm4.static.flickr.com/3545/3422866222_bacb61f825_o.png'/></a><br/><br/>the bandwidth by tool graph shows some custom processing done on each hit to determine which Sakai "tool" it was for and the size of the response, again, near-realtime.<br/><br/>There are a whole lot of uncommon stats for web applications that we can graph this way, and it is very useful for trending.<br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=e509538c-2981-8f49-9819-9c5d293c88e3' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8377424720732022266.post-31954109373388750792009-04-07T17:48:00.001-07:002009-04-07T17:48:19.450-07:00undelete resource (file) for Sakai (CTools)<div xmlns='http://www.w3.org/1999/xhtml'><a href='http://ctools.umich.edu' target='_blank'>CTools</a>, the learning management system (LMS) for the <a href='http://www.umich.edu' target='_blank'>University of Michigan</a> is based on <a href='http://sakaiproject.org' target='_blank'>Sakai</a>. Current versions of Sakai allow for uploads of resources -- binary blobs (files) that are managed internally, but in CTools case are stored on the filesystem. Sakai keeps a map of the original filename and the name as stored on disk (based on a GUID and hashed in a directory structure that looks like Year/DayOfYear/HourOfDay/fileGUID) in a SQL table called content_resource. Deletes of a resource remove the file on disk and the table row entirely. This means undeletes are not possible out-of-the-box. Based on the "event" table one could reconstruct which file was deleted and retrieve it from a filesystem snapshot manually and quite painfully (esp. when it was on AFS as that involved requesting the snapshot volume being mounted etc. which took time).<br/><br/>A couple of years ago, all the CTools resource storage was moved to a <a href='http://www.netapp.com' target='_blank'>Netapp</a> filer (snapmirrored to a standby at the secondary site every 10 minutes) and the files served over NFS to CTools/Sakai. The Netapp was managed by our group and we kept 10 days of snapshots online (readonly). This meant we could automate undeletes -- for now only CTools support staff can request them, but they do so through a web interface which drives a fully automated process not requiring sysadmin hands.<br/><br/>Here's how it works:<br/><ul><li>snapshots are made nightly, so a file has to exist when the snapshot is taken -- files created and deleted before a snapshot is made is not recoverable</li><li>the undelete has to be requested within 10 days of deletion</li><li>a ticket number has to be provided as that is used to name a directory in the support AFS space where the undeleted files are copied to from the snapshot</li><li>CTools uses Oracle, so a table was created:<br/><code><br/>CREATE TABLE CONTENT_RESOURCE_DELETED <br/> ( RESOURCE_ID VARCHAR2(256 BYTE), <br/> XML CLOB, <br/> IN_COLLECTION VARCHAR2(256 BYTE), <br/> FILE_PATH VARCHAR2(128 BYTE), <br/> RESOURCE_UUID VARCHAR2(36 BYTE), <br/> DELETE_DATE DATE <br/> ) ; <br/></code> with an accompanying trigger:<br/><code><br/>CREATE OR REPLACE TRIGGER TRG_CONTENT_RESOURCE_4_DELETED <br/>AFTER DELETE ON CONTENT_RESOURCE <br/>FOR EACH ROW <br/>BEGIN <br/> INSERT INTO CONTENT_RESOURCE_DELETED <br/>(RESOURCE_ID,XML,IN_COLLECTION,FILE_PATH,RESOURCE_UUID,DELETE_DATE) <br/> <br/>VALUES(:OLD.RESOURCE_ID,:OLD.XML,:OLD.IN_COLLECTION,:OLD.FILE_PATH,:OLD.RESOURCE_UUID,SYSDATE); <br/>END;<br/></code></li><li>Each time a file is deleted, the row is copied to the content_resource_deleted table and preserved for 30 days (after which it is dropped).</li><li>The web-interface (a simple JSP that does a read-only lookup of the content_resource _deleted table based on a site_id) allows the support staff to pick the files to be undeleted (it only allows them to undelete files deleted before the last snapshot and deleted at most 11 days ago); picked files are saved to an undelete_queue table <code><br/>---+---------------+---------------+------+---------+---------------+----+<br/> # | column | type | null | default | pk | fk |<br/>---+---------------+---------------+------+---------+---------------+----+<br/> 1 | FILE_PATH | VARCHAR2(128) | NO | [NULL] | SYS_C00121850 | |<br/> 2 | RESOURCE_ID | VARCHAR2(256) | NO | [NULL] | | |<br/> 3 | TICKET | VARCHAR2(64) | NO | [NULL] | | |<br/> 4 | STATUS | VARCHAR2(12) | YES | [NULL] | | |<br/> 5 | DELETE_DATE | DATE(7) | YES | [NULL] | | |<br/> 6 | INSERTEDBY | VARCHAR2(16) | NO | [NULL] | | |<br/> 7 | UPDATEDBY | VARCHAR2(16) | NO | [NULL] | | |<br/> 8 | UNDELETE_DATE | DATE(7) | YES | [NULL] | | |<br/>---+---------------+---------------+------+---------+---------------+----+<br/></code></li><li>a script runs out of cron on a machine that has access to both AFS and the Netapp snapshots (currently one of our spare application servers) and polls the undelete_queue table for undelete requests</li><li>upon encountering an undelete request, the script searches for the file (knowing the deletion date and file-on-disk name it is a rather easy process to step through the snapshots from most recent to oldest so that the most recent copy is used) and copies it to the support AFS space into a directory named with the ticket number, naming the file with the original names (not GUID) that the user uploaded them with<br/></li><li>the undelete_queue row status is updated appropriately depending on whether the file is successfully undeleted on not (ie., might not have existed when the snapshot was made) and an email is sent to the ticketing system with the result, alerting the support staff so that they can provide the file to the end-user</li><li>apart from some issues with the original file having a UTF-8 name (not all the toolchain is UTF-8 friendly) in which case it is copied preserving the GUID name, there have been remarkably few problems</li><li>stats so far are:<code><br/>dbmon@ctools.vip> select min(undelete_date) from UNDELETE_QUEUE ;<br/>----------------------+<br/> MIN(UNDELETE_DATE) <br/>----------------------+<br/> 2009-01-26 10:23:25.0 <br/>----------------------+<br/>1 row in result (first row: 74 msec; total: 74 msec)<br/>dbmon@ctools.vip> select count(*), status from UNDELETE_QUEUE group by status;<br/>---------+----------+<br/> COUNT(*) STATUS <br/>---------+----------+<br/> 258 UNDELETED <br/> 8 NotFound <br/> 8 Exists <br/>---------+----------+<br/>3 rows in result (first row: 42 msec; total: 43 msec)<br/></code></li><li>we probably could increase the number of snapshots (say every 3 hours) though given that only 8 were not found, that doesn't seem worth the extra storage required (though that might still be manageable)<br/><a title='vol_ctfs2009_.snapshot by adramblah, on Flickr' href='http://www.flickr.com/photos/adram/3422830360/'><img width='591' height='244' alt='vol_ctfs2009_.snapshot' src='http://farm4.static.flickr.com/3643/3422830360_2506d6f046_o.png'/></a><br/></li><li>it would be ideal if Sakai provided user-managed soft-deletes and restores within the application (something promised for JCR backed resources in the future)</li><li>for now, this system has worked remarkably well and saved a lot of sysadmin time with minimal development (took about a week including debugging and testing)</li></ul><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=d11da1e4-1bc2-8c50-bc80-ea2019bc9007' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-13033788984212434102009-02-25T10:38:00.000-08:002009-02-25T10:38:00.138-08:00Dada this<div xmlns='http://www.w3.org/1999/xhtml'>I'm not easily impressed by spam, but I liked this one:<br/><br/><a title='20090225175246-obama_spam by adramblah, on Flickr' href='http://www.flickr.com/photos/adram/3309722786/'><img width='680' height='121' alt='20090225175246-obama_spam' src='http://farm4.static.flickr.com/3387/3309722786_d9181a110c_o.jpg'/></a><br/><br/>I am glad that Google warned me about the impersonation -- I might have thought I got it straight from the man's Blackberry following his address to the joint session of Congress.<br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=e8967447-940b-49b6-ac80-d629fcac5d8f' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-1597254186577989112009-02-03T19:06:00.001-08:002009-02-03T19:06:58.227-08:00scooped<div xmlns='http://www.w3.org/1999/xhtml'>At the beginning of my love affair with Google Earth, I proudly wrote some <a href='http://grot.org/maps/tour.jsp' target='_blank'>KML-spitting-out pages</a> that allowed me to record or playback a tour in it. It was written using the generic reporting framework I built using the once-upon-a-time-and-still-somewhat-spiffy-but-totally-unsupported <a href='http://www.zapatec.com' target='_blank'>Zapatec</a> framework in a few hours. It worked and still works well. Too bad that <a href='http://code.google.com/apis/kml/documentation/touring.html' target='_blank'>Google Earth 5 now has support for Touring (recording and playback native in KML without using network links) built-in</a>.<br/><br/>I suppose I can rewrite my KML to do either view-based refresh or the new way based on the user-agent. Wait. Can I do capability detection in KML?<br/></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-14058195727137342362009-02-03T18:32:00.001-08:002009-02-03T18:32:27.480-08:00on calendars and things<div xmlns='http://www.w3.org/1999/xhtml'>Google calendar has become my preferred way of keeping track and coordinating events with my wife, family, cohousing community, friends, travel and almost anything else that is temporal it seems. The hard exception is work, which till recently used "Meeting Maker", a piece of bloatware that had no way to exchange calendars in any known, open format, but now is based on Microsoft Exchange. <br/><br/>Exchange doesn't have an ical feed (that Google Calendar can easily consume, and that I've set almost everything else up to produce for its' consumption), however Exchange sends event data as iCalendar attachments in emails. Thankfully, Google Mail (Gmail and mail for apps) recognizes the text/calendar attachments, parses the iCalendar info, and <a href='http://www.google.com/support/calendar/bin/answer.py?hl=en&answer=47802' target='_blank'>offers to add it to your Google Calendar</a>.<br/><br/><img width='500' height='191' class='reflect' onload='show_notes_initially();' title='' alt='Google Mail recognises .ics attachments by djfiander.' src='http://farm4.static.flickr.com/3396/3218080604_91a8f7dfb1.jpg?v=0'/><br/><br/>Amazingly, Exchange also will parse and allow Google Calendar invites (which are also iCalendar format) to be added (or refused) to my work calendar (I just had to get the correct email address to send it to for it to work!), there is a bit of broken-ness in dealing with replies to invitations from Google Calendar, but that I can bear to kludge by hand.<br/><br/>An well-documented, open, hardly novel way of exchanging calendar information by email is fantastic and I've added such attachments to the GO online meal signup and shift system, here's an example (part of a multipart/alternative message):<br/><br/><code><br/>------=MIME_BOUNDRY_altpparts<br/>Content-Type: text/calendar; charset="utf-8"; method=REQUEST<br/>Content-Transfer-Encoding: 8bit<br/>Content-Disposition: attachment; filename=invite.ics<br/><br/>BEGIN:VCALENDAR<br/>PRODID:-//Grot Org//Meal tracker//EN<br/>VERSION:2.0<br/>CALSCALE:GREGORIAN<br/>METHOD:REQUEST<br/>BEGIN:VEVENT<br/>DTSTART:20090203T231500Z<br/>DTEND:20090204T000000Z<br/>DTSTAMP:20090129T154454Z<br/>ORGANIZER;CN=go-meal:mailto:foo@plzs.org<br/>UID:1680@meals.plzs.org<br/>ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=FALSE;CN=Fitzgerald/Aditya;X-NUM-GUESTS=4:mailto:nobody@grot.org<br/>CLASS:PRIVATE<br/>CREATED:20090203T130300Z<br/>DESCRIPTION:Wings Over Great Oak by tim details at https://example.com/meal-signup/show?m=1680<br/>LAST-MODIFIED:20090129T154454Z<br/>LOCATION:go-meal<br/>SEQUENCE:0<br/>STATUS:CONFIRMED<br/>SUMMARY:Wings Over Great Oak (go-meal)\, 4 diners<br/>TRANSP:OPAQUE<br/>BEGIN:VALARM<br/>ACTION:DISPLAY<br/>DESCRIPTION:REMINDER<br/>TRIGGER;RELATED=START:-PT15M<br/>END:VALARM<br/>END:VEVENT<br/>END:VCALENDAR<br/>------=MIME_BOUNDRY_altpparts--<br/></code></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-91929002249787255462009-02-03T17:53:00.001-08:002009-02-03T17:53:01.618-08:00Netapp OnTap per-volume statistics<div xmlns='http://www.w3.org/1999/xhtml'>I'm a fan of Netapps, and I've grown used to using the OnTap SNMP agent to collect statistics on various filer functions, stuff them into <a href='http://www.rrdtool.org' target='_blank'>RRDs</a> and troubleshoot using trend graphs (I really like <a href='http://web.taranis.org/drraw/' target='_blank'>drraw</a> for that). I can then make cool graphs like:<br/><br/><img width='500' height='349' class='reflect' onload='show_notes_initially();' title='' alt='drraw by you.' src='http://farm4.static.flickr.com/3078/3252053838_29f4cdf3eb.jpg?v=0'/><br/><br/>However, those ops numbers are for the filer as a whole making it hard to tell *what* is the target for all that activity -- we need per volume and even per disk stats to find hot spots. The "stats" command in OnTap can expose that data, however not via SNMP and only via the cli (maybe via the SDK, but that's a whole level of complication I'd like to avoid). The whole list of supported stats counters is exposed using the command <code>stats list counters</code>. So using ssh with public keys (and using stats start/stop every 5 minutes), I was able to "plug-in" the output from periodically querying the stats command into the existant set of RRDs that drraw draws from. Here's the per-volume read/write/other ops for the same filer:<br/><br/><img width='491' height='445' class='reflect' onload='show_notes_initially();' title='' alt='drraw by you.' src='http://farm4.static.flickr.com/3379/3252056200_78eecba8d3.jpg?v=0'/><br/><br/>and one showing total time spent serving along with amount of data served in bytes:<br/><br/><img width='491' height='224' class='reflect' onload='show_notes_initially();' title='' alt='drraw by you.' src='http://farm4.static.flickr.com/3256/3252060458_c6640cd344.jpg?v=0'/><br/><br/>and bandwidth by volume:<br/><br/><img width='491' height='380' class='reflect' onload='show_notes_initially();' title='' alt='drraw by you.' src='http://farm4.static.flickr.com/3452/3251385437_7a0097890f.jpg?v=0'/><br/>the relevant code fragment is quite simple and follows the SNMP_util::snmpmaptable semantics, each "row" of instance data is sent to a callback function which writes it into the appropriate RRD (with an example invocation):<br/><code><br/>my($getStatCols);<br/><br/>$getStatCols->{'volume'}->{'type'} = "volStats";<br/>@{$getStatCols->{'volume'}->{'cols'}} = ("read_data", "read_latency", "read_ops", "write_data", "write_latency", "write_ops", "other_latency", "other_ops");<br/><br/>for my $stat (keys %{$getStatCols}){<br/> my($stattxt) = "${stat}:*:" . join(" ${stat}:*:", @{$getStatCols->{$stat}->{'cols'}});<br/> getStatTable($username, $netappHostname, $getStatCols->{$stat}->{'type'}, $stattxt, \&printfun);<br/>}<br/><br/>sub getStatTable {<br/> my($user, $host, $id, $statcmd, $callback) = @_;<br/><br/> my(@ret) = `ssh ${user}\@${host} "stats stop -I ${id} -O print_zero_values=off -c -d |"`;<br/> my(@start) = `ssh ${user}\@${host} "stats start -I ${id} ${statcmd}"`;<br/> my($startcmd) = join(' ', @start);<br/> if ($startcmd){<br/> $startcmd =~ s/\s+//g;<br/> chomp($startcmd);<br/> if ($startcmd ne ""){<br/> print STDERR "ERROR starting stats collection for ${user}\@${host} $statcmd: " . $startcmd . "\n";<br/> }<br/> }<br/><br/> if ($#ret <= 2){<br/> print STDERR "ERROR retrieving stats from ${user}\@${host} ${statcmd}: " . join(" ", @ret) . "\n";<br/> } else {<br/> shift(@ret);<br/> shift(@ret);<br/> shift(@ret);<br/> for (my $i=0;$i<=$#ret;$i++){<br/> my($l) = $ret[$i];<br/> chomp($l);<br/> $l =~ s/^\s+//g;<br/> $l =~ s/\s+$//g;<br/> if ($l !~ /|$/){<br/> $l .= "|";<br/> }<br/> my(@cols) = ($id, $i, split(/\|/, $l));<br/> &$callback(@cols);<br/> }<br/> }<br/>}<br/><br/>sub printfun {<br/> #shift(@_);<br/> my(@vals) = @_;<br/> for (my $i=0;$i <= $#vals; $i++){<br/> if (! $vals[$i] || $vals[$i] eq ''){<br/> $vals[$i] = 0;<br/> }<br/> }<br/> #next if (! @vals);<br/> #next if (! $vals[0] || ! $vals[1]);<br/> print join('|', @vals) . "|\n";<br/>}<br/><br/></code></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8377424720732022266.post-60022020546106296982009-01-20T11:32:00.001-08:002009-01-20T11:32:48.098-08:00name the reason for that blip<div xmlns='http://www.w3.org/1999/xhtml'>See that blip in requests around noon EST today? Should be easy to tell what it was...<br/><br/><a href='https://ctstats.ds.itd.umich.edu/stats-bin/drraw.cgi?Mode=view;Graph=1201793762.5119' target='c'><img border='0' align='center' onerror='this.onerror=null; this.src ="/icons/unknown.gif"' src='https://ctstats.ds.itd.umich.edu/stats-bin/drraw.cgi?Mode=show;Graph=g1201793762.5119;Start=end%20-%2028%20hours;End=now;Width=400;Height=133' title='g1201793762.5119'/></a><br/><br/>yes, all those UM students and faculty who turned away from <a href='http://ctools.umich.edu' target='_blank'>CTools</a> to watch the Obama inauguration. Never noticed that blip for the 43rd president, but then again it is probably due to the fact that CTools is pervasive enough now that we can use it instead of Nielsen ratings. Or maybe not.<br/></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-16662925068889593892008-12-24T07:53:00.001-08:002008-12-24T07:53:16.513-08:00photos side-by-side aka montages<div xmlns='http://www.w3.org/1999/xhtml'>I seem to do this infrequently enough that I need to make myself a reminder, luckily I wrote a script that is pretty self-explanatory -- in this example it puts two photos side by side (similar method can be used to make 6 2"x2" passport photographs print on a single 4x6 print -- much cheaper than going to one of those passport places).<br/><br/><code><br/>#!/usr/bin/perl<br/><br/>use strict;<br/>local($|) = 1;<br/><br/>use Image::Magick;<br/>my(@file) = @ARGV;<br/><br/>my($rv);<br/><br/>my($image)=Image::Magick->new;<br/><br/>$rv = $image->Read(@file);<br/>warn "$rv" if $rv;<br/><br/>my($montage) = $image->Montage(<br/> tile=>'2x1',<br/> geometry=>'1704x2272',<br/> mattecolor=>'#FFFFFF', #does not take?<br/> frame=>'10',<br/> );<br/><br/>$rv = $montage->Write('mp.jpg');<br/>warn "$rv" if "$rv";<br/></code><br/><br/>If you have ImageMagick installed but not the perl bindings, you can do this on the command line too.</div>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-8377424720732022266.post-80122594402744182372008-12-23T17:52:00.001-08:002008-12-23T17:52:35.816-08:00terminal reset and why enter doesn't return<div xmlns='http://www.w3.org/1999/xhtml'>occasionally, if for some reason, my ssh session to a remote machine, probably running screen, doesn't terminate cleanly, and I have to return-~. to kill it, my Mac OSX terminal gets "screwed up" -- the number of rows gets reduced, the characters don't all echo, etc.. Usually, running the <code>reset</code> command will fix things, but sometimes it doesn't help. Of course I can't find the reference now, but some site suggested entering <code>^jreset^j</code> (ctrl-j reset ctrl-j) repeatedly till it works. Incredulous, I tried it, and indeed it does work!</div>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8377424720732022266.post-8005917906606073462008-12-15T07:36:00.002-08:002008-12-15T07:36:45.440-08:00searching UMOD with JNDI<div xmlns='http://www.w3.org/1999/xhtml'>For some of the support tools I've been writing for <a href='http://ctools.umich.edu' target='_blank'>CTools</a> (in JSP with JSTL) I need to authorize against a group in the LDAP interface to <a href='http://directory.umich.edu' target='_blank'>UMOD</a>. JNDI is very complete, so it should have been an easy task, but <a href='http://java.sun.com/products/jndi/tutorial/objects/reading/search.html' target='_blank'>searching</a> to see if a given logged-in (via <a href='http://www.weblogin.org' target='_blank'>Cosign</a>) user was in the requisite group wasn't working. I had some example code in Perl that a colleague had once sent out, and a 1-to-1 transcription into Java using JNDI didn't work. It turns out that the <a href='http://java.sun.com/products/jndi/tutorial/basics/directory/scope.html' target='_blank'>scope for searches in JNDI does not default to "SUB"</a> AND if you try to bind (even anonymously) the query tries to ADD the attribute instead of searching for it, and so had to be explicitly set. To help you (and remind me) avoid this pain, here is the requisite code:<br/><br/><code><br/>private boolean isMember(String grp, String un) throws Exception { <br/> boolean isMem = false;<br/> Hashtable env = new Hashtable();<br/> env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");<br/> env.put(Context.PROVIDER_URL, "ldap://ldap.itd.umich.edu:389/dc=umich,dc=edu");<br/><br/> try {<br/> javax.naming.directory.DirContext ctx = new javax.naming.directory.InitialDirContext(env);<br/> String[] attrIDs = {"member"};<br/><br/> javax.naming.directory.SearchControls ctls = new javax.naming.directory.SearchControls();<br/> String filter = "(&(cn=" + grp + ") (objectclass=rfc822MailGroup))";<br/> ctls.setReturningAttributes(attrIDs);<br/> ctls.setReturningObjFlag(true);<br/> ctls.setSearchScope(javax.naming.directory.SearchControls.SUBTREE_SCOPE);<br/> String searchBase = "ou=Groups";<br/> javax.naming.NamingEnumeration s = ctx.search(searchBase, filter, ctls);<br/> String positiveMatch = "uid=" + un + ",";<br/> while (s.hasMore()) {<br/> javax.naming.directory.SearchResult sr = (javax.naming.directory.SearchResult)s.next();<br/> javax.naming.NamingEnumeration e = (sr.getAttributes()).getAll();<br/> while (e.hasMoreElements()){<br/> javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) e.nextElement();<br/> javax.naming.NamingEnumeration a = attr.getAll();<br/> while (a.hasMoreElements()){<br/> String val = (String) a.nextElement();<br/> if(val.indexOf(positiveMatch) != -1){<br/> isMem = true;<br/> }<br/> }<br/> a.close();<br/> }<br/> e.close();<br/> }<br/> s.close();<br/> ctx.close();<br/> return isMem;<br/> } catch (javax.naming.NamingException e) {<br/> System.err.println("Problem getting attribute:" + e);<br/> return false;<br/> }<br/>}<br/></code><br/><br/>There must be a better way of formatting code in HTML without JS.</div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8377424720732022266.post-48009931053410897482008-09-07T16:30:00.000-07:002009-04-06T07:09:20.511-07:00my second cohousing head cooking trial<div xmlns='http://www.w3.org/1999/xhtml'><strong>Tandoori murgh boti kebab (Chicken) <br/> by aditya</strong><br/><br/>This will be a non-vegetarian North Indian complement to my mother's vegetarian South Indian meal.<br/><br/>Vegetarian option: sorry, there will be no vege entree (too much work<br/>on the carne entree for this occasional head cook), though the sides<br/>will be vege<br/><br/>Carnivore option: grilled, moderately spicy tandoori murgh boti kebab<br/>(skewers of chicken thigh/breast pieces) Rice or Naan depending on the<br/>number of people signed up.<br/><br/>Kid option: less spicy chicken kebabs<br/><br/>Side Dish: saag aloo (sauteed mixed greens and potatoes North Indian<br/>style).<br/><br/>Salad: diced tomato, cucumber, onion with cumin, pepper and lime/lemon<br/>dressing on the side<br/><br/>Dessert: fruit in season<br/><br/>Organic: where possible<br/><br/>Dairy: easy to avoid<br/><br/>Wheat/Gluten: easy to avoid<br/><br/>worked out to $5.84 per adult (scaled appropriately for teens and big kids) there were 30 adults and 10 kids in total.<br/><br/><a href='http://s3.amazonaws.com/images.grot.org/people/2008/aditya/20080910125419/640x480/IMG_9020.jpg' rel='lightbox[date:20080907]' title='cook with Tandoori murgh boti kebab (Great Oak Common Meals) received from aditya on 09/10/2008 13:14:14'><br/><img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2008/aditya/20080910125419/tn_IMG_9020.jpg' alt='cook with Tandoori murgh boti kebab' onerror='this.onerror=null; this.src = 'http://s3.amazonaws.com/images.grot.org/clipart/photo.jpg'' title='received from aditya on 09/10/2008 13:14:14'/><br/></a><a href='http://s3.amazonaws.com/images.grot.org/people/2008/aditya/20080910125419/640x480/IMG_9018.jpg' rel='lightbox[date:20080907]' title='Tandoori murgh boti kebab (Great Oak Common Meals) received from aditya on 09/10/2008 13:13:14'><br/><img border='0' src='http://s3.amazonaws.com/images.grot.org/people/2008/aditya/20080910125419/tn_IMG_9018.jpg' alt='Tandoori murgh boti kebab' onerror='this.onerror=null; this.src = 'http://s3.amazonaws.com/images.grot.org/clipart/photo.jpg'' title='received from aditya on 09/10/2008 13:13:14'/></a><a href='http://s3.amazonaws.com/images.grot.org/people/2008/aditya/20080910125419/640x480/IMG_9018.jpg' rel='lightbox[date:20080907]' title='Tandoori murgh boti kebab (Great Oak Common Meals) received from aditya on 09/10/2008 13:13:14'><br/></a><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=d60bb4e5-9621-8315-9062-d15209ca9650' class='zemanta-pixie-img'/></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-50636575947452443442008-05-12T10:52:00.000-07:002008-05-12T12:12:41.168-07:00स्पेल्लिंग namesजयUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-8377424720732022266.post-38028011170535351472008-02-02T17:09:00.000-08:002008-11-30T18:43:00.614-08:00reminder<div xmlns='http://www.w3.org/1999/xhtml'><p>When the Michigan winter is harsh, the wind bitter, my commute to work tedious and I don't get enough exercise or sleep or think about dried, sauteed green beans, I reflexively tell myself that <em>this</em> is stupid, illogical and pointless, and that we should move to a sane climate (Berkeley) and live without a car (Berkeley), be able to exercise outdoors year-round (Berkeley) without watching for icy patches, live in walking and biking distance of work, restaurants, Berkeley Bowl and a short BART ride away from Shalimar. I've served my time in Michigan, braving the weather and isolation from downtown, dependence on a car and far from the hill.<br/></p><p>Yesterday, one of our neighbors said her husband wants her to move to California, but that though it would be nice, "it wouldn't be cohousing". I should have said, "I feel the same way", and tell her I've wanted to move Great Oak many times. In those moments I want to escape, escape the tedium of the weather, the petty indiginities of putting up with this or that less-than-considerate act, I ultimately get to this:<br/></p><ul><br/> <li> People at Great Oak, and probably on the whole who want to live<br/> in Cohousing, are so reasonable, so much more so than the world at large. </li><br/><br/> <li> I <em>want</em> to do more and depend more on my neighbors,<br/> because I like them and I'd much rather spend time with them than<br/> living isolated in my home, as I might in Berkeley </li><br/><br/> <li> Living in community, especially this community is wonderful;<br/> most of the time we take it for granted, but it is so much better<br/> than not living in community.</li><br/><br/></ul>Of course the fear is that we're missing something, maybe that other cohousing community that is in Berkeley would be the ideal place in the ideal locale and climate, and that's where we should be heading. But as a I learned so many years ago when travelling and looking for a better home than Berkeley, the memory is always better than the present, but being involved in the present community is the best of all.<br/><br/><p/></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8377424720732022266.post-7429212740243153902007-12-21T18:34:00.000-08:002008-11-30T18:36:21.970-08:00what goes around...<div xmlns='http://www.w3.org/1999/xhtml'>Another idea that makes me love Berkeley -- the <a href='http://www.csmonitor.com/2007/1025/p20s01-ussc.html' target='_blank'>Karma<br/>Kitchen</a>.</div>Unknownnoreply@blogger.com0