<?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/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>A mind less ordinary &#187; Personal</title>
	<atom:link href="http://www.dmi.me.uk/blog/category/personal/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dmi.me.uk/blog</link>
	<description></description>
	<lastBuildDate>Wed, 23 Nov 2011 16:01:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
		<item>
		<title>Creating a presentation with LaTeX and powerdot</title>
		<link>http://www.dmi.me.uk/blog/2010/11/08/creating-a-presentation-with-latex-and-powerdot/</link>
		<comments>http://www.dmi.me.uk/blog/2010/11/08/creating-a-presentation-with-latex-and-powerdot/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 12:52:59 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[HOWTOs]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Talks]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[powerdot]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[talk]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[trick]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[useful]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=254</guid>
		<description><![CDATA[A few days ago, I gave a talk at PHP London about using OAuth with PHP. I started out building it in OpenOffice, but quickly found the process annoying, especially considering that I wanted to export to PDF with progressive disclosure on some slides. After putting the skeleton of the talk together, I decided to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.phplondon.org/wiki/November_4th_2010" target="_blank">A few days ago</a>, I gave a talk at <a href="http://www.phplondon.org/" target="_blank">PHP London</a> about <a href="http://slidesha.re/a31GKM" target="_blank">using OAuth with PHP</a>. I started out building it in OpenOffice, but quickly found the process annoying, especially considering that I wanted to export to PDF with progressive disclosure on some slides. After putting the skeleton of the talk together, I decided to move to something else instead.</p>
<p>I've had some experience with the <a href="http://www.latex-project.org/" target="_blank">LaTeX</a> document typesetting system before, having used it quite a lot during university for <a title="Insight semantic file system" href="http://www.dmi.me.uk/code/insight/" target="_blank">my final project</a>'s <a title="Insight final report" href="http://www.dmi.me.uk/code/insight/final-report.pdf" target="_blank">reports</a> and presentation. I used the <code class="codecolorer text default"><span class="text">beamer</span></code> package before, but this time I found its styles too restrictive. The three major presentation packages that I'm aware of are <a title="The prosper package" href="http://ctan.org/tex-archive/macros/latex/contrib/prosper/" target="_blank"><code class="codecolorer text default"><span class="text">prosper</span></code></a> (which I believe is quite old now), <a title="The beamer package" href="http://ctan.org/tex-archive/macros/latex/contrib/beamer/" target="_blank"><code class="codecolorer text default"><span class="text">beamer</span></code></a>, and <a title="The powerdot package" href="http://ctan.org/tex-archive/macros/latex/contrib/powerdot/" target="_blank"><code class="codecolorer text default"><span class="text">powerdot</span></code></a>. After some investigation (looking primarily at features and visual styles), I settled for <code class="codecolorer text default"><span class="text">powerdot</span></code>. I will explain the basics of putting a presentation together in the rest of this post, but be warned: it assumes some basic familiarity with LaTeX, and I don't explain everything!<br />
<span id="more-254"></span></p>
<h2>Starting out</h2>
<p>The first steps when creating a slideshow are different to a regular document. In standard LaTeX, you open the document and just start writing, adding part, chapter and section headings as necessary. Creating a presentation is necessarily different. Here is a skeleton presentation:</p>
<pre>
<div class="codecolorer-container latex twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="latex codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E02020; ">\</span><span style="color: #800000;">documentclass</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;">style=paintings</span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">powerdot</span><span style="color: #E02020; ">}</span><br />
<span style="color: #2C922C; font-style: italic;">% Presentation metadata</span><br />
<span style="color: #E02020; ">\</span><span style="color: #800000;">title</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">My First Powerdot Presentation<span style="color: #E02020; ">}</span><br />
<span style="color: #E02020; ">\</span><span style="color: #800000;">author</span><span style="color: #E02020; ">{</span>Joe Bloggs<span style="color: #E02020; ">}</span><br />
<span style="color: #E02020; ">\</span><span style="color: #800000;">date</span><span style="color: #E02020; ">{</span>8th November 2010<span style="color: #E02020; ">}</span><br />
<br />
<span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">document</span></span><span style="color: #E02020; ">}</span><br />
<br />
&nbsp; <span style="color: #2C922C; font-style: italic;">% title slide</span><br />
&nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">maketitle</span><br />
<br />
&nbsp; <span style="color: #2C922C; font-style: italic;">% section: title takes up full slide</span><br />
&nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">section</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">First section</span><span style="color: #E02020; ">}</span><br />
<br />
&nbsp; <span style="color: #2C922C; font-style: italic;">% text slide:</span><br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}{</span>Slide Title<span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is an item<br />
&nbsp; &nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is also an item<br />
&nbsp; &nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> Finally, a third item in my list<br />
&nbsp; &nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}</span><br />
<br />
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">document</span></span><span style="color: #E02020; ">}</span></div></div>
</pre>
<p>Doesn't look too bad, right? The presentation is contained within the <code class="codecolorer text default"><span class="text">document</span></code>, and each slide is contained within a <code class="codecolorer text default"><span class="text">slide</span></code> environment. The <code class="codecolorer latex default"><span class="latex"><span style="color: #E02020; ">\</span><span style="color: #800000;">section</span></span></code> command now builds a standalone slide, as does the initial <code class="codecolorer latex default"><span class="latex"><span style="color: #E02020; ">\</span><span style="color: #800000;">maketitle</span></span></code>.</p>
<p>Almost anything that you can include in a normal document can be used on a slide, including tables and images, and tricks like using <code class="codecolorer latex default"><span class="latex"><span style="color: #E02020; ">\</span><span style="color: #800000;">vspace</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\stretch</span>{1}</span><span style="color: #E02020; ">}</span></span></code> at the beginning and end of the slide to vertically centre the content.</p>
<h2>Progressive disclosure</h2>
<p>Powerdot allows you to show only parts of a slide to your audience at a time, to emphasise each point (for example), or to better illustrate the flow through a diagram. This can be accomplished in two ways: the simple <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\pause</span></span></code> command, or the more complex and more powerful <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide</span></span></code>.</p>
<p>The simple <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\pause</span></span></code> command takes no arguments, and simply stops anything in the slide after that command from appearing, as if content display had been "paused" at that point. It is important to note that everything following the command is typeset, in order to work out the space it would have taken up. This ensures that your slide content doesn't shift around as you go through.</p>
<pre>
<div class="codecolorer-container latex twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="latex codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}{</span>Progressive Disclosure<span style="color: #E02020; ">}</span><br />
  <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is my first item<br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is the second item, after which we wait <span style="color: #800000; font-weight: normal;">\pause</span><br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> The third item appears on the page following the second <span style="color: #800000; font-weight: normal;">\pause</span><br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> And this fourth and final item appears on the page after the third<br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">slide</span></span><span style="color: #E02020; ">}</span></div></div>
</pre>
<p>Note that the command can be used multiple times, and it will work just as you might expect. If you want to do something more complex (such as displaying things out of order, displaying something over multiple frames, or scoping a change to a subset of the frames) you will need to use <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide</span></span></code>.</p>
<p>This command is much more powerful, and takes two arguments: the frames on which the contents should be displayed, and the contents themselves. The example above could be rewritten:</p>
<pre>
<div class="codecolorer-container latex twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="latex codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}{</span>Progressive Disclosure<span style="color: #E02020; ">}</span><br />
  <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is my first item<br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This is the second item, after which we wait<br />
&nbsp; &nbsp; <span style="color: #800000; font-weight: normal;">\onslide</span><span style="color: #E02020; ">{</span>2-<span style="color: #E02020; ">}{\</span><span style="color: #800000;">item</span> The third item appears on the page following the second<span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #800000; font-weight: normal;">\onslide</span><span style="color: #E02020; ">{</span>3-<span style="color: #E02020; ">}{\</span><span style="color: #800000;">item</span> And this fourth and final item appears on the page after the third<span style="color: #E02020; ">}</span><br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">slide</span></span><span style="color: #E02020; ">}</span></div></div>
</pre>
<p>But we could also (in theory) choose to do something more bizarre:</p>
<pre>
<div class="codecolorer-container latex twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="latex codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}{</span>Progressive Disclosure<span style="color: #E02020; ">}</span><br />
  <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #800000; font-weight: normal;">\onslide</span><span style="color: #E02020; ">{</span>4-<span style="color: #E02020; ">}{\</span><span style="color: #800000;">item</span> This is my first item, and the last to appear<span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #800000; font-weight: normal;">\onslide</span><span style="color: #E02020; ">{</span>3-<span style="color: #E02020; ">}{\</span><span style="color: #800000;">item</span> This is the second item, although technically the third<span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #800000; font-weight: normal;">\onslide</span><span style="color: #E02020; ">{</span>2-<span style="color: #E02020; ">}{\</span><span style="color: #800000;">item</span> The third item appears on the page following the fourth<span style="color: #E02020; ">}</span><br />
