<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dossy&#039;s Blog&#187; Tcl</title>
	<atom:link href="http://dossy.org/category/tcl/feed/" rel="self" type="application/rss+xml" />
	<link>http://dossy.org</link>
	<description>Everything that comes out of Dossy, from the strange to the banal.</description>
	<lastBuildDate>Wed, 18 Jan 2012 16:42:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Getting ActiveState&#8217;s &#8220;teacup&#8221; working on MacOS X</title>
		<link>http://dossy.org/2009/10/getting-activestates-teacup-working-on-macos-x/</link>
		<comments>http://dossy.org/2009/10/getting-activestates-teacup-working-on-macos-x/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 19:31:16 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Geeking out]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/?p=842</guid>
		<description><![CDATA[ActiveState has created a Tcl Extension Archive tool called teacup which simplifies the installation of binary extensions to Tcl. It&#8217;s included with ActiveTcl, but if you&#8217;re using Tcl from MacPorts and want to use teacup, it&#8217;s fairly easy: 1. Download teacup for MacOS X The teacup binary can be downloaded from this location: http://teapot.activestate.com/entity/name/teacup/index Here [...]
Related posts:<ol>
<li><a href='http://dossy.org/2005/08/activestate-adds-expect-for-windows-to-activetcl/' rel='bookmark' title='ActiveState Adds Expect for Windows to ActiveTcl'>ActiveState Adds Expect for Windows to ActiveTcl</a></li>
<li><a href='http://dossy.org/2008/10/tivo-hacking-getting-a-linksys-wusb54g-working/' rel='bookmark' title='TiVo Hacking: Getting a Linksys WUSB54G working'>TiVo Hacking: Getting a Linksys WUSB54G working</a></li>
<li><a href='http://dossy.org/2009/06/getting-adaptec-afacli-working-on-ubuntu/' rel='bookmark' title='Getting Adaptec afacli working on Ubuntu'>Getting Adaptec afacli working on Ubuntu</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>ActiveState has created a <a href="http://wiki.tcl.tk/17340">Tcl Extension Archive</a> tool called <a href="http://wiki.tcl.tk/17305">teacup</a> which simplifies the installation of binary extensions to Tcl.  It&#8217;s included with ActiveTcl, but if you&#8217;re using Tcl from <a href="http://www.macports.org/">MacPorts</a> and want to use teacup, it&#8217;s fairly easy:</p>
<h3>1. Download teacup for MacOS X</h3>
<p>The teacup binary can be downloaded from this location:</p>
<ul>
<li><a href="http://teapot.activestate.com/entity/name/teacup/index">http://teapot.activestate.com/entity/name/teacup/index</a></li>
</ul>
<p>Here is a <a href="http://teapot.activestate.com/application/name/teacup/ver/8.5.7.2.291420/arch/macosx-universal/file.exe">direct link to the latest teacup binary</a>.  The file is named <tt>file.exe</tt> &#8212; simply rename that to <tt>teacup</tt> and put it in <tt>/usr/local/bin</tt> or another convenient place in your <tt>$PATH</tt>.</p>
<h3>2. Create the installation repository</h3>
<p>You will need an installation repository where teacup can store its data locally.  The default location is <tt>/Library/Tcl/teapot</tt> and you can create it like this:</p>
<blockquote>
<pre><code>$ <b>sudo teacup create</b>
Repository @ /Library/Tcl/teapot
    Created</code></pre>
</blockquote>
<h3>3. Patch MacPorts tclsh to handle teapot repositories</h3>
<blockquote>
<pre><code>$ <b>sudo teacup setup /opt/local/bin/tclsh</b>
Looking at tcl shell /opt/local/bin/tclsh ...
  Already able to handle Tcl Modules.
  Already has the platform packages.
  Patching: Adding code to handle teapot repositories ...
Done</code></pre>
</blockquote>
<h3>4. Link teacup to MacPorts tclsh</h3>
<blockquote>
<pre><code>$ <b>sudo teacup link make /Library/Tcl/teapot /opt/local/bin/tclsh</b>
Ok</code></pre>
</blockquote>
<p>That&#8217;s it!  You&#8217;re done.  You should now be able to list available packages within TEA using <tt>teacup list</tt> and install them using <tt>sudo teacup install "packagename"</tt>.</p>
<p>I&#8217;ve tested this on MacOS X 10.6.1 Snow Leopard with Tcl 8.5.7 from MacPorts.</p>
<p>Tags: <a href="http://technorati.com/tag/HOWTO" rel="tag">HOWTO</a>, <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/ActiveState" rel="tag">ActiveState</a>, <a href="http://technorati.com/tag/TEA" rel="tag">TEA</a>, <a href="http://technorati.com/tag/teacup" rel="tag">teacup</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2005/08/activestate-adds-expect-for-windows-to-activetcl/' rel='bookmark' title='ActiveState Adds Expect for Windows to ActiveTcl'>ActiveState Adds Expect for Windows to ActiveTcl</a></li>
<li><a href='http://dossy.org/2008/10/tivo-hacking-getting-a-linksys-wusb54g-working/' rel='bookmark' title='TiVo Hacking: Getting a Linksys WUSB54G working'>TiVo Hacking: Getting a Linksys WUSB54G working</a></li>
<li><a href='http://dossy.org/2009/06/getting-adaptec-afacli-working-on-ubuntu/' rel='bookmark' title='Getting Adaptec afacli working on Ubuntu'>Getting Adaptec afacli working on Ubuntu</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2009/10/getting-activestates-teacup-working-on-macos-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOLserver in Google&#8217;s Summer of Code 2009</title>
		<link>http://dossy.org/2009/03/aolserver-in-googles-summer-of-code-2009/</link>
		<comments>http://dossy.org/2009/03/aolserver-in-googles-summer-of-code-2009/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 16:39:32 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[AOLserver]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/?p=745</guid>
		<description><![CDATA[Are you a student that meets Google&#8217;s eligibility criteria, who is interested in contributing to an Open Source project this summer? Google&#8217;s Summer of Code 2009 is on, and once again, the Tcl community has been accepted as a mentoring organization, which includes AOLserver. Students can apply until the deadline of 19:00 UTC on April [...]
Related posts:<ol>
<li><a href='http://dossy.org/2007/02/nsjsapi-serverside-js-in-aolserver/' rel='bookmark' title='nsjsapi, server-side JS in AOLserver'>nsjsapi, server-side JS in AOLserver</a></li>
<li><a href='http://dossy.org/2007/05/aolserver-4010-vmware-appliance-and-aolserver-conference/' rel='bookmark' title='AOLserver 4.0.10 VMware appliance, and AOLserver Conference'>AOLserver 4.0.10 VMware appliance, and AOLserver Conference</a></li>
<li><a href='http://dossy.org/2006/06/aolserver-450-released-june-27-2006/' rel='bookmark' title='AOLserver 4.5.0 released June 27, 2006'>AOLserver 4.5.0 released June 27, 2006</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div style="float: left; padding-right: 10px;"><a href="http://socghop.appspot.com/"><img src="http://dossy.org/images/2009/03/gsoc-2009.jpg" alt="Google Summer of Code 2009" border="0" width="128" height="128" /></a></div>
<p>Are you a student that meets <a href="http://socghop.appspot.com/document/show/program/google/gsoc2009/faqs#student_eligibility">Google&#8217;s eligibility criteria</a>, who is interested in contributing to an Open Source project this summer?  <a href="http://socghop.appspot.com/">Google&#8217;s Summer of Code 2009</a> is on, and once again, the <a href="http://www.tcl.tk/">Tcl</a> community has been <a href="http://socghop.appspot.com/org/show/google/gsoc2009/tcltk">accepted</a> as a mentoring organization, which includes <a href="http://aolserver.com/">AOLserver</a>.</p>
<p>Students can <a href="http://socghop.appspot.com/student/apply/google/gsoc2009">apply</a> until the <strong>deadline of 19:00 UTC on April 3rd</strong>.  If you have any questions about GSoC or AOLserver&#8217;s involvement in it, please ask me!  I&#8217;ll try to help answer whatever questions you might have.</p>
<p>Good luck to all the students and mentoring organizations this summer!</p>
<p>Tags: <a href="http://technorati.com/tag/Google%20Summer%20of%20Code%202009" rel="tag">Google Summer of Code 2009</a>, <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/AOLserver" rel="tag">AOLserver</a>, <a href="http://technorati.com/tag/open source" rel="tag">open source</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2007/02/nsjsapi-serverside-js-in-aolserver/' rel='bookmark' title='nsjsapi, server-side JS in AOLserver'>nsjsapi, server-side JS in AOLserver</a></li>
<li><a href='http://dossy.org/2007/05/aolserver-4010-vmware-appliance-and-aolserver-conference/' rel='bookmark' title='AOLserver 4.0.10 VMware appliance, and AOLserver Conference'>AOLserver 4.0.10 VMware appliance, and AOLserver Conference</a></li>
<li><a href='http://dossy.org/2006/06/aolserver-450-released-june-27-2006/' rel='bookmark' title='AOLserver 4.5.0 released June 27, 2006'>AOLserver 4.5.0 released June 27, 2006</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2009/03/aolserver-in-googles-summer-of-code-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple &#8220;google for&#8221; Tcl script</title>
		<link>http://dossy.org/2008/11/a-simple-google-for-tcl-script/</link>
		<comments>http://dossy.org/2008/11/a-simple-google-for-tcl-script/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 22:46:04 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Geeking out]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/2008/11/a-simple-google-for-tcl-script/</guid>
		<description><![CDATA[I make extensive use of Google throughout the day and I&#8217;ve always got &#8220;g&#8221; set up as the keyword for a Quick Search in Firefox. However, I also spend a lot of time at shell prompts, and sometimes I don&#8217;t want to bounce to a browser just to Google for something. So, tonight, I wrote [...]
Related posts:<ol>
<li><a href='http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/' rel='bookmark' title='A simple MySQL client in Tcl/Tk using mysqltcl'>A simple MySQL client in Tcl/Tk using mysqltcl</a></li>
<li><a href='http://dossy.org/2007/09/google-reader-finally-gets-searchwithinsubscriptions/' rel='bookmark' title='Google Reader (finally) gets search-within-subscriptions'>Google Reader (finally) gets search-within-subscriptions</a></li>
<li><a href='http://dossy.org/2008/02/adding-an-unsubscribe-button-to-google-reader-using-greasemonkey/' rel='bookmark' title='Adding an &#8220;Unsubscribe&#8221; button to Google Reader using Greasemonkey'>Adding an &#8220;Unsubscribe&#8221; button to Google Reader using Greasemonkey</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I make extensive use of Google throughout the day and I&#8217;ve always got &#8220;g&#8221; set up as the keyword for a Quick Search in Firefox. However, I also spend a lot of time at shell prompts, and sometimes I don&#8217;t want to bounce to a browser just to Google for something.</p>
<p>So, tonight, I wrote a small <a href="http://dossy.org/files/google.txt">Tcl script that lets me &#8220;google for&#8221;</a> at the prompt. Just save the previous link and rename it to &#8220;<tt>google</tt>&#8221; and move it somewhere in your PATH like <tt>/usr/local/bin</tt>, then make it executable with <tt>chmod 755</tt>.</p>
<p>The script requires Tcl with tDOM installed, as well as Tidy&#8211;both of these things are installed out-of-the-box on MacOS X 10.5 Leopard.</p>
<p>Once you get the script installed, you can do something like this:</p>
<div style="text-align: center;">
  <img src="http://dossy.org/images/2008/11/google-for-screenshot-1.png" width="420" height="215" alt="'google for' screenshot" />
</div>
<p>If you notice, for Google search queries that have a special result like the one above, the script displays it separately before the results. The script also emits the search query URL so you can just Control-click on it in Terminal and then select &#8220;Open URL&#8221; and have it pop up in your browser, which also works for any of the search result URLs.</p>
<p>I don&#8217;t know if anyone else would find this script useful, but it&#8217;s already saved me a ton of time&#8211;especially when I&#8217;m on a slow 64 kb/s GPRS connection like I am this evening. Either way, I&#8217;m releasing this script into the public domain.</p>
<p>Tags: <a href="http://technorati.com/tag/Google" rel="tag">Google</a>, <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/open%20source" rel="tag">open source</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/' rel='bookmark' title='A simple MySQL client in Tcl/Tk using mysqltcl'>A simple MySQL client in Tcl/Tk using mysqltcl</a></li>
<li><a href='http://dossy.org/2007/09/google-reader-finally-gets-searchwithinsubscriptions/' rel='bookmark' title='Google Reader (finally) gets search-within-subscriptions'>Google Reader (finally) gets search-within-subscriptions</a></li>
<li><a href='http://dossy.org/2008/02/adding-an-unsubscribe-button-to-google-reader-using-greasemonkey/' rel='bookmark' title='Adding an &#8220;Unsubscribe&#8221; button to Google Reader using Greasemonkey'>Adding an &#8220;Unsubscribe&#8221; button to Google Reader using Greasemonkey</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2008/11/a-simple-google-for-tcl-script/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tcl is alive and well with Tcl 8.5</title>
		<link>http://dossy.org/2008/01/tcl-is-alive-and-well-with-tcl-85/</link>
		<comments>http://dossy.org/2008/01/tcl-is-alive-and-well-with-tcl-85/#comments</comments>
		<pubDate>Tue, 15 Jan 2008 21:25:52 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/archives/000580.html</guid>
		<description><![CDATA[As much as people wonder &#8220;who still uses Tcl?&#8221; or &#8220;what the heck is Tcl?&#8221; &#8230; it&#8217;s still alive and well and under steady new development. The long-awaited release of Tcl 8.5 happened this past December 20, 2007. You can download it from here. The discussion on Slashdot about it shows that there&#8217;s still a [...]
Related posts:<ol>
<li><a href='http://dossy.org/2008/12/yes-im-still-alive/' rel='bookmark' title='Yes, I&#8217;m still alive'>Yes, I&#8217;m still alive</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tcl.tk/"><img height="49" alt="Tcl logo" src="http://static.dossy.org/images/2008/01/tcl-logo-116x49.png" width="116" align="right" border="0" / / /></a></p>
<p>As much as people wonder &#8220;who still uses <a href="http://www.tcl.tk/">Tcl</a>?&#8221; or &#8220;what the heck is <a href="http://www.tcl.tk/">Tcl</a>?&#8221; &#8230; it&#8217;s still alive and well and under steady new development. The long-awaited <a href="http://www.tcl.tk/software/tcltk/8.5.tml">release of Tcl 8.5</a> happened this past December 20, 2007. You can <a href="http://www.tcl.tk/software/tcltk/8.5.tml">download it from here</a>.</p>
<p>The <a href="http://it.slashdot.org/article.pl?sid=07/12/22/2315246">discussion on Slashdot</a> about it shows that there&#8217;s still a lot of misinformation and outright <acronym title="Fear, Uncertainty and Doubt">FUD</acronym> being spread about Tcl, now 20 years old. Of course, the Tcl community seems to focus more on excellence in engineering than evangelism and PR, so Tcl will likely remain &#8220;<a href='http://it.slashdot.org/comments.pl?sid=397528&amp;cid=21798374'>a well-kept secret, sitting out in plain sight</a>&#8221; for the next 20 years.</p>
<p>For people who are already familiar with Tcl but would like to know what significant changes were introduced in Tcl 8.5, <a href="http://blog.cleverly.com/">Michael Cleverly</a> has <a href="http://blog.cleverly.com/permalinks/308.html">a fantastic write-up on it</a>. I highly recommend reading what he wrote if you&#8217;re looking to take advantage of Tcl 8.5&#8242;s new features.</p>
<p>Tags: <a href="http://technorati.com/tag/tcl" rel="tag">Tcl</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2008/12/yes-im-still-alive/' rel='bookmark' title='Yes, I&#8217;m still alive'>Yes, I&#8217;m still alive</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2008/01/tcl-is-alive-and-well-with-tcl-85/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple MySQL client in Tcl/Tk using mysqltcl</title>
		<link>http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/</link>
		<comments>http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/#comments</comments>
		<pubDate>Fri, 05 Oct 2007 04:19:35 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Geeking out]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/archives/000529.html</guid>
		<description><![CDATA[Yesterday, Ron Cripe emailed me asking if I knew of any simple examples of how to use Tcl/Tk with MySQL. I knew about mysqltcl and pointed him in that direction, but he said he needed an actual example on how to use it. I&#8217;ve done a lot of Tcl programming but have mostly avoided doing [...]
Related posts:<ol>
<li><a href='http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/' rel='bookmark' title='tcl-mysql-udf 0.2 and Win32 DLL binary'>tcl-mysql-udf 0.2 and Win32 DLL binary</a></li>
<li><a href='http://dossy.org/2008/11/a-simple-google-for-tcl-script/' rel='bookmark' title='A simple &#8220;google for&#8221; Tcl script'>A simple &#8220;google for&#8221; Tcl script</a></li>
<li><a href='http://dossy.org/2006/09/clientside-query-term-highlighting-demo-using-jquery/' rel='bookmark' title='Client-side query term highlighting demo using jQuery'>Client-side query term highlighting demo using jQuery</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Yesterday, Ron Cripe emailed me asking if I knew of any simple examples of how to use Tcl/Tk with MySQL. I knew about <a href="http://www.xdobry.de/mysqltcl/">mysqltcl</a> and pointed him in that direction, but he said he needed an actual example on how to use it.</p>
<p>I&#8217;ve done a lot of Tcl programming but have mostly avoided doing GUI&#8217;s with Tk, so I figured this might be a good opportunity to do some learning, myself. I quickly wrote a simple application that connects to a MySQL database, then lets you execute queries against it and displays the results. You can download it here:</p>
<ul>
<li><a href="http://static.dossy.org/images/2007/10/mysqltcl-client.tcl.txt">mysqltcl-client.tcl.txt</a> (5KB)</li>
</ul>
<p>It&#8217;s named .txt to make it easier to download&#8211;just rename it to only .tcl (removing the .txt) once you&#8217;ve saved it.</p>
<p>When you start the app, it presents you with a simple login dialog:</p>
<p align="center"><img height="276" alt="mysqltcl-client login dialog" src="http://static.dossy.org/images/2007/10/mysqltcl-client-login-266x276.png" width="266" border="0" /></p>
<p>Enter your username and password, change the host, port and database values if necessary, and press Enter or click the Connect button. If all goes well, the login dialog will go away and the query window will appear:</p>
<p align="center"><img height="359" alt="mysqltcl-client query dialog" src="http://static.dossy.org/images/2007/10/mysqltcl-client-query-390x359.png" width="390" border="0" /></p>
<p>This is an example of what the query dialog looks like after executing a <tt>SHOW TABLES</tt> query. Very simple, not terribly exciting, but what do you want for a 5KB, 181-line Tcl script?</p>
<p>If you have Tcl, Tk and mysqltcl installed, go ahead and grab a copy of this script and check it out. If you have questions about the code, just ask: I&#8217;ll try my best to answer them.</p>
<p>Tags: <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/Tk" rel="tag">Tk</a>, <a href="http://technorati.com/tag/MySQL" rel="tag">MySQL</a>, <a href="http://technorati.com/tag/programming" rel="tag">programming</a>, <a href="http://technorati.com/tag/open%20source" rel="tag">open source</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/' rel='bookmark' title='tcl-mysql-udf 0.2 and Win32 DLL binary'>tcl-mysql-udf 0.2 and Win32 DLL binary</a></li>
<li><a href='http://dossy.org/2008/11/a-simple-google-for-tcl-script/' rel='bookmark' title='A simple &#8220;google for&#8221; Tcl script'>A simple &#8220;google for&#8221; Tcl script</a></li>
<li><a href='http://dossy.org/2006/09/clientside-query-term-highlighting-demo-using-jquery/' rel='bookmark' title='Client-side query term highlighting demo using jQuery'>Client-side query term highlighting demo using jQuery</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>tcl-mysql-udf 0.2 and Win32 DLL binary</title>
		<link>http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/</link>
		<comments>http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/#comments</comments>
		<pubDate>Fri, 31 Aug 2007 05:02:36 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Geeking out]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/archives/000503.html</guid>
		<description><![CDATA[Last week, I released some code that would enable MySQL to evaluate Tcl scripts as a stored function, which I called tcl-mysql-udf. My friend Steve asked if I could prepare a Win32 DLL binary for him, so I worked on that tonight and am releasing version 0.2, along with the DLL: Source: tcl-mysql-udf-0.2.tar.gz (328K) Win32 [...]
Related posts:<ol>
<li><a href='http://dossy.org/2007/08/evaluate-tcl-scripts-as-a-udf-in-mysql/' rel='bookmark' title='Evaluate Tcl scripts as a UDF in MySQL'>Evaluate Tcl scripts as a UDF in MySQL</a></li>
<li><a href='http://dossy.org/2006/02/storing-binary-data-in-mysql-with-aolserver/' rel='bookmark' title='Storing binary data in MySQL with AOLserver'>Storing binary data in MySQL with AOLserver</a></li>
<li><a href='http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/' rel='bookmark' title='A simple MySQL client in Tcl/Tk using mysqltcl'>A simple MySQL client in Tcl/Tk using mysqltcl</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Last week, I <a href="http://dossy.org/archives/000496.html">released some code</a> that would enable MySQL to evaluate Tcl scripts as a stored function, which I called <strong>tcl-mysql-udf</strong>. My friend Steve asked if I could prepare a Win32 DLL binary for him, so I worked on that tonight and am releasing version 0.2, along with the DLL:</p>
<ul>
<li>Source: <a href="http://static.panoptic.com/tcl-mysql-udf/tcl-mysql-udf-0.2.tar.gz">tcl-mysql-udf-0.2.tar.gz</a> (328K)</li>
<li>Win32 DLL: <a href="http://static.panoptic.com/tcl-mysql-udf/tcl-mysql-udf-0.2.dll.zip">tcl-mysql-udf-0.2.dll.zip</a> (144K)</li>
</ul>
<p>In order to play with this, you&#8217;ll need the following prerequisites installed:</p>
<ul>
<li><a href="http://dev.mysql.com/downloads/">MySQL</a> (I&#8217;m testing on 5.1.21-beta)</li>
<li><a href="http://activestate.com/Products/activetcl/">Tcl</a> (I&#8217;m testing on 8.4.15.0)</li>
</ul>
<p>Inside the <tt>tcl-mysql-udf-0.2-dll.zip</tt> will be the file <tt><strong>tcl-mysql-udf.dll</strong></tt>. On MySQL 5.0.x, it expects it to reside in the <tt><strong>Program Files\MySQL\MySQL Server 5.0\bin</strong></tt> directory, so copy it there. On MySQL 5.1.x, however, it expects it to be in the <tt><strong>Program Files\MySQL\MySQL Server 5.1\lib</strong></tt> directory. Pay close attention to what version of MySQL you&#8217;re using and the correct directory to copy the DLL into.</p>
<p>Once you&#8217;ve got everything installed and copied to the right locations so far, connect to your MySQL database with your favorite MySQL client, and issue the following command (you only type what&#8217;s in <strong>bold</strong>):</p>
<blockquote>
<p><tt>mysql&gt; <strong>CREATE FUNCTION TCL RETURNS STRING SONAME 'tcl-mysql-udf.dll';</strong><br />Query OK, 0 rows affected (0.10 sec)</tt></p>
</blockquote>
<p>We can check what version of Tcl we&#8217;ve loaded this way:</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT TCL('info patchlevel') AS script;</strong><br />+--------+<br />| script |<br />+--------+<br />| 8.4.15 |<br />+--------+<br />1 row in set (0.04 sec)</tt></p>
</blockquote>
<p>Here&#8217;s a goofy example of storing Tcl scripts in the database and having MySQL evaluate them:</p>
<blockquote>
<p><tt>mysql&gt; <strong>CREATE TABLE code (<br />n INT NOT NULL AUTO_INCREMENT,<br />script TEXT NOT NULL,<br />PRIMARY KEY pk_code (n)<br />) ENGINE=MyISAM;</strong><br />Query OK, 0 rows affected (0.20 sec)</p>
<p>mysql&gt; <strong>INSERT INTO code (script) VALUES<br />('set x 123'),<br />('expr {$x + 432}'),<br />('clock format [clock seconds]'),<br />('incr x [clock seconds]'),<br />('expr {$x * rand()}');</strong><br />Query OK, 5 rows affected (0.04 sec)<br />Records: 5&nbsp; Duplicates: 0&nbsp; Warnings: 0</tt></p>
</blockquote>
<p>So, we now have a table with five rows in it, each row containing a Tcl script. We can have MySQL evaluate those Tcl scripts like this:</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT n, TCL(script)<br />FROM code<br />ORDER BY n;</strong></p>
<pre>+---+---------------------------------------------------+
| n | TCL(script)                                       |
+---+---------------------------------------------------+
| 1 | 123                                               |
| 2 | 555                                               |
| 3 | Fri Aug 31 12:41:25 AM Eastern Daylight Time 2007 |
| 4 | 1188535408                                        |
| 5 | 6935485.39171                                     |
+---+---------------------------------------------------+
5 rows in set (0.05 sec)</pre>
<p></tt></p></blockquote>
<p>So what, right? How about fetching HTML documents via HTTP, right from within MySQL?</p>
<blockquote>
<p><tt>mysql&gt; <strong>CREATE TABLE urls (<br />n INT NOT NULL AUTO_INCREMENT,<br />url VARCHAR(255) NOT NULL,<br />PRIMARY KEY pk_urls (n)<br />) ENGINE=MyISAM;</strong><br />Query OK, 0 rows affected (0.03 sec)</p>
<p>mysql&gt; <strong>INSERT INTO urls (url) VALUES<br />('http://dossy.org/'),<br />('http://aolserver.com/'),<br />('http://njgeeks.org/');</strong><br />Query OK, 3 rows affected (0.00 sec)<br />Records: 3&nbsp; Duplicates: 0&nbsp; Warnings: 0</p>
<p>mysql&gt; <strong>SELECT n, url, TCL(<br />'package require http;'<br />'set url [lindex $args 0];'<br />'set token [http::geturl $url];'<br />'set data [http::data $token];'<br />'http::cleanup $token;'<br />'regexp -all -inline {&lt;title&gt;.*?&lt;/title&gt;} $data',<br />url) AS script<br />FROM urls<br />ORDER BY n \G</strong><br /></tt></p>
<pre>*************************** 1. row ***************************
     n: 1
   url: http://dossy.org/
script: {&lt;title&gt;Dossy's Blog&lt;/title&gt;}
*************************** 2. row ***************************
     n: 2
   url: http://aolserver.com/
script: &lt;title&gt;AOLserver&lt;/title&gt;
*************************** 3. row ***************************
     n: 3
   url: http://njgeeks.org/
script: {&lt;title&gt;NJ Geeks | - New Jersey's IT Community&lt;/title&gt;}
3 rows in set (1.54 sec)</pre>
</blockquote>
<p>This query uses the Tcl &#8220;http&#8221; package to fetch the documents specified by the url column and plucks out the <tt>&lt;title&gt;</tt> tag using a regular expression. The <tt>TCL()</tt> stored function takes a variable number of arguments, the first being the Tcl script to evaluate, followed by zero or more arguments that are placed into the <tt>$args</tt> Tcl variable. In this case, we pass in &#8220;url&#8221; so that on each row, we execute our Tcl script with the value from that row.</p>
<p>Be aware that this stored function is a security issue: allowing database users to execute arbitrary code has obvious risks, especially since that code will be executed as the user that the MySQL server is running as.</p>
<p>Hopefully this is enough to get you started and might even give you an idea as to how this could be useful to you in some way. If you have any questions, just leave them in the comments below.</p>
<p>Tags: <a href="http://technorati.com/tag/MySQL" rel="tag">MySQL</a>, <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/Win32" rel="tag">Win32</a>, <a href="http://technorati.com/tag/stored%20function" rel="tag">stored function</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2007/08/evaluate-tcl-scripts-as-a-udf-in-mysql/' rel='bookmark' title='Evaluate Tcl scripts as a UDF in MySQL'>Evaluate Tcl scripts as a UDF in MySQL</a></li>
<li><a href='http://dossy.org/2006/02/storing-binary-data-in-mysql-with-aolserver/' rel='bookmark' title='Storing binary data in MySQL with AOLserver'>Storing binary data in MySQL with AOLserver</a></li>
<li><a href='http://dossy.org/2007/10/a-simple-mysql-client-in-tcltk-using-mysqltcl/' rel='bookmark' title='A simple MySQL client in Tcl/Tk using mysqltcl'>A simple MySQL client in Tcl/Tk using mysqltcl</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Evaluate Tcl scripts as a UDF in MySQL</title>
		<link>http://dossy.org/2007/08/evaluate-tcl-scripts-as-a-udf-in-mysql/</link>
		<comments>http://dossy.org/2007/08/evaluate-tcl-scripts-as-a-udf-in-mysql/#comments</comments>
		<pubDate>Sat, 25 Aug 2007 13:01:52 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Geeking out]]></category>
		<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/archives/000496.html</guid>
		<description><![CDATA[In the previous blog entry, I mentioned evaluating Tcl scripts from within MySQL using the User-Defined Function (UDF) capability already in MySQL. For example, it would allow you to do this: CREATE FUNCTION&#160;TCL RETURNS STRING SONAME 'libtcl-mysql-udf.so'; SELECT TCL('expr {2 + 2}'); Well, after a few hours of productive coding and hacking, I want to [...]
Related posts:<ol>
<li><a href='http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/' rel='bookmark' title='tcl-mysql-udf 0.2 and Win32 DLL binary'>tcl-mysql-udf 0.2 and Win32 DLL binary</a></li>
<li><a href='http://dossy.org/2007/08/no-happiness-using-cstore-as-a-mysql-storage-engine/' rel='bookmark' title='No happiness using C-Store as a MySQL storage engine'>No happiness using C-Store as a MySQL storage engine</a></li>
<li><a href='http://dossy.org/2006/02/storing-binary-data-in-mysql-with-aolserver/' rel='bookmark' title='Storing binary data in MySQL with AOLserver'>Storing binary data in MySQL with AOLserver</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://dossy.org/archives/000495.html">previous blog entry</a>, I mentioned evaluating Tcl scripts from within MySQL using the <a href="http://dev.mysql.com/doc/refman/5.1/en/create-function.html">User-Defined Function</a> (UDF) capability already in MySQL. For example, it would allow you to do this:</p>
<blockquote>
<p><tt>CREATE FUNCTION&nbsp;<strong>TCL</strong> RETURNS STRING SONAME <strong>'libtcl-mysql-udf.so'</strong>;</tt></p>
<p><tt>SELECT TCL('expr {2 + 2}');</tt></p>
</blockquote>
<p>Well, after a few hours of productive coding and hacking, I want to share <a href="http://static.panoptic.com/tcl-mysql-udf/tcl-mysql-udf-0.1.tar.gz">tcl-mysql-udf-0.1.tar.gz</a> with you.</p>
<p>I&#8217;ve done very limited testing on this and on very little sleep, so I wholly expect there to be really stupid mistakes in there&#8211;but, it does &#8220;work&#8221; on my personal Debian 4.0 Linux and MySQL 5.1.20 setup with Tcl 8.4.12. If you want to play around with this, I strongly urge you to read over the README included in the tarball, as it should have all the relevant bits of information necessary to get you started.</p>
<p>A quick demonstration of what&#8217;s currently possible with this version:</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT TCL('info patchlevel') AS script;</strong><br />+--------+<br />| script |<br />+--------+<br />| 8.4.12 |<br />+--------+<br />1 row in set (0.00 sec)</tt></p>
</blockquote>
<blockquote>
<p><tt></tt><tt>mysql&gt; <strong>SELECT TCL('info commands') AS script \G<br /></strong>*************************** 1. row ***************************<br />script: tell socket subst open eof pwd glob list exec pid time eval lrange fblocked lsearch gets case lappend proc break variable llength return linsert error catch clock info split array if fconfigure concat join lreplace source fcopy global switch update close<br />1 row in set (0.00 sec)</tt></p>
</blockquote>
<p>Currently, Tcl errors result in the function returning NULL&#8211;I haven&#8217;t figured out how to propagate the error string back up, yet.</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT TCL('error foo') AS script;</strong><br />+--------+<br />| script |<br />+--------+<br />| NULL&nbsp;&nbsp; |<br />+--------+<br />1 row in set (0.01 sec)</tt></p>
</blockquote>
<p>Also, the maximum length string that the function can return is currently hard-coded to 255 characters.</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT LENGTH(TCL('string repeat x 1024')) AS script;</strong><br />+--------+<br />| script |<br />+--------+<br />|&nbsp;&nbsp;&nbsp; 255 |<br />+--------+<br />1 row in set (0.07 sec)</tt></p>
</blockquote>
<p>I implemented the function as accepting a variable number of arguments, the first being the Tcl script, followed by values that get appended to the $args Tcl variable&#8211;as though it were a Tcl proc call, in a sense.</p>
<blockquote>
<p><tt>mysql&gt; <strong>SELECT TCL('concat [llength $args] $args', 'abc', 123, NOW()) AS script;</strong><br />+---------------------------------+<br />| script&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />+---------------------------------+<br />| 3 abc 123 {2007-08-25 08:50:35} |<br />+---------------------------------+<br />1 row in set (0.05 sec)</tt></p>
</blockquote>
<p>If you&#8217;re familiar with Tcl and MySQL and aren&#8217;t afraid of compiling something and fooling around with it in your dev playground, I&#8217;d love to hear what you think of this code.&nbsp;Can you see any use for it? What else would it need to be able to do before it would be useful to you?</p>
<p>Tags: <a href="http://technorati.com/tag/MySQL" rel="tag">MySQL</a>, <a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>, <a href="http://technorati.com/tag/User-Defined%20Function" rel="tag">User-Defined Function</a>, <a href="http://technorati.com/tag/UDF" rel="tag">UDF</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2007/08/tclmysqludf-02-and-win32-dll-binary/' rel='bookmark' title='tcl-mysql-udf 0.2 and Win32 DLL binary'>tcl-mysql-udf 0.2 and Win32 DLL binary</a></li>
<li><a href='http://dossy.org/2007/08/no-happiness-using-cstore-as-a-mysql-storage-engine/' rel='bookmark' title='No happiness using C-Store as a MySQL storage engine'>No happiness using C-Store as a MySQL storage engine</a></li>
<li><a href='http://dossy.org/2006/02/storing-binary-data-in-mysql-with-aolserver/' rel='bookmark' title='Storing binary data in MySQL with AOLserver'>Storing binary data in MySQL with AOLserver</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2007/08/evaluate-tcl-scripts-as-a-udf-in-mysql/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Multiple threads opening the same Berkeley DB in Tcl</title>
		<link>http://dossy.org/2006/07/multiple-threads-opening-the-same-berkeley-db-in-tcl/</link>
		<comments>http://dossy.org/2006/07/multiple-threads-opening-the-same-berkeley-db-in-tcl/#comments</comments>
		<pubDate>Mon, 17 Jul 2006 18:14:40 +0000</pubDate>
		<dc:creator>Dossy Shiobara</dc:creator>
				<category><![CDATA[Tcl]]></category>

		<guid isPermaLink="false">http://dossy.org/archives/000307.html</guid>
		<description><![CDATA[Thanks to the Tcl thread extension, you can use threads within your Tcl scripts with a thread-enabled build and this extension. There&#8217;s also a Tcl binding for Berkeley DB (BDB) available, as well. But, what if you want to combine the two, and access the same Berkeley DB from multiple threads in Tcl? Since Berkeley [...]
Related posts:<ol>
<li><a href='http://dossy.org/2005/04/tcl-847-introduced-memory-leak-in-tcl-threaded-memory-allocator/' rel='bookmark' title='Tcl 8.4.7 introduced memory leak in Tcl threaded memory allocator'>Tcl 8.4.7 introduced memory leak in Tcl threaded memory allocator</a></li>
<li><a href='http://dossy.org/2006/08/why-it-might-be-a-bad-idea-to-forkexec-in-a-multithreaded-application/' rel='bookmark' title='Why it might be a bad idea to fork/exec in a multi-threaded application'>Why it might be a bad idea to fork/exec in a multi-threaded application</a></li>
<li><a href='http://dossy.org/2004/06/aolserver-php-and-stack-size/' rel='bookmark' title='aolserver, php and stack size'>aolserver, php and stack size</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Thanks to the <a href="http://sourceforge.net/project/showfiles.php?group_id=10894&#038;package_id=10438">Tcl thread extension</a>, you can use threads within your Tcl scripts with a thread-enabled build and this extension.  There&#8217;s also a <a href="http://www.sleepycat.com/docs/api_tcl/api_tcl.html">Tcl binding</a> for <a href="http://www.sleepycat.com/products/bdb.html">Berkeley DB</a> (BDB) available, as well.  But, what if you want to combine the two, and access the same Berkeley DB from multiple threads in Tcl?  Since Berkeley DB is <a href="http://www.sleepycat.com/docs/gsg_txn/CXX/txnconcurrency.html">free-threaded</a> (or thread-safe), this should be simple, right?  You&#8217;re right, it <b>should be</b> but it was pretty non-obvious, to me at least.</p>
<h3>It&#8217;s not a bug, it&#8217;s just an undocumented feature!</h3>
<p>First off, the <a href="http://www.sleepycat.com/docs/">BDB documentation</a> makes mention of <tt><a href="http://www.sleepycat.com/docs/api_c/env_open.html#DB_THREAD">DB_THREAD</a></tt> needing to be set on the environment handle to get the free-threaded behavior, but the <tt><a href="http://www.sleepycat.com/docs/api_tcl/env_open.html">berkdb env</a></tt> documentation lacks any mention of how to do this.  Turns out, the parameter <tt>-thread</tt> is undocumented, but does set <tt>DB_THREAD</tt> as expected.  Fantastic!  That&#8217;s all you should need to know, right?  Wrong.  There&#8217;s a peculiar constraint (bug?) which I ran up against, scratching my head, reading (and re-reading) the BDB source, trying to understand.  Here&#8217;s an example script I started with:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
package require Thread

set t1 [thread::create]
thread::send $t1 {
  package require Db_tcl
  set e [berkdb env -create -home bdb -thread -cdb]
  set db [berkdb open -env $e -thread -create -hash tables.db test]
}
thread::send $t1 {$db put foo bar}
  # => 0
thread::send $t1 {$db get foo}
  # => {foo bar}

set t2 [thread::create]
thread::send $t2 {
  package require Db_tcl
  set e [berkdb env -create -home bdb -thread -cdb]
  set db [berkdb open -env $e -thread -create -hash tables.db test]
}
thread::send $t1 {$db get foo}
  # => error: NULL db info pointer
</pre>
</blockquote>
<h3>You&#8217;d think this would work, right?</h3>
<p>Naturally, what&#8217;s happened here is that two threads have attempted to use the same environment, and when the second thread does it, it invalidates the environment for the first thread, resulting in the &#8220;<tt>NULL db info pointer</tt>&#8221; error.  Fine, I wouldn&#8217;t expect this to work for just this reason, so lets try to create the environment once and reuse it in the child threads.  We&#8217;ll use <tt>tsv</tt>&#8216;s (thread-shared variables) to share the environment handle across threads.</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
package require Db_tcl
package require Thread

tsv::set bdb env [berkdb env -create -home bdb -thread -cdb]
  # => env0

set t1 [thread::create]
thread::send $t1 {
  package require Db_tcl
  set e [tsv::get bdb env]
    # => env0
  set db [berkdb open -env $e -thread -create -hash tables.db test]
    # => error: db open: illegal environment
}
</pre>
</blockquote>
<h3>Illegal?  I&#8217;ll show YOU illegal!</h3>
<p>This really puzzled me, getting the &#8220;<tt>db open: illegal environment</tt>&#8221; error.  I looked at the source for <tt>db-4.2.52</tt>, in file <tt>tcl_db_pkg.c</tt> around lines 1464&#8211;1473:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
   1464         switch ((enum bdbenvopen)optindex) {
   1465         case TCL_DB_ENV0:
   1466             arg = Tcl_GetStringFromObj(objv[i], NULL);
   1467             envp = NAME_TO_ENV(arg);
   1468             if (envp == NULL) {
   1469                 Tcl_SetResult(interp,
   1470                     "db open: illegal environment", TCL_STATIC);
   1471                 return (TCL_ERROR);
   1472             }
   1473         }
</pre>
</blockquote>
<p>I mean, look at that.  <tt>NAME_TO_ENV()</tt> is a macro that&#8217;s defined as <tt>(DB_ENV *)_NameToPtr((name))</tt> which simply fishes data out of <tt>DBTCL_GLOBAL __dbtcl_global</tt> &#8230; it shouldn&#8217;t be returning a <tt>NULL</tt>, here.  What gives?  Since we have to initialize each thread&#8217;s state on creation (it doesn&#8217;t inherit anything from the thread that created it), we have to <tt>package require Db_tcl</tt> and load the BDB module in each thread.  I bet there&#8217;s something goofy going on there.  Looking at <tt>Db_tcl_Init()</tt>, we see:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
     72 int
     73 Db_tcl_Init(interp)
     74     Tcl_Interp *interp;     /* Interpreter in which the package is
     75                      * to be made available. */
...
     97     LIST_INIT(&#038;__db_infohead);
     98     return (TCL_OK);
     99 }
</pre>
</blockquote>
<h3>Aha!  The villain is revealed!</h3>
<p>Oh, look, it initializes the global each time the package is loaded!  So, the list that points to the environments gets wiped out once our newly created thread loads the <tt>Db_tcl</tt> package.  While this is frustrating, there&#8217;s a work-around: create the environment <b>after</b> creating the threads and loading the <tt>Db_tcl</tt> package inside of them:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
package require Db_tcl
package require Thread

## Create our threads, making sure Db_tcl is loaded.
set t1 [thread::create]
thread::send $t1 {
  package require Db_tcl
}
set t2 [thread::create]
thread::send $t2 {
  package require Db_tcl
}

## Now, we can create the environment once:
tsv::set bdb env [berkdb env -create -home bdb -thread -cdb]

## ... and then, use it in our threads:
thread::send $t1 {
  set e [tsv::get bdb env]
  set db [berkdb open -env $e -thread -create -hash tables.db test]
}
thread::send $t2 {
  set e [tsv::get bdb env]
  set db [berkdb open -env $e -thread -create -hash tables.db test]
}

## See:
thread::send $t1 {$db put foo bar}
  # => 0
thread::send $t1 {$db get foo}
  # => {foo bar}
thread::send $t2 {$db get foo}
  # => {foo bar}
</pre>
</blockquote>
<h3>All this, for what?</h3>
<p>So, this is how the story ends.  It <b>is</b> possible to use BDB across multiple threads in a Tcl application, with the restriction that all threads that will load the <tt>Db_tcl</tt> package must be created and initialized before you create environments and probably any other operation that relies on the <tt>__dbtcl_global</tt> structure, as it gets initialized on package load and the single global is shared across all threads.  Presumably, this might be considered a bug, in that the structure should probably only be initialized once per process rather than every package load.</p>
<h3>Can I do something about it now?</h3>
<p>Here&#8217;s my proposed patch to fix this, although there&#8217;s a potential race<br />
condition here:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<pre style="overflow: auto;">
$ diff -u tcl_db_pkg.c.orig tcl_db_pkg.c
--- tcl_db_pkg.c.orig   2006-07-17 11:22:20.000000000 -0700
+++ tcl_db_pkg.c        2006-07-17 11:23:40.000000000 -0700
@@ -78,6 +78,7 @@
 {
   int code;
   char pkg[12];
+    static int initialized = 0;

   snprintf(pkg, sizeof(pkg), "%d.%d", DB_VERSION_MAJOR, DB_VERSION_MINOR);
   code = Tcl_PkgProvide(interp, "Db_tcl", pkg);
@@ -98,7 +99,10 @@
   (void)Tcl_LinkVar(
       interp, "__debug_test", (char *)&#038;__debug_test,
       TCL_LINK_INT);
-  LIST_INIT(&#038;__db_infohead);
+    if (!initialized) {
+        initialized = 1;
+        LIST_INIT(&#038;__db_infohead);
+    }
   return (TCL_OK);
 }
</pre>
</blockquote>
<p>My recommendation would be to load the <tt>Db_tcl</tt> package in a single-threaded environment (before any additional threads are created) to ensure that only one thread initializes <tt>__db_infohead</tt>, then you can freely create threads and load the <tt>Db_tcl</tt> package in them without each package load re-initializing the <tt>__db_infohead</tt>.</p>
<p>If this was helpful, feel free to let me know in the comments below.  Or, if you have any questions, ask those too!</p>
<p><b>UPDATE:</b> I received a response from an Oracle engineer (who now owns Sleepycat) about this issue.  Here&#8217;s it is:</p>
<blockquote type="cite" style="border-left: 2px solid #666; padding-left: 0.5em; margin-left: 3em;">
<p>[...] Although the fix you sent in the SR is one of the<br />
ones needed to allow threaded access to BDB&#8217;s Tcl API, it is<br />
not the only one.  The __db_infohead is the beginning of a<br />
global linked list and manipulation of that linked list is<br />
not protected in the API.  All manipulation of it would need<br />
a mutex.  That isn&#8217;t necessarily hard, but we have not had<br />
customer demand for multi-threading the Tcl API.</p>
<p>I have fixed our Reference Guide Programming Notes on Tcl to<br />
include a statement that says it does not support multi-threading.</p>
</blockquote>
<p>So, if you&#8217;d like to see full threaded support in Tcl for Berkeley DB, leave a comment below and we&#8217;ll see what kind of demand really exists for it.  In the meantime, I might try to work on it myself, just in case.</p>
<p>Tags:<br />
<a href="http://technorati.com/tag/Tcl" rel="tag">Tcl</a>,<br />
<a href="http://technorati.com/tag/threads" rel="tag">threads</a>,<br />
<a href="http://technorati.com/tag/Berkeley%20DB" rel="tag">Berkeley DB</a>,<br />
<a href="http://technorati.com/tag/tutorial" rel="tag">tutorial</a></p>
<p>Related posts:<ol>
<li><a href='http://dossy.org/2005/04/tcl-847-introduced-memory-leak-in-tcl-threaded-memory-allocator/' rel='bookmark' title='Tcl 8.4.7 introduced memory leak in Tcl threaded memory allocator'>Tcl 8.4.7 introduced memory leak in Tcl threaded memory allocator</a></li>
<li><a href='http://dossy.org/2006/08/why-it-might-be-a-bad-idea-to-forkexec-in-a-multithreaded-application/' rel='bookmark' title='Why it might be a bad idea to fork/exec in a multi-threaded application'>Why it might be a bad idea to fork/exec in a multi-threaded application</a></li>
<li><a href='http://dossy.org/2004/06/aolserver-php-and-stack-size/' rel='bookmark' title='aolserver, php and stack size'>aolserver, php and stack size</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://dossy.org/2006/07/multiple-threads-opening-the-same-berkeley-db-in-tcl/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using apc
Database Caching 1/87 queries in 0.733 seconds using apc
Object Caching 2268/2342 objects using apc

Served from: dossy.org @ 2012-02-03 21:40:13 -->
