<?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>Griffon26's Blog</title>
	<atom:link href="http://griffon26.kfk4ever.com/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://griffon26.kfk4ever.com/wordpress</link>
	<description>A weblog about Planner, Gentoo and whatever I'm working on.</description>
	<lastBuildDate>Wed, 05 Nov 2008 20:43:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Debugging GTK+ printing support</title>
		<link>http://griffon26.kfk4ever.com/wordpress/2008/11/05/debugging-gtk-printing-support/</link>
		<comments>http://griffon26.kfk4ever.com/wordpress/2008/11/05/debugging-gtk-printing-support/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 20:42:39 +0000</pubDate>
		<dc:creator>Griffon26</dc:creator>
				<category><![CDATA[Planner]]></category>

		<guid isPermaLink="false">http://griffon26.kfk4ever.com/wordpress/?p=9</guid>
		<description><![CDATA[During my vacation I have been fixing some bugs in Planner, hoping to strike a few things off of my todo list for a change.
One of those things is support for the GTK+ printing API. Francisco Moraes implemented most of this already, but it needed some final touches: a property page allowing you to select [...]]]></description>
			<content:encoded><![CDATA[<p>During my vacation I have been fixing some bugs in Planner, hoping to strike a few things off of my todo list for a change.</p>
<p>One of those things is support for the GTK+ printing API. Francisco Moraes <a href="http://mail.gnome.org/archives/gtk-list/2006-September/msg00267.html">implemented most of this already</a>, but it needed some final touches: a property page allowing you to select what to print, a few minor changes in the layout and the removal of some magic numbers.</p>
<p>Most of these things I completed already a while ago, but there were a few problems with font sizes that I could not quite get a handle on. Francisco was <a href="http://mail.gnome.org/archives/gtk-list/2006-August/msg00168.html">aware of the issue</a> when he was working on GTK+ printing support, but did not find a solution.</p>
<p><span id="more-9"></span>The problematic piece of code is in <code><a href='http://svn.gnome.org/viewvc/planner/trunk/src/planner-print-job.c?rev=937&#038;view=markup'>src/planner-print-job.c</a></code> in the function planner_print_job_get_extents(). As you can see the current font description is set in the layout, a text string is also set and then the pango_layout_get_extents() function is used to get the dimensions of the rendered string. Unfortunately the width returned is about twice what you would expect.</p>
<p><center><img src='/wordpress/wp-content/uploads/2008/07/too_much_space.png' title='Too much space for the contents' alt='Too much space for the contents' /></center></p>
<p>When I got to work on GTK+ printing I saw the same thing; no matter what string I used, the (horizontal) size was always roughly double what I expected. As I&#8217;m no expert in pango and font stuff and because planner does not use the vertical size, I only had an estimate for what the horizontal size should be. It determined the width of columns and I could see they were about twice as wide as they needed to be for their content.</p>
<p>Then I thought, maybe it&#8217;s using the wrong font. So I searched for where current_font was assigned a value. I found it in planner_print_job_set_font_regular(), planner_print_job_set_font_bold() and planner_print_job_set_font_italic(), all of them in <code><a href='http://svn.gnome.org/viewvc/planner/trunk/src/planner-print-job.c?rev=937&#038;view=markup'>src/planner-print-job.c</a></code>.  They set priv->current_font to either priv->font or priv->bold_font. (I guess the italic function is not used =) ).</p>
<p>So now I wanted to know what priv->bold_font and priv->font were set to.  Searching for them showed that they are assigned their value in planner_print_job_new(). In this function the font descriptions are created from a string like &#8220;Sans Regular 6&#8243;.</p>
<p>If these are the fonts used, then changing &#8220;Sans Regular 6&#8243; to &#8220;Sans Regular 18&#8243; should have an effect on the width returned by pango_layout_get_extents(), right?</p>
<p>Yes, it _should_ indeed, but it doesn&#8217;t. Instead it kept giving me the same width.</p>
<p>I suppose that could happen if the planner_print_job_set_font_* functions were not called, so let&#8217;s see what the font IS set to. I used pango_font_description_to_string() for that.  Guess what?</p>
<blockquote><pre>(planner:25972): Pango-CRITICAL **: pango_font_description_to_string: assertion `desc != NULL' failed
Determining extents with font: '(null)'
</pre>
</blockquote>
<p>Oops! It turns out that planner_print_job_get_extents() is already called a couple of times before the first call to planner_print_job_set_font_*().</p>
<p>In order to find out where to add calls to planner_print_job_set_font_*(), I will look at where planner_print_job_get_extents() is called and go from there.</p>
<p>Adding a g_print() statement just before each call to planner_print_job_get_extents() that prints the name of the calling function gives me this:</p>
<blockquote><pre>
print_job_begin_print

(planner:27322): Pango-CRITICAL **: pango_font_description_to_string: assertion `desc != NULL' failed
Determining extents with font: '(null)'
planner_gantt_print_data_new 1

(planner:27322): Pango-CRITICAL **: pango_font_description_to_string: assertion `desc != NULL' failed
Determining extents with font: '(null)'
planner_gantt_print_data_new 2

(planner:27322): Pango-CRITICAL **: pango_font_description_to_string: assertion `desc != NULL' failed
Determining extents with font: '(null)'
planner_gantt_print_data_new 3

(planner:27322): Pango-CRITICAL **: pango_font_description_to_string: assertion `desc != NULL' failed
Determining extents with font: '(null)'
planner_print_job_set_font_regular

planner_print_job_set_font_regular
planner_print_job_set_font_bold
planner_print_job_set_font_regular
</pre>
</blockquote>
<p>Now let&#8217;s see if there&#8217;s a common parent function of all of these.<br />
The ones with a number behind them are all from the planner_gantt_print_data_new function. A little grepping shows that this function is called from gantt_view_print_init(), which is set as the print_init function for the PlannerViewClass in <code><a href='http://svn.gnome.org/viewvc/planner/trunk/src/planner-view.h?rev=937&#038;view=markup'>src/planner-view.h</a></code>.  print_job_begin_print() in <code><a href='http://svn.gnome.org/viewvc/planner/trunk/src/planner-print-job.c?rev=937&#038;view=markup'>src/planner-print-job.c</a></code> loops through planner&#8217;s views (gantt, task, resource usage) and calls print_init for each of them.  Lucky for me this is also the function that makes the one call to planner_print_job_get_extents() that I did not yet cover.  In other words, the perfect place to insert our call to planner_print_job_set_font_regular(). </p>
<p>That concludes the overview of this debugging session. </p>
<p>I just checked in the the changes discussed in this post, so Planner now finally uses GTK+ printing instead of the old libgnomeprint. This should fix a bunch of long-standing problems people were having with printing on Windows. That is, if your GTK+ installation is recent enough.</p>
]]></content:encoded>
			<wfw:commentRss>http://griffon26.kfk4ever.com/wordpress/2008/11/05/debugging-gtk-printing-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixing dependency loops</title>
		<link>http://griffon26.kfk4ever.com/wordpress/2008/03/15/5/</link>
		<comments>http://griffon26.kfk4ever.com/wordpress/2008/03/15/5/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 13:26:43 +0000</pubDate>
		<dc:creator>Griffon26</dc:creator>
				<category><![CDATA[Planner]]></category>

		<guid isPermaLink="false">http://griffon26.kfk4ever.com/wordpress/2008/03/15/5/</guid>
		<description><![CDATA[Since last time I posted, the libgda-3 work has been finished and checked in. The final patch turned out to be 81K in size. =)
For this post I will describe what I&#8217;ve been doing to fix bug #382548. This bug allows you to create dependency loops in tasks.
The simplest type of loop that can be [...]]]></description>
			<content:encoded><![CDATA[<p>Since last time I posted, the libgda-3 work has been finished and checked in. The final patch turned out to be 81K in size. =)</p>
<p>For this post I will describe what I&#8217;ve been doing to fix bug <a href='http://bugzilla.gnome.org/show_bug.cgi?id=382548'>#382548</a>. This bug allows you to create dependency loops in tasks.</p>
<p>The simplest type of loop that can be created is this one:</p>
<p><img src='/wordpress/wp-content/uploads/2008/03/simpleloop.png' title='A simple loop' alt='A simple loop' /></p>
<p>You could create this by first setting task2 as a predecessor of task1 and then indenting task2 to become a child of task1. Planner does not allow you to do it the other way around, first indenting task2 and then adding it as a predecessor of task1.</p>
<p>To see how Planner tries to detect these loops, we&#8217;ll have to take a look at <code><a href='http://svn.gnome.org/viewvc/planner/trunk/libplanner/mrp-task-manager.c?rev=893&#038;view=markup'>libplanner/mrp-task-manager.c</a></code>.</p>
<p><span id="more-5"></span>There are basically two operations you can perform on a task: moving and setting predecessors. All other actions are mapped to these two. Indenting a task for instance is implemented as moving it under a new parent. To check if these operations can be performed without creating loops, two functions named <code>mrp_task_manager_check_move()</code> and <code>mrp_task_manager_check_predecessor()</code> are used. Both of these functions have the following structure:</p>
<ol>
<li>perform the operation in the dependency graph</li>
<li>traverse the graph to detect loops</li>
<li>undo the operation in the dependency graph</li>
<li>return a boolean indicating whether or not the operation can be done without creating loops</li>
</ol>
<p>The dependency graph that these functions refer to is a <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">directed acyclic (or at least it should be <img src='http://griffon26.kfk4ever.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) graph</a>. The tasks will be nodes in this graph and the edges are either predecessor relationships or child-to-parent relationships. Think of this graph as showing the order in which tasks can be scheduled; a predecessor must be scheduled before its successor and children should be scheduled before you are able to tell the duration of the parent. Note that adding a predecessor to a parent task has to result in <b>adding this predecessor to (certain) children of the task as well</b>, otherwise it would not be clear from the graph that none of the children can be scheduled before the predecessor has been scheduled.</p>
<p>The above is implemented as follows for adding a predecessor. <code>mrp_task_manager_check_predecessor()</code> calls <code>add_predecessor_to_dependency_graph()</code>, which connects the predecessor node with the parent node and then calls <code>add_predecessor_to_dependency_graph_recursive()</code> that loops over all children, connects the predecessor node to them and calls itself for the children&#8217;s children. If the predecessor link in the above image had been created when task2 was already a child of task1, then this recursive adding of predecessors would have connected task2 to task2, thereby creating a loop.</p>
<p>When a task that is already a predecessor of another is indented, the process is a bit different. <code>mrp_task_manager_check_move()</code> calls <code>remove_task_from_dependency_graph()</code> to remove the task node from its current position in the graph followed by  <code>add_task_to_dependency_graph()</code> to add it at the new position. <code>add_task_to_dependency_graph()</code> reconnects the task to all of its predecessors and finally connects it to its new parent. Keen readers may have noticed that planner has not done anything yet about the predecessor relationships of the new parent. If the task that is being indented is a predecessor of its new parent, Planner would happily indent and create the situation seen in the image above.</p>
<p>What should be done when a task is moved under a new parent is to add all predecessors from the parent as predecessors to the task and all of its children. This is part 1 of the fix for <a href='http://bugzilla.gnome.org/show_bug.cgi?id=382548'>#382548</a>.</p>
<p>Unfortunately even with this fix, the following is still possible.</p>
<p><img src='/wordpress/wp-content/uploads/2008/03/slightlylesssimpleloop.png' title='A slightly less simple loop' alt='A slightly less simple loop' /></p>
<p>The reason for this is that loop detection is only started at the task that is indented (task2 in this case). Take a look at the &#8220;before&#8221; and &#8220;after&#8221; pictures of the dependency graph for indenting task 2. The dotted lines indicate predecessor relations and the normal lines child-to-parent relations. As you can see starting traversal at task2 will not go through the loop that was created.</p>
<p><img src='/wordpress/wp-content/uploads/2008/03/predecessorloop.png' title='Dependency loop' alt='Dependency loop' /></p>
<p>Ok, so how about starting loop detection at the indented task and each of its children individually?</p>
<p>Let&#8217;s take a look at the loop detection function <code>check_predecessor_traverse()</code>:</p>
<blockquote><pre>static gboolean
check_predecessor_traverse (MrpTaskManager *manager,
                            MrpTask        *task,
                            MrpTask        *end,
                            gint            length)
{
        MrpTaskGraphNode *node;
        GList            *l;

        if (length > 1 &#038;&#038; task == end) {
                return FALSE;
        }

        /* Avoid endless loop. */
        if (imrp_task_get_visited (task)) {
                return TRUE;
        }

        imrp_task_set_visited (task, TRUE);

        node = imrp_task_get_graph_node (task);
        for (l = node->next; l; l = l->next) {
                if (!check_predecessor_traverse (manager, l->data, end, length + 1)) {
                        return FALSE;
                }
        }

        return TRUE;
}
</pre>
</blockquote>
<p>This is first called as <code>check_predecessor_traverse (manager, predecessor, predecessor, 1);</code>.<br />
First it returns FALSE (i.e. reports a loop) if the current task is the same as the one passed in &#8216;end&#8217; and this is not the first call. Then it aborts searching down a path if it has been there before. Next it marks the current task as visited so it will not continue searching when it comes here the next time through another path. And finally it will go on to all tasks that follow the current one in the graph.</p>
<p>What I wanted to know before implementing the proposed solution of starting loop detection at the indented task and each of its children is if I could get away with calling <code>check_predecessor_traverse()</code> multiple times without marking all nodes &#8216;unvisited&#8217; in between. As you can see the function only detects loops that include the task that it starts at and only if none of the nodes in the loop have been visited before.</p>
<p>I think the answer is no and here&#8217;s why:</p>
<ol>
<li>assume we start with a graph without cycles</li>
<li>now if adding a predecessor to a child results in a loop, this means there is a forward path from the child to the predecessor</li>
<li>this forward path either goes through visited nodes or it doesn&#8217;t</li>
<li>if it doesn&#8217;t, the <code>check_predecessor_traverse()</code> function will detect a loop when it is called on this child</li>
<li>if it does go through visited nodes, then there was already a forward path from the visited node to the predecessor</li>
<li>because the visited node has been visited before, there must already be a forward path from a node that the traverse function started at to the visited node</li>
<li>because we only call the traverse function on nodes that the predecessor is added to (the indented task and all its children), there must also be a forward path from predecessor to the node the traverse started at</li>
<li>this means that there is a loop that would have been detected in the earlier <code>check_predecessor_traverse()</code> call</li>
</ol>
<p>This is part 2 of the fix. I just committed these fixes in <code><a href='http://svn.gnome.org/viewvc/planner/trunk/libplanner/mrp-task-manager.c?rev=894&#038;view=markup'>libplanner/mrp-task-manager.c</a></code> (revision 894).</p>
<p>It would have been fun to use a model checker to formally verify the last part, but in the end looking for one took too much time. If anyone has a suggestion, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://griffon26.kfk4ever.com/wordpress/2008/03/15/5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Planner and libgda-3 support</title>
		<link>http://griffon26.kfk4ever.com/wordpress/2008/02/03/planner-and-libgda-3-support/</link>
		<comments>http://griffon26.kfk4ever.com/wordpress/2008/02/03/planner-and-libgda-3-support/#comments</comments>
		<pubDate>Sun, 03 Feb 2008 17:04:31 +0000</pubDate>
		<dc:creator>Griffon26</dc:creator>
				<category><![CDATA[Planner]]></category>

		<guid isPermaLink="false">http://griffon26.kfk4ever.com/wordpress/?p=4</guid>
		<description><![CDATA[Planner&#8217;s support for storing projects in databases has been rather broken for a while. I recently fixed a bug that caused Planner to crash when you tried to save over an existing project in the database (#397132), so it was once again possible to use a database for storage. There was also a problem with [...]]]></description>
			<content:encoded><![CDATA[<p>Planner&#8217;s support for storing projects in databases has been rather broken for a while. I recently fixed a bug that caused Planner to crash when you tried to save over an existing project in the database (<a href='http://bugzilla.gnome.org/show_bug.cgi?id=397132'>#397132</a>), so it was once again possible to use a database for storage. There was also a problem with newer postgresql versions (<a href='http://bugzilla.gnome.org/show_bug.cgi?id=318440'>#318440</a>), but that turned out to be a bug in postgresql that has subsequently been solved in postgresql-8.2.5.</p>
<p>Just last week I got a request to add support for libgda-3, because some distributions were dropping support for older libgda versions.  I expected this to be more or less a configure fix, but it turns out it was quite a bit more work than that.</p>
<p><span id="more-4"></span>Planner accesses the database from two files: <code><a href='http://svn.gnome.org/viewvc/planner/trunk/libplanner/mrp-sql.c?rev=877&#038;view=markup'>libplanner/mrp-sql.c</a></code> and <code><a href='http://svn.gnome.org/viewvc/planner/trunk/src/planner-sql-plugin.c?rev=877&#038;view=markup'>src/planner-sql-plugin.c</a></code>. Both used a convenience function called <code>sql_execute_query()</code> which was just a wrapper around gda&#8217;s <code>gda_connection_execute_single_command()</code> and is used to do both queries (SELECTs) and other commands (BEGIN, INSERT, &#8230;). It was even used to execute a whole bunch of commands in one go when setting up the planner database. In the mean time libgda has become more strict in checking what is passed to its functions (and rightly so), forcing me to properly fix this code.</p>
<p>The three functions available are <code><a href='http://library.gnome.org/devel/libgda-3.0/stable/GdaConnection.html#gda-connection-execute-select-command'>gda_connection_execute_select_command()</a></code>, <code><a href='http://library.gnome.org/devel/libgda-3.0/stable/GdaConnection.html#gda-connection-execute-non-select-command'>gda_connection_execute_non_select_command()</a></code> and <code><a href='http://library.gnome.org/devel/libgda-3.0/stable/GdaConnection.html#gda-connection-execute-command'>gda_connection_execute_command()</a></code>. The first two are just wrappers around the second. Since planner is only interested in query results for single select queries and does sometimes need to execute multiple commands at once, I decided to split <code>sql_execute_query()</code> into two functions:</p>
<ul>
<li><code>sql_execute_query()</code>:<br />
uses <code>gda_connection_execute_select_command()</code> and returns a <code>GdaDataModel *</code> that you need to pass to <code>g_object_unref()</code> when it&#8217;s done with it, and </li>
<li><code>sql_execute_command()</code><br />
uses <code>gda_connection_execute_command()</code> and returns a <code>gboolean </code>indicating success or failure. This function cleans up whatever results it receives on its own.</li>
</ul>
<p>I then went through the sources modifying all calls to <code>sql_execute_query()</code>. The result of calls to <code>sql_execute_query()</code> will now always be stored in a local variable named <code>model</code>, while the result of <code>sql_execute_command()</code> will be stored in the <code>gboolean success</code>. I think it&#8217;s important to have such a clear distinction between cases where you have to catch a return value and clean up an object and cases where you don&#8217;t.</p>
<p>After modifying configure.in to detect the right GDA version and making the above changes as well as a few other fixes, it was time to run some tests.<br />
*create a few task*, *save*, *load*.. hmm.. did I just see that task duration change?&#8230;<br />
*modify task length*, *save*, *load*.. no, wait.. the project start date is shifting.. it&#8217;s 31 January 2008 now<br />
*modify something*, *save*, *load*.. now it&#8217;s 30 January 2008!?</p>
<p>I could hardly believe my changes were causing this problem and sure enough, the same happened with <a href="http://svn.gnome.org/viewvc/planner/trunk/libplanner/?pathrev=876">svn HEAD</a>. Some debugging and quite a bit of reading of the postgresql docs made it clear that the cause of this was a different interpretation of dates between Planner and postgresql. On one hand we were doing the calculation from time to seconds-since-epoch ourselves in Planner, but on the other we were letting postgresql do the reverse calculation when a project was loaded. The time zone used in these calculations was UTC for Planner, but local time for postgresql.<br />
An example:</p>
<p>A seconds-since-epoch value of 86400 (which is the number of seconds in a single day) corresponds to the timestamp 02 Jan 1970 00:00:00 UTC.</p>
<ol>
<li>When planner saves a project with a start date equal to 86400, it will store <strong>02</strong> Jan 1970 in the database.</li>
<li>When planner loads the project, it asks postgresql to do the conversion to seconds-since-epoch. Postgresql interprets the date to be local time, which at this time is UTC + 1 in my case. My local time of 02 Jan 1970 00:00:00 corresponds to 01 Jan 1970 23:00:00 UTC, so postgresql returns 86400 &#8211; 3600 = 82800 seconds-since-epoch.</li>
<li>When planner saves this project again, it will store <strong>01</strong> Jan 1970 in the database as a date without time, shifting the project start date not just by an hour but by an entire day.</li>
</ol>
<p>This bug <a href="http://svn.gnome.org/viewvc/planner?view=revision&#038;revision=877">has now been fixed</a>, but I&#8217;m still working on the libgda-3 changes. I broke compatibility with older gda versions, so I&#8217;ll have to restore that. I&#8217;ve put <a href="http://www.kfk4ever.com/~griffon26/shared/planner-draft-libgda3-fixes.patch">the latest version of the libgda-3 patch</a> online for anyone to take a look at it and maybe contribute. I&#8217;m only working on it during CET evenings, so there&#8217;s at least an 18-hour window for a second person to work on it without having to solve merge conflicts all the time. Just send me your changes before I start working on it the next day.</p>
]]></content:encoded>
			<wfw:commentRss>http://griffon26.kfk4ever.com/wordpress/2008/02/03/planner-and-libgda-3-support/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Who&#8217;d a thunk it?</title>
		<link>http://griffon26.kfk4ever.com/wordpress/2008/02/03/whod-a-thunk-it/</link>
		<comments>http://griffon26.kfk4ever.com/wordpress/2008/02/03/whod-a-thunk-it/#comments</comments>
		<pubDate>Sun, 03 Feb 2008 01:17:14 +0000</pubDate>
		<dc:creator>Griffon26</dc:creator>
				<category><![CDATA[Planner]]></category>

		<guid isPermaLink="false">http://www.kfk4ever.com/wordpress/?p=3</guid>
		<description><![CDATA[That I of all people would have started a blog. I won&#8217;t bore you with details of why this is atypical for me, I&#8217;ll just skip to the reasons for doing this.
For some time now I&#8217;ve been working on Gnome Planner and just last week I found myself updating the topic of #planner on GIMPNet [...]]]></description>
			<content:encoded><![CDATA[<p>That I of all people would have started a blog. I won&#8217;t bore you with details of why this is atypical for me, I&#8217;ll just skip to the reasons for doing this.</p>
<p>For some time now I&#8217;ve been working on <a href="http://live.gnome.org/Planner">Gnome Planner</a> and just last week I found myself updating the topic of #planner on GIMPNet every night to keep people informed of my progress on some requested feature. After a few of those rather short and cryptic descriptions, I decided to look for a better way to present this information: this blog.</p>
<p>In this blog I plan to write about what I&#8217;m working on, which is most likely to be Planner and maybe some Gentoo stuff.  I&#8217;m not good at writing stories, so I&#8217;ll stick to the technical stuff. There are lots of things that this blog could do: provide insight into what Planner developers are working on or what the roadmap looks like, give prospective developers an easy way to get familiar with the project, generate more involvement from the community, etc. I have no idea if anything will come out of this, but let&#8217;s give it a try.</p>
<p>Tomorrow I plan to write about the stuff I&#8217;m working on at the moment: getting Planner&#8217;s database support in better shape.</p>
]]></content:encoded>
			<wfw:commentRss>http://griffon26.kfk4ever.com/wordpress/2008/02/03/whod-a-thunk-it/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