&nbsp; &nbsp; <span style="color: #E02020; ">\</span><span style="color: #800000;">item</span> This fourth and final item is actually the first that is visible<br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">itemize</span><span style="color: #E02020; ">}</span><br />
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">slide</span></span><span style="color: #E02020; ">}</span></div></div>
</pre>
<p>The <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide</span></span></code> command has three variations. The first version, as shown above, allocates space for items that have not yet been displayed. If you add a star to the command before its arguments (<code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide*</span></span></code>) then no space will be allocated. In the example above, this means that the new bullet points would appear to push the existing items downwards. If you add a plus to the command (<code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide</span>+</span></code>) then the contents will always be typeset, but a different colour will be used for the item on the specified slide(s).</p>
<p>I have found <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide*</span></span></code> to be particularly useful for progressive disclosure of diagrams, where not displaying an item at all can be very important.</p>
<h2>Graphics and diagrams</h2>
<p>It is important to remember that LaTeX itself will only accept graphics in EPS format via the <code class="codecolorer latex default"><span class="latex"><span style="color: #E02020; ">\</span><span style="color: #800000;">includegraphics</span></span></code> command from the <code class="codecolorer text default"><span class="text">graphicx</span></code> package. pdfTeX will allow other formats if used directly (including PNG) but something like <code class="codecolorer text default"><span class="text">pstricks</span></code> may then become unusable. For my presentation, I used a combination of <code class="codecolorer text default"><span class="text">pstricks</span></code> diagrams and included EPS images.</p>
<p>Building diagrams in <code class="codecolorer text default"><span class="text">pstricks</span></code> gave me a major advantage that I had not foreseen: the ability to define and then re-use a picture. I used this to good effect with the diagram of the OAuth "dance", showing the data flow between the User, Consumer, and Provider. When it came to the code samples for the implementation, I kept a miniature of this diagram on each slide to remind the viewer which stages of the dance were covered by the code on the current slide. This would not have been possible to do with OpenOffice (as far as I'm aware), and it saved me a great deal of time when I made changes to the original diagram.</p>
<p>If you have never used <code class="codecolorer text default"><span class="text">pstricks</span></code>, then I highly recommend it. Although it may seem weird to specify co-ordinates in a text file rather than drawing the image graphically, it is extremely powerful and I found that I soon got used to it. It is worth remembering that some programs, like Inkscape, can actually save a vector image as a set of <code class="codecolorer text default"><span class="text">pstricks</span></code> macros.</p>
<h2>Code samples</h2>
<p>Something that's often important when building a technical presentation is including one or more code samples. It's usually nice if they are syntax-highlighted in one way or another, to make it easier to read at a glance. By the way, it is generally advised that code samples in a presentation should be dark-coloured text on a light background rather than the other way round.</p>
<p>When it comes to using code samples in <code class="codecolorer text default"><span class="text">powerdot</span></code> presentations, there are two things to be aware of. Firstly, choosing the typesetting package. I have always used the <code class="codecolorer text default"><span class="text">listings</span></code> package for code samples. It has support for a large number of languages (as well as defining your own), and it is very configurable. You can even define short-cut environments for re-using options if you are working on a multiple-language presentation, for example.</p>
<p>The second thing to remember when adding listings to the presentation is that you need to inform the <code class="codecolorer text default"><span class="text">powerdot</span></code> package that a slide has special "verbatim" content. This is done with an optional argument to the slide, <code class="codecolorer text default"><span class="text">method</span></code>. This has three possible values (<code class="codecolorer text default"><span class="text">normal</span></code>, <code class="codecolorer text default"><span class="text">direct</span></code>, and <code class="codecolorer text default"><span class="text">file</span></code>), but I have only found the first two to work reliably.</p>
<p>If the slide contains verbatim content, you must use either the <code class="codecolorer text default"><span class="text">direct</span></code> or <code class="codecolorer text default"><span class="text">file</span></code> rendering method, otherwise you will get an error. The <code class="codecolorer text default"><span class="text">file</span></code> method can easily get confused (in my experience) and so I used <code class="codecolorer text default"><span class="text">direct</span></code>. The downside is that you cannot use the <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\pause</span></span></code> or <code class="codecolorer latex default"><span class="latex"><span style="color: #800000; font-weight: normal;">\onslide</span></span></code> commands in a <code class="codecolorer text default"><span class="text">direct</span></code>-rendered slide; they will be silently ignored.</p>
<pre>
<div class="codecolorer-container latex twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="latex codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">slide</span><span style="color: #E02020; ">}[</span><span style="color: #C08020; font-weight: normal;">method=direct</span><span style="color: #E02020; ">]{</span>Hello World in C<span style="color: #E02020; ">}</span><br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">lstlisting</span><span style="color: #E02020; ">}[</span><span style="color: #C08020; font-weight: normal;">language=c,gobble=4</span><span style="color: #E02020; ">]</span><br />
&nbsp; &nbsp; #include &lt;stdio.h&gt;<br />
<br />
&nbsp; &nbsp; int main(int c, char **v) <span style="color: #E02020; ">{</span><br />
&nbsp; &nbsp; &nbsp; fprintf(stdout, &quot;Hello, world!<span style="color: #800000; font-weight: normal;">\n</span>&quot;);<br />
&nbsp; &nbsp; &nbsp; return 0;<br />
&nbsp; &nbsp; <span style="color: #E02020; ">}</span><br />
&nbsp; <span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">lstlisting</span><span style="color: #E02020; ">}</span><br />
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #0000D0; font-weight: normal;">slide</span></span><span style="color: #E02020; ">}</span></div></div>
</pre>
<h2>Choosing and customising your style</h2>
<p>The visual style of your presentation can make a difference to how it is received. Dark text on a very light background is usually considered to be the most readable. The <code class="codecolorer text default"><span class="text">powerdot</span></code> package has <a title="Powerdot documentation" href="http://www.ctan.org/tex-archive/macros/latex/contrib/powerdot/docs/powerdot.pdf" target="_blank">a number of built-in styles</a> (pp. 21-25), and I eventually settled on a modified version of <code class="codecolorer text default"><span class="text">paintings</span></code> with the <code class="codecolorer text default"><span class="text">Charon</span></code> palette. Creating your own style is not difficult, and you have a large amount of control over how it looks. I won't go into it here, as it is already well covered by the <a title="Powerdot manual" href="http://www.ctan.org/tex-archive/macros/latex/contrib/powerdot/docs/powerdot.pdf" target="_blank">manual</a>.</p>
<h2>And finally...</h2>
<p>This is all very much a work in progress. This post was based upon my first experience of writing a presentation in LaTeX with <code class="codecolorer text default"><span class="text">powerdot</span></code>. As time goes on, I hope to build upon and standardise a visual style for both personal and company presentations. I am also prepared to send the LaTeX sources of my OAuth presentation to anyone who is interested, so please let me know either in the comments below or contact me by email or Twitter.</p>
<p>For me, the biggest advantage of LaTeX is that content comes first -- it's much easier to write a presentation without obsessing over how it looks until the very end. The better-defined your visual style, the less you have to worry about the design, and the more time you can spend making your presentation great!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2010/11/08/creating-a-presentation-with-latex-and-powerdot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Useful git configuration fragments</title>
		<link>http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/</link>
		<comments>http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 13:17:48 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[git]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[trick]]></category>
		<category><![CDATA[useful]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=240</guid>
		<description><![CDATA[Time for a quick micro-post, I think. I feel like sharing two useful fragments of my git configuration. First up, aliases. I have a few useful shortcuts defined, as well as some nice ways of displaying a repository's history. I've aliased many of the common commands to two-letter versions which evoke the similar Subversion command [...]]]></description>
			<content:encoded><![CDATA[<p>Time for a quick micro-post, I think. I feel like sharing two useful fragments of my git configuration.</p>
<p>First up, aliases. I have a few useful shortcuts defined, as well as some nice ways of displaying a repository's history. I've aliased many of the common commands to two-letter versions which evoke the similar Subversion command aliases:</p>
<pre>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[alias]<br />
  st = status<br />
&nbsp; di = diff<br />
&nbsp; co = checkout<br />
&nbsp; ci = commit<br />
&nbsp; br = branch<br />
&nbsp; sta = stash<br />
  graph = log --decorate --oneline --graph --branches --date-order<br />
  lg = log --graph --pretty=format:'%C(yellow)%h%Creset -%C(yellow)%d%Creset %s %C(green)(%cr)%Creset %Cred&lt;%an&gt;%Creset' --abbrev-commit --date=relative --date-order<br />
&nbsp; today = !git log --author=$(git config user.email) --since=yesterday</div></div>
</pre>
<p><span id="more-240"></span>The last alias (<code class="codecolorer text default"><span class="text">git today</span></code>) reminds you what you've done today. The previous two aliases provide a nice graphical view of history in the console. <code class="codecolorer text default"><span class="text">git graph</span></code> displays all history of all local branches in date order rather than topological order. This means that commits on different branches may be interleaved, rather than grouping commits on different branches. <code class="codecolorer text default"><span class="text">git lg</span></code> displays a little more information (including author and relative timestamps), and allows me to pick which branches I want to see. The examples below are all taken from the <a href="http://github.com/dingram/jerity" target="_blank">Jerity</a> repository.<br />

<a href='http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/screenshot-20100818-140818/' title='git graph example'><img width="150" height="150" src="http://www.dmi.me.uk/blog/wp-content/uploads/2010/08/screenshot-20100818-140818-150x150.png" class="attachment-thumbnail" alt="git graph example" title="git graph example" /></a>
<a href='http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/screenshot-20100818-140906/' title='git graph example with many branches'><img width="150" height="150" src="http://www.dmi.me.uk/blog/wp-content/uploads/2010/08/screenshot-20100818-140906-150x150.png" class="attachment-thumbnail" alt="git graph example with many branches" title="git graph example with many branches" /></a>
<a href='http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/screenshot-20100818-140936/' title='git lg example'><img width="150" height="150" src="http://www.dmi.me.uk/blog/wp-content/uploads/2010/08/screenshot-20100818-140936-150x150.png" class="attachment-thumbnail" alt="git lg example" title="git lg example" /></a>
<br />
The second tip is repository URL rewriting. This tackles the annoying problem of having submodules in projects that you want to be able to commit to, while making sure other people only see/use the read-only URLs. Git will very helpfully rewrite URLs from one form to another, so by having:</p>
<pre>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[url &quot;ssh://git@github.com/dingram/&quot;]<br />
  pushInsteadOf = git://github.com/dingram/</div></div>
</pre>
<p>in my configuration, I can <code class="codecolorer text default"><span class="text">git clone git://github.com/dingram/repository</span></code> and when I push, it will automatically push to <code class="codecolorer text default"><span class="text">git@github.com:dingram/repository</span></code> instead. This can be verified using <code class="codecolorer text default"><span class="text">git remote -v</span></code>. The only thing to beware of is the format: the replacement URL goes in the section header, and the pattern to be replaced appears in the section itself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2010/08/18/useful-git-configuration-fragments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Recovering from pvmove failure</title>
		<link>http://www.dmi.me.uk/blog/2010/01/07/recovering-from-pvmove-failure/</link>
		<comments>http://www.dmi.me.uk/blog/2010/01/07/recovering-from-pvmove-failure/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 23:25:29 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[emergency]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[lvm2]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[trick]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[useful]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=203</guid>
		<description><![CDATA[Note: This is a fairly rambling explanation of recent events. I assume that you have at least a passing knowledge of LVM and its terminology. This was written to prove that it is possible to recover from pvmove failing (in certain cases) due to the way it performs its operations and backs up metadata. The [...]]]></description>
			<content:encoded><![CDATA[
<p>Note: This is a fairly rambling explanation of recent events. I assume that you have at least a passing knowledge of <a title="LVM HOWTO (Chapter 3: Anatomy of LVM)" href="http://tldp.org/HOWTO/LVM-HOWTO/anatomy.html" target="_blank">LVM</a> and its terminology. This was written to prove that it is possible to recover from <code class="codecolorer text default"><span class="text">pvmove</span></code> failing (in certain cases) due to the way it performs its operations and backs up metadata.<span id="more-203"></span></p>
<h2>The background</h2>
<p>I recently received a new hard drive, and so I excitedly partitioned and formatted it, extended my <abbr title="Logical Volume Manager">LVM</abbr> <abbr title="Volume Groups">VGs</abbr> and merrily moved my <abbr title="logical volumes">LVs</abbr> completely across to the new drive using <code class="codecolorer text default"><span class="text">pvmove</span></code>. So far, so wonderful -- I was now ready to rebuild my other two drives so that only critical things were covered by <abbr title="Redundant Array of Inexpensive Disks">RAID</abbr> and everything else was just in a large VG that spanned multiple drives. I now had three drives, all Samsung SpinPoint:</p>
<ol>
<li>500GB  (<code class="codecolorer text default"><span class="text">sdb</span></code>)</li>
<li>1TB (<code class="codecolorer text default"><span class="text">sda</span></code>)</li>
<li>1.5TB (<code class="codecolorer text default"><span class="text">sdc</span></code>, and brand-new)</li>
</ol>
<p>The partition setup I wanted:</p>
<ul>
<li>48MiB RAID-1 across all drives, for <code class="codecolorer text default"><span class="text">/boot</span></code> (already set up across <code class="codecolorer text default"><span class="text">sda</span></code> and <code class="codecolorer text default"><span class="text">sdb</span></code>)</li>
<li>4.8GiB RAID-1 across all drives, for <code class="codecolorer text default"><span class="text">/</span></code>(already set up across <code class="codecolorer text default"><span class="text">sda</span></code> and <code class="codecolorer text default"><span class="text">sdb</span></code>)</li>
<li>50GiB RAID-1 across all drives, for  <code class="codecolorer text default"><span class="text">/usr</span></code>, <code class="codecolorer text default"><span class="text">/opt</span></code>, <code class="codecolorer text default"><span class="text">/var</span></code></li>
<li>50GiB RAID-5 across all drives, for <code class="codecolorer text default"><span class="text">/home</span></code> (giving 100GiB usable space)</li>
<li>The rest of each drive divided into 50/100GiB partitions, to be spread among my large data VG, containing films, music, backups, and other large data.</li>
</ul>
<h2>The disaster</h2>
<p>I moved all of the existing LVs to the new drive, which had plenty of space. Next, I sorted out the partitions for the two older drives, and initialised the RAIDs for my <code class="codecolorer text default"><span class="text">sys</span></code> and <code class="codecolorer text default"><span class="text">safe</span></code> VGs:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># set up RAID-1 across /dev/sda3, /dev/sdb3 and (later) /dev/sdc3</span><br />
mdadm <span style="color: #660033;">-C</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md2 <span style="color: #660033;">-l1</span> <span style="color: #660033;">-n3</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda3 <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb3 missing<br />
<span style="color: #666666; font-style: italic;"># initialise the RAID for LVM</span><br />
pvcreate <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md2<br />
<span style="color: #666666; font-style: italic;"># set up RAID-5 across /dev/sda5, /dev/sdb5 and (later) /dev/sdb5</span><br />
mdadm <span style="color: #660033;">-C</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3 <span style="color: #660033;">-l5</span> <span style="color: #660033;">-n3</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda5 <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb5 missing<br />
pvcreate <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3</div></div>
<p>I then expanded the VGs and started to copy data across. I began with the <code class="codecolorer text default"><span class="text">safe</span></code> VG that contained <code class="codecolorer text default"><span class="text">/home</span></code>, as I wanted to be sure it was indeed safe. I have all of the photos I've ever taken, my email backups and archives, and various private keys and other important data, as well as things that could be replaced due to duplication elsewhere (including working copies of most of my projects). Being LVM, I could move the LVs around without needing to unmount them or reboot into a LiveCD:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># extend the volume groups</span><br />
vgextend sys <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md2<br />
vgextend safe <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3<br />
<span style="color: #666666; font-style: italic;"># move all data from /dev/sdc2 to other volumes in the group</span><br />
pvmove <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdc2<br />
<span style="color: #666666; font-style: italic;"># ... disaster struck before the second pvmove</span><br />
pvmove <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdc1</div></div>
<p>Then, disaster struck:  <code class="codecolorer text default"><span class="text">pvmove</span></code> spat a set of I/O errors at me... but kept running! I wasn't paying attention (as moving 40GiB of data takes quite a while) and so I had just left it to work away.</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">pvmove: dev_open(/dev/sda) called while suspended<br />
pvmove: dev_open(/dev/sda1) called while suspended<br />
pvmove: dev_open(/dev/sda2) called while suspended<br />
pvmove: dev_open(/dev/sda3) called while suspended<br />
pvmove: dev_open(/dev/sda5) called while suspended<br />
pvmove: dev_open(/dev/md2) called while suspended<br />
pvmove: dev_open(/dev/md3) called while suspended</div></div>
<p>It was only after it had completed and I started getting I/O and "permission denied" errors while trying to access my home directory that I first realised anything had gone wrong. After some <a title="Google: pvmove dev_open called while suspended recover" href="http://www.google.com/search?q=pvmove+dev_open+called+while+suspended+recover" target="_blank">frantic searching</a> on the Internet, it seemed that I had to wave goodbye to all of my personal data, including those bits that weren't backed up (though I've learned my lesson about backups now!).</p>
<p>I was determined not to give in to data loss, and so I gave myself a few recovery options:</p>
<ol>
<li>Create an image of the partition where the data used to reside.</li>
<li>Try to recover pictures (the most critical thing for me) via <a title="Foremost on SourceForge" href="http://foremost.sourceforge.net/" target="_blank">foremost</a>, which is a non-destructive operation.</li>
<li>Try to rebuild the file system using <code class="codecolorer text default"><span class="text">reiserfsck --rebuild-tree</span></code>.</li>
</ol>
<p>During my investigations and poking around, I discovered that there was another option: I could try to rebuild the VG from an old copy of its metadata.</p>
<h2>Introduction to recovery</h2>
<p>It turns out that many LVM utilities store a backup of the VG's metadata before and after performing various operations, so as long as your <code class="codecolorer text default"><span class="text">/etc/lvm</span></code> directory is fine, you have a fighting chance. (Actually, it is theoretically possible to retrieve old versions of the metadata from the LVM partition itself, but this gets much more complex and I won't deal with it here.)</p>
<p>The reason for this is that <code class="codecolorer text default"><span class="text">pvmove</span></code> works by creating a temporary target LV, mirroring data from the existing LV to the temporary target (making checkpoints along the way), and only removing the original once the mirroring has completed. This operation can then be interrupted and resumed at any time without loss of data. This also has the advantage that a full copy of the data on the original LV is still available; only the metadata explaining where it begins and ends has changed.</p>
<p>To access the old versions of this metadata, investigate the contents of your <code class="codecolorer text default"><span class="text">/etc/lvm/archive</span></code> directory as root. You should find one or more files of the form <code class="codecolorer text default"><span class="text">volgroup_nnnnn.vg</span></code>, where <code class="codecolorer text default"><span class="text">volgroup</span></code> is the name of the relevant VG and <code class="codecolorer text default"><span class="text">nnnnn</span></code> is a number. These files contain a backup of the volume group's metadata, such as which partitions it resides on and where it's located. The contents may look something like this:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># Generated by LVM2 version 2.02.56(1) (2009-11-24): Mon Jan &nbsp;4 17:09:24 2010<br />
<br />
contents = &quot;Text Format Volume Group&quot;<br />
version = 1<br />
<br />
description = &quot;Created *before* executing 'vgextend safe /dev/md/3'&quot;<br />
<br />
creation_host = &quot;hostname&quot; &nbsp;# Linux hostname 2.6.31-gentoo-r3 #3 SMP Mon Nov 23 11:31:59 GMT 2009 i686<br />
creation_time = 1262624964 &nbsp;# Mon Jan &nbsp;4 17:09:24 2010<br />
<br />
safe {<br />
id = &quot;zbSAI8-ExUy-PxJw-SHX7-y9PL-AL2y-kiTk8g&quot;<br />
seqno = 10<br />
status = [&quot;RESIZEABLE&quot;, &quot;READ&quot;, &quot;WRITE&quot;]<br />
flags = []<br />
extent_size = 8192 &nbsp; &nbsp;# 4 Megabytes<br />
max_lv = 0<br />
max_pv = 0<br />
<br />
physical_volumes {<br />
<br />
pv0 {<br />
id = &quot;Vw3IF5-U92i-V2aL-9we1-A4E7-7j1P-4G142u&quot;<br />
device = &quot;/dev/sdc1&quot; &nbsp;# Hint only<br />
<br />
status = [&quot;ALLOCATABLE&quot;]<br />
flags = []<br />
dev_size = 199993122 &nbsp;# 95.3642 Gigabytes<br />
pe_start = 384<br />
pe_count = 24413 &nbsp;# 95.3633 Gigabytes<br />
}<br />
}<br />
<br />
logical_volumes {<br />
<br />
home {<br />
id = &quot;glU5zb-l9I7-SzGg-aXx5-lvgL-on4r-Faqkes&quot;<br />
status = [&quot;READ&quot;, &quot;WRITE&quot;, &quot;VISIBLE&quot;]<br />
flags = []<br />
segment_count = 1<br />
<br />
segment1 {<br />
start_extent = 0<br />
extent_count = 12799 &nbsp;# 49.9961 Gigabytes<br />
<br />
type = &quot;striped&quot;<br />
stripe_count = 1 &nbsp;# linear<br />
<br />
stripes = [<br />
&quot;pv0&quot;, 0<br />
]<br />
}<br />
}<br />
}<br />
}</div></div>
<p>I went through the backups for my <code class="codecolorer text default"><span class="text">safe</span></code> volume group, and found the one before I extended the volume group to the (now corrupt) <code class="codecolorer text default"><span class="text">/dev/md3</span></code>, which is actually the example given above.</p>
<h2>Recovering the volume group</h2>
<p>It was at this point that I rebooted and held my breath. I brought the system into runlevel 1 (single-user mode) and logged in as root. Out of curiosity I ran some SMART tests on the drives -- <code class="codecolorer text default"><span class="text">sda</span></code> was reporting no partitions, and internal testing eventually reported a persistent read error at about 80% into the drive. It looked like that drive was toast, which would explain why writing to the RAID-5 had failed.</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">smartctl <span style="color: #660033;">-t</span> short <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda<br />
<span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">180</span><br />
smartctl <span style="color: #660033;">--all</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda</div></div>
<p>After verifying that it was a hardware issue, I decided to try to point the VG at its previous location (just <code class="codecolorer text default"><span class="text">/dev/sdc1</span></code>), thereby getting it to forget that the <code class="codecolorer text default"><span class="text">home</span></code> LV was on the now-inaccessible RAID-5. This could be accomplished by the magic of <code class="codecolorer text default"><span class="text">vgcfgrestore</span></code>:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># restore the VG metadata for the &quot;safe&quot; VG from the given file</span><br />
vgcfgrestore <span style="color: #660033;">-f</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>lvm<span style="color: #000000; font-weight: bold;">/</span>archive<span style="color: #000000; font-weight: bold;">/</span>safe_00006.vg safe<br />
<span style="color: #666666; font-style: italic;"># re-scan for VGs, and &quot;safe&quot; should show up as inactive</span><br />
vgscan<br />
<span style="color: #666666; font-style: italic;"># activate the VG and any LVs inside</span><br />
vgchange <span style="color: #660033;">-ay</span> safe<br />
<span style="color: #666666; font-style: italic;"># re-scan for LVs and verify that safe/home exists</span><br />
lvscan<br />
<span style="color: #666666; font-style: italic;"># not taking any chances -- mount it read-only</span><br />
<span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">-o</span> ro <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>safe<span style="color: #000000; font-weight: bold;">/</span>home <span style="color: #000000; font-weight: bold;">/</span>home</div></div>
<p>After the <code class="codecolorer text default"><span class="text">mount</span></code> succeeded, I began to copy all of the data to my large partition, where it should be safe. I also copied the major bits I didn't want to lose to a USB flash drive as well, just to be certain. Once that was done, I took a deep breath and rebooted again, this time back to the full system.</p>
<h2>Clearing up afterwards</h2>
<p>Fortunately, everything worked fine -- it was as if nothing had ever gone wrong! All that was left now was to rebuild the broken RAID section.</p>
<p>I decided for safety that I would re-initialise the <code class="codecolorer text default"><span class="text">safe</span></code> VG's RAID as RAID-1 rather than RAID-5, so that any two of the drives could fail without losing my precious data:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># stop the RAID array</span><br />
mdadm <span style="color: #660033;">-S</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3<br />
<span style="color: #666666; font-style: italic;"># remove the RAID descriptors from the partitions</span><br />
mdadm <span style="color: #660033;">--zero-superblock</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda5<br />
mdadm <span style="color: #660033;">--zero-superblock</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb5<br />
<span style="color: #666666; font-style: italic;"># create as RAID-1</span><br />
mdadm <span style="color: #660033;">-C</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3 <span style="color: #660033;">-l1</span> <span style="color: #660033;">-n3</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda5 <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb5 missing</div></div>
<p>What I hadn't anticipated was that this would rebuild the RAID-1 using the data from the previous RAID-5... including the LVM descriptors and corrupt content. Once the RAID was online, I ran <code class="codecolorer text default"><span class="text">pvscan</span></code> and received a warning that the VG metadata was inconsistent. For one heart-stopping moment, it also appeared that LVM thought my home partition was on the corrupt RAID! I quickly stopped the array and thought again.</p>
<p>After some further investigation, I discovered that the first 256 sectors of a partition are used by LVM to hold various information (including multiple copies of the VG metadata). All I had to do to fix this was to destroy that information:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># ensure the array is stopped</span><br />
mdadm <span style="color: #660033;">-S</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3<br />
<span style="color: #666666; font-style: italic;"># zero the first 256 sectors</span><br />
<span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda5 <span style="color: #007800;">bs</span>=<span style="color: #000000;">512</span> <span style="color: #007800;">count</span>=<span style="color: #000000;">256</span><br />
<span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb5 <span style="color: #007800;">bs</span>=<span style="color: #000000;">512</span> <span style="color: #007800;">count</span>=<span style="color: #000000;">256</span><br />
<span style="color: #666666; font-style: italic;"># recreate the array -- it may complain that they are already in an array</span><br />
mdadm <span style="color: #660033;">-C</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>md3 <span style="color: #660033;">-l1</span> <span style="color: #660033;">-n3</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sda5 <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb5 missing</div></div>
<p>Once this was done, I could run <code class="codecolorer text default"><span class="text">pvcreate /dev/md3</span></code> and proceed to extend the VG and <code class="codecolorer text default"><span class="text">pvmove</span></code> data as before, without worrying that <code class="codecolorer text default"><span class="text">sda</span></code> would give out on me and cause everything to fail again.</p>
<p>I hope this helps someone!</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 3427px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">mdadm -C /dev/md3 -l1 -n3 /dev/sda5 /dev/sdb5 missing</div>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2010/01/07/recovering-from-pvmove-failure/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Hearing aid direct audio input</title>
		<link>http://www.dmi.me.uk/blog/2009/11/16/hearing-aid-dai/</link>
		<comments>http://www.dmi.me.uk/blog/2009/11/16/hearing-aid-dai/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 22:59:16 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[dai]]></category>
		<category><![CDATA[direct audio input]]></category>
		<category><![CDATA[europlug]]></category>
		<category><![CDATA[hearing aid]]></category>
		<category><![CDATA[pinout]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=195</guid>
		<description><![CDATA[Many hearing aids can handle direct audio input (DAI), often via a "shoe" that attaches to contacts on the aid itself. This shoe then provides a DAI jack (sometimes called a europlug or eurojack) that cables can be plugged into. There seems to be a complete lack of cables designed for people with a single [...]]]></description>
			<content:encoded><![CDATA[<p>Many hearing aids can handle direct audio input (DAI), often via a "shoe" that attaches to contacts on the aid itself. This shoe then provides a DAI jack (sometimes called a europlug or eurojack) that cables can be plugged into.</p>
<p>There seems to be a complete lack of cables designed for people with a single hearing aid, so one of my upcoming projects will be to convert a Y-cable that can serve two hearing aids into a joint DAI/earphone cable instead.</p>
<div id="attachment_199" class="wp-caption alignright" style="width: 160px"><img class="size-thumbnail wp-image-199" title="DAI connector pinout" src="http://www.dmi.me.uk/blog/wp-content/uploads/2009/11/dai-connector-pinout-150x150.jpg" alt="DAI connector pinout" width="150" height="150" /><p class="wp-caption-text">DAI connector pinout</p></div>
<p>The DAI connector has the following pinout:</p>
<ul>
<li><strong>short/thick pin:</strong> ground</li>
<li><strong>long/thin pin:</strong> VDD (apparently -- doesn't seem to actually be connected to anything on a 3.5mm cable)</li>
<li><strong>short/thin pin:</strong> signal</li>
</ul>
<p>Remember that a standard 3.5mm audio plug has the following pinout:</p>
<ul>
<li> <strong>tip:</strong> left signal</li>
<li><strong>inner sheath:</strong> right signal</li>
<li><strong>outer sheath:</strong> ground</li>
</ul>
<p>Next stage: connecting an earphone to the plug on one side of the cable, to see if there are any impedance issues, although the cable I am using (an fmGenie one) is a very low-impedance cable because I have an Oticon hearing aid. Measured with a multimeter, it seems to be around 0Ω, so I think that's good enough for me. I believe attenuated cables have a 330kΩ resistor in series with each signal line (according to Neil Ferguson's <a href="http://gfern.com/btha/btha.html" target="_blank">bluetooth hearing aid hack</a> page).</p>
<p>My ultimate goal is to get hold of a DAI jack that I can solder directly to an old earphone, so that I can just plug the spare DAI cable into the earphone directly, almost as if it were a hearing aid itself. Unfortunately, it seems that it is impossible to get hold of such things. According to Connevans, DAI jacks are only custom-made for hearing aid shoes. After some discussion, it seems like I should be able to make one myself though (with some help!) so we shall have to see how that turns out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2009/11/16/hearing-aid-dai/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>A content-based file manager</title>
		<link>http://www.dmi.me.uk/blog/2009/06/04/a-content-based-file-manager/</link>
		<comments>http://www.dmi.me.uk/blog/2009/06/04/a-content-based-file-manager/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 22:12:38 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Insight (semantic filesystem)]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Braindump]]></category>
		<category><![CDATA[file manager]]></category>
		<category><![CDATA[ideas]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=124</guid>
		<description><![CDATA[I've been thinking recently about Insight again, and I've been considering part of the problem with naming and uniqueness. Names in a traditional file system are made unique based on a full path to the file, but most people think of a file name as just the final component. This would then cause a problem [...]]]></description>
			<content:encoded><![CDATA[<p>I've been thinking recently about Insight again, and I've been considering part of the problem with naming and uniqueness.</p>
<p>Names in a traditional file system are made unique based on a full path to the file, but most people think of a file name as just the final component. This would then cause a problem with the move to Insight, as a file could appear in multiple directories, and its only distinguishing feature would be the final component of its path. This is counter-intuitive and can cause all sorts of problems.</p>
<p>Consider makefiles, for example. They rely on a standard named file (<tt>Makefile</tt>) appearing at various levels in the hierarchy in order to work. Obviously, you would want different makefiles at different levels and in different projects, but Insight as it stands has no way to handle this.</p>
<p>I then started thinking about what makes a file unique. In the end, I came up with two things: name and content. This covers the makefile case (same name, different content) as well as the backup case (same content, different name). It then occurred to me that, in the general case, all you need to distinguish a file is its content, and then actually finding it can all be left up to metadata.</p>
<p><span id="more-124"></span>If files are then thought of as containers for data that happen to have a unique internal identifier (which never needs to be exposed to the user, although it can be accessed as, say, the file's inode number) then the idea of a content-based file manager comes into play. These examples work best with visual media, particularly images, but there is no reason in principle that this could not be extended.</p>
<p>Imagine searching for a file. You know it's a photo, but you have a large collection of them. With a digital camera and a large-capacity memory card, who needs to ever delete a photo? We'll assume that you've dilligently tagged the photos with metadata as you've imported them from the camera, through some easy batch process.</p>
<p>On the tagging point: a lot can be taken from the metadata stored by the camera (date/time, resolution, orientation, black and white/colour, perhaps GPS co-ordinates) and with the right tools, more can be inferred (auto-tagging faces, buildings, perhaps recognising common events like football matches, converting GPS co-ordinates to places, ...). As time goes on, people will need to do less and less manual tagging.</p>
<p>Anyway, back to the file manager. You know you are after a picture or a set of pictures. Normal thought processes will probably follow a path similar to: "Yeah, I wanted to show dad those <strong>photos</strong> from that <strong>holiday</strong> in <strong>Paris</strong> that we had <strong>two months ago</strong>. I think he'd particularly like the ones we got of the <strong>Louvre</strong>, as well as the ones <strong>with me in</strong>, of course." I've highlighted various key words that can be translated directly to metadata searches. Notice how these all involve a narrowing down of the query.</p>
<p>To convert these to filters, we then have:</p>
<ul>
<li>type: <strong>photo</strong></li>
<li><strong>holiday</strong></li>
<li>location: <strong>Paris</strong></li>
<li>date: <strong>two months ago</strong></li>
<li>at least one of:
<ul>
<li>location: <strong>Louvre</strong></li>
<li>person: <strong>Me</strong></li>
</ul>
</li>
</ul>
<p>This could also be represented by a query:</p>
<blockquote>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">type:photo AND holiday AND location:Paris AND date:-2m<br />
AND (location:Louvre OR person:me)</div></div>
</blockquote>
<p>Breaking it down in this way feels fairly technical and wordy, however. I'd much prefer a visual view.</p>
<p>Imagine a black field, speckled with points of light representing your photos:</p>
<p><img class="aligncenter size-full wp-image-131" title="Content File Manager 1" src="http://www.dmi.me.uk/blog/wp-content/uploads/2009/06/content-file-manager-1.png" alt="Content File Manager 1" width="450" height="340" /></p>
<p>You filter by "holiday", and (because it learns based on previous searches) it then groups by location. The ones which have been filtered out fade into nothing, and the photos group into labelled blobs and enlarge slightly:</p>
<p><img class="aligncenter size-full wp-image-132" title="Content File Manager 2" src="http://www.dmi.me.uk/blog/wp-content/uploads/2009/06/content-file-manager-2.png" alt="Content File Manager 2" width="450" height="340" /></p>
<p>You filter by date, and as you drag the slider, irrelevant items fade away and relevant ones enlarge:</p>
<p><img class="aligncenter size-full wp-image-133" title="Content File Manager 3" src="http://www.dmi.me.uk/blog/wp-content/uploads/2009/06/content-file-manager-3.png" alt="Content File Manager 3" width="450" height="340" /></p>
<p>Then you add the final filters and set the photos up for viewing, perhaps as a slideshow... and you're done!</p>
<p>Pretty neat, I think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2009/06/04/a-content-based-file-manager/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>In-place array uniq in C</title>
		<link>http://www.dmi.me.uk/blog/2008/07/10/in-place-uniq-in-c/</link>
		<comments>http://www.dmi.me.uk/blog/2008/07/10/in-place-uniq-in-c/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 21:43:55 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Insight (semantic filesystem)]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=64</guid>
		<description><![CDATA[I've been developing Insight even though the uni project has come to an end, because it's fun! I also want to make it more stable and eventually release it under an open-source licence of some kind. There will be an update coming soon, I promise! I now have Internet, so I can write up some [...]]]></description>
			<content:encoded><![CDATA[<p>I've been developing <strong>Insight</strong> even though the uni project has come to an end, because it's fun! I also want to make it more stable and eventually release it under an open-source licence of some kind. There will be an update coming soon, I promise! I now have Internet, so I can write up some things...  Anyway, one of the interesting things I wanted to do for Insight was an in-place form of <tt>uniq</tt> for an array, ideally without any additional memory allocation. It seems that this is something nobody else has done yet! So I set about doing it myself...  For those of you who are unfamiliar with the Linux/UNIX command <tt>uniq</tt>, it takes a sorted list and removes any duplicates. This is almost exactly what I'm trying to do, with one caveat: I need to keep the "discarded" duplicates.  What happens is that I have an array containing a number of strings, and these have all been dynamically allocated via <tt>malloc()</tt> or <tt>calloc()</tt>. If I just remove or overwrite their pointers, they'll vanish and cause a memory leak. While I've now fixed a large number of leaks thanks to <a title="Valgrind debugger/profiler" href="http://valgrind.org" target="_blank">Valgrind</a>, I'm trying to actively avoid any possibility of adding them.  Read on for the details... <span id="more-64"></span></p>
<h2>The Idea</h2>
<p>The basic idea is that we have a sorted list of items that may have some duplicates, say:</p>
<pre>{A<sub>0</sub>, A<sub>1</sub>, B<sub>0</sub>, C<sub>0</sub>, C<sub>1</sub>, E<sub>0</sub>, F<sub>0</sub>, F<sub>1</sub>, F<sub>2</sub>, G<sub>0</sub>, H<sub>0</sub>, H<sub>1</sub>}</pre>
<p>and we want to remove all of the duplicates, so we get two sets:</p>
<pre>{A<sub>0</sub>, B<sub>0</sub>, C<sub>0</sub>, E<sub>0</sub>, F<sub>0</sub>, G<sub>0</sub>, H<sub>0</sub>} {A<sub>1</sub>, C<sub>1</sub>, F<sub>1</sub>, F<sub>2</sub>, H<sub>1</sub>}</pre>
<p>Note that it doesn't matter which of the duplicates ends up in which set, just that the items in the first are all unique and that we don't lose any. Also, <tt>A<sub>0</sub></tt> and <tt>A<sub>1</sub></tt> have the same value but the subscript will help to distinguish exactly which of the <tt>A</tt>s I'm talking about.  Now we have the problem, let's look at some solutions.</p>
<h3>Lossless solution - additional lists</h3>
<p>So the first solution uses two temporary lists, <tt>unique</tt> and <tt>duplicate</tt>. We start with two pointers into the original list: <tt>p</tt> and <tt>q</tt>. We set <tt>p</tt> to point to the start of the list, and <tt>q</tt> to point to the element after <tt>p</tt>. We then copy the item <tt>p</tt> points at to our <tt>unique</tt> list. Then, while we still have more items to examine:</p>
<ul>
<li>If the items pointed to by <tt>p</tt> and <tt>q</tt> have the same value, then we copy the item <tt>q</tt> points at to the <tt>duplicate</tt> list and advance <tt>p</tt> and <tt>q</tt>.</li>
<li>If they are different, we copy the item at <tt>q</tt> to our <tt>unique</tt> list, and advance <tt>p</tt> and <tt>q</tt>.</li>
</ul>
<p>We keep doing this until we get to the end of the array, and then copy the <tt>unique</tt> list to the start of the array, the <tt>duplicate</tt> list after that (both overwriting the previous contents) and set the number of unique items to the length of the <tt>unique</tt></p>
<p>list.</p>
<h3>Lossy solution - one list</h3>
<p>We can do a similar thing in-place, although this will result in data loss. The essential idea is:</p>
<ul>
<li>We start in the same way: <tt>p</tt> pointing to the first element, and <tt>q</tt> to the second</li>
<li>While <tt>q</tt> has the same value as <tt>p</tt>, advance <tt>q</tt> along the list</li>
<li>When they are different, advance <tt>p</tt>, copy <tt>q</tt> to <tt>p</tt>, and advance <tt>q</tt></li>
<li>Once <tt>q</tt> goes past the end of the list, we're done, and the offset of <tt>p</tt> is the number of unique items.</li>
</ul>
<p>Now this is quite simple, and only requires one pass through the list, but it results in the loss of information, which is unacceptable in this case.</p>
<h3>Lossless solution - one list</h3>
<p>For this solution, we can also do it with one pass through the list and two pointers.  The basic intuition is that we're going through the array, accumulating a rotating block of stuff that we don't want. At any given point:</p>
<ul>
<li>Everything between the start and <tt>p</tt> (not inclusive) is the unique list (so far)</li>
<li>Everything between <tt>p</tt> and <tt>q</tt> (not inclusive) is an unwanted duplicate</li>
<li>Everything between <tt>q</tt> (inclusive) and the end is yet to be processed.</li>
</ul>
<p>At the end, we return the number of unique items at the start of the list; everything above that is a duplicate.</p>
<h2>For integers</h2>
<p>Here is some pseudo-Java that performs my algorithm for a set of integers.</p>
<pre>
<div class="codecolorer-container c twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">int</span> set_uniq<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> set<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #993333;">int</span> count <span style="color: #339933;">=</span> set.<span style="color: #202020;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #993333;">int</span> tmp<span style="color: #339933;">,</span> p<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> q<span style="color: #339933;">=</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>p <span style="color: #339933;">&lt;</span> set.<span style="color: #202020;">length</span> <span style="color: #339933;">&amp;&amp;</span> q <span style="color: #339933;">&lt;</span> set.<span style="color: #202020;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>p <span style="color: #339933;">&lt;</span> set.<span style="color: #202020;">length</span> <span style="color: #339933;">&amp;&amp;</span> set<span style="color: #009900;">&#91;</span>p<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> set<span style="color: #009900;">&#91;</span>q<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; p <span style="color: #339933;">=</span> p <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>q <span style="color: #339933;">&lt;</span> set.<span style="color: #202020;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p <span style="color: #339933;">&lt;</span> q<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tmp <span style="color: #339933;">=</span> set<span style="color: #009900;">&#91;</span>p<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set<span style="color: #009900;">&#91;</span>p<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> set<span style="color: #009900;">&#91;</span>q<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set<span style="color: #009900;">&#91;</span>q<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> tmp<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; q <span style="color: #339933;">=</span> q <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&gt;</span> p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; count <span style="color: #339933;">=</span> p<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>q <span style="color: #339933;">&lt;</span> max <span style="color: #339933;">&amp;&amp;</span> set<span style="color: #009900;">&#91;</span>p<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> set<span style="color: #009900;">&#91;</span>q<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; q <span style="color: #339933;">=</span> q <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// q hit the end and is still the same as p</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&gt;</span> p<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; count <span style="color: #339933;">=</span> p <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">return</span> count<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<h2>The general code</h2>
<p>The arguments to the general <tt>set_uniq()</tt> function are very similar to the arguments to standard <tt>qsort()</tt>:</p>
<ul>
<li>The (sorted) array to work on</li>
<li>The number of items in the array</li>
<li>The size of each item in the array</li>
<li>A comparator function that returns a negative integer if the first argument is less than the second, zero if they are equal, and a positive integer if the first argument is greater than the second.</li>
</ul>
<p>So, without further ado, my code:</p>
<pre>
<div class="codecolorer-container c twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">int</span> set_uniq<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>set<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #993333;">size_t</span> count<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #993333;">size_t</span> elem_size<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #993333;">int</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>cmp<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>q<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>max<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>tmp<span style="color: #339933;">=</span><span style="color: #000066;">calloc</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> elem_size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* TODO: check for failure */</span><br />
&nbsp; p<span style="color: #339933;">=</span>set<span style="color: #339933;">;</span><br />
&nbsp; q<span style="color: #339933;">=</span>set<span style="color: #339933;">+</span>elem_size<span style="color: #339933;">;</span><br />
&nbsp; max<span style="color: #339933;">=</span>set<span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span>count<span style="color: #339933;">*</span>elem_size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">&lt;</span> p<span style="color: #339933;">-</span>set<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; count <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-</span>set<span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span>elem_size<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>q p<span style="color: #339933;">-</span>set<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; count <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-</span>set<span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span>elem_size<span style="color: #339933;">;</span><br />
&nbsp; ifree<span style="color: #009900;">&#40;</span>tmp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> count<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<h2>Conclusion</h2>
<p>This code is released under a Creative Commons licence (see below). A similar idea will work well for other solutions, like set difference. I'll post those later if anyone really cares.  Also, there is a better way of swapping the items by using the fact that:</p>
<pre>
<div class="codecolorer-container c twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">a <span style="color: #339933;">^=</span> b<span style="color: #339933;">;</span><br />
b <span style="color: #339933;">^=</span> a<span style="color: #339933;">;</span><br />
a <span style="color: #339933;">^=</span> b<span style="color: #339933;">;</span></div></div>
</pre>
<p>swaps a and b without needing a temporary variable. If you just go along the data in 32-bit chunks, performing those XOR operations to swap the data. This actually works out to be 30% or so faster (if I remember correctly).  Finally - general code like this is always going to be slower than code that's been specialised for a particular purpose. Calling this on integers, for example, will be much slower than coding an integer-specific version. I should also point out that you can just overwrite integers, as you don't need to free them <img src='http://www.dmi.me.uk/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' title="icon wink photo" /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2008/07/10/in-place-uniq-in-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Insight: An update</title>
		<link>http://www.dmi.me.uk/blog/2008/06/09/insight-an-update/</link>
		<comments>http://www.dmi.me.uk/blog/2008/06/09/insight-an-update/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 16:29:55 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Insight (semantic filesystem)]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[University]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=56</guid>
		<description><![CDATA[Just a very brief update for the last few days: Files can now be opened and read - writing and deletion coming soon! File import does tend to confuse ln, as it expects the new destination to be a symlink rather than a file. Nothing I can really do about this for now though! I've [...]]]></description>
			<content:encoded><![CDATA[<p>Just a very brief update for the last few days:</p>
<ul>
<li>Files can now be opened and read - writing and deletion coming soon!</li>
<li>File import does tend to confuse ln, as it expects the new destination to be a symlink rather than a file. Nothing I can really do about this for now though!</li>
<li>I've manually assigned some tags to files, and queries now work beautifully (apart from subcategory union, which I hope to tackle later tonight).</li>
<li>Having said that, only simple conjunctive queries work, as there's no support for negation or disjunction. Yet.</li>
<li>Inode set functions are now in place and working.</li>
</ul>
<p>One more update before I get back to coding... Insight now has an official logo!</p>
<p><img class="aligncenter size-full wp-image-57" title="Insight logo (blue)" src="http://www.dmi.me.uk/blog/wp-content/uploads/2008/06/insight_blue_letters.png" alt="Insight logo" width="300" height="100" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2008/06/09/insight-an-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Insight: Where am I now, and where next?</title>
		<link>http://www.dmi.me.uk/blog/2008/06/05/insight-where-am-i-now-and-where-next/</link>
		<comments>http://www.dmi.me.uk/blog/2008/06/05/insight-where-am-i-now-and-where-next/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 23:18:29 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Insight (semantic filesystem)]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[University]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=55</guid>
		<description><![CDATA[So I've been in Deep Coding Mode™ for quite a while. What have I got to show for it? Well, the short answer is that Insight is now a functioning file system... for a given definition of "functioning". As of this morning: It can successfully import files from the rest of the hierarchy Tags (i.e. [...]]]></description>
			<content:encoded><![CDATA[<p>So I've been in Deep Coding Mode™ for quite a while. What have I got to show for it?</p>
<p>Well, the short answer is that <strong>Insight</strong> is now a functioning file system... for a given definition of "functioning".</p>
<p><span id="more-55"></span></p>
<p>As of this morning:</p>
<ul>
<li>It can successfully import files from the rest of the hierarchy</li>
<li>Tags (i.e. directories) can be created and removed at any level.</li>
<li>Tags appear and disappear more or less as you expect (i.e. if you already have a tag in your path, it won't show up in listings again).</li>
<li>Tags that are synonyms will show up as symbolic links to the actual target tag (but currently do not obey the rule in the point above, i.e. if their target has been used in the path, they may still appear).</li>
</ul>
<p>So far, so good. Now for the limitations:</p>
<ul>
<li>Files cannot currently be opened, read from, written to, or deleted.</li>
<li>Files must be imported in a strange manner: as absolute symbolic links. They then show up as regular files, although they are actually just links to the originals elsewhere in the filesystem.</li>
<li>Tags cannot be assigned to files (or removed from them)</li>
<li>Files can therefore only be imported at the root level</li>
<li>Queries have no effect on file listing, and so listings just show files in limbo</li>
<li>Of course, there is no subcategory union either.</li>
</ul>
<p>But I am working on all of these things. At the moment, the main thing is sorting out the internal inode lists. Once those are done, then it should be quite straightforward to do tag assignment/removal and import directly into tags. Plan of action, therefore:</p>
<ol>
<li>Implement inode insertion/deletion</li>
<li>Implement inode set functions (intersection, union, difference)</li>
<li>Re-implement query tree builder from path. Currently only deals with building a basic conjunctive query tree and assumes that all components are tags. Should:
<ul>
<li> Take a path</li>
<li>Canonicalise it</li>
<li>Check path components (left-to-right) to ensure tags exist</li>
<li>If last part is an incomplete tag, treat appropriately</li>
<li>If last part is a complete tag, then fine</li>
<li>If last part does not resolve as a tag, then hash it and see if it translates to a known inode</li>
<li>If not, or if any tags in path do not exist, then path is invalid</li>
<li>If it is a valid inode, then add QUERY_IS_INODE node to tree</li>
<li>Otherwise return query tree</li>
</ul>
</li>
<li>Implement query processing:
<ul>
<li>Given input set of inodes, produce an output set at each node of the query tree.</li>
<li>In trivial case with top-level <tt>IS_ANY</tt> node, output set is the set of limbo inodes, with internal negation flag set to false</li>
<li>With an <tt>IS</tt> node, the output set is the recursive union of the inodes belonging to that tag and its subtags, with internal negation flag set to false</li>
<li>With an <tt>IS_NOSUB</tt> node, the output set is the set of inodes belonging tag, with internal negation flag set to false</li>
<li>With an <tt>IS_INODE</tt> node, the output set contains a single element: the inode.</li>
<li>With an <tt>IS_NOT</tt> node with a subquery, the output set is identical to the subquery resultset, with an internal negation flag inverted</li>
<li>With an <tt>IS_NOT</tt> node with a tag, the output set is the same as for an IS node, with an internal negation flag set to true</li>
<li>An <tt>AND</tt> node output depends on the negation flags of its subqueries:
<ul>
<li>Both false: output is the set intersection of its subqueries, with negation flag clear</li>
<li>Both true: output is union of subqueries, with negation flag set</li>
<li>Otherwise: output is set difference, with the negation-true set removed from the negation-false set, and the negation flag cleared</li>
</ul>
</li>
<li>An <tt>OR</tt> node output depends on the negation flags of its subqueries:
<ul>
<li>Both false: output is union of subquery results, with negation flag clear</li>
<li>Both true: output is intersection of subquery results, with negation flag set</li>
<li>Otherwise: output is <strong><span style="color: #ff0000;">???</span></strong></li>
</ul>
</li>
<li>Probably very likely to be an error if the negation flag is found to be set at the top level.</li>
<li>Also have to think about how to build a tree from a bracketed expression. But later. Much later.</li>
</ul>
</li>
<li>Output of query processing is an inode set.</li>
<li>Maybe low-overhead query processing just to see if an inode would match the query?</li>
<li>Implement open/read/write as pass-through operations on the inode symlink targets.</li>
<li>Implement symlinking directories as creating synonyms.</li>
<li>Add <strong>LOTS</strong> of checks.</li>
<li>Note: also have to track inode reference count, so that when it gets to zero the inode is added to the limbo list. Once removed from there, it is removed from the filesystem completely.</li>
</ol>
<p>These should be quite straightforward to do (I hope), especially as I know more or less exactly what I'm doing. Deadlines are closing in, however, and I have a report and presentation and demo to write yet. Hopefully I can get much of this done by Tuesday, then can spend the day doing bits of my report.</p>
<p>I must say that I do love developing this. It's just so amazing to be developing a file system and see it work!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2008/06/05/insight-where-am-i-now-and-where-next/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Insight: The current plan</title>
		<link>http://www.dmi.me.uk/blog/2008/05/19/insight-the-current-plan/</link>
		<comments>http://www.dmi.me.uk/blog/2008/05/19/insight-the-current-plan/#comments</comments>
		<pubDate>Mon, 19 May 2008 12:51:03 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Insight (semantic filesystem)]]></category>
		<category><![CDATA[University]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=54</guid>
		<description><![CDATA[As it comes time to work on my project again, it's time to take stock and work out what my plan of action should be. Looking at the code I have already, I think it's clear that there is no way I will be able to write a kernel-level file system driver within the 2-3 [...]]]></description>
			<content:encoded><![CDATA[<p>As it comes time to work on my project again, it's time to take stock and work out what my plan of action should be.</p>
<p>Looking at the code I have already, I think it's clear that there is no way I will be able to write a kernel-level file system driver within the 2-3 weeks I have left. Fortunately, I had more or less expected this (as writing kernel code would be likely to take quite a while and be quite complex!) so I'm retreating to my fallback position: a FUSE-wrapped program that will interface with the metadata store.</p>
<p>Also on the cards is the use of <a href="http://check.sourceforge.net/" target="_blank">Check</a> as a C unit testing framework for my tree code - if I have time. At the moment, getting something to work is far more important than proving it is correct or works in all cases.</p>
<p>Finally, I need to come up with and write the demo programs, and I will shortly be posting about this and then asking the Twitterverse for ideas <img src='http://www.dmi.me.uk/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' title="icon smile photo" /> </p>
<p>Time to enter Deep Coding Mode.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2008/05/19/insight-the-current-plan/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>No more exams!</title>
		<link>http://www.dmi.me.uk/blog/2008/05/16/no-more-exams/</link>
		<comments>http://www.dmi.me.uk/blog/2008/05/16/no-more-exams/#comments</comments>
		<pubDate>Fri, 16 May 2008 10:00:09 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[University]]></category>

		<guid isPermaLink="false">http://www.dmi.me.uk/blog/?p=52</guid>
		<description><![CDATA[So my exams have finally finished... it's a very surreal feeling. Still got the project to go, but my time at university is even closer to being over. I don't think it's really sunk in yet. Once the exam was over, a group of us headed to get some drinks, and came away with four [...]]]></description>
			<content:encoded><![CDATA[<p>So my exams have finally finished... it's a very surreal feeling. Still got the project to go, but my time at university is even closer to being over. I don't think it's really sunk in yet.</p>
<p>Once the exam was over, a group of us headed to get some drinks, and came away with four bottles of cheap <span style="text-decoration: line-through;">champagne</span> sparkling white wine ("We've just finished our exams and want quantity over quality. What have you got?") and headed to the Union to consume it. Sadly things got slightly out of hand there, but I eventually headed back home after completely failing to work out how I could get to Camden (because I managed to completely forget the Tube existed).</p>
<p>Came back after the post-exam celebrations to find these stashed in the kitchen:</p>
<p><a href="http://www.dmi.me.uk/blog/wp-content/uploads/2008/05/dsc01157.jpg"><img class="aligncenter size-medium wp-image-53" title="Old Rosie cider" src="http://www.dmi.me.uk/blog/wp-content/uploads/2008/05/dsc01157-300x225.jpg" alt="Six 2L bottles of Old Rosie scrumpy" width="300" height="225" /></a></p>
<p>My cider has arrived!</p>
<p>So, next stop: project. The due date now seems incredibly close!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dmi.me.uk/blog/2008/05/16/no-more-exams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license>
	</item>
	</channel>
</rss>

