<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/">
<channel>
<title>In Theory...</title>
<description>Bob Balaban&#8217;s Blog</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/</link>
<language>en-us</language>
<lastBuildDate>Fri, 26 Jun 2009 01:12:42 -0400</lastBuildDate>
<item>
<title>Geek-o-Terica 9: Memory Sub-allocator (or, why your server&#8217;s memory usage only goes up), and Happy Father&#8217;s Day</title>
<pubDate>Fri, 26 Jun 2009 01:12:42 -0400</pubDate>
<description>
<![CDATA[ 
I did an exploration of product memory management many years ago. I worked on a couple of different Lotus products (1-2-3, Notes) that had sophisticated memory-management packages in them. All of them ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-9-memory-sub-allocator-or-why-your-servers-memory-usage-only-goes-up-and-happy-fathers-day</link>
<category>Lotus Notes</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-9-memory-sub-allocator-or-why-your-servers-memory-usage-only-goes-up-and-happy-fathers-day?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-9-memory-sub-allocator-or-why-your-servers-memory-usage-only-goes-up-and-happy-fathers-day</guid>
<content:encoded><![CDATA[ I did an exploration of product memory management many years ago. I worked on a couple of different Lotus products (1-2-3, Notes) that had sophisticated memory-management packages in them. All of them were what you might call "sub-allocators", basically they grabbed big chunks of memory from the operating system, and broke up the big chunk into smaller chunks for program code to use. <br /> <br />This past Sunday was Father's Day, a nice, family-oriented holiday, essentially invented by Hallmark. I got to thinking about my father, and also about my father's father. He was an ordinary, yet interesting man, born either on the boat over from the Ukraine (or maybe Byelorus, the people who knew for sure have been dead a long time, and nobody's sure), or shortly after arrival in 1900. His name was Sam. My father relates that Sam went into the clothing business in New York City as a young man. When the Depression hit hard, in the early 1930s (editorial comment: it was MUCH worse than the one we're in now, bad as that is...), Sam got laid off, and had the guts to start his own business. He formed a company to buy large amounts of fabric from the cloth manufacturers (this was when the United States still had a textile industry, now long gone), and sell that cloth in smaller chunks to the clothing makers of New York's Garment District. One of his sons, my Uncle Ed, joined the business. My father, Al, did not. Al went to college, then got drafted into the Army during World War 2.  <br /> <br />My grandfather used to be a sub-allocator, though he never would have called it that. The analogy works really well. Sam thought of himself as a broker: he'd get enough money together (couldn't have been easy in the early 30's) to buy big bolts of cloth, haul a sample case around to the clothing manufacturers and sell them what they needed. He tended to specialize in cloth for women's dresses. Sam's company lasted until the mid 1960s, I remember going to visit "the office" once or twice. Rolls of cloth everywhere. <br /> <br />How is that like memory management in Notes or 1-2-3 (does anyone still use 1-2-3?)? There were 2 &nbsp;problems with memory allocation in earlier versions of Windows: it was slow, and each chunk that you would get from the OS represented one "system handle", regardles of the size of the chunk. And system handles were a finite resource, you couldn't get more than (in one version of Windows NT, as I recall) 4096 of them. When they were gone, you were "out of memory", and you'd mostly likely crash. The other problem with it was that it was slooowwww. Not so much <em>getting </em>&nbsp;the memory, but "freeing" it, or retuning memory you no longer needed back to the system was very slow. Why? Because of something called "free block consolidation". &nbsp;The OS would try to figure out when you told it you were done with a particular block of memory, what other "free blocks" there were (if any) adjacent to your's, so it could consolidate them together, raising the odds that the next big allocation would find a contiguous chunk of the size needed easily. Otherwise, the system's memory would become "fragmented", and allocating new chunks would become much more difficult. <br /> <br />So what does sub-allocation do for you? Say 3 pieces of a program each want around 100KB of memory for a little while. They could each go to the Windows API and request 100KB, but that would use up 3 (scarce) system handles. But what if, instead, we had a "memory manager", a "broker" (we could name it Sam) who, instead would track requests for memory allocations. "Sam" could request say, 64MB of memory from the OS all at once, then break that big chunk up into 3 100KB blocks as requested, using only 1 system handle. If we wrote Sam to be clever enough, he'd hve an efficient way of knowing which bits of his big 64MB chunk were being used, and which were not. And when the 3 program tasks were done with their 100K bits, they could "free" them with a call back to Sam, who could efficiently consolidate them back into his pool of available memory. <br /> <br />We (the 1-2-3 and Notes product teams) did write such memory managers (we didn't call them Sam, though), and they worked a whole lot better and a whole lot faster than the Windows API did. <br /> <br />One interesting side-effect of using a memory sub-allocator in a product is something that people who pay careful attention to system memory usage often notice. If you use a system monitor (say Windows Task Manager) to track system memory usage, and then run some kind of performance test suite (maybe a browser client hitting a web page over and over, or hitting different web pages over and over to avoid the page-caching optimization), you see what might appear to be strange behavior: memory usage goes up, up, up, up, and then plateaus, but rarely does it go back down again. <br /> <br />Why does it happen this way? Well, Sam could have told you. The sub-allocator grabs memory from the OS in bug chunks, and parcels it out in smaller chunks. If it's block gets used up, it goes back to the OS for another (big) block. Both big blocks would be notieced by TaskManager. But sub-allocating out of those blocks is not registered by Task Manager, because it's done only within the program. When a task (HTTP server, for example) asks for a bunch of memory to process an outgoing web page, it gets a sub-allocated block. When the HTTP task returns ("frees") that smaller block back to the memory manager ("Sam"), the memory manager does NOT go return it to the OS. First of all, it's too small, it doesn't represent (usually) a full "handle's worth" of memory that was obtained from the OS in the first place. Secondly, Sam is going to keep it around because he knows that it's probably going to be needed again, laer, for something else. <br /> <br />That's why you see (at the system level) more and more memory going to the product's process, and only once in a while (when Sam has an entire big block of memory that he got from Windows free again, and decides he doesn' need it anymore) does the number go down again, maybe when the server is idle for a while. <br /> <br />So, there you have it. Yet another example of art imitating life. Here's to my father Al, on Father's Day, and here's to my Grandfather Sam, sadly now no longer with us. I love you, Dad.  <br />And here's to all fathers out there, everywhere. Happy Father's Day! <br /> <br />Geek ya later! <br /> <br />(Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-9-memory-sub-allocator-or-why-your-servers-memory-usage-only-goes-up-and-happy-fathers-day</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-9-memory-sub-allocator-or-why-your-servers-memory-usage-only-goes-up-and-happy-fathers-day?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 8: LotusScript, To Delete, or Not to Delete?</title>
<pubDate>Mon, 15 Jun 2009 23:41:32 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I have written at length recently about garbage collection in both LotusScript and Java (see Geek-o-Tericas 3, 5, and 6 especially). I went on (and on...) about how and why you need ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-8-lotusscript-to-delete-or-not-to-delete</link>
<category>Geek-o-Terica</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-8-lotusscript-to-delete-or-not-to-delete?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-8-lotusscript-to-delete-or-not-to-delete</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />I have written at length recently about garbage collection in both LotusScript and Java (see Geek-o-Tericas <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript">3</a>, <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java">5</a>, and <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads">6</a> especially). I went on (and on...) about how and why you need to use the "recycle()" call in the Java classes for Notes, and why that call doesn't really exist in LotusScript, which has a more robust and automated gc mechanism integrated with the Notes classes. <br /> <br />But, I neglected to mention the built-in LotusScript "delete" function, and since I've received 1 or 2 questions about it, I decided to do another (not so long, I hope) post on that topic. <br /> <br />"Delete" in LotusScript is very close in function to recycle() in Java: it destroys an object instance, and causes it to be garbage-collected immediately. If the object you delete is a Notes back-end (OR front-end) class object, then all of the memory associated with that object is freed. <br /> <br />Ok, that was easy! But the question remains: why would you ever need (or want) to use delete, when the LotusScript gc mechanism is invoked after every statement anyway?  <br /> <br />I have only ever needed it in one particular situation, having to do with (wait for it...) NotesAgent.Run() and NotesAgent.RunOnServer(). Why? Because there's a cute trick you can use to pass "parameters" to agents that you invoke from LotusScript, <em>and</em>, which you can also use to get back complex results from an agent. BUT, you need delete. <br /> <br />So, let's say you have an agent that you want to invoke from a pice of LotusScript code. Maybe the agent is local, or maybe it lives on a server somewhere. The first thing you need to do is "navigate" your way to the agent. Typically you'd do that by using NotesSession.GetDatabase() to get the database containing the agent, then NotesDatabase.GetAgent() to get an instance of NotesAgent.  <br /> <br />If you want the agent code to execute on the same machine as the code that invokes it, you will be using NotesAgent.Run(). If the target agent lives on a server, you can use NotesAgent.RunOnServer() to have the agent code run on that server (your calling program waits for the agent to finish before resuming in both cases). For both methods, as of Notes v5.02, you may optionally supply the NOTEID of a "parameter" document. This comes in handy when you want to be able to pass runtime info to the executing agent to tell it specifically what to do. You just create a document instance (NotesDatabase.CreateDocument) -- locally for the Run() method, on the target server for the RunOnServer() method. You can put any data you want into the new document, obviously you have to know what the target agent is expecting. <br /> <br />Then, you have to Save() the document object to disk. Why? Becuase you need a NOTEID (NotesDocument.NoteID) to pass to the agent, and a document object does not acquire a NOTEID until you've saved it. So then you can pass your newlly minted NOTEID to Run() or RunOnServer(). <br /> <br />The target agent is set up and invoked. That agent can find out what NOTEID was passed to it as follows: <br /> <br />&nbsp; &nbsp; &nbsp;Dim s as New NotesSession <br />&nbsp; &nbsp; &nbsp;Dim db as NotesDatabase <br />&nbsp; &nbsp; &nbsp;Dim currentagent as NotesAgent <br />&nbsp; &nbsp; &nbsp;Dim noteid as String <br />&nbsp; &nbsp; &nbsp;Dim parameters as NotesDocument <br />&nbsp; &nbsp; &nbsp;set currentagent = s.CurrentAgent <br />&nbsp; &nbsp; &nbsp;noteid = currentagent.ParameterDocID <br />&nbsp; &nbsp; &nbsp;set db = s.CurrentDatabase <br />&nbsp; &nbsp; &nbsp;set parameters db.GetDocumentByID(noteid) <br /> <br />And off you go. Pretty convenient, huh? But we haven't even got to the REALLY cool part yet! <br /> <br />What if your agent runs, and wants to pass a bunch of results BACK to the calling agent? You can! Just use the existing parameters document you already have. Your target agent can fill it up with whatever data you want to "pass back", and (of course) you have to call Save() on it again to get those changes committed to disk. Then, in your original calling agent, you have to get the <em>modified</em> version of that document back. You can't just use the NotesDocument instance you created to store your invocation parameters, because that document object still exists in memory,and it does not have your target agent's result data in it. <br /> <br />THAT is why you need delete! Your calling agent has to delete the original parameter document, then re-fetch it with a NotesDatabase.GetDocumentByID() call (it will still have the same NOTEID it had before). Cool, huh?  <br /> <br />Does it work in Java? YES, with only one small difference: you don't get the "current agent" from the Session in Java, you get it from the AgentContext, which you get from the Session. Otherwise, this mechanism works the same in Java as in LotusScript. <br /> <br />So, there's the one situation I've come across personally that requires "delete" (thanks to Daniel Lehtihet for suggesting this as a topic). <br /> <br />Geek ya later! <br /> <br />(Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)  <br />&nbsp; &nbsp; &nbsp;  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-8-lotusscript-to-delete-or-not-to-delete</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-8-lotusscript-to-delete-or-not-to-delete?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 7: Garbage, threads and the CORBA classes in Notes</title>
<pubDate>Sat, 23 May 2009 12:15:00 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I actually thought that my previous Geek-o-Terica post on garbage collection (gc) and java and Notes and threads would be the final one on that topic. For one thing, there's only so ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-7-garbage-threads-and-the-corba-classes-in-notes</link>
<category>CORBA</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-7-garbage-threads-and-the-corba-classes-in-notes?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-7-garbage-threads-and-the-corba-classes-in-notes</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />I actually thought that my previous Geek-o-Terica<a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads"> post on garbage collection (gc) and java and Notes and threads </a>would be the final one on that topic. For one thing, there's only so much you can say about it without falling asleep.  <br /> <br />However, I had a couple of requests to map that discussion onto the "other" Java APIs for Notes, the so-called CORBA classes. It's a good point, so here we go. <br /> <br />First, a brief review of what's different about the CORBA classes. They're different from the "regular" back-end classes for Notes in that they constitute a Java library (NCSO.jar) that does not need a locally installed Notes Client or Domino Server in order to operate. They work remotely with any Domino server that runs the DIIOP server task. The CORBA classes (so named because the remoting technology they use is based on the <a href=http://www.omg.org>Object Management Group's</a> "Common Object Request Broker Architecture" specification). <br /> <br />The classes in NCSO.jar implement the exact same Java interfaces (Session, Database, View, Document, etc etc) that the "local" classes in Notes.jar do, so you (with a few very minor exceptions) use them the same way. But the implementation is entirely different. When you invoke a method on a "local" object instance, a piece of Java wrapper code calls into the C++ code in Notes/Domino that implements the back-end classes (lsxbe). The C++ code uses the Notes C API, and things rock on. <br /> <br />The job of the "remote" Java classes is entirely different. Each object instance in NCSO.jar is really just a proxy object: it's job is to assemble the input parameters into a command buffer, format it according to the CORBA wire-protocol specification (IIOP, thus the name DIIOP for the server task), and ship it to the server. Each CORBA proxy object is bound to a "real" back-end object on the server, which is the thing that does the real work.  <br /> <br />This architecture has a number of different implications on how you code your CORBA-based Java app: <br /> <br />&nbsp; &nbsp; &nbsp;1) You still have to use recycle(). Not so much to protect the memory heap of your local JVM (because there are no "real" back-end classes to de-allocate there), but to recover lsxbe/C++ memory <em>on the server.</em> <br />&nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp;2) There's no (discernable) connection between threads you may generate on your client machine and threads within the DIIOP server task. Since your program is not directly using the CAPI, your CORBA program is not bound by any of the threading rules you have when running on a Notes/Domino machine using the local classes. You can freely use CORBA objects across threads, no init/term required. <br /> <br />&nbsp; &nbsp; &nbsp;3) You can actually connect to multiple servers using the CORBA classes. You'd do that by creating one Session instance for each server. But you can NOT mix and match child objects across servers, that dog just won't hunt. <br /> <br />Hope this helps. (Hope this is <em>enough</em> ) <br /> <br />Geek ya later! <br /> <br />(Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-7-garbage-threads-and-the-corba-classes-in-notes</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-7-garbage-threads-and-the-corba-classes-in-notes?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Welcome Rocky back to the &quot;independence-sphere&quot;!</title>
<pubDate>Wed, 20 May 2009 12:29:09 -0400</pubDate>
<description>
<![CDATA[ 
Allow me to be among the first to congratulate my pal Rocky Oliver back to the land of the independent consultants! Read the full story here. One small observation I can't help making: for years it l ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/welcome-rocky-back-to-the-independence-sphere</link>
<category>Rocky Oliver</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/welcome-rocky-back-to-the-independence-sphere?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/welcome-rocky-back-to-the-independence-sphere</guid>
<content:encoded><![CDATA[ Allow me to be among the first to congratulate my pal Rocky Oliver back to the land of the independent consultants! Read the full story <a href="http://www.lotusgeek.com/LotusGeek/LotusGeekBlog.nsf/d6plinks/ROLR-7S8KDD">here</a>. <br /> <br />One small observation I can't help making: for years it looked as though my "career path" (loosely defined) was following Rocky's. I re-joined IBM a few months after he did in 2005, and I left IBM again a few months after he did in late 2007/early 2008. <br /> <br />This time, I'm actually <em>ahead</em> of him!  <br /> <br />So, Rocky: Welcome back! It is my strong prediction that you will be doing great things, and it is my fervent hope &nbsp;that we get to work together again.  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/welcome-rocky-back-to-the-independence-sphere</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/welcome-rocky-back-to-the-independence-sphere?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 6: Now it Gets Complicated: Java, Garbage-Collection, Notes, and Threads</title>
<pubDate>Sun, 17 May 2009 13:00:00 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! If you're not interested in the swirling, sexy synergy at the intersection of Java memory management and Notes back-end classes and multi-threaded programs, you might want to go ca ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads</link>
<category>Java</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> If you're not interested in the swirling, sexy synergy at the intersection of Java memory management and Notes back-end classes and multi-threaded programs, you might want to go catch up on events elsewhere. Don't worry, I don't take this stuff personally. <br /> <br /> Ok! For the 2 of you still here, have you already scanned my <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java"><span style="text-decoration:underline">previous post</span></a> on the topic of garbage collection (gc) in Java? The point of this gloss on the topic is to try to explain what happens to gc, recycle() and so on when you also mix in multi-threading. As <a href=http://www.jefffoxworthy.com/homepage.shtml><span style="text-decoration:underline">Jeff Foxworthy</span></a> says, "And then it got WEIRD..." <br />  <br />You probably already know that the Notes back-end classes, regardless of what programming language you use to access them, are implemented internally as a bunch of C++ code, which in turn manipulates the product (Notes/Domino) via a rather large C API. Thus, the needs and requirements of the C API drive some of the fundamental behavior of the C++ code that implements the back-end classes, and, to one extent or another, also impose constraints on the various language-specific implementations of your agents, standalone programs, etc. <br /> <br />One of these "requirements" (or constraints, if you prefer) has to do with a nasty (IMHO) little programming technique called "thread-local storage", or TLS. TLS is one of those ideas that sounds cool, if you're a codegeek, but which can actually really tie you in knots in some situations. Basically, TLS means that any given "thread of execution" within a process can allocate some memory that only it can "see". In other words, your code has to be running on the thread that allocated the TLS in order for that code to be able to access that memory.  <br /> <br />Why would you do that? Well, it's a convenient way to "remember" context in certain situations. If you're a server, for example, and you bind a thread to each client session, so that all client requests are serviced by a single thread, you can use TLS to easily remember stuff like, who is this client anyway? Is she authenticated? What databases is she accessing, and so on. <br /> <br />Where it gets nasty is that the use of TLS in Notes imposes two non-breakable requirements on multi-threaded programs which use the CAPI to get things done: 1) Any TLS allocated on a given thread must also be de-allocated on that same thread, and b) All threads accessing the Notes C API must explicitly initialize (and terminate) themselves before using any CAPI services. Why? Because Notes uses TLS. Since only the thread that creates TLS can "see" it, it's logical that no other thread can de-allocate it. And, like most storage/memory systems in any complicated program (like Notes or Domino), TLS requires per-thread initialization, and therefore, termination.  <br /> <br />Now, when you're using (or writing) a single-threaded program using the CAPI (or back-end classes), there's no problem, because everything happens on the same thread. Examples of single-threaded programs using the Notes C API include: all LotusScript programs; a Notes CAPI program where you don't create extra threads; Java agents or standalone programs where you don't create extra ("child") threads; most of the Notes Client. <br /> <br />It gets weird fast in Java, though, partly because it's so easy to spin off child threads in that language. So what happens if you create an instance of the java.lang.Thread class and run some code that accesses the back-end classes on that thread? The answer is: it won't work, unless you do the right thread initialization. There are 2 ways to do that: <br /> <br />&nbsp; &nbsp; &nbsp;A) Make your code use NotesThread instead of Thread (your class can extend it, or you can launch it in any of the ways you can launch Thread). NotesThread extends Thread, and adds just a little bit of logic: it calls the correct Notes CAPI entry points to do the required initialization when it starts running, and when it terminates, it does the required call for termination. <br /> <br />&nbsp; &nbsp; &nbsp;2) If you don't want to extend NotesThread (or can't, for some reason), any instance of java.lang.Thread can be explicitly initialized (and terminated) with a pair of "static" methods on the NotesThread class. "Static" means that you can call the methods without having an actual instance of the class around. You can call NotesThread.sinitThread() and NotesThread.stermThread() from any thread instance, and then go use back-end classes as you wish. <br /> <br />Ok. Still with me? Next question: What the heck does this have to do with recycle()? The bottom line: remember from my previous post how I attributed the need to explicity recycle() to the fact that Java gc doesn't have a way to invoke Notes API to free up resources? Well, it's actually worse than that. Even if there WERE such a way (e.g., if the finalize() call in Java were actually reliable), it would still be NO GOOD! <br /> <br />Why? Because of TLS. And, because in the Java virtual machine, garbage collection takes place on <em>its own thread. </em>So even if there were a way to reliably invoke the Notes API when an object (say an instance of lotus.domino.Database) was being gc'ed, it would violate the rule that TLS MUST be de-allocated on the thread that created it! <br /> <br />So, what happens, then when you create a Notes object (such as a Database) on one thread, and then use it on another? It works! Why? because the back-end classes code internally figures out that you're accessing the internal data structures of that object (a CAPI thing called a DBHANDLE, in the case of a Database) on another thread, and it compensates by creating new TLS for that object on your thread. When your thread terminates, the back-end classes logic has to go find EVERY object that has TLS allocated on that thread and reclaim it. This happens automatically if you're using NotesThread, or explicitly when you use the static stermThread() call.  <br /> <br />And now, to get FULLY weird (and, I hope, your head will not explode): what happens if you create (say) a Database object on ThreadA, then access it on ThreadB and ThreadC, and then you decide you're ready to recycle it? Think about it (but not TOO hard)! Which thread should you use to call Database.recycle()? Whichever one it is, doesn't that leave 2 threads' worth of TLS still allocated?  <br /> <br />So, when is a "recycle" not a "recycle"? Answer: when you have an object "open" on multiple threads! The only way to avoid memory leaks in the above situation is to not fully destroy the object until you're done with it on ALL threads that have accessed it.  <br /> <br />How much of this does the everyday Java developer using Notes back-end classes have to worry about? Some, but not a whole lot (again, IMHO and YMMV). Here are a few "best practices" I have developed over the years to keep my own code relatively (if not squeaky) clean: <br /> <br />&nbsp; &nbsp; &nbsp;1) Don't write multi-threaded programs. They're harder to code, harder to debug and harder to maintain. And you can get unintended memory leaks... <br />&nbsp; &nbsp; &nbsp;2) If you MUST write multi-threaded programs, make sure you really have to. If you don't REALLY have to, see point #1. Yes, you can derive big performance gains with multi-threading. But ask yourself this: is it worth the extra pain? <br />&nbsp; &nbsp; &nbsp;3) Don't share Notes objects across threads. <br />&nbsp; &nbsp; &nbsp;4) If you MUST share Notes objects across threads, make sure you really have to. If you don't REALLY have to, see point #3. <br />&nbsp; &nbsp; &nbsp;5) Adopt this convention: If a thread created the object, that thread "owns" the object and ONLY that thread may recycle it. Of course there are a couple of corollaries to this:  <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a) ALL objects should be recycled when you're done with them <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b) When you go to recycle an object on the owning thread, make sure no other threads expect that object to still be there. Ideally, you'd have the non-owning threads terminate before the owning thread, then that last-thread-standing can recycle the object(s) safely, and all TLS gets cleaned up. <br />&nbsp; &nbsp; &nbsp;6) Try to avoid writing multi-threaded programs, unless you really know what you're doing. <br /> <br />Isn't this fun?  <br /> <br />Geek ya later! <br /> <br />(Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-6-now-it-gets-complicated-java-garbage-collection-notes-and-threads?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 5: Taking out the Garbage (Java)</title>
<pubDate>Mon, 4 May 2009 15:00:00 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I posted a short article last week on garbage collection in LotusScript. This post is about a whole different set of issues you need to be aware of if you're writring Java code for ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java</link>
<category>Java</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />I posted a short article last week on <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript">garbage collection in LotusScript</a>. This post is about a whole different set of issues you need to be aware of if you're writring Java code for Notes or Domino. <br /> <br />Like LotusScript, the Java language creates objects with a built-in "new" operator, and, like LotusScript sweeping up the no-longer-used memory ("garbage collection",or gc) is supposed to be automatic. But. The gc mechanism in Java is nothing like the one in LotusScript -- you have to do more work to avoid memory leaks, and you have to know more about how it all works. The basic saying people like to quote about gc in Java is: "You never have to worry about memory." I generally add to that: "Until you run out." <br /> <br />There are two major differences in the way LotusScript and Java each handle allocated memory: the first has to do with<strong> how many kinds </strong>of memory there are, and the second has to do with <strong>when</strong> each language does gc. <br /> <br />How many kinds of memory are involved with a Notes/Domino Java program? <strong>At least 2</strong>. First there's all the memory your java program allocates directly in the Java Virtual Machine (JVM): space for your code, space for your objects, space for the JVM itself to use. This all comes from the Java "heap": a big pool of memory that the JVM gets from the operating system, and parcels out to your program, and any other Java programs that might be running at the time.  <br /> <br />The second set of memory that your Java program is going to consume comes from a completely different place: It comes from the "Notes runtime heap" -- a different big pool of memory that the Notes/Domino core (which, after all, has nothing to do with any JVMs) gets from the operating system. This pool is what the Notes back-end classes use, as well as the Notes core itself. So, for example, when you instantiate a lotus.domino.Session object (or Notes does it for you, if you're running an Agent), a number of things happen: <br /> <br />&nbsp; &nbsp; &nbsp;- If the JVM isn't running yet, it starts up. A bunch of .jar files are pre-loaded, using up some JVM heap. <br />&nbsp; &nbsp; &nbsp;- Notes (or Domino) creates an instance of the Session class for the agent to use. This uses a bit more memory from the JVM heap. The new Java Session object calls into the back-end classes DLL ("lsxbe") to initialize the corresponding C++ Session object. Every Notes Java object is linked to a corresponding lsxbe back-end C++ object. <br />&nbsp; &nbsp; &nbsp;- The C++ object that gets created to go with the new Java object uses up some memory of its own. This memory, however, comes from the "other" heap -- what I called the "Notes runtime heap" above. ALL of the lsxbe objects that are linked to the Java objects you create and use in your Agent come from this other heap. Some of them (Docuemnts, Databases, and others) consume Notes CAPI resources, such as NOTEHANDLEs and DBHANDLEs, which might represent lots and lots of other allocated memory in the Notes core (just as one example, an "open" Notes document that consumes 10mb of disk space might also consume 10mb of memory).  <br /> <br />So here's where it gets interesting: The JVM has a background thread that runs all the time (at lower priority than "normal" application threads), looking for objects which have been allocated out of the JVM heap and which are no longer used anywhere. When it finds such, it frees the memory used by those objects, and that memory in the JVM heap is then available for re-use. HOWEVER, there is no automatic mechanism by which the C++ objects associated with those Java objects can be notified to free up the memory THEY are consuming (which is often far larger). If nothing is done, all of that memory taken from the Notes runtime heap is "leaked": it never gets released. <br /> <br />Thus, because there's no way for Notes to know for sure when a given Java object is being garbage-collected, we need another way to tell the back-end classes to clean up and take out the garbage. Unfortunately, the only way is to enlist the aid of the developer: you have to TELL lsxbe to clean up with the notorious recycle() call. What makes this unfortunate, from a product point of view, is that developers have to know to do this, and have to know how to do it correctly, so that they don't mess theselves up accidentally. <br /> <br />So what, exactly, does recycle() do? First, it finds the link stored in the Java object to the corresponding C++ object. Then it invokes some code in lsxbe to destroy that C++ object. The "destructor" code in the back-end classes does a couple of things: it first finds and destroys any "owned" objects that it knows about. When you invoke recycle() on a lotus.domino.Database object, for example, any Document objects that were instantiated out of that database are also destroyed. The object's destructor also knows how to lilnk back to the JVM and tell it to invalidate (and garbage-collect) the corresponding Java object. It also tells the Notes CAPI to release any temporary memory it has consumed, and then the memory taken up by the C++ object itself is reclaimed. <br /> <br />Try this experiment: FInd (or create) a Notes database that contains a view with 50,000 or so documents in it (the number of fields in the document is relatively unimportant for this purpose). Then write a Java agent that walks the view, and accesses each document (just use View.getFirstDocument/getNextDocument). Don't use recycle(). If your view is big enough, you might actually crash Notes this way, because every time you assign a new Document object to your local variable inside the iteration loop, the previous object referred to by that variable will be gc'ed, but the corresponding C++ document object will not.  <br /> <br />Of course, even when you leak megabytes of memory in this way, Notes (and the operating system) get it all back when the Agent terminates. Why? Because the CurrentDatabase and the Session objects that Notes created for your Agent to use get recycled automatically when the Agent is done, and therefore all other objects "owned" by that Session and Database (i.e., all of them) get recycled automatically. Of course, if you run out of memory before that point, you're screwed.  <br /> <br />So: recycle early, recycle often! <br /> <br />Believe it or not, there's actually a bunch more to say on this topic. Look for my next blog post in a couple of days: "So Now it Gets Complicated: Java, Garbage-Collection, Notes, and Threads". <br /> <br />Geek ya later. <br /> <br />(Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-5-taking-out-the-garbage-java</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-5-taking-out-the-garbage-java?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Cool new blog, AWESOME rocket launch video</title>
<pubDate>Wed, 29 Apr 2009 19:44:50 -0400</pubDate>
<description>
<![CDATA[ 
New blog from Teamstudio: http://voices.teamstudio.com/voices/TSVoices.nsf/d6plinks/ROLR-7RKJSP ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/cool-new-blog-awesome-rocket-launch-video</link>
<category></category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/cool-new-blog-awesome-rocket-launch-video?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/cool-new-blog-awesome-rocket-launch-video</guid>
<content:encoded><![CDATA[ New blog from Teamstudio: <br /><a href="http://voices.teamstudio.com/voices/TSVoices.nsf/d6plinks/ROLR-7RKJSP">http://voices.teamstudio.com/voices/TSVoices.nsf/d6plinks/ROLR-7RKJSP</a> <br />  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/cool-new-blog-awesome-rocket-launch-video</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/cool-new-blog-awesome-rocket-launch-video?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>I do not like plagiarism</title>
<pubDate>Wed, 29 Apr 2009 09:17:02 -0400</pubDate>
<description>
<![CDATA[ 
Check out Kevin Pettitt's blog. If things are as he reports, someone needs some serious head-shaping. http://planetlotus.org/4b7f58 ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/i-do-not-like-plagiarism</link>
<category>plagiarism</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/i-do-not-like-plagiarism?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/i-do-not-like-plagiarism</guid>
<content:encoded><![CDATA[ Check out Kevin Pettitt's blog. If things are as he reports, someone needs some serious head-shaping. <br /><a href=http://planetlotus.org/4b7f58>http://planetlotus.org/4b7f58</a> <br />  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/i-do-not-like-plagiarism</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/i-do-not-like-plagiarism?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 4: AutoUpdate on View navigation</title>
<pubDate>Wed, 29 Apr 2009 04:44:00 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I was getting ready to write a new Geek-o-Terica post about how the NotesView.AutoUpdate property (which also exists in Java) can affect view navigation. But Kathy Brown already di ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-4-autoupdate-on-view-navigation</link>
<category>LotusScript</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-4-autoupdate-on-view-navigation?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-4-autoupdate-on-view-navigation</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> I was getting ready to write a new Geek-o-Terica post about how the NotesView.AutoUpdate property (which also exists in Java) can affect view navigation. But Kathy Brown already did, so I'm just going to<a href="http://www.runningnotes.net/kbrown/runningnotes.nsf/d6plinks/KBRN-7RHJAF"><span style="text-decoration:underline"> link t</span></a>o her post. <br /> <br /> Geek ya later! <br /> <br /> (Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-4-autoupdate-on-view-navigation</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-4-autoupdate-on-view-navigation?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 3: Taking out the garbage (LotusScript)</title>
<pubDate>Mon, 27 Apr 2009 05:56:24 -0400</pubDate>
<description>
<![CDATA[ 
Greetings Geeks! LotusScript is a cool language. One of the reasons it's cool is a feature called "automatic garbage collection". What does that mean? It means that you can litter your code landscap ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript</link>
<category>LotusScript</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript</guid>
<content:encoded><![CDATA[ Greetings Geeks! <br /> <br /> LotusScript is a cool language. One of the reasons it's cool is a feature called "automatic garbage collection". What does that mean? It means that you can litter your code landscape with snippets of memory to your heart's content, and never have to worry about keeping track or picking it up ("deallocating", or "freeing" the allocated memory chunks) later. <br /> <br /> It means you can code a loop like this (skipping all the DIMs, but you get the idea): <br /> <br />  &nbsp; &nbsp;set view = db.GetView("$all") <br />  &nbsp; &nbsp;set doc = view.GetFirstDocument() <br />  &nbsp; &nbsp;while not (doc is nothing) <br />  &nbsp; &nbsp; &nbsp; &nbsp; ' do something... <br />  &nbsp; &nbsp; &nbsp; &nbsp; set doc = view.GetNextDocument(doc) <br />  &nbsp; &nbsp;wend <br /> <br /> Every time you do "set doc = ", the Notes back-end classes infrastructure is generating a new NotesDocument object in memory. What happens to the object that used to be stored in the "doc" variable? LotusScript automatically keeps track of all references to objects, and when there are none (in this case, when you assign a new object reference to "doc", overwriting the old one), the memory used by that object is reclaimed. <br /> <br /> When does garbage collection happen? It happens in LotusScript after the execution of every statement (which can lead to some interesting side-effects, as we'll see in a minute). It wasn't always like that, though. In Notes V4.0 (the first appearance of LotusScript in the product), garbage collection only happened at the end of each Sub or Function. But that wasn't good enough, because, as in the above snippet, if the View had, say, 100,000 documents in it, you'd run out of memory before you got to the end of the function. <br /> <br /> But, as with all great boons to humanity, automatic garbage collection in LotusScript has its dark side. Consider this: <br /> <br />  &nbsp; &nbsp;dim s as new NotesSession <br />  &nbsp; &nbsp;dim entry as NotesEntry <br />  &nbsp; &nbsp;set entry = s.CurrentDatabase.ACL.GetFirstEntry <br /> <br /> Seems innocuous, right? But you'll never get an object in "entry". Why? Because there's another rule I haven't reminded you of yet (you probably already knew it, but you didn't realize it could bite you like this in some cases). The rule is that when an object is garbage-collected, <em>all of its child objects are also garbage-collected.</em> &nbsp;That might seem needlessly destructive, but it's actually necessary. Notes does not allow free-floating objects that exist outside their container, or "owner" object. Documents, for example, must belong to a database. Items must belong to a document, and ACLEntries must belong to an ACL object. <br /> <br /> So, what really happens in the above snippet? The expression "s.CurrentDatabase.ACL.GetFirstEntry" is perfectly legal in an agent, where the NotesSession will always exist, as will the CurrentDatabase. And we know that every Notes database has an ACL object with at least one ACLEntry in it. So the expression will always evaluate and create an ACNEntry object, which then gets assigned to the "entry" variable. <br /> <br /> But then, once that all happens, garbage collection kicks in. It says, "What can I sweep up that is no longer referenced?" Session and CurrentDatabase are special, they have to stay around until the agent is done. But, AHA! The ACL object isn't used anymore after this statement is done (the object reference is not saved in any local variables). So it gets destroyed. And, invoking the rule above, all of its instantiated children also get destroyed, including the ACLEntry instance that we just saved in "entry". All before the next statement is executed. Easy come, easy go. <br /> <br /> Everything would have been fine if we had coded the above thusly: <br /> <br />  &nbsp; &nbsp;dim s as new NotesSession <br />  &nbsp; &nbsp;dim entry as NotesEntry <br />  &nbsp; &nbsp;dim acl as NotesACL <br />  &nbsp; &nbsp;set acl = s.CurrentDatabase.ACL <br />  &nbsp; &nbsp;set entry = acl.GetFirstEntry <br /> <br /> This way, the NotesACL object hangs around until the Sub exits, and so our ACLEntry object is also preserved. <br /> <br /> Now consider this bit of logic: <br /> <br />  &nbsp; &nbsp;set item = doc.items(0) <br /> <br /> Do we have a similar problem here? Will "item" always be Nothing? Actually, no, this works. It's true that the array of NotesItem objects created by the "doc.items" property is garbage-collected, but the single NotesItem object we saved in "item" is fine. Why? Because the item is "owned" by the NotesDocument object, not by the array. The array disappears, but the document doesn't. <br /> <br /> Of course you would be making a mistake to code a loop such as this: <br /> <br />  &nbsp; &nbsp;for i = 0 to ubound(doc.items) <br />  &nbsp; &nbsp; &nbsp; set item = doc.items(i) <br />  &nbsp; &nbsp; &nbsp; ' do something.... <br />  &nbsp; &nbsp;next i <br /> <br /> This is horribly inefficient, because every invocation of "doc.items" above will create an array, and then populate that array with a set of NotesItem objects. Then at the end of each statement, the array will be garbage-collected, along with all but one of the NotesItem objects. That's a lot of work to do over and over. Much better to access the array one time, save it in a Variant variable, and then iterate over the array. <br /> <br /> Next time: How garbage collection in Java is way different. <br /> Geek ya later! <br /> <br /> (Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-3-taking-out-the-garbage-lotusscript</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-3-taking-out-the-garbage-lotusscript?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Geek-o-Terica 2: Using parentheses in LotusScript</title>
<pubDate>Tue, 21 Apr 2009 04:49:49 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! Parentheses in LotusScript can be confusing. For example, check out this seemingly innocuous statement: MyFunc(arg1, arg2) Easy, right? Well, it's fine if "MyFunc" is a Fun ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-2-using-parentheses-in-lotusscript</link>
<category>Geek-o-Terica</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-2-using-parentheses-in-lotusscript?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-2-using-parentheses-in-lotusscript</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> Parentheses in LotusScript can be confusing. For example, check out this seemingly innocuous statement: <br /> <br />  &nbsp; &nbsp;MyFunc(arg1, arg2) <br /> <br /> Easy, right? Well, it's fine if "MyFunc" is a Function, but it will cause a compiler error if "MyFunc" is a Sub. Want to know why? <br /> <br /> The difference between a Sub and &nbsp;Function (you already know this) is that a Function returns a value, and can therefore be used on the right-hand side of an assignment statement ("="), while a Sub does not return a function. <br /> <br /> So think about this from the compiler's point of view. An invocation of a Sub does not need parentheses around the parameter list being passed to the Sub, syntactically. Because the statement that invokes the Sub stands alone (no value is returned, so you can't assign the result of the invocation to something else, or use it in a more complex expression), there's no ambiguity: <br /> <br />  &nbsp; &nbsp;MyFunc "arg1", "arg2" <br /> <br /> works fine, I (the compiler) know just what to do. Likewise, if MyFunc is an actual Function that returns something, but I (the programmer) don't care, I can still code the above statement and the compiler knows what to do. BUT, if I use MyFunc's return value in some way -- assign it to a variable, or use it to invoke another Sub or Function, I MUST enclose the paremeter list in parentheses: <br /> <br />  &nbsp; &nbsp;stvar = MyFunc("arg1", "arg2") <br />  &nbsp; &nbsp;MySub MyFunc("arg1", "arg2"), 7 <br /> <br /> You can see that if the language allowed me to omit the parens, line 1 might be ok, but line 2 would be impossible to parse. <br /> <br /> So, why is it "wrong" (compiler error) to code my original example above if "MyFunc" is a Sub? BECAUSE enclosing a paremeter in parentheses during a Sub invocation has ANOTHER MEANING! It means "pass this parementer by value, not by reference". <br /> <br /> What's the difference, and why would anyone care? Consider this sample agent: <br /> <br /> option declare &nbsp; &nbsp; ' ALWAYS use Option Declare! <br /> Sub Initialize <br />  &nbsp; &nbsp; &nbsp; Dim st As String <br />  &nbsp; &nbsp; &nbsp; st = "set in Initialize" <br />  &nbsp; &nbsp; &nbsp; subr st <br />  &nbsp; &nbsp; &nbsp; Msgbox "String is: " &amp; st <br />  &nbsp; &nbsp; &nbsp; st = "reset in initialize" <br />  &nbsp; &nbsp; &nbsp; subr (st) <br />  &nbsp; &nbsp; &nbsp; Msgbox "Now string is: " &amp; st <br /> End Sub <br /> Sub subr(arg As String) <br />  &nbsp; &nbsp; &nbsp; arg = "set in subr" <br /> End Sub <br /> <br /> The result of the first Msgbox will be: "set in subr". The result of the second one will be: "reset in initialize". Why? <br /> <br /> Because the first call to "subr" passes the "st" parameter as a reference -- a pointer to the variable's memory location. So when the Sub "subr" modifies the parameter, that memory location gets updated with the new string, and Initialize "sees" the change. In the second call, the parens around "st" tell the compiler to "pass by value", the calling code does not pass a reference to "st" to the Sub, it passes a COPY of the VALUE of "st" (the string "set in initialize"). The Sub modifies the copy's memory location, but Initialize does not "see" that after the call. <br /> <br /> You can accomplish the same thing as using pass-by-value parens by changing the declaration of "subr" to: <br /> <br />  &nbsp; &nbsp;Sub subr(ByVal arg As String) <br /> <br /> So, now you can see why <br /> <br />  &nbsp; &nbsp;MyFunc(arg1, arg2) <br /> <br /> is weird when MyFunc is a Sub: pass-by-value around TWO parameters like that makes no sense, syntactically, so the compiler throws an error. <br /> <br /> Get it? Yes, it's a little odd, but don't blame LotusScript -- this little feature was copied from BASIC, as was most of the LotusScript language (BASIC as it was back in 1990, that is). <br /> <br /> Geek ya later.  <br />(Topic inspired by <a href=http://kathysrunningnotes.blogspot.com/>Kathy Brown</a>. Thanks Kathy!)  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/geek-o-terica-2-using-parentheses-in-lotusscript</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/geek-o-terica-2-using-parentheses-in-lotusscript?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Introducing &quot;Geek-o-terica&quot;</title>
<pubDate>Sat, 18 Apr 2009 13:17:05 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I was getting bored with stuff, so I decided to make up a new term: Geek-o-terica. "Geek" because this is kind of a blog for geeks, and I've always introduced postings by shouting ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/introducing-geek-o-terica</link>
<category>Geek-o-terica</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/introducing-geek-o-terica?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/introducing-geek-o-terica</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> I was getting bored with stuff, so I decided to make up a new term: Geek-o-terica. "Geek" because this is kind of a blog for geeks, and I've always introduced postings by shouting that out. <br /> <br /> The "o-terica" part is there because it is reminiscent of (is actually a non-null substring of, for you Geeks out there) the word "esoterica", which basically (pun intended) means "<a href=http://dictionary.reference.com/browse/esoterica><span style="text-decoration:underline">things understood by or meant for a select few</span></a>" (NOT the face cream!). It also means "recondite", but if I said that, you'd have to go look that up too. This is also cool, because the origin of the word "esoteric" is Greek, which, if you remove the "r" is.... ok, never mind. <br /> <br /> So. I thought I'd start a series (meaning, when I feel like it) of blog posts on specific Notes/Domio/Whatever technical topics. LotusScript or @Function or CAPI snippets or tips, perhaps other topics which interest me, and which I therefore assume have at least a small chance of interesting someone else. This will be different from SNTT (<a href=http://www.rhs.com/web/blog/gregate/v3test.nsf><span style="text-decoration:underline">Show 'N' Tell Thursdays</span></a>), because I'm not going to force myself to offer complete code samples, and I'm certainly not going to be constrained by what day of the week it happens to be when I get inspired to post. <br /> <br /> I've started a list of future Geek-o-terica topics, please post suggestions for topics you'd like to see. <br /> <br /> For my kickoff Geek-o-teric offering, here's a little something I like to call, "Multi-Language Character Sets, What They Are, and How to Use Them" (MLCS-WTAAHTUT). This isn't new material, in fact I first wrote it over 2 or 3 days in a hotel room in London in 2001. It was originally a 2-hour Freelance presentation (remember Freelance?) for a customer who wanted some technical background on character sets, LMBCS, Unicode, and fonts. I used Symphony to convert it to PDF format, and here it is. Sorry for the slidemaster... <br /> <br /> Ever wondered what the differences are between LMBCS and Unicode? Hungering to know the real impact of coding strings in utf-8 vs. utf-32? Didn't know there <em>was</em> such a thing as utf-32? Always had a secret itch because you weren't clear on the precise distinction between "character" and "glyph"? Mystified by ligatures? Never knew for sure why programmers groan when confronted with EBCDIC? <br /> <br /> Well then, you have most definitely come to the right place, my fellow Geeks! Read on, and enjoy! <br /> <br /> <br /> Geek ya next time.  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/introducing-geek-o-terica</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/introducing-geek-o-terica?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Come Visit at Lotus Admin/Developer &#8217;09, in Boston</title>
<pubDate>Wed, 15 Apr 2009 03:07:20 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! Consider this my personal invitation to you to come visit The View's Admin/Developer09 conference, in Boston (at the Sheraton Hotel, as always). Today was Jumpstart and booth set ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/come-visit-at-lotus-admindeveloper-09-in-boston</link>
<category>I will be showing up</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/come-visit-at-lotus-admindeveloper-09-in-boston?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/come-visit-at-lotus-admindeveloper-09-in-boston</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> Consider this my personal invitation to you to come visit <a href=http://www.viewadmin2009.com/><span style="text-decoration:underline">The View's Admin/Developer09 </span></a>conference, in Boston (at the Sheraton Hotel, as always). <br /> <br /> Today was Jumpstart and booth set-up day. I'm there working for one of my customers, <a href=http://www.bcc.biz/><span style="text-decoration:underline">BCC</span></a>. I will be working in the BCC booth (come visit!) Wednesday afternoon and all day Thursday, as well as helping to present a vendor session Thursday afternoon on BCC's premier product, Client Genie. Essentially, Client Genie is a Notes Client management tool that takes over where policies peter out. There are other cool products on display too, so come on by.  <br /> <br />The Wednesday morning keynote (8:30am) will be presented by Lotus General Manager Bob Picciano, should be a good session. My understanding is that you can catch a live-blog of it <a href="http://www.11tmr.com/11tmr.nsf/d6plinks/MWHE-7R4PM8">here</a>.<br /> <br /> I was at the conference site for a couple of hours this afternoon, helping with boot setup. Not too much activity, as the jumpstarts were still going on. Because I live only 15 miles from the conference site, it looks like I'll be commuting from home each day. <br /> <br /> Hope to see you there!   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/come-visit-at-lotus-admindeveloper-09-in-boston</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/come-visit-at-lotus-admindeveloper-09-in-boston?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Relief for the COBRA bite</title>
<pubDate>Fri, 10 Apr 2009 16:45:57 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I got some VERY good news yesterday, and for those of you in the U.S. who are on COBRA health plans, it may apply to you as well, so I thought I'd share (Non-U.S.ians or those who a ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/relief-for-the-cobra-bite</link>
<category>COBRA</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/relief-for-the-cobra-bite?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/relief-for-the-cobra-bite</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />I got some VERY good news yesterday, and for those of you in the U.S. who are on COBRA health plans, it may apply to you as well, so I thought I'd share (Non-U.S.ians or those who are on employer-sponsored health plans probably won't care, go do something useful.) <br /> <br />As you may have read in these pages, I got <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/the-difference-between-duh-and-doh-it-got-around-to-me...-revised">laid off</a> from my job back in January. Given that unemployment meant that my previously employer-sponsored health insurance was terminated, I needed to do something. So I converted the previous plan to a "COBRA" plan. That means that I was able to continue the health insurance coverage for me and for my family by paying the full amount of the monthly premium. This "conversion" ability is mandated by US Federal law. The idea is that you (the newly unemployed worker) pick up the full cost of the insurance (your former employer pays nothing), but the cost is still calculated at the group rate you were getting before, so (<a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/as-you-may-recall-from-my-previous-post...">in theory...</a>) the premiums are still lower than they would be if you had to go get your own policy. <br /> <br />So, that's a nice thing, especially during an economic melt-down, when it's not so easy to get a new job. Unfortunately, health insurance is still incredibly expensive, even at group rates. My monthly bill for a family plan is approximately $1500. Of that, maybe $150 or so is dental coverage, the rest is "normal" health coverage. Naturally, there's still deductibles and co-pays and all the rest, just like before. <br /> <br />That's a LOT of money to come up with every month when you're unemployed. Luckily, President Obama and the Democratic Congress (I say that not only because the Democratic Party has a majority in both houses of Congress now, but because almost all of the Republicans voted against the bill I'm talking about) added a provision to the recently passed "Stimulus Package" that subsidizes COBRA payments. <br /> <br />I heard something about this on the radio, and phoned my former employer's benefits department. DO NOT RELY on what I am about to tell you here: go check FOR YOURSELF!! <br /> <br />Here's a summary of what they told me: <br /> <br />&nbsp; &nbsp; &nbsp;<strong>Eligibility</strong> - you can get the subsidy if you were involuntarily terminated from your job, and are currently paying for a COBRA health plan. If you quit, you're not eligible. <br /> <br />&nbsp; &nbsp; &nbsp;<strong>When does it start?</strong> - The subsidies are retroactive to March 1, 2009. <br /> <br />&nbsp; &nbsp; &nbsp;<strong>What do I get?</strong> - The Government will pay 65% of your COBRA payments, you continue to pay 35%.  <br /> <br />&nbsp; &nbsp; &nbsp;<strong>How does it work?</strong> -- Your insurance company will be in touch with you later this month. As you can imagine, they are scrambling to catch up with all this. Your payments (supposedly starting in May, assuming they get you the info in time) will be reduced to the new, lower amount. The retroactive amount (the "overpayment" you made for March and April, if any) is applied to future payments. <br /> <br />&nbsp; &nbsp; &nbsp;<strong>How long does the subsidy continue?</strong> - I didn't think to ask that, though I'm sure they'll let me know. Anyone else know the answer? Please post it! <br /> <br />This is a GREAT deal and, if it works out as expected, will save me a lot of money each month. <br /> <br />Remember - Check with your own COBRA provider to find out exactly how this applies to you, don't rely on what I was told. <br /> <br />Anyone have more detail or corrections? Please post 'em! <br /> <br />Personal comment: DAMN I'm GLAD I voted for that guy!! <br />  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/relief-for-the-cobra-bite</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/relief-for-the-cobra-bite?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Huzzah! New LSX Toolkit is posted (Part 1)!!</title>
<pubDate>Tue, 31 Mar 2009 03:13:39 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I am pleased to report that a very long, and sorry saga, lasting more than 6 years, has finally come to a close! I am, of course referring to the LSX Toolkit. I got my new version ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/huzzah-new-lsx-toolkit-is-posted-part-1</link>
<category>LotusScript</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/huzzah-new-lsx-toolkit-is-posted-part-1?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/huzzah-new-lsx-toolkit-is-posted-part-1</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> I am pleased to report that a very long, and sorry saga, lasting more than 6 years, has finally come to a close! I am, of course referring to the LSX Toolkit. I got my new version of it today, the previous release having come out in 2001. That's a long time to wait, but Friends! The waiting is Over! <br /> <br /> Few living now remember (or care) what the brouhaha (brew? ha ha!) as all about, but I will give you a radically shortened history. <br /> <strong><span style="text-decoration:underline"><br /> What is the LSX Toolkit anyway?</span></strong> <br /> <br /> LSX (originally "LotusScript Extention") is an architectrue that was invented in the course of developing the LotusScript "back-end classes" for Notes version 4.0, back in 1994 or so. We (primarily me) were developing the original set of back-end classes (meaning, they would run on either the client or the server) using what we'd now call "extension points" in the LotusScript interpreter code. <br /> <strong><br /> English translation:</strong> A developer could create a bunch of C++ classes, put them in a DLL, and have the "host product" (Notes in the initial case) load the DLL. The host would, as part of the load-and-register protocol, would provide to the DLL code a specially crafted object instance of the LotusScript interpreter. This object has methods that allow "foreign" (or "extension") code to "register" the classes and methods and properties and errors that it implements with LotusScript. From the LotusScript developer's point of view, suddenly a whole bunch of new classes were available to be used in the LS editor and runtime environments. <br /> <br /> The Notes back-end classes were the first ever LSX. The LSX-i-ness of that DLL (nlsxbe.dll on windows, other name prefixes and suffixes on other OS platforms) resided in the fact that without that DLL, Notes had no "native" LotusScript classes at all (beyond the ones built to implement the editor and debugger). The DLL is hard-coded to load automatically when Notes (and now Domino) starts up. Other LSXs can be dynamically loaded when needed with a "USELSX <path>" type statement in a LS program. <br /> <br /> This had two very interesting and immediate impacts on the thinking of how LotusScript could be used: <br />  &nbsp; &nbsp; 1. Since, at that time (1995) Lotus had several products which embedded LotusScript (remember SmartSuite? 1-2-3? Freelance? Wordpro? Approach?), these "desktop products" could (easily, it turned out) be made to ALSO use the Notes LSX! You could run a script in the spreadsheet that could (behind the scenes, as these were the "back-end" classes) have 1-2-3 talk directly to the Notes objects. Cool! <br /> <br />  &nbsp; &nbsp; 2. Anyone could write ANY DLL that did, well, ANYTHING, and make it a "plug-in" to either the client or the server, exposing entirely new (and not necessarily strctly Notes-related) functionality. <br /> <br /> And both of these things were done. SmartSuite products learned to be able to load the Notes LSX. People actually built apps using it. More people created new LSXs to be used with Notes/Domino to do different things: connectors to outside data sources (eventually rationalized and collected into the Lotus Connector LSX, a single LotusScript API to talk to a variety of outside (non-Notes) relationsl databases. Still in use today!! <br /> <br /> One major problem remained: it was HARD to configure an LSX just so such that your classes and methods and constants and errors would all get registered properly. And it was HARD to set up the code so that when the LS Interpreter needed to invoke a function whose code resided in an LSX, it would happen correctly, passing through the right data structures and so on. The first few LSXs that were built were all hand-crafted, with a lot of help from those few who'd done it before. <br /> <br /> So the cry went out across the Lotus Rogers St. building in Cambridge, Massachusetts: "We need a TOOLKIT for this bugger! It needs to be easier! And it CAN be made easier!" <br /> <br /> Fortunately, management at the tiem were very responsive and supportive. A team was created at Lotus, and they architected and built the first edition of the LSX Toolkit. It was AWESOME. A thing of beauty. You operated it by creating documents in a Notes database, describinb what you wanted (classes, methods, etc). Then you pushed a button, and it generated a crapload of C++ code that created the "skeleton" of your implementation (of course, the "Wizard" as it was called knew nothing about your business logic, but it COULD create all the code you needed to build, register with LotusScript and accept callbacks for evaluation at runtime. You would then go and "flesh out the skeleton" to add the business logic. <br /> <br /> I think that first version came out in 1998 or 1999, only 4 years after Notes v4.0 had shipped. <br /> <br /> I wrote an LSX to sell as a product at my then new company (I had departed Iris Associates in 1997 to create Looseleaf Software). I had decided that it might make me some money (and be fun) to write an LSX that expanded the reach of the Lotus-owned back-end classes across more of the CAPI functionality than was currently available to LotusScript. Is there a Notes CAPI function you want that you can't (easily) access from LotusScript? Tell me, and I'll "wrap" it in a class in my "ScriptExpander" LSX, and you can buy it from me. <br /> <br /> I found lots, and people suggested others. I sold a bunch of copies over a few years. In fact: Here's what I'm gonna do. EVERYONE reading this blog post can HAVE (for free!) my Notes database that contains the entire product, except for the DLL itself. You can read the documentation, take a look at all the sample agents that show you how each and every one of the 100 or so LSX functions worked. Go on, take it! I said it was free (about 1.5mb zip file containing 1 NSF): <br /><a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/lsxdoc.zip/$file/lsxdoc.zip" title="lsxdoc.zip"lsxdoc.zip/>lsxdoc.zip</a> <br /> <br />Much cool stuff in there. You want to set the replicaid of a database from LS? It's in there. You want to create a relica stub on another server (not a full replica, the way Notes -- at the time -- made you do it? It's in there. Need text fields up to 2gb in size? It's there.  <br /> <br />Other people wrote LSXs too. The most famous is probably Ben Langhinrich's MIDAS rich text conversion classes (<a href=http://www.geniisoft.com/>http://www.geniisoft.com). Bill Buchan (<a href=http://www.hadsl.com/>http://www.hadsl.com/) wrote one for his FIRM product.</a></a> <br /> <br />Life was good (or at least, fun). The toolkit supported all of the client and server platforms for Notes and Domino. An updated kit came out in 2001. Some of the code that glues your LSX stuff to the LotusScript stuff and brings them together is actually delivered in the kit in source code form. I found a couple of bugs there (Reported them, of course!), but I was able to just fix them locally, 'cause I had the code. Life went on.  <br /> <br />As a few of us used LSXs more and more frequently, we noticed some, er, glitches that made things, um, inconvenient. Some could be worked around by tweaking the skeleton code after it got generated, other stuff (crashes in the toolkit wizard, for example), we had no source code for. A list of complaints began to accumulate, but Lotus was, um, slllloooooowwww to acknowledge that fixing these were a priority. The group that had been maintaining the kit was disbanded (ALWAYS a bad sign).  <br /> <br />Yet, I (and oathers) had real products out in the market depending on this technology. What could we do? It was frustrating. So. I think it was 2003, or maybe it was 2004 (I admit to being hazy about this, heck it might have been 2002) that I showed up at the "Meet the Developers" Session at Lotusphere (I think now it's called "Ask the Developers", we just always called it "Beat the Developers"). I happened to be invited to ask the first question. I mentioned that I was having a bunch of problems with the lsx toolkit, and said that, if Lotus wasn't really staffed to fix the problems, I would be happy to donate some time for free to sit in the Westford lab (where I used to work) and do it for them. <br /> <br />At first I thought something might actually happen. One Vice President asked for my bizcard, and said he'd call me to set it up. He never did. The following year, I was again able to position myself to be the first one called on at "Beat the Developers" at Lotusphere. I repeated my offer. And again the following year! This continued right up to Lotusphere 2006, the first oneat which I was again an IBM employee. This time, a few other people asked if, now that Bob was back at IBM, would the kit get fixed. Damn thing was turning into a joke, and all I wanted was for it to be fixed.  <br /> <br />I was given permission at Lotusphere 2007 to pull a project together to begin the work. Of course things had deteriorated. Whereas the 2001 version of the kit built fine (on Windows) with Visual Studio 2003, it did not work with the 2005 version. There was an extensive list of outright bugs and a fairly long list of important enhancements. To be honest, I didn't spend a lot of time on this project. But I did convince a couple of other developers to do most of the work. We engaged with the release management team to get trhough the paperwork and legal review. At Lotusphere 2008 "Beat the Developers", I "announced" that we were finally going to ship it within a few months. <br /> <br />Then, in February of 2008, I left IBM to join a Lotus Business Partner company. LSX pretty much fell off my radar. But I did notice, around early January of 2009, that the updated kit had still not shipped. EIGHT YEARS, and they were still sitting on it. Once again, for the 5th or 6th (maybe) time, I complained at "Beat the Developers, Lotusphere 2009 Edition". Brent Peters made a joke at my expense, implying that the delay had been caused by the poor quality of my code. I guess he didn't realize that virtually none of the code in the LSX Toolkit was mine. <br /> <br />But! Brent also promised that the kit would be released by Feb. 1. Whoo hoo! Light-at-end-of-tunnel! AND, light-is-not-train-coming-my-way! I forgave him for the joke.  <br /> <br />After Lotusphere, Feb. 1 came and went. Brent blogged that the date had slipped to Feb. 15, which also came and went. Buchan blogged about the delays in a way designed (successfully) to embarrass IBM. Brent stepped up in a posted reply and said he agreed, enough was enough, he was going to make sure it got out. Soon. <br /> <br />Sure enough! I read on Brent's blog last week (<a href=http://www.lotusstaffnotes.com/LotusStaffNotes/LSNblog.nsf/>http://www.LotusStaffNotes.com/LotusStaffNotes/LSNblog.nsf/) that it was REALLY READY!!! (And! he dedicated it to me. How sweet!).</a> <br /> <br />BUT! I couldn't find it on the old toolkit site (<a href=http://www.notes.net/>http://www.notes.net). Only the old one was there. But TODAY! I got the link to the page where it REALLY lives:</a> <br /><a href="http://www14.software.ibm.com/webapp/download/preconfig.jsp?id=2006-09-14+09%3A05%3A37.162620R&amp;S_TACT=104CBW71&amp;S_CMP=">http://www14.software.ibm.com/webapp/download/preconfig.jsp?id=2006-09-14+09%3A05%3A37.162620R&amp;S_TACT=104CBW71&amp;S_CMP=</a> <br /> <br />Note: This is the windows-only version, unix version to come....soon. You have to register to get the download, but it's free. <br /> <br />Phew. I'm exhausted. Eight years! And now it's here. I'm thinking I may just begin a project to revive and extend ScriptExpander with this baby, see how that goes. You can assume I will be blogging about that experience. <br /> <br />But for now, MANY thanks to: <br />&nbsp; &nbsp; &nbsp;Brent Peters, George Langlais, Scott Morris, Willie Arbuckle, Roberto Olivares, John Beck <br />and everyone else who helped get the darn thing FINALLY out the door. <br /> <br />The saga continues! This has been but the end of the beginning! <br />  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/huzzah-new-lsx-toolkit-is-posted-part-1</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/huzzah-new-lsx-toolkit-is-posted-part-1?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>New IBM-skills-centric recruiting db from BlueWave</title>
<pubDate>Thu, 12 Mar 2009 15:55:53 -0400</pubDate>
<description>
<![CDATA[ 
If you're hiring, or need to be hired, check out the recruitment site that Paul Mooney just announced: http://www.pmooney.net/pmooney/pmooneynet.nsf/d6plinks/PMOY-7Q3R54 Cool idea! ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/new-ibm-skills-centric-recruiting-db-from-bluewave</link>
<category></category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/new-ibm-skills-centric-recruiting-db-from-bluewave?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/new-ibm-skills-centric-recruiting-db-from-bluewave</guid>
<content:encoded><![CDATA[  <br />If you're hiring, or need to be hired, check out the recruitment site that Paul Mooney just announced: <br /><a href="http://www.pmooney.net/pmooney/pmooneynet.nsf/d6plinks/PMOY-7Q3R54">http://www.pmooney.net/pmooney/pmooneynet.nsf/d6plinks/PMOY-7Q3R54</a> <br /> <br />Cool idea!  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/new-ibm-skills-centric-recruiting-db-from-bluewave</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/new-ibm-skills-centric-recruiting-db-from-bluewave?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>&quot;Separation Agreement&quot;, or Spawn of the Devil??</title>
<pubDate>Tue, 10 Mar 2009 19:53:16 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! It's happened to me a couple of times, maybe it's happened to you too: You get "terminated" from your job (downsized, laid off, made redundant...). There are lots of names for it, b ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/separation-agreement-or-spawn-of-the-devil</link>
<category>unemployment</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/separation-agreement-or-spawn-of-the-devil?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/separation-agreement-or-spawn-of-the-devil</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />It's happened to me a couple of times, maybe it's happened to you too: You get "terminated" from your job (downsized, laid off, made redundant...). There are lots of names for it, but no matter what they call it, the situation totally sucks. Especially if it was a surprise (as it most often is).  <br /> <br />Usually the "termination" conversation includes some explanation of what the company will "do for you". Sometimes there's "severance" pay (basically, they continue to pay your salary for some period of time while you start looking for another job), sometimes benefits continuation. Sometimes there's nothing (nada, zip, zilch, bupkis, gar nicht, zero, don't let the door hit you in the butt on your way out).  <br /> <br />But maybe you have rights. Maybe that's not really the end of it. Maybe there's stuff you can negotiate. <br /> <br />I thought I'd summarize some of the things I've learned here and there, over the years, from my own experience and from that of my friends. However, in the spirit of full disclosure, some caveats: <br /> <br />&nbsp; &nbsp; &nbsp;- I am NOT a lawyer, don't want to be, don't play one on TV <br />&nbsp; &nbsp; &nbsp;- I am making every effort to be clear and accurate in this post, but I could be making unintentional mistakes <br />&nbsp; &nbsp; &nbsp;- If you find yourself in this situation with questions, ASK A REAL LAWYER! It can be expensive ($300 per hour and up is common), but I gurarantee you, it will be worth it. <br />&nbsp; &nbsp; &nbsp;- The laws governing employement, separation and contracts are different EVERYWHERE: state by state, and for sure country by country. I am not a scholar of them all, take what I say with a very large grain of salt <br />&nbsp; &nbsp; &nbsp;- My observations are probably very US-centric. The EU has VERY different rules and regulations, as, probably, does the rest of the world <br /> <br />And another important caveat: <br /> <br />&nbsp; &nbsp; &nbsp;- I am not referring here, either implicitly or explicitly to any company from which I may or may not have been separated, either voluntarily or involuntarily, at any time in the past, present or future. Got that? <br /> <br />So, one day you get a phone call or an office visit from your manager, and you find yourself jobless. Sometimes they give you time to "find another job in the company" (that's not uncommon for large companies, rather rare in smaller ones). My attitude about that is that it's a rather humane way to handle the situation, and (if your attitude about the company hasn't been poisoned by the job action), you should think about taking advantage of it. If you decide that you want OUT, by all means use the time to start a job search out in the wild. Either way, you'll want to update your resume/CV. I strongly suggest you find a friend or a relative or an outplacement consultant (sometimes provided for you for free by the company) to help you pull it together, check your spelling and grammar, etc. <br /> <br />Let's say, though, that at some point you're really out. You probably get some kind of "exit interview", and you probably are given a "separation agreement", which they'll ask you to sign. DO NOT SIGN IT RIGHT AWAY!!!!!!!! In the United States, by Federal law, you have 21 days to decide to accept or reject this agreement, or to negotiate for changes. You don't have to sign it immediately, regardless of what they tell you. If you are over (i think, again CONSULT A LAWYER IF YOU HAVE QUESTIONS) 45, you have longer to make up your mind. <br /> <br />So, chill. Think about the paper and study it carefully, What are they asking you to agree to, and what are they offering you in compensation for said agreement? <br /> <br />Of course every company will have their own version of this document. Some are reasonable and fair, many are one-sided (not in your favor) and unreasonable. YOU get to decide which category you think the "agreement" falls into. Read it CAREFULLY. There are many implications and commitments, both express and implied in the document. You need to understand them all. Some common provisions I've encountered go like this: <br /> <br />&nbsp; &nbsp; &nbsp;1. You agree not to sue the company for wrongful termination, or, basically, anything else that might have happened in the past. This is the "release" part of the document. If you sign it, and later discover that you were the victim of (for example) age discrimination (VERY illegal in the US), it might be too late for you to do anything about it. Consider carefully! Generally this provision is not mutual. I.e., you agree not to sue them, but they usually won't offer not to sue you. NEGOTIATE! Ask for the provision to be mutual. What have you got to lose? <br /> <br />&nbsp; &nbsp; &nbsp;2. They bribe you. This is the part where they offer you some money to sign the agreement. They WANT your promise that you won't sue them for anything, and they are willing to pay (something) for it. The amount varies. It might be based on length of service, it might be N weeks of salary (and they'll withhold taxes and other stuff, just like in a normal paycheck), or maybe a lump sum. Note Well: this is not the same as "severance", where they continue your salary while you try to find another job. The difference is IMPORTANT for things like unemployment benefits. If you should apply for unemployment (and why not?), you are (in most states, but of course it can vary, so DOUBLE CHECK) required to report severance pay and any other income you may get, and this will probably reduce your payment from your state. The money promised in exchange for the "release" may NOT count as "income" for unemployment purposes (DOUBLE CHECK IT!). If you think the amount they're offering you is unfair, then SAY SO, and ask for more. What are they going to do, fire you? <br /> <br />&nbsp; &nbsp; &nbsp;3. NEGOTIATE, if you feel like it. Sometimes a company will agree to continue your medical bennies, or life insurance for some amount of time after "separation". That can be worth a lot of money to you. <br /> <br />&nbsp; &nbsp; &nbsp;4. If you've got accumulated vacation time when you get "terminated", they owe you that RIGHT AWAY, again by Federal law (in the US). While the separation payment discussed above is generally contingent on you signing the separation agreement (you no sign, they no pay), by law they OWE you the money for your accumulated vacation time, and they're supposed to give it to you on your last day of work. They can NOT hold that over your head to try to get you to sign the agreement. <br /> <br />&nbsp; &nbsp; &nbsp;5. The agreement will probably reiterate a confidentiality provision that you probably already signed (often when you started working for them). Get a copy of the "employment agreement" that you probably signed when you took the job, and you thought you'd be there forever, and that everything would be great and nothing bad would ever happen. Most likely, there's language in there that binds you to those provisions after you no longer work there. There is likely nothing you can do about that (but DOUBLE CHECK with a lawyer if you have questions). Other provisions that you may still be required to observe: non-compete (this is now illegal in some states, and will be in more over the next couple of years, but if you signed it, and if it was legal at the time you did, then you have to at least worry that if you violate it, they can sue you); non-disparagement (you agree not to say or write anything nasty about your soon-to-be former company). This last one is particularly insidious, IMHO. There is no reason (again, IMHO, but the company may or may not agree) that this provision should not be mutual. If you agree to only say nice things about them (or nothing), shouldn't they agree to not say nasty things about you? I would think so. NEGOTIATE! Of course, certain kinds of nasty sayings/writings done in public can violate the libel and/or slander laws, so BE CAREFUL! <br /> <br />The non-compete clauses are particularly evil, IMHO. They can drastically limit the range of places you can try to get a new job. The language in the separation agreement is probably very vague about what companies you can or can't go to work for, and what constitutes "competitive activity". How do you know? The real (legal) answer is that you don't. The one who gets to decide is a judge, and you may have to spend a lot of money before you get to tell a judge your side of the story. Companies suing former employees based on a non-compete agreement is rare, but it happens. Some companies may ask to see your former companies' non-compete provisions, and may even decline to employ you based on it, because their lawyers are fraidy-cats. Probably not much you can do about that, except maybe refuse to agree to a non-compete next time. <br /> <br />Note that non-compete clauses, whether they exist in your employee agreement (what you probably signed when you started work and everything was rosy) or your separation agreement, are completely separate from confidentiality promises. You still can't take secrets or intellectual property that you may know about from your now-former job, and give/reveal them to your next employer.  <br /> <br />&nbsp; &nbsp; &nbsp; 6. Governing law. There may, or may not, be a paragraph in the separation agreement specifying the state or other jurisdiction under whose laws the agreement will be interpreted in case of later disagreement. Generally speaking, your now-former company will probably pick the state that their headquarters (and most of their lawyers) is in. If you live and work in that same state, then this is probably not controversial. However, if you worked in (and got paid in) another state, you may want to ask the company to change this provision so that the "governing law" is the law of YOUR state, not theirs. They may or may not agree, but it can be worth asking. Remember, they WANT you to sign, or they wouldn't be offering you a bribe to do it. As a practical matter, it usually means that if they decide to sue you (we hope that will never happen) or you them (likewise), it has to happen in your state. And that can be a whole lot more convenient (cheaper) that having to travel to and/or hire a lawyer in their state. <br /> <br />So. This post is already overlong, but it covers most of the main points. Again, don't take my word for ANYTHING, get a lawyer if you have questions. You may well not need to pay said lawyer for more than 1 or 2 hours of his/her time, and that investment could easily save you lots more money and/or grief later. If you do decide to consult a lawyer, get one who is a specialist in employment law, it's a well recognized sub-specialty. Also remember that getting fired/laid off is an emotionally traumatic experience, even if you're not surprised when it happens. You will feel very vulnerable, and frankly, some companies bank on that to manipulate you into signing an agreement that is NOT necessarily in your best interest.  <br /> <br />Good luck! <br />Stay warm, it's COLD out there!  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/separation-agreement-or-spawn-of-the-devil</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/separation-agreement-or-spawn-of-the-devil?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>Manipulating Notes preferences via CSS (8.5)</title>
<pubDate>Sat, 14 Feb 2009 21:32:55 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! I was going to write a blog post about how the notes.css file that many of us found and modified in version 8.0 (for me, I wanted to make the unread document color in Inbox red agai ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/manipulating-notes-preferences-via-css-8.5</link>
<category>Notes 8.5</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/manipulating-notes-preferences-via-css-8.5?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/manipulating-notes-preferences-via-css-8.5</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br />I was going to write a blog post about how the notes.css file that many of us found and modified in version 8.0 (for me, I wanted to make the unread document color in Inbox red again) has disappeared (as a standalone file) from the 8.5 install tree. When I asked someone at Lotus about it, was told that as part of the performance enhancements in 8.5, many individual files were collected together into JARs, for faster loading, and notes.css was one of these. <br /> <br />So, I was going to figure out where the notes.css file now lives, and post about it. However, in scanning <a href=http://www.planetlotus.org>PlanetLotus</a> tonight, I saw <a href="http://www.chrissparshott.com/2009/02/change-lotus-notes-v85-unread-email-to-red/">this post</a> by Chris Sparshott, who has already done all the legwork, saving me some tmie. Thanks Chris!! (PlanetLotus strikes again!)  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/manipulating-notes-preferences-via-css-8.5</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/manipulating-notes-preferences-via-css-8.5?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>The difference between &quot;Duh!&quot; and &quot;D&#8217;oh!&quot; (It got around to me...) - revised</title>
<pubDate>Sat, 31 Jan 2009 08:19:31 -0400</pubDate>
<description>
<![CDATA[ 
Greetings Geeks! Here's the difference: "Duh" is a shorthand label that means "that was obvious". "D'oh!" tends to mean either "that was stupid", or "that s ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/the-difference-between-duh-and-doh-it-got-around-to-me...-revised</link>
<category>Binary Tree</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/the-difference-between-duh-and-doh-it-got-around-to-me...-revised?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/the-difference-between-duh-and-doh-it-got-around-to-me...-revised</guid>
<content:encoded><![CDATA[ Greetings Geeks! <br /> <br />Here's the difference: "Duh" is a shorthand label that means "that was obvious". <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"D'oh!" tends to mean either "that was stupid", or "that sure was a surprise!" <br /> <br />In a surprising (to me) phone call from my manager at Binary Tree on Thursday (29th), I was informed that I was to be laid off from the company.  <br /> <br />Yesterday (30th) was my last day of employment at Binary Tree. <br /> <br />Because of the current economic climate, I've decided to pursue contracting opportunities for a while. I was able to re-create Looseleaf Software online (love that Internet!), but no web site yet (some things take longer than others). Got some nibbles already, I'm hopeful this will work out well. <br /> <br />Thanks to everyone who has already sent me messages of support, I really appreciate it.  <br /> <br />Stay warm, it's COLD out there! <br />  ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/the-difference-between-duh-and-doh-it-got-around-to-me...-revised</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/the-difference-between-duh-and-doh-it-got-around-to-me...-revised?opendocument&amp;comments</wfw:comment>
</item>
<item>
<title>So I&#8217;m a political leftist. So sue me (How I celebrated Obama&#8217;s inauguration)</title>
<pubDate>Mon, 26 Jan 2009 18:58:59 -0400</pubDate>
<description>
<![CDATA[ 
Greetings, Geeks! Back from Lotusphere09 (my 16th!) and mostly caught up on my huge sleep deficit. It was a good conference, maybe I'll post a summary later. This post, however, is about radicalis ...
 ]]>
</description>
<link>http://www.bobzblog.com/tuxedoguy.nsf/dx/so-im-a-political-leftist.-so-sue-me-how-i-celebrated-obamas-inauguration</link>
<category>Lotusphere</category>
<dc:creator>Bob Balaban</dc:creator>
<comments>http://www.bobzblog.com/tuxedoguy.nsf/dx/so-im-a-political-leftist.-so-sue-me-how-i-celebrated-obamas-inauguration?opendocument&amp;comments</comments>
<guid isPermaLink="true">http://www.bobzblog.com/tuxedoguy.nsf/dx/so-im-a-political-leftist.-so-sue-me-how-i-celebrated-obamas-inauguration</guid>
<content:encoded><![CDATA[ Greetings, Geeks! <br /> <br /> Back from Lotusphere09 (my 16th!) and mostly caught up on my huge sleep deficit. It was a good conference, maybe I'll post a summary later. <em><br /> <br /> This </em>post, however, is about radicalism, politics, political radicalism, who's right, and who's, well, left. <br /> <br /> By way of background, I began studying Marxism in college. I'd been a bit of a "60's radical" in high school (nothing violent or illegal, but some friends and I did close down our high school for 3 days to protest Nixon's illegal (and probably war-criminal) invasion of Cambodia in 1970. Oh yeah, we were protesting the killing of 4 students by Ohio National Guard at Kent State University (the student protesters who survived were arrested for rioting, the National Guardsmen who shot live ammo at college students, killing 4 of them, were never prosecuted). And oh yeah, we were also protesting The Draft. <br /> <br /> Studying (and I mean <em>studying</em>, not just reading a book or a few articles on it) Marxism was enlightening, a whole new (to me) way of explaining Capitalism. No, "Das Kapital" is NOT about Communism (or even Socialism -- how many of you know the difference?), it's about Capitalism, that's why he picked that title for it.... Understanding something (I'd never claim to be an expert) of Marxism also helped me in my studies of Chinese history, especially 20th Century history. I carried all that into grad school and studied it all some more. Great stuff (no, I am NOT going to try to convince you that Marxism is cool. If you want to find out for yourself, go study it). <br /> <br /> By the way -- for you science-oriented geeks, go get yourself a copy of Friederich Engels' "Dialectics of Nature". It's very readable if you get a good translation. See if you can spot the errors. Is he related to our own Gregory? I keep forgetting to ask.... <br /> <br /> So, politically, I'm probably significantly more "left" than most of you. Mostly I keep it to myself. But pal and colleague <a href=http://www.lotusgeek.com/><span style="text-decoration:underline">Rocky Oliver</span></a> and I came up with what we thought was a cool and unique way to celebrate the new President's inaugural last Tuesday. <br /> <br /> Both of us were, of course, at Lotusphere. We had a session ("Lotus Notes and Domino Mythbusters") scheduled for 11:15am on the 20th, the day the chief executiveshiphood of the United States changes hands every 4 years. You can imagine, given my political and philosophical leanings, that I was very happy to see George Bush vacate the office, and also pretty happy that a SMART guy was taking over. True, he tends to be a little (a lot?) more "centrist" than I am, but after 8 Bushed years, I can certainly live with that. <br /> <br /> So Rocky and I delivered our session starting at 11:15. The session was scheduled for an hour, and we knew that (by law) the previous President's term ends at noon. We went through a bunch of techie "myths" about Notes, explaining each in some detail, and pronouncing "True", "False" or "Weasel" on each one. For those who are wondering about the cement truck, YES it IS possible to make one disappear, IF you have enough dynamite. <br /> <br /> Having considered the session schedule the night before, we'd added one final "myth" to our list. We lucked out, the timing was <em>perfect!</em> &nbsp;We finished the last Notes myth at 2 minutes to 12. We hit the next slide, announced that Bush had only 2 more minutes to be President (there was a cheer from the audience of about 300), and read it out: "Myth: A Black man will never be President of the United States". <br /> <br /> We both shouted "FALSE!" and cut the big screen over to a live TV feed on CNN.com, JUST in time to see President Obama begin his inaugural address. I'll also note, for the record, that this was the first time that either Rocky or I had ever finished a session early. <br /> <br /> A bunch of people left to go get lunch, but somewhere around 50 stayed to watch. The video and the sound were both good. The speech itself was, IMHO, terrific. I was tracking in a pleased but more or less normal emotional state, until I heard him say somewhere in there: <br /> <br /> "We will restore science to its rightful place, and wield technology's wonders to raise health care's quality and lower its cost. We will harness the sun and the winds and the soil to fuel our cars and run our factories. And we will transform our schools and colleges and universities to meet the demands of a new age. All this we can do. And all this we will do." <br /> <br /> After the presidential horrors of the last 8 years, this sounded so GOOD, I did choke up a little. <br /> <br /> We turned the feed off at the end of the speech, and I saw more than a couple of people in the audience wiping eyes. One person said to me, "I've never cried at a Lotusphere session before!" I relate to that, though I have, in the past, cried at some of my own Lotusphere presentations.... :-) <br /> <br /> I have to say, in closing, that I did do one thing that I possibly should not have done, because it was kind of unprofessional. However, I refuse to apologize for it. At one point during Obama's speech, the camera cut to George Bush for a few seconds, and I flipped him off. Gave him the finger. Whispered softly the words that usually go with that particular gesture. I am NOT sorry. I MEANT it, it was my session (half mine, anyway), the session was over anyway, and this was a BIG moment, for me and (regardless of how they may feel about it) for all Americans. One person did complain in the session evaluations. A friend said privately to me that he thought it was disrespectful. I AGREE! It WAS! It was SUPPOSED to be, otherwise what would be the point of doing it? It will not surprise anyone who knows me, or anyone who has read this far, that I have zero respect for George W. Bush, and I don't care who knows it. <br /> <br /> Links: <span style="text-decoration:underline"><br /> </span><a href=http://www.cnn.com/2009/POLITICS/01/20/obama.politics/index.html><span style="text-decoration:underline">Text of Obama's speech</span></a> <span style="text-decoration:underline"><br /> </span><a href="http://www.youtube.com/watch?v=VjnygQ02aW4"><span style="text-decoration:underline">YouTube video</span></a> (watch Supreme Court Chief Justice Roberts screw up the oath of office...painful) <br /> Here's a PDF of the MythBusters presentation:<span style="text-decoration:underline"> <a href="http://www.bobzblog.com/tuxedoguy.nsf/dx/BP114.pdf/$file/BP114.pdf" title="BP114.pdf"BP114.pdf/>BP114.pdf</a><br /> <br /> </span><a href="http://search.barnesandnoble.com/booksearch/results.asp?WRD=karl+marx"><span style="text-decoration:underline">Barnes &amp; Noble page showing many books by/about Karl Marx</span></a> <span style="text-decoration:underline"><br /> </span><a href="http://search.barnesandnoble.com/Dialectics-of-Nature/Friedrich-Engels/e/9780717800483/?itm=10"><span style="text-decoration:underline">Barnes &amp; Noble page on Engels' "Dialectics of Nature"</span></a> Highly recommended (though I am not familiar with this particular translation) <br /> <br /> REMINDER: The opinions expressed in this blog are my own, and do not necessarily represent those of my current employer, past employers, nor of the organization hosting this site. My opinions on this particular topic are probably fairly similar to those of my parents, my spouse, my children, and several of my friends. They, however, are all perfectly capable of speaking for themselves.   ]]></content:encoded>
<wfw:commentRss> http://www.bobzblog.com/tuxedoguy.nsf/dxcomments/so-im-a-political-leftist.-so-sue-me-how-i-celebrated-obamas-inauguration</wfw:commentRss>
<wfw:comment> http://www.bobzblog.com/tuxedoguy.nsf/dx/so-im-a-political-leftist.-so-sue-me-how-i-celebrated-obamas-inauguration?opendocument&amp;comments</wfw:comment>
</item>
</channel></rss>
