<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>IONCANNON</title>
	
	<link>http://www.ioncannon.net</link>
	<description>Thoughts on Software Development and Engineering</description>
	<lastBuildDate>Tue, 07 Sep 2010 13:06:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ioncannon" /><feedburner:info uri="ioncannon" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://www.ioncannon.net/?pushpress=hub" /><item>
		<title>Using a HTTP Proxy to Debug JAX-WS and SOAP Over HTTPS</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/7pxJcUMyC5A/</link>
		<comments>http://www.ioncannon.net/programming/1280/using-a-http-proxy-to-debug-jax-ws-and-soap-over-https/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 13:06:13 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1280</guid>
		<description><![CDATA[Every once in a while I run into something I need to debug from the network up. Most of the time I can do this using Wireshark but there are a few instances where what I&#039;m really looking for is a man in the middle proxy. I usually find an alternative way to debug what [...]]]></description>
			<content:encoded><![CDATA[<p>Every once in a while I run into something I need to debug from the network up. Most of the time I can do this using <a href="http://www.wireshark.org/">Wireshark</a> but there are a few instances where what I&#039;m really looking for is a man in the middle proxy. I usually find an alternative way to debug what I&#039;m working on but recently I decided to find a combination that worked so the next time I can use it.</p>
<p>Most of the time what I&#039;m working on when I need a proxy has something to do with SOAP and there is actually a MITM proxy in <a href="http://www.soapui.org/">SoapUI</a> but it doesn&#039;t have support for HTTPS. If you are working with SOAP and can use HTTP then SoapUI is a great tool. If that doesn&#039;t fit the bill then <a href="http://www.parosproxy.org/">Paros proxy</a> does a good job.</p>
<p><span id="more-1280"></span></p>
<p>Paros proxy is pretty easy to set up, just download the binary distribution and run it. The only thing I wanted to change was the port that Paros listened on and that can be done by going to the Tools menu option then Options and then selecting Local proxy:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/09/Paros-Options.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/09/Paros-Options.png" alt="" title="Paros Local Proxy Options" width="600" height="450" class="alignnone size-full wp-image-1284" /></a> </p>
<p>From the description of this option you can see the Paros listens for both HTTP and HTTPS on the same port. Tell Java where to find the proxy server either on the command line with the following system settings:</p>
<pre class="brush: plain;">
-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8081 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8081
</pre>
<p>or in code using the System.setProperty call:</p>
<pre class="brush: java;">
    System.setProperty(&quot;http.proxyHost&quot;, &quot;localhost&quot;);
    System.setProperty(&quot;http.proxyPort&quot;, &quot;8081&quot;);
    System.setProperty(&quot;https.proxyHost&quot;, &quot;localhost&quot;);
    System.setProperty(&quot;https.proxyPort&quot;, &quot;8081&quot;);
</pre>
<p>At this point if you try to use the proxy with HTTPS you are going to get an error because the proxy doesn&#039;t have the correct certificate or a matching hostname for the proxied service. Luckily you can tell Java to ignore all SSL certificate problems and any hostname miss-matches with the following code:</p>
<pre class="brush: java;">
// The following tells Java to ignore certificate problems
TrustManager[] trustAllCerts = new TrustManager[]
{
  new X509TrustManager()
  {
    public java.security.cert.X509Certificate[] getAcceptedIssuers()
    {
      return null;
    }

    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
    {
    }

    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
    {
    }
  }
};

try
{
  SSLContext context = SSLContext.getInstance(&quot;TLS&quot;);
  context.init(null, trustAllCerts, new java.security.SecureRandom());
  HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
}
catch (Exception e)
{
}

// This tells Java to not worry about hostnames matching
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
  public boolean verify(String string, SSLSession ssls)
  {
    return true;
  }
});
</pre>
<p>Make sure the above block of code is executed before any SOAP calls need to be made.</p>
<p>Now if you start Paros proxy and run your application you should see the SOAP requests in their raw form. If you are debugging SOAP messages these raw requests can be exported to text files and then loaded into SoapUI for further processing if need be.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=7pxJcUMyC5A:PonzNQzQlto:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=7pxJcUMyC5A:PonzNQzQlto:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=7pxJcUMyC5A:PonzNQzQlto:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=7pxJcUMyC5A:PonzNQzQlto:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=7pxJcUMyC5A:PonzNQzQlto:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=7pxJcUMyC5A:PonzNQzQlto:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/7pxJcUMyC5A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/1280/using-a-http-proxy-to-debug-jax-ws-and-soap-over-https/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/programming/1280/using-a-http-proxy-to-debug-jax-ws-and-soap-over-https/</feedburner:origLink></item>
		<item>
		<title>Converting from VirtualBox or VMWare to EC2 now Easier than Ever</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/rvZYV_ldFlY/</link>
		<comments>http://www.ioncannon.net/system-administration/1246/converting-from-virtualbox-or-vmware-to-ec2-now-easier-than-ever/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 13:19:48 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1246</guid>
		<description><![CDATA[The new PV-Grub ability introduced by Amazon for EC2 has opened the door for more than just custom kernels, it also makes it a lot easier to turn VirtualBox and VMWare instances into EC2 instances. In the past I have written about transfering VirtualBox images to Xen but to do that with EC2 required a [...]]]></description>
			<content:encoded><![CDATA[<p>The new PV-Grub ability introduced by Amazon for EC2 has opened the door for more than just custom kernels, it also makes it a lot easier to turn <a href="http://www.virtualbox.org/">VirtualBox</a> and <a href="http://www.vmware.com/">VMWare</a> instances into EC2 instances. In the past I have written about <a href="http://www.ioncannon.net/system-administration/80/how-to-transfer-linux-from-virtualbox-to-xen/">transfering VirtualBox images to Xen</a> but to do that with EC2 required a matching kernel exist for your VirtualBox installed OS that was blessed by Amazon. With PV-Grub as long as you can get a kernel for your existing system that is compatible with the EC2 infrastructure you can transfer it. A lot of the most popular distributions already have compatible kernels so that shouldn&#039;t be an issue and if you had to you could always compile the kernel by hand.</p>
<p>Some of what follows is exactly the same as my post about <a href="http://www.ioncannon.net/system-administration/1205/installing-cent-os-5-5-on-ec2-with-the-cent-os-5-5-kernel/">installing CentOS 5.5 on EC2 with the stock kernel</a>. Once you get the hang of it you can install just about anything Linux based to EC2. I&#039;ve broken this post into two parts to try and separate the generic transfer information from the specifics of an example. The first part that goes over the basics of what needs to be done to transfer any VirtualBox or VMWare box to EC2. The second part is an example of transferring an Ubuntu Server install to from VirtualBox to EC2. </p>
<p><span id="more-1246"></span></p>
<p>The following steps should work for any Linux OS but the main sticking point is that the kernel needs to be compatible with EC2 (see the <a href="http://aws.typepad.com/aws/2010/07/use-your-own-kernel-with-amazon-ec2.html">anouncment</a> for a list of some distros that have compatible kernels and remember you can always compile by hand as well).</p>
<ol>
<li>Make sure your VirtualBox or VMWare install has a kernel that is able to boot on EC2.</li>
<li>Make sure you have grub installed and set up your /boot/grub/menu.lst file to point to the correct Xen kernel and initrd file. See the Ubuntu instructions that follow for an example menu.lst.</li>
<li>Make sure you have your /boot directory in the correct place. If your disk is just one big partition you shouldn&#039;t need to do anything (use the hd0 PV-Grub kernel in the last step when booting). If you have a partition for /boot you will need to make sure it is the first partition on the disk and you will also need to copy the directory into /boot/boot so that the menu.lst file would be in /boot/boot/grub/menu.lst after the copy. For an example of this see the Ubuntu instructions that follow (use the hd00 PV-Grub kernel in the last step when booting).</li>
<li>Export the image to a raw form. This includes the partition table and everything. For VMWare you can use qemu-img to convert the VMDK to a raw image with the following command:
<pre class="brush: plain;">
   qemu-img convert -O raw vmware-image.vmdk myosimage.raw
</pre>
<p>Or if you are using VirtualBox you would use the VBoxManage command (I&#039;m currently using VirtualBox 3.2.6 and since the VBoxManage command has changed before that might be important for those reading this at a later date):</p>
<pre class="brush: plain;">
   VBoxManage internalcommands converttoraw myosimage.vdi myosimage.img
</pre>
<p>In both cases you should be able to run fdisk against the resulting raw image file and see a partition table:</p>
<pre class="brush: plain;">
   fdisk -lu myosimage.img
</pre>
</li>
<li>Create an EBS volume that is the same size or larger than the raw disk image created in step 4 and then attach it to a running EC2 instance:
<pre class="brush: plain;">
ec2-create-volume -z us-east-1a -s 2
ec2-attach-volume volume-id -i instance-id -d /dev/sdh
</pre>
<p>Note: The instance you attach the volume to is just a place used to copy the image file onto the volume. There is no need to be too picky about the type of instance it is as long as you have access to the dd command that should be all you need.
</li>
<li>Transfer the exported VirtualBox or VMWare disk image to the running EC2 instance created in step 5 and then copy it to the volume with the following dd command (this example assumes the volume is attached to the /dev/sdh device):
<pre class="brush: plain;">
dd if=myosimage.img of=/dev/sdh bs=10M
</pre>
<p>Note: It may make sense to compress your raw image before transferring it since any free space will be represented in the raw file and will compress down a lot.
</li>
<li>Make a snapshot of the volume:
<pre class="brush: plain;">
ec2-create-snapshot -d &quot;Volume Description&quot; volume-id
</pre>
</li>
<li>Register the snapshot as a new AMI:
<pre class="brush: plain;">
ec2-register -n &quot;AMIName&quot; -d &quot;AMI Description&quot; --root-device-name /dev/sda2 -b /dev/sda=snap-id:2:true
</pre>
</li>
<li>Boot the new AMI using the correct PV-Grub kernel. The correct kernel will depend on how your partition structure. For more information see the <a href="http://developer.amazonwebservices.com/connect/entry.jspa?categoryID=174&#038;externalID=3967">AWS PV-Grub documentation</a>. The main thing to know is that if you have /boot on its own partition use the hd00 kernel otherwise use the hd0 kernel:
<pre class="brush: plain;">
ec2-run-instances -z us-east-1a -g your-group -k your-keypair -n 1 --kernel pv-grub-kernel-id ami-from-step-19
</pre>
</li>
</ol>
<p>The following is a specific example of converting an existing <a href="http://www.ubuntu.com/server">Ubuntu 10.04 LTS Server</a> installed on VirtualBox to a bootable EC2 AMI. Note that steps 1 to 4 of the following create my &#034;existing&#034; Ubuntu Server so skip those if you have something that already exists. The last portion of this will look just like the above generic steps:</p>
<ol>
<li>Use the Ubuntu Server ISO to install Ubuntu on a fresh VirtualBox VM. For this example I used 512M of memory and a 2G disk. This is what my VirtualBox setup looked like:<br/><br/>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuVMSummary.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuVMSummary.png" alt="" title="EC2 Ubuntu VirtualBox Summary" width="699" height="453" class="alignnone size-full wp-image-1248" /></a>
</li>
<li>Because I wanted /boot to be on its own partition I used the manual partition creation option:<br/><br/>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuManualPartitions.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuManualPartitions.png" alt="" title="EC2 Ubuntu Manual Partitions" width="648" height="555" class="alignnone size-full wp-image-1251" /></a></p>
<p>You don&#039;t have to do this but I wanted these instructions to align with my previous post for CentOS 5.5. In this case I made the first partition mount at /boot and the second partition was everything else mounted at / and the result looked like:<br/></p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuPartitionTable.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuPartitionTable.png" alt="" title="EC2 Ubuntu Partition Table" width="648" height="555" class="alignnone size-full wp-image-1249" /></a></p>
<p>Notice that I didn&#039;t include any swap, that is something you probably want to put on the EC2 instance&#039;s ephemeral storage.
</li>
<li>For Ubuntu you are prompted to install other software after the base install and setting up a user. Make sure you install OpenSSH server:<br/><br/>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuOpenSSHServer.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/08/EC2UbuntuOpenSSHServer.png" alt="" title="EC2 Ubuntu OpenSSH Server" width="648" height="555" class="alignnone size-full wp-image-1250" /></a>
</li>
<li>When prompted to install grub answer yes.</li>
<li>At this point you should have a bootable Ubuntu system either from following the previous steps or from an existing bootable install. You will need to install the libuuid-perl package so that the EC2 compatible Xen kernels will be installable:
<pre class="brush: plain;">
   sudo apt-get install libuuid-perl
</pre>
</li>
<li>Grab a Xen kernel and initrd that are compatible with EC2:
<pre class="brush: plain;">
wget http://ftp.debian.org/debian/pool/main/l/linux-2.6/linux-base_2.6.32-20_all.deb
wget http://ftp.debian.org/debian/pool/main/l/linux-2.6/linux-image-2.6.32-5-xen-686_2.6.32-20_i386.deb

sudo dpkg -i linux-base_2.6.32-20_all.deb linux-image-2.6.32-5-xen-686_2.6.32-20_i386.deb
</pre>
<p>Notes: I was unable to find a compatible kernel that was apt-get installable from Ubuntu and that is why I grab the two above from the Debian site. Also, If you want to continue to boot the system outside of EC2 then make sure to edit the /boot/grub/grub.cfg file so that it has the correct kernel set to boot by default.
</li>
<li>Create a menu.lst file that points to the correct kernel and initrd that were just installed:
<pre class="brush: plain;">
   sudo vi /boot/grub/menu.lst
</pre>
<p>For this example mine contains:</p>
<pre class="brush: plain;">
default 0
timeout 1
title UBEC2
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-5-xen-686 root=/dev/xvda2
        initrd /boot/initrd.img-2.6.32-5-xen-686
</pre>
<p>Notes: The grub root command is pointing to hard disk 0 and partition 0 because I put the boot directory on the first partition. The root parameter for the kernel is pointing to /dev/xvda2 and not /dev/sda2 because the kernel patch to disable XSAVE changes the names of the devices.
</li>
<li>Copy everything from /boot into /boot/boot, this is just the easiest way of making things work since EC2 PV-Grub looks for the menu.lst file /boot/boot/grub/ when you specify the hd00 kernel:
<pre class="brush: plain;">
sudo cp -Rp /boot/ /boot/boot
</pre>
</li>
<li>Shut the VirtualBox system down and extract the hard drive image with the following command:
<pre class="brush: plain;">
VBoxManage internalcommands converttoraw ~/.VirtualBox/HardDisks/YourHardDiskName.vdi /tmp/myosimage.img
</pre>
<p>Notes: The raw image that results will be the full size of the disk as it was seen by VirtualBox so if you have a lot of free disk space on your image you will probably want to compress it before you transfer it to EC2. At this point the commands are exactly as they are for the generic instructions above.
</li>
<li>Start a temporary EC2 instance and transfer your image:
<pre class="brush: plain;">
ec2-run-instances -z us-east-1a -g your-group -k your-keypair -n 1 ami-84db39ed
</pre>
</li>
<li>Create an EBS volume of the correct size to put your image onto and attach it to the previously created temporary EC2 instance:
<pre class="brush: plain;">
ec2-create-volume -z us-east-1a -s 2
ec2-attach-volume volume-id -i instance-id -d /dev/sdh
</pre>
</li>
<li>Transfer the image to the volume:
<pre class="brush: plain;">
dd if=myosimage.img of=/dev/sdh bs=10M
</pre>
</li>
<li>Create a snapshot of the volume:
<pre class="brush: plain;">
ec2-create-snapshot -d &quot;Volume Description&quot; volume-id
</pre>
</li>
<li>Register the snapshot as an AMI:
<pre class="brush: plain;">
ec2-register -n &quot;AMIName&quot; -d &quot;AMI Description&quot; --root-device-name /dev/sda2 -b /dev/sda=snap-id:2:true
</pre>
</li>
<li>Boot the AMI:
<pre class="brush: plain;">
ec2-run-instances -z us-east-1a -g your-group -k your-keypair -n 1 --kernel pv-grub-kernel-id ami-from-step-19
</pre>
<p>Note: Because the partition table contains /boot on hd00 I used the kernel named aki-4c7d9525 for the east region.
</li>
</ol>
<p>Once you get the hang of transferring the image these steps aren&#039;t as complicated as they seem. It may help to imagine the extracted disk image as a physical hard drive that you are moving around. The main pain points are selecting the correct PV-Grub kernel and making sure your grub menu.lst file is in the correct location on the partition.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=rvZYV_ldFlY:mIPkWaR6eQU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=rvZYV_ldFlY:mIPkWaR6eQU:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=rvZYV_ldFlY:mIPkWaR6eQU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=rvZYV_ldFlY:mIPkWaR6eQU:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=rvZYV_ldFlY:mIPkWaR6eQU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=rvZYV_ldFlY:mIPkWaR6eQU:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/rvZYV_ldFlY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/1246/converting-from-virtualbox-or-vmware-to-ec2-now-easier-than-ever/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/system-administration/1246/converting-from-virtualbox-or-vmware-to-ec2-now-easier-than-ever/</feedburner:origLink></item>
		<item>
		<title>Installing Cent OS 5.5 on EC2 with the Cent OS 5.5 Kernel</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/oSq7cSxpkwg/</link>
		<comments>http://www.ioncannon.net/system-administration/1205/installing-cent-os-5-5-on-ec2-with-the-cent-os-5-5-kernel/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 10:51:37 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[system administration]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1205</guid>
		<description><![CDATA[Amazon recently introduced the ability to boot a custom kernel using pv-grub on EC2. This opens the door for all kinds of interesting ideas that I&#039;ve been thinking about for a while, like seeing if I can boot right into a web server and skip all that extra junk that comes with Linux distributions, but [...]]]></description>
			<content:encoded><![CDATA[<p>Amazon recently introduced the ability to <a href="http://aws.typepad.com/aws/2010/07/use-your-own-kernel-with-amazon-ec2.html">boot a custom kernel</a> using pv-grub on EC2. This opens the door for all kinds of interesting ideas that I&#039;ve been thinking about for a while, like seeing if I can boot right into a web server and skip all that extra junk that comes with Linux distributions, but that is just me. The main door it is going to open for most people interested in EC2 will be the ability to upgrade the kernel that comes with their distribution. That brings us to how to install Cent OS 5.5 on EC2 and use the kernel that is part of the distribution.</p>
<p>For those who might just be interested in booting a custom kernel using EC2 pv-grub I will try to produce a few more posts with more details on that but for now here are the main things to know:</p>
<ul>
<li>The pv-grup kernels named with hd00 will look on the first partition of the registered device in the /boot/boot/grub directory for a menu.lst file. Use this type of kernel if you create want to use a partitioned disk.</li>
<li>The pv-grup kernels named with hd0 will look on the registered device in the /boot/grub directory for a menu.lst file. Use this type of kernel if you don&#039;t have a partition on your disk.</li>
<li>You won&#039;t get anything meaningful back from the boot attempt if your grub menu.lst file is in the wrong place or is not valid. See the end of the post for what a pv-grub error message looks like and some tips on what to do if you see it.</li>
<li>The kernel you use does matter but the current mainline Linux kernel (2.6.35) contains everything you need except for a small change to turn off XSAVE. The main thing to know is that not every distribution may have made the change needed to work on EC2.</li>
<li>I have tried non-Linux kernels to no avail. See the end of the post for a little more information.</li>
</ul>
<p><span id="more-1205"></span></p>
<p>A lot of what follows is similar, both steps and concepts, to the &#034;from scratch&#034; section of my post on <a href="http://www.ioncannon.net/system-administration/894/fedora-12-bootable-root-ebs-on-ec2/">Fedora 12 on EC2 using a root EBS</a>. I&#039;ve also bundled all the instance building commands up into one <a href="http://www.ioncannon.net/examples/centos5.5.sh">script (centos5.5.sh)</a>. If you want to use that script then do 1 and 2 of what follows, make sure to change the password used for root in the script and then pick back up at 18. The following steps should not be taken as the only way to do this but more of a recipe:</p>
<ol>
<li>
Start an EC2 instance that has yum on it to be used as a setup box. A RedHat based box, Fedora or CentOS will work best unless you want to install yum. For the following steps I used a Fedora 8 based EC2 node.</p>
<pre class="brush: plain;">
ec2-run-instances -z us-east-1a -g your-group -k your-keypair -n 1 ami-84db39ed
</pre>
</li>
<li>
Create a new EBS volume to install to and map it to the running instance from step 1. Your volume should be greater than 2G for a base install. I mapped this new volume to the /dev/sdh device on the setup machine so you will notice that in the following steps (if you are using the script you will want to make sure you map to /dev/sdh as well):</p>
<pre class="brush: plain;">
ec2-create-volume -z us-east-1a -s 2
ec2-attach-volume volume-id -i instance-id -d /dev/sdh
</pre>
</li>
<li>
<p>Create a <a href="http://tldp.org/HOWTO/Partition/fdisk_partitioning.html">partion table using fdisk</a> on the volume you are going to install to.</p>
<p>I created both a /boot and / partion on /dev/sdh1 and /dev/sdh2 respecivly. I also made the /dev/sdh1 partition active so it is exactly as it would be if it had been installed on a real machine.</p>
<p>Note that this step is optional but I am going to include it because I think it makes for a more natural setup and is more in line with what you would get if you did a VirtualBox install and then transfered the image.
</li>
<li>
Format your partition(s) and mount them into /mnt. For me that was done with the following:</p>
<pre class="brush: plain;">
echo &quot;y&quot; | mkfs.ext3 /dev/sdh1
echo &quot;y&quot; | mkfs.ext3 /dev/sdh2
mount /dev/sdh2 /mnt
mkdir /mnt/boot
mkdir /mnt/dev
mkdir /mnt/proc
mkdir /mnt/etc
mount /dev/sdh1 /mnt/boot
mount -t proc none /mnt/proc
</pre>
</li>
<li>
Create a base device setup for the new instance:</p>
<pre class="brush: plain;">
for i in console null zero ; do /sbin/MAKEDEV -d /mnt/dev -x $i ; done
</pre>
</li>
<li>
Create a base fstab file in /mnt/etc/fstab. The following is the one I used:</p>
<pre class="brush: plain;">
/dev/sda1               /boot                   ext3    defaults 1 1
/dev/sda2               /                       ext3    defaults 1 2
none                    /dev/pts                devpts  gid=5,mode=620 0 0
none                    /dev/shm                tmpfs   defaults 0 0
none                    /proc                   proc    defaults 0 0
none                    /sys                    sysfs   defaults 0 0
/dev/sdc1               /mnt                    ext3    defaults 0 0
/dev/sdc2               swap                    swap    defaults 0 0
</pre>
</li>
<li>
Create the yum repo configuration, prepare for the yum install and then install the base OS onto the new volume.<br/><br/></p>
<p>The following is the yum configuration file I used:</p>
<pre class="brush: plain;">
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
exclude=*-debuginfo
gpgcheck=0
obsoletes=1
reposdir=/dev/null

[os]
name=CentOS 5.5 - i386 - OS
mirrorlist=http://mirrorlist.centos.org/?release=5&amp;arch=i386&amp;repo=os
enabled=1

[updates]
name=CentOS 5.5 - i386 - Updates
mirrorlist=http://mirrorlist.centos.org/?release=5&amp;arch=i386&amp;repo=updates
enabled=1
</pre>
<p>The following command will install the base of Cent OS 5.5 into /mnt (note that I created the above config file as /tmp/yumec2.conf):</p>
<pre class="brush: plain;">
yum -c /tmp/yumec2.conf --installroot=/mnt -y groupinstall Base
</pre>
</li>
<li>
Install sshd, grub, the Cent OS Xen kernel and then clean the repo to free up disk space:</p>
<pre class="brush: plain;">
yum -c /tmp/yumec2.conf --installroot=/mnt -y install openssh-server
yum -c /tmp/yumec2.conf --installroot=/mnt -y install grub
yum -c /tmp/yumec2.conf --installroot=/mnt -y install kernel-xen.i686

yum -c /tmp/yumec2.conf --installroot=/mnt -y clean packages
</pre>
</li>
<li>
Disable DNS checks and allow root to log in via SSH:</p>
<pre class="brush: plain;">
echo &quot;UseDNS no&quot; &gt;&gt; /mnt/etc/ssh/sshd_config
echo &quot;PermitRootLogin yes&quot; &gt;&gt; /mnt/etc/ssh/sshd_config
</pre>
</li>
<li>
Set up networking by creating the /mnt/etc/sysconfig/network file. The contents for this example are:</p>
<pre class="brush: plain;">
NETWORKING=yes
</pre>
<p>As well as the /mnt/etc/sysconfig/network-scripts/ifcfg-eth0 file. The contents for this example are:</p>
<pre class="brush: plain;">
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
</pre>
</li>
<li>
I&#039;m not sure if this is needed still but in the past there have been some /dev file missing on boot so I always add the following to the startup script to make sure they are available. The first two are the random devices and the last three are where the ephimeral drive is usually mapped:</p>
<pre class="brush: plain;">
echo &quot;/sbin/MAKEDEV /dev/urandom&quot; &gt;&gt; /mnt/etc/rc.sysinit
echo &quot;/sbin/MAKEDEV /dev/random&quot; &gt;&gt; /mnt/etc/rc.sysinit
echo &quot;/sbin/MAKEDEV /dev/sdc&quot; &gt;&gt; /mnt/etc/rc.sysinit
echo &quot;/sbin/MAKEDEV /dev/sdc1&quot; &gt;&gt; /mnt/etc/rc.sysinit
echo &quot;/sbin/MAKEDEV /dev/sdc2&quot; &gt;&gt; /mnt/etc/rc.sysinit
</pre>
</li>
<li>
Change the root password for the new instance. This is optional as you could create scripts to download your SSH key from EC2 but for these instructions setting the root password is the easiest:</p>
<pre class="brush: plain;">
chroot /mnt
pwconv
passwd
exit
</pre>
</li>
<li>
Change the network settings so that the NetworkManager is off and network is on</p>
<pre class="brush: plain;">
chroot /mnt chkconfig --level 2345 NetworkManager off
chroot /mnt chkconfig --level 2345 network on
</pre>
</li>
<li>
Disable a few things that are enabled by default but won&#039;t do any good for an EC2 instance:</p>
<pre class="brush: plain;">
chroot /mnt chkconfig --level 2345 avahi-daemon off
chroot /mnt chkconfig --level 2345 firstboot off
</pre>
</li>
<li>
The stock CentOS Xen initrd doesn&#039;t load the Xen block or net drivers and those are required to boot. I unpacked the installed initrd and created a modified version by hand using the following commands (note that as soon as the CentOS Xen kernel version changes this will stop functioning):</p>
<pre class="brush: plain;">
cp /mnt/boot/initrd-2.6.18-194.8.1.el5xen.img /mnt/boot/initrd-2.6.18-194.8.1.el5xen.img.orig
mkdir /tmp/initrdextract
cd /tmp/initrdextract
gzip -dc /mnt/boot/initrd-2.6.18-194.8.1.el5xen.img | cpio -id
cp /mnt/lib/modules/2.6.18-194.8.1.el5xen/kernel/drivers/xen/blkfront/xenblk.ko lib
cp /mnt/lib/modules/2.6.18-194.8.1.el5xen/kernel/drivers/xen/netfront/xennet.ko lib
chmod -x lib/xenblk.ko
chmod -x lib/xennet.ko
cat &lt;&lt;EOL &gt; init
#!/bin/nash

mount -t proc /proc /proc
setquiet
echo Mounting proc filesystem
echo Mounting sysfs filesystem
mount -t sysfs /sys /sys
echo Creating /dev
mount -o mode=0755 -t tmpfs /dev /dev
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
mkdir /dev/shm
mkdir /dev/mapper
echo Creating initial device nodes
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mknod /dev/urandom c 1 9
mknod /dev/systty c 4 0
mknod /dev/tty c 5 0
mknod /dev/console c 5 1
mknod /dev/ptmx c 5 2
mknod /dev/rtc c 10 135
mknod /dev/tty0 c 4 0
mknod /dev/tty1 c 4 1
mknod /dev/tty2 c 4 2
mknod /dev/tty3 c 4 3
mknod /dev/tty4 c 4 4
mknod /dev/tty5 c 4 5
mknod /dev/tty6 c 4 6
mknod /dev/tty7 c 4 7
mknod /dev/tty8 c 4 8
mknod /dev/tty9 c 4 9
mknod /dev/tty10 c 4 10
mknod /dev/tty11 c 4 11
mknod /dev/tty12 c 4 12
mknod /dev/ttyS0 c 4 64
mknod /dev/ttyS1 c 4 65
mknod /dev/ttyS2 c 4 66
mknod /dev/ttyS3 c 4 67
echo Setting up hotplug.
hotplug
echo Creating block device nodes.
mkblkdevs
echo &quot;Loading jbd.ko module&quot;
insmod /lib/jbd.ko
echo &quot;Loading ext3.ko module&quot;
insmod /lib/ext3.ko
echo &quot;Loading xenblk.ko module&quot;
insmod /lib/xenblk.ko
echo &quot;Loading xennet.ko module&quot;
insmod /lib/xennet.ko
mkblkdevs
echo Scanning and configuring dmraid supported devices
resume /dev/sdc2
echo Creating root device.
mkrootdev -t ext3 -o defaults,ro /dev/sda1
echo Mounting root filesystem.
mount /sysroot
echo Setting up other filesystems.
setuproot
echo Switching to new root and running init.
switchroot
EOL
find ./ | cpio -H newc -o | gzip &gt; /mnt/boot/initrd-2.6.18-194.8.1.el5xen.img
cd -
</pre>
</li>
<li>
Install grub on the new instance, move the boot directory into a subdirectory and create a grub menu.lst file that points to the CentOS kernel and initrd file:</p>
<pre class="brush: plain;">
chroot /mnt grub-install /dev/sdh

mkdir /mnt/boot/boot/
mv /mnt/boot/* /mnt/boot/boot/ 2&gt; /dev/null &gt; /dev/null
</pre>
<p>Put the following in /mnt/boot/boot/grub/menu.lst  (note that as soon as the CentOS Xen kernel version changes this will be incorrect):</p>
<pre class="brush: plain;">
default 0
timeout 1
title CentOS5.5
     root (hd0,0)
     kernel /boot/vmlinuz-2.6.18-194.8.1.el5xen root=/dev/sda2
     initrd /boot/initrd-2.6.18-194.8.1.el5xen.img
</pre>
<p>Note that this goes in /mnt/boot/boot/grub and that isn&#039;t the normal spot you would expect it in. This is where the AWS EC2 pv-grub expects to find the file on the first partition and moving the boot directory around just keeps everything in line with those expectations.
</li>
<li>
Make sure everything is written to disk and unmount the volume. At this point you have a CentOS 5.5 install that is almost ready to boot.</p>
<pre class="brush: plain;">
sync
umount /mnt/proc
umount /mnt/boot
umount /mnt
</pre>
</li>
<li>
Make a snapshot of the volume you just installed to, you will need to volume ID that came from step 2:</p>
<pre class="brush: plain;">
ec2-create-snapshot -d &quot;Volume Description&quot; volume-id
</pre>
</li>
<li>
Use the snapshot from step 18 along with the ec2-register command to register your instance:</p>
<pre class="brush: plain;">
ec2-register -n &quot;AMIName&quot; -d &quot;AMI Description&quot; --root-device-name /dev/sda2 -b /dev/sda=snap-id:2:true
</pre>
<p>There are a number of things to take note of with the above command:</p>
<ol>
<li>Running this command will result in output something like: IMAGE   ami-a5ae9bb</li>
<li>The -b option can now assign a snapshot to a block device, the options in this example tell EC2 to generate 2G of space for the snapshot and to delete the volume it creates from the snapshot if the instance terminates. If you plan to use an instance long term you should replace that true at the end with a false to keep EC2 from deleting the volume when the instance terminates.</li>
<li>Notice that the -b option is assigning the snapshot to the device and not to a partition of the device, that is /dev/sda instead of /dev/sda1. You can still assign a snapshot directly to a partition but now you can also assign a block device to a raw partitioned disk. Because I created the partition table earlier the snapshot is the raw disk device here.</li>
<li>Also note that we are missing the kernel configuration option. As of this post using it with a pv-grub kernel causes the register command to fail. It isn&#039;t a big issue but just keep that in mind when you fire the AMI up otherwise it won&#039;t boot with the correct pv-grub kernel.</li>
</ol>
<p><br/>
</li>
<li>
Start an instance of the fresh CentOS 5.5 install. One key thing here is picking the correct pv-grub kernel to boot from. There are currently 4 different kernels at each location, see the <a href="http://developer.amazonwebservices.com/connect/entry.jspa?categoryID=174&#038;externalID=3967">Enabling User Provided Kernels in Amazon EC2</a> document for a full list of kernels in each availability zone. In this case because the root disk was created with a partition table I used the &#034;ec2-public-images/pv-grub-hd00-V1.01-i386.gz.manifest.xml&#034; kernel to boot with (on US-East-1 that is kernel id aki-4c7d9525). For example:</p>
<pre class="brush: plain;">
ec2-run-instances -z us-east-1a -g your-group -k your-keypair -n 1 --kernel pv-grub-kernel-id ami-from-step-19
</pre>
</li>
</ol>
<p><b>Tips on debugging the boot process</b></p>
<p>If your instance won&#039;t boot you can use the ec2-get-console-output command to get the console output created from the pv-grub boot process. If your console output ends up like the following there are a number of things you may have done wrong.</p>
<ul>
<li>You may have selected the wrong kernel and it is trying to boot from a non-existant partition. Make sure you are using the correct pv-grub kernel hd0 vs hd00.</li>
<li>You forgot to install grub or installed grub in the wrong place. Make sure you have either /boot/grub/menu.lst or /boot/boot/grub/menu.lst</li>
<li>You have a bad menu.lst file. One mistake I made was giving a boot item a title with a space in it. Make the menu.lst as simple as you can until you get it to boot.</li>
</ul>
<pre class="brush: plain;">
    Xen Minimal OS!
  start_info: 0xb10000(VA)
    nr_pages: 0x6a400
  shared_inf: 0x002f9000(MA)
     pt_base: 0xb13000(VA)
nr_pt_frames: 0x9
    mfn_list: 0x967000(VA)
   mod_start: 0x0(VA)
     mod_len: 0
       flags: 0x0
    cmd_line:  root=/dev/sda1 ro 4
  stack:      0x946780-0x966780
MM: Init
      _text: 0x0(VA)
     _etext: 0x621f5(VA)
   _erodata: 0x76000(VA)
     _edata: 0x7b6d4(VA)
stack start: 0x946780(VA)
       _end: 0x966d34(VA)
  start_pfn: b1f
    max_pfn: 6a400
Mapping memory range 0xc00000 - 0x6a400000
setting 0x0-0x76000 readonly
skipped 0x1000
MM: Initialise page allocator for e6c000(e6c000)-0(6a400000)
MM: done
Demand map pfns at 6a401000-7a401000.
Heap resides at 7a402000-ba402000.
Initialising timer interface
Initialising console ... done.
gnttab_table mapped at 0x6a401000.
Initialising scheduler
Thread &quot;Idle&quot;: pointer: 0x7a402008, stack: 0x6a030000
Initialising xenbus
Thread &quot;xenstore&quot;: pointer: 0x7a402478, stack: 0x6a040000
Dummy main: start_info=0x966880
Thread &quot;main&quot;: pointer: 0x7a4028e8, stack: 0x6a050000
&quot;main&quot; &quot;root=/dev/sda1&quot; &quot;ro&quot; &quot;4&quot;
vbd 2048 is hd0
******************* BLKFRONT for device/vbd/2048 **********

backend at /local/domain/0/backend/vbd/2111/2048
Failed to read /local/domain/0/backend/vbd/2111/2048/feature-barrier.
Failed to read /local/domain/0/backend/vbd/2111/2048/feature-flush-cache.
12582912 sectors of 0 bytes
**************************
vbd 2051 is hd1
******************* BLKFRONT for device/vbd/2051 **********

backend at /local/domain/0/backend/vbd/2111/2051
Failed to read /local/domain/0/backend/vbd/2111/2051/feature-barrier.
Failed to read /local/domain/0/backend/vbd/2111/2051/feature-flush-cache.
1835008 sectors of 0 bytes
**************************

    [H
    [J

    GNU GRUB  version 0.97  (1740800K lower / 0K upper memory)

       [ Minimal BASH-like line editing is supported.   For

         the   first   word,  TAB  lists  possible  command

         completions.  Anywhere else TAB lists the possible

         completions of a device/filename. ]

grubdom&gt;
    [9;10H
</pre>
<p><br/><br/></p>
<p><b>Booting non-Linux OSes with EC2</b></p>
<p>I have attempted both FreeBSD and NetBSD in particular with no luck. </p>
<p>FreeBSD is tricky because it really wants to use its loader and while you can do that with the grub chainloader command it results in a grub error from EC2 about needing to load the kernel before booting:</p>
<pre class="brush: plain;">
root (hd0,1)

 Filesystem type unknown, partition type 0xa5

chainloader +1

Error 8: Kernel must be loaded before booting

Press any key to continue...
</pre>
<p>I was also able to try a modified version of FreeBSD that should boot without the loader but with that I get an error claiming the kernel isn&#039;t bziped:</p>
<pre class="brush: plain;">
root (hd0,1,a)

 Filesystem type is ufs2, partition type 0xa5

kernel /boot/loader

xc_dom_probe_bzimage_kernel: kernel is not a bzImage
ERROR Invalid kernel: xc_dom_find_loader: no loader found

xc_dom_core.c:523: panic: xc_dom_find_loader: no loader found
xc_dom_parse_image returned -1

Error 9: Unknown boot failure

Press any key to continue...
</pre>
<p>For NetBSD the result is actually a completely blank console log so I assume it causes some catastrophic failure that keeps the EC2 system from even being able to pull back a log.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=oSq7cSxpkwg:aPd02X78OBA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=oSq7cSxpkwg:aPd02X78OBA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=oSq7cSxpkwg:aPd02X78OBA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=oSq7cSxpkwg:aPd02X78OBA:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=oSq7cSxpkwg:aPd02X78OBA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=oSq7cSxpkwg:aPd02X78OBA:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/oSq7cSxpkwg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/1205/installing-cent-os-5-5-on-ec2-with-the-cent-os-5-5-kernel/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/system-administration/1205/installing-cent-os-5-5-on-ec2-with-the-cent-os-5-5-kernel/</feedburner:origLink></item>
		<item>
		<title>Compiling WebM into FFMpeg for Windows</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/MHjPSS2yt0U/</link>
		<comments>http://www.ioncannon.net/meta/1128/compiling-webm-ffmpeg-windows/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 10:30:55 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[meta]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[vp8]]></category>
		<category><![CDATA[webm]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1128</guid>
		<description><![CDATA[I have updated this post with a newer version of the VP8 patches to FFMpeg and support for libvorbis instead of the built in vorbis support. Google has released source for the VP8 codec as the WebM project. The WebM project will be an open alternative in the HTML5 video tag codec space and being [...]]]></description>
			<content:encoded><![CDATA[<p>I have updated this post with a newer version of the VP8 patches to FFMpeg and support for libvorbis instead of the built in vorbis support.</p>
<p>Google has released source for the VP8 codec as the <a href="http://www.webmproject.org/">WebM project</a>. The WebM project will be an open alternative in the HTML5 video tag codec space and being backed by Google, who will use it for YouTube, will give it a fighting chance. WebM is starting to be integrated into FFMpeg but there are still some patches that need to be applied. While there are some guides to how to <a href="http://lardbucket.org/blog/archives/2010/05/19/vp8-webm-and-ffmpeg/">build FFMpeg for Linux with VP8 WebM support</a> I wanted to get it compiled for Windows.</p>
<p>First off this won&#039;t be done using a Windows install but instead using <a href="http://www.virtualbox.org/">Virtual Box</a> with a fresh install of <a href="http://releases.ubuntu.com/lucid/">Ubuntu 10.04</a> desktop. It is just faster and easier that way. So go ahead and grab Virtual Box and get Ubuntu installed on it before you continue.</p>
<p><span id="more-1128"></span></p>
<p>I used this <a href="http://www.bluebottle.net.au/blog/2010/cross-compiling-x264-for-win32-on-ubuntu-linux/">cross compiling X264 using Ubuntu</a> as a base for part of my script. The entire script follows but if you want to make sure you get a good copy you can <a href="http://www.ioncannon.net/examples/vp8-webm/vp8webmffmpeg.sh">download it</a>:</p>
<pre class="brush: plain;">
mkdir ffmpeg
cd ffmpeg

BASEDIR=`pwd`
MINGBASE=$BASEDIR/win32-webm

sudo apt-get install pkg-config yasm subversion cvs git-core gcc-mingw32

cat &gt; mingw32-setup.sh &lt;&lt; EOF
#!/bin/sh
export CC=i586-mingw32msvc-gcc
export CXX=i586-mingw32msvc-g++
export CPP=i586-mingw32msvc-cpp
export AR=i586-mingw32msvc-ar
export RANLIB=i586-mingw32msvc-ranlib
export ADD2LINE=i586-mingw32msvc-addr2line
export AS=i586-mingw32msvc-as
export LD=i586-mingw32msvc-ld
export NM=i586-mingw32msvc-nm
export STRIP=i586-mingw32msvc-strip

export PATH=&quot;/usr/i586-mingw32msvc/bin:$PATH&quot;
export PKG_CONFIG_PATH=&quot;$MINGBASE/lib/pkgconfig/&quot;
exec &quot;\$@&quot;
EOF
chmod +x mingw32-setup.sh

mkdir $MINGBASE $MINGBASE/src $MINGBASE/lib $MINGBASE/include $MINGBASE/share $MINGBASE/bin

cd $MINGBASE/src

wget -qO - http://downloads.xiph.org/releases/ogg/libogg-1.2.0.tar.gz | tar xzf -
cd libogg-1.2.0
$BASEDIR/mingw32-setup.sh ./configure --enable-static --disable-shared --host=mingw32
make
DESTDIR=$MINGBASE make install prefix=
cd ..

wget -qO - http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.1.tar.gz | tar xzf -
cd libvorbis-1.3.1
LDFLAGS=&quot;-L$MINGBASE/lib&quot; CFLAGS=&quot;-I$MINGBASE/include&quot; $BASEDIR/mingw32-setup.sh ./configure --enable-static --disable-shared --host=mingw32
make
DESTDIR=$MINGBASE make install prefix=
cd ..

wget -qO - ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz | tar xzf -
cd pthreads-w32-2-8-0-release
make GC-static CROSS=i586-mingw32msvc-
cp libpthreadGC2.a $MINGBASE/lib
cp *.h $MINGBASE/include
cd ..

wget -qO - http://zlib.net/zlib-1.2.5.tar.gz | tar xzf -
cd zlib-1.2.5/
$BASEDIR/mingw32-setup.sh ./configure
sed -i&quot;&quot; -e 's/-lc//' Makefile
make
DESTDIR=$MINGBASE make install prefix=
cd ..

git clone git://review.webmproject.org/libvpx.git
cd libvpx/
git checkout fd0d7ff4c155b94d3f322addc7b66234b6908cc6
cat &gt; /tmp/libvpx.x.patch &lt;&lt; EOP
diff -rupN libvpx.orig/configure libvpx/configure
--- libvpx.orig/configure	2010-07-11 14:49:18.703230816 -0400
+++ libvpx/configure	2010-07-11 14:50:33.747300030 -0400
@@ -436,9 +436,9 @@ process_detect() {
         }
     fi
     check_header stdio.h || die &quot;Unable to invoke compiler: \${CC} \${CFLAGS}&quot;
-    check_ld &lt;&lt;EOF || die &quot;Toolchain is unable to link executables&quot;
-int main(void) {return 0;}
-EOF
+#    check_ld &lt;&lt;EOF || die &quot;Toolchain is unable to link executables&quot;
+#int main(void) {return 0;}
+#EOF
     # check system headers
     check_header stdint.h
     check_header pthread.h
diff -rupN libvpx.orig/vp8/common/postproc.c libvpx/vp8/common/postproc.c
--- libvpx.orig/vp8/common/postproc.c	2010-07-11 14:49:18.939266476 -0400
+++ libvpx/vp8/common/postproc.c	2010-07-11 14:51:03.855300662 -0400
@@ -481,7 +481,7 @@ int vp8_post_proc_frame(VP8_COMMON *oci,
     }

 #if ARCH_X86||ARCH_X86_64
-    vpx_reset_mmx_state();
+//    vpx_reset_mmx_state();
 #endif

     if (flags &amp; VP8D_DEMACROBLOCK)
diff -rupN libvpx.orig/vp8/common/systemdependent.h libvpx/vp8/common/systemdependent.h
--- libvpx.orig/vp8/common/systemdependent.h	2010-07-11 14:49:18.947263304 -0400
+++ libvpx/vp8/common/systemdependent.h	2010-07-11 14:51:25.019253115 -0400
@@ -10,12 +10,12 @@

 #include &quot;vpx_ports/config.h&quot;
-#if ARCH_X86 || ARCH_X86_64
-void vpx_reset_mmx_state(void);
-#define vp8_clear_system_state() vpx_reset_mmx_state()
-#else
+//#if ARCH_X86 || ARCH_X86_64
+//void vpx_reset_mmx_state(void);
+//#define vp8_clear_system_state() vpx_reset_mmx_state()
+//#else
 #define vp8_clear_system_state()
-#endif
+//#endif

 struct VP8Common;
 void vp8_machine_specific_config(struct VP8Common *);
EOP
patch -p1 &lt; /tmp/libvpx.x.patch
$BASEDIR/mingw32-setup.sh ./configure --disable-examples --disable-mmx --disable-sse --disable-sse2 --disable-sse3 --disable-ssse3
$BASEDIR/mingw32-setup.sh make
DESTDIR=$MINGBASE make install prefix=/
cd ../..
mv usr/local/lib/* lib
mv usr/local/include/vpx/ include/
cd src

wget -qO - http://webm.googlecode.com/files/ffmpeg-0.6_libvpx-0.9.1.diff.gz | zcat - &gt; /tmp/ffmpeg-0.6_libvpx-0.9.1.diff
wget -qO - http://www.ffmpeg.org/releases/ffmpeg-0.6.tar.gz | tar xzf -
cd ffmpeg-0.6
patch -p0 &lt; /tmp/ffmpeg-0.6_libvpx-0.9.1.diff

LDFLAGS=&quot;-L$MINGBASE/lib&quot; CFLAGS=&quot;-I$MINGBASE/include&quot; ./configure --target-os=mingw32 --cross-prefix=i586-mingw32msvc- --arch=x86 --prefix=$MINGBASE --enable-memalign-hack --enable-gpl --enable-avisynth --enable-version3 --enable-postproc --enable-libvpx --enable-runtime-cpudetect --disable-network --disable-devices --disable-encoder=vorbis --enable-libvorbis
make

cp ffmpeg.exe $BASEDIR
</pre>
<p>Just transfer that script to the user you create when you installed Ubuntu and run it. You will need to provide your password once so that the system can install a few tools but after that everything is done automatically. At the end you will have exe files in the directory you ran the script from.</p>
<p>Transfer the exe files that are created to a windows machine and then transcode a video like this:</p>
<div class="codesnip-container" >ffmpeg.exe -i Big_Buck_Bunny_1080p.avi -acodec libvorbis -ac 2 -ab 128k -ar 44100 -s 720&#215;480 Big_Buck_Bunny_1080p.webm</div>
<p>Please note that you need to include the audio codec information above to correctly encode the video. If you don&#039;t include rate values you will get an error telling you the libvorbis can&#039;t be initialized.</p>
<p>When the transcoding is done you will have a WebM video. Grab your closest HTML5 video player like <a href="http://videojs.com/">VideoJS</a> and you are ready to go.</p>
<p>For a demo video encoded using FFMpeg created with the above script check out this <a href="http://www.ioncannon.net/examples/vp8-webm/demo.html">WebM demo video</a>. You will need to use one of the following browsers to view the demo (all of these are as of July 13 2010, support will eventually be added to the main build):</p>
<ul>
<li><a href="http://www.chromium.org/getting-involved/dev-channel">Chromium</a> dev channel build</li>
<li><a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox</a> 4 beta</li>
<li><a href="http://www.opera.com/download/">Opera</a></li>
<li><a href="http://windowsteamblog.com/windows/b/bloggingwindows/archive/2010/05/19/another-follow-up-on-html5-video-in-ie9.aspx">IE 9</a> when the user has the Direct Show DLLs installed</li>
</ul>
<p>I have tested the demo video on each of the above, except for IE9 that doesn&#039;t have WebM support as of yet, and it seems to work pretty well.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=MHjPSS2yt0U:_roZaeLMcME:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=MHjPSS2yt0U:_roZaeLMcME:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=MHjPSS2yt0U:_roZaeLMcME:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=MHjPSS2yt0U:_roZaeLMcME:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=MHjPSS2yt0U:_roZaeLMcME:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=MHjPSS2yt0U:_roZaeLMcME:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/MHjPSS2yt0U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/meta/1128/compiling-webm-ffmpeg-windows/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/meta/1128/compiling-webm-ffmpeg-windows/</feedburner:origLink></item>
		<item>
		<title>Upgrade to Fedora 13 from Fedora 12</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/p7ZzhbDp8u8/</link>
		<comments>http://www.ioncannon.net/system-administration/1136/upgrade-to-fedora-13-from-fedora-12/#comments</comments>
		<pubDate>Thu, 27 May 2010 10:53:40 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[system administration]]></category>
		<category><![CDATA[Fedora]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1136</guid>
		<description><![CDATA[After a week delay Fedora 13 has been released and it is time to upgrade of course. As always there are a decent number of features in this release but here are a few that stand out to me: boot.fedoraproject.org &#8211; A small bootable image to start the install from. IntelliJ IDEA &#8211; IntelliJ IDEA [...]]]></description>
			<content:encoded><![CDATA[<p>After a week delay <a href="http://docs.fedoraproject.org/en-US/Fedora/13/html/Release_Notes/index.html">Fedora 13</a> has been released and it is time to upgrade of course. As always there are a decent number of features in this release but here are a few that stand out to me:</p>
<ul>
<li><a href="http://boot.fedoraproject.org/">boot.fedoraproject.org</a> &#8211; A small bootable image to start the install from.</li>
<li><a href="https://fedoraproject.org/wiki/Features/IntelliJ_IDEA">IntelliJ IDEA</a> &#8211; IntelliJ IDEA community edition. I&#039;m glad to see my favorite IDE make it in along with Netbeans and Eclipse even if it is just the stripped down version.</li>
<li><a href="https://fedoraproject.org/wiki/Features/Python3F13">Python 3</a> &#8211; Running along side Python 2.</li>
<li><a href="https://fedoraproject.org/wiki/Features/NouveauDisplayPort">Nouveau DisplayPort</a> &#8211; Support for NVIDIA cards with a DisplayPort.</li>
<li><a href="https://fedoraproject.org/wiki/Features/RadeonDisplayPort">Radeon DisplayPort</a> &#8211; Support for Radeon cards with a DisplayPort.</li>
<li><a href="https://fedoraproject.org/wiki/Features/NetworkManagerCmdline">NetworkManager Command Line</a> &#8211; A command line interface for NetworkManager. As much as I find myself hating NetworkManager maybe this will help.</li>
<li><a href="http://library.gnome.org/misc/release-notes/2.30/">Gnome 2.30</a> &#8211; The latest stable version of Gnome.</li>
<li><a href="http://www.kde.org/announcements/announce-4.4.3.php">KDE 4.4</a> &#8211; The latest stable version of KDE.</li>
</ul>
<p>Check out the <a href="http://fedoraproject.org/wiki/Releases/13/FeatureList">Fedora 13 feature list<a> for all the major features in this release.</p>
<p><span id="more-1136"></span></p>
<p>I&#039;m continuing with the trend of using <a href="http://fedoraproject.org/wiki/Features/PreUpgrade">PreUpdate</a> to do the upgrade:</p>
<ol>
<li>Make sure you are using a Fedora 12 install. If you need instructions on getting to Fedora 12 then start with <a href="http://www.ioncannon.net/system-administration/719/upgrade-to-fedora-12-from-fedora-11/">upgrading from Fedora 11 to Fedora 12</a>.</li>
<li>yum clean all</li>
<li>yum update</li>
<li>Make sure you have plenty of space free in the /boot partition. I learned this lesson the last time I upgraded.</li>
<li>I always back up my xorg.conf file since because it seems to disappear sometimes.</li>
<li>preupgrade-cli &#034;Fedora 13 (Goddard)&#034; &#8211; My Fedora 12 to Fedora 13 upgrade weighed in at 1.0GB</li>
<li>reboot and wait</li>
</ol>
<p>No dependency issues when upgrading this time making it two in a row. I was tempted to try out the Nouveau NVIDIA drivers this time around but the driver from NVIDIA are not too hard to upgrade now so I haven&#039;t found a real reason. If you don&#039;t want to compile the NVIDIA drivers by hand you can get them from <a href="http://www.atrpms.net/">atrpms</a>, make sure to remove the Nouveau drivers first. The Fedora 13 version of <a href="http://www.virtualbox.org/wiki/Linux_Downloads">Virtualbox</a> was also needed.</p>
<p>I did run into a small issue with xorg after the upgrade. The NVIDIA driver requires the ignoreABI flag be sent to the X server on startup. I was able to modify startx but I always forget how to modify GDM. It turns out that you can also just put the flag in the xorg.conf file like this:</p>
<pre class="brush: plain;">
Section &quot;ServerFlags&quot;
        Option      &quot;ignoreABI&quot; &quot;true&quot;
EndSection
</pre>
<p>If you prefer the yum upgrade option here are the steps for that as well:</p>
<ol>
<li>yum clean all</li>
<li>yum update</li>
<li>rpm -Uvh http://mirrors.kernel.org/fedora/releases/13/Fedora/i386/os/Packages/fedora-release-13-1.noarch.rpm http://mirrors.kernel.org/fedora/releases/13/Fedora/i386/os/Packages/fedora-release-notes-13-3.fc13.noarch.rpm</li>
<li>yum clean all</li>
<li>yum -y update</li>
<li>You may need to resolve dependencies and then do another yum -y update or in my case I had to use &#8211;skip-broken to resolve some issues with packages I&#039;ve installed from atrpm.</li>
<li>reboot</li>
</ol>
<p>I needed to use the &#8211;skip-broken flag on yum this time but I didn&#039;t have to resolve any dependency issues. The resulting update was about 1.2G so it took a little while to apply. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=p7ZzhbDp8u8:6E0w2lsBFB0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=p7ZzhbDp8u8:6E0w2lsBFB0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=p7ZzhbDp8u8:6E0w2lsBFB0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=p7ZzhbDp8u8:6E0w2lsBFB0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=p7ZzhbDp8u8:6E0w2lsBFB0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=p7ZzhbDp8u8:6E0w2lsBFB0:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/p7ZzhbDp8u8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/system-administration/1136/upgrade-to-fedora-13-from-fedora-12/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/system-administration/1136/upgrade-to-fedora-13-from-fedora-12/</feedburner:origLink></item>
		<item>
		<title>Faceted Search With Sphinx</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/IjRht47qDXE/</link>
		<comments>http://www.ioncannon.net/programming/1055/faceted-search-with-sphinx/#comments</comments>
		<pubDate>Tue, 18 May 2010 10:42:34 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1055</guid>
		<description><![CDATA[I decided to use the Sphinx search engine for the GeeQe iPhone app I build last year because it was fast and had a very small memory footprint. Recently I wanted to experiment with a search interface that had facets and wondered if I would need to move away from Sphinx to something like Solr. [...]]]></description>
			<content:encoded><![CDATA[<p>I decided to use the <a href="http://www.sphinxsearch.com/">Sphinx</a> search engine for the <a href="http://www.ioncannon.net/projects/geeqe/">GeeQe</a> iPhone app I build last year because it was fast and had a very small memory footprint. Recently I wanted to experiment with a search interface that had facets and wondered if I would need to move away from Sphinx to something like <a href="http://lucene.apache.org/solr/">Solr</a>. As it turns out Sphinx can do <a href="http://en.wikipedia.org/wiki/Faceted_search">faceted search</a> almost as well as Solr can. The first half of what follows contains instructions on how to get Sphinx ready for faceted searches. If you are familiar with setting up Sphinx and already have data indexed by Sphinx you may find it better to skip to the second half after reading the intro to faceted search.</p>
<p>You have almost certainly seen faceted searching or faceted browsing already. A lot of online retailers now use facets in their online stores. Here are a few examples: </p>
<ul>
<li><a href="http://www.amazon.com/s/?url=search-alias%3Daps&#038;field-keywords=java+programming&#038;sprefix=java+pro">An Amazon search for java programming</a></li>
<li><a href="http://www.bestbuy.com/site/Televisions/All-Flat-Panel-TVs/abcat0101001.c?id=abcat0101001">A Best Buy search for flat panel TVs</a></li>
<li><a href="http://www.newegg.com/Store/SubCategory.aspx?SubCategory=32&#038;name=Laptops-Notebooks">A New Egg search for Laptops</a></li>
</ul>
<p><span id="more-1055"></span></p>
<p>In each of the above cases you will find the left hand navigation displaying the facets. Here is what the Amazon search looks like:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/05/AmazonFacetedSearchExampleAllDepartments.jpg"><img src="http://www.ioncannon.net/wp-content/uploads/2010/05/AmazonFacetedSearchAllDepartments-Small.jpg" alt="All Departments Amazon Faceted Search Example" title="All Departments Amazon Faceted Search Example" width="300" height="250" class="alignnone size-medium wp-image-1056" /></a></p>
<p>One of the ways facets are useful is the ability to drill down into the results and create filters based on the facets. In the Amazon example I went from looking for anything that was related to &#034;java programming&#034; to only things related to books:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/05/AmazonFacetedSearchExampleBooksOnly.jpg"><img src="http://www.ioncannon.net/wp-content/uploads/2010/05/AmazonFacetedSearchExampleBooksOnly-300x268.jpg" alt="Books Only Amazon Faceted Search Example" title="Books Only Amazon Faceted Search Example" width="300" height="268" class="alignnone size-medium wp-image-1057" /></a><br/></p>
<p>Some sites build a breadcrumb of facets you have selected as you drill down into the results. This lets you remove facets by just clicking one of the crumbs. The search for laptops on Newegg above provides an example of breadcrumb navigation:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/05/NeweggFacetsAndBreadcrumbs.jpg"><img src="http://www.ioncannon.net/wp-content/uploads/2010/05/NeweggFacetsAndBreadcrumbs-Small.jpg" alt="Breadcrumb Search Navagation with Facets" title="Breadcrumb Search Navagation with Facets" width="300" height="250" class="alignnone size-medium wp-image-1075" /></a></p>
<p>Now that you have some examples of what faceted search looks like we can move on to creating the same using Sphinx. First we need some type of data to work from and in these examples I&#039;m using the Stack Overflow CC data dump. The following steps should get you a database ready to index by Sphinx if you want to follow along with the same data:</p>
<ol>
<li>Download the latest <a href="http://blog.stackoverflow.com/2010/05/creative-commons-data-dump-may-10/">Stack Overflow CC data dump</a>.</li>
<li>Create a MySQL database that will be used to hold the data.</li>
<li>Grab the <a href="http://github.com/carsonmcdonald/ExampleSphinxSearchWithFacets/blob/master/schema.sql">schema</a> I created to hold the data and load it into your new database.</li>
<li>Extract the Stack Overflow CC data dump into a directory.</li>
<li>Use the Ruby <a href="http://github.com/carsonmcdonald/ExampleSphinxSearchWithFacets/blob/master/load.rb">load script</a> to load the XML files from the data dump into the database you created.</li>
</ol>
<p>If you haven&#039;t already, now is the time to install Sphinx. I&#039;m using version 0.9.9 for the following examples. I&#039;ve created a sample configuration file that will get you started:</p>
<pre class="brush: plain;">
source stack_overflow_src
{
	type				= mysql

	sql_host			= localhost
	sql_user			= root
	sql_pass			=
	sql_db			= yourdbname
	sql_port			= 3306

	sql_query			= SELECT post.id AS post_id, post.owner_id AS owner_id, UNIX_TIMESTAMP(post.created) AS date_added, post.post_type_id AS post_type_id, post.score AS post_score, post.view_count AS post_view_count, post.favorite_count AS post_favorite_count, NOT ISNULL(post.accepted_answer_id) AS has_accepted_answer, GROUP_CONCAT(distinct(post_to_tag.tag_id)) AS tag_ids, title, body_text, GROUP_CONCAT(comment_text SEPARATOR '\n') AS comments, GROUP_CONCAT(distinct(tag.name) SEPARATOR ', ') as tags from post LEFT OUTER JOIN comment ON post.id = comment.post_id LEFT OUTER JOIN post_to_tag ON post_to_tag.post_id = post.id LEFT OUTER JOIN tag ON tag.id = post_to_tag.tag_id GROUP BY post.id;

	sql_attr_uint			= owner_id
	sql_attr_timestamp		= date_added
	sql_attr_uint			= post_type_id
	sql_attr_uint			= post_score
	sql_attr_uint			= post_view_count
	sql_attr_uint			= post_favorite_count
	sql_attr_bool			= has_accepted_answer
	sql_attr_multi			= uint tag_ids from field

	sql_ranged_throttle	= 0
	sql_query_info		= SELECT * FROM post WHERE id=$id
}

#############################################################################
## index definition
#############################################################################

index so_index
{
	source			= stack_overflow_src

	path			= ./data/so_index

	docinfo			= extern
	mlock			= 0
	morphology		= none
	min_word_len		= 1
	charset_type		= sbcs
	html_strip		= 1
}

index so_indexstemmed : so_index
{
	path			= ./data/so_index_stemmed
	morphology	= stem_en
}

#############################################################################
## indexer settings
#############################################################################

indexer
{
	mem_limit		= 512M
}

#############################################################################
## searchd settings
#############################################################################

searchd
{
	port			= 3312
	log			= /tmp/searchd.log
	query_log		= /tmp/query.log
	read_timeout	= 5
	max_children	= 30
	pid_file		= /tmp/searchd.pid
	max_matches	= 1000
	seamless_rotate= 1
	preopen_indexes= 1
	unlink_old		= 1
}
</pre>
<p>The above configuration file will index all posts in the database by title, body text, comments and tags as well add fields to each record for owner id, date added, post type, post score, post view count, post favorite count, if the post has an accepted answer and tag ids. The fields that get associated with each record can later be used in filters and for facets. For more information on how to use the configuration to create your index and start the Sphinx search server check out the <a href="http://www.sphinxsearch.com/docs/current.html">Sphinx documentation</a>.</p>
<p>You should now be able to test against the index. There is a handy PHP script named test.php included with the Sphinx source that will let you test just about every option available in the Sphinx search API (other language API wrappers are also available in the source but the test script is in PHP). The following is a simple search that will give you back every post related to &#034;C#&#034;:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;">php test.php <span class="re5">-h</span> localhost <span class="re5">-p</span> 3312 <span class="re5">-l</span> <span class="nu0">10</span> <span class="st_h">&#039;c#&#039;</span></div>
</div>
<p>The key to faceted searching with Sphinx is the <a href="http://sphinxsearch.com/docs/current.html#clustering">group by</a> feature. Now try out the same search using the group and group sort options:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;">php test.php <span class="re5">-h</span> localhost <span class="re5">-p</span> 3312 <span class="re5">-l</span> 10 <span class="re5">-g</span> tag_ids <span class="re5">-gs</span> <span class="st_h">&#039;@count desc&#039;</span> <span class="st_h">&#039;c#&#039;</span></div>
</div>
<p>In the above case we group by tag ids and sort by the count of documents containing each from the result of the search for &#034;C#&#034;.</p>
<p>Faceted searches in Sphinx require multiple search calls to work in conjunction with a normal search. The query will first be run to generate the non-faceted results. The same search query is then run again with a grouping for each facet you want to include in the results. </p>
<p>It is worth noting that doing the group by is not a simple operation for Sphinx to execute and can result in long queries. Take for instance the above search for &#034;C#&#034; where the non-faceted search returns 704556 documents. It will take a lot of work for Sphinx to count the tags for each of those documents. Slow here is 5 or 6 seconds per facet compared to sub-second for the non-faceted query.</p>
<p>A better approach is to only attempt to find faceted results when the query returns a limited enough set. Something generic enough to return hundreds of thousands of results probably won&#039;t be helped a lot by facets. In my final example I&#039;ve limited the faceted search to queries that produce fewer than 1000 results.</p>
<p>I&#039;ve created a couple simple examples in PHP to help get you started. These examples assume the sphinxapi.php library is in the current directory, you can find it in the Sphinx source API directory along with the test.php file mentioned above. The first example is a stripped down non-faceted search:</p>
<pre class="brush: php;">
&lt;?php

require ( &quot;sphinxapi.php&quot; );

$sphinx_client = new SphinxClient ();

$query = &quot;java war file deploy&quot;;

$sphinx_client-&gt;SetServer ( 'localhost', 3312 );
$sphinx_client-&gt;SetConnectTimeout ( 1 );
$sphinx_client-&gt;SetArrayResult ( true );
$sphinx_client-&gt;SetWeights ( array ( 100, 1 ) );
$sphinx_client-&gt;SetMatchMode ( SPH_MATCH_ALL );
$sphinx_client-&gt;SetLimits( 0, 20, 20 );
$sphinx_client-&gt;SetRankingMode ( SPH_RANK_PROXIMITY_BM25 );

$results = $sphinx_client-&gt;Query ( $query, '*' );

if( $results===false )
{
  print &quot;Query failed: &quot; . $sphinx_client-&gt;GetLastError() . &quot;.\n&quot;;
}
else
{
  if ( $sphinx_client-&gt;GetLastWarning() )
    print &quot;WARNING: &quot; . $sphinx_client-&gt;GetLastWarning() . &quot;\n\n&quot;;

  print_results($query, $results);
}

function print_results($query, $results)
{
  print &quot;Query '$query' retrieved $results[total] of $results[total_found] matches in $results[time] sec.\n&quot;;
  print &quot;Query stats:\n&quot;;
  if ( is_array($results[&quot;words&quot;]) )
    foreach ( $results[&quot;words&quot;] as $word =&gt; $info )
      print &quot;    '$word' found $info[hits] times in $info[docs] documents\n&quot;;
  print &quot;\n&quot;;

  if ( is_array($results[&quot;matches&quot;]) )
  {
    $n = 1;
    print &quot;Matches:\n&quot;;
    foreach( $results[&quot;matches&quot;] as $docinfo )
    {
      print &quot;$n. doc_id=$docinfo[id], weight=$docinfo[weight]&quot;;
      foreach( $results[&quot;attrs&quot;] as $attrname =&gt; $attrtype )
      {
        $value = $docinfo[&quot;attrs&quot;][$attrname];
        if( $attrtype &amp; SPH_ATTR_MULTI )
          $value = &quot;(&quot; . join ( &quot;,&quot;, $value ) .&quot;)&quot;;
        else if ( $attrtype==SPH_ATTR_TIMESTAMP )
          $value = date ( &quot;Y-m-d H:i:s&quot;, $value );
        print &quot;, $attrname=$value&quot;;
      }
      print &quot;\n&quot;;
      $n++;
    }
  }
}
?&gt;
</pre>
<p>This second script does the same group by as the above test script example to create faceted results where the facets are tag ids:</p>
<pre class="brush: php;">
&lt;?php

require ( &quot;sphinxapi.php&quot; );

$sphinx_client = new SphinxClient ();

$query = &quot;java war file deploy&quot;;

$sphinx_client-&gt;SetServer ( 'localhost', 3312 );
$sphinx_client-&gt;SetConnectTimeout ( 1 );
$sphinx_client-&gt;SetArrayResult ( true );
$sphinx_client-&gt;SetWeights ( array ( 100, 1 ) );
$sphinx_client-&gt;SetMatchMode ( SPH_MATCH_ALL );
$sphinx_client-&gt;SetLimits( 0, 20, 20 );
$sphinx_client-&gt;SetRankingMode ( SPH_RANK_PROXIMITY_BM25 );

$sphinx_client-&gt;SetGroupBy( 'tag_ids', SPH_GROUPBY_ATTR, '@count desc' );

$results = $sphinx_client-&gt;Query ( $query, '*' );

if( $results===false )
{
  print &quot;Query failed: &quot; . $sphinx_client-&gt;GetLastError() . &quot;.\n&quot;;
}
else
{
  if ( $sphinx_client-&gt;GetLastWarning() )
    print &quot;WARNING: &quot; . $sphinx_client-&gt;GetLastWarning() . &quot;\n\n&quot;;

  print_results($query, $results);
}

function print_results($query, $results)
{
  print &quot;Query '$query' retrieved $results[total] of $results[total_found] matches in $results[time] sec.\n&quot;;
  print &quot;Query stats:\n&quot;;
  if ( is_array($results[&quot;words&quot;]) )
    foreach ( $results[&quot;words&quot;] as $word =&gt; $info )
      print &quot;    '$word' found $info[hits] times in $info[docs] documents\n&quot;;
  print &quot;\n&quot;;

  if ( is_array($results[&quot;matches&quot;]) )
  {
    $n = 1;
    print &quot;Matches:\n&quot;;
    foreach( $results[&quot;matches&quot;] as $docinfo )
    {
      print &quot;$n. doc_id=$docinfo[id], weight=$docinfo[weight]&quot;;
      foreach( $results[&quot;attrs&quot;] as $attrname =&gt; $attrtype )
      {
        $value = $docinfo[&quot;attrs&quot;][$attrname];
        if( $attrtype &amp; SPH_ATTR_MULTI )
          $value = &quot;(&quot; . join ( &quot;,&quot;, $value ) .&quot;)&quot;;
        else if ( $attrtype==SPH_ATTR_TIMESTAMP )
          $value = date ( &quot;Y-m-d H:i:s&quot;, $value );
        print &quot;, $attrname=$value&quot;;
      }
      print &quot;\n&quot;;
      $n++;
    }
  }
}
?&gt;
</pre>
<p>The last example is a more complex and complete <a href="http://github.com/carsonmcdonald/ExampleSphinxSearchWithFacets">faceted search example</a> that I have put on github. This example gives you a full search interface for the Stack Overflow CC data that includes filters and faceted searches. Here is a screen shot of the resulting interface displaying a faceted search result:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/05/ExampleFacetedSearch.jpg"><img src="http://www.ioncannon.net/wp-content/uploads/2010/05/ExampleFacetedSearch-300x249.jpg" alt="Faceted Search Example" title="Faceted Search Example" width="300" height="249" class="alignnone size-medium wp-image-1058" /></a><br/></p>
<p>If you are interested in more information about faceted searches I found the following articles helpful:</p>
<ul>
<li><a href="http://blog.linkedin.com/2010/03/05/designing-linkedin-faceted-search/">LinkedIn&#039;s Faceted Search</a></li>
<li><a href="http://webonrails.com/2008/11/25/presented-faceted-search-using-ultrasphinx/">Using Rails UltraSphinx for Faceted search</a></li>
<li><a href="http://www.lucidimagination.com/Community/Hear-from-the-Experts/Articles/Faceted-Search-Solr">Solr faceted search</a></li>
<li><a href="http://www.uxmatters.com/mt/archives/2010/04/design-patterns-for-mobile-faceted-search-part-i.php">Design Patterns for Mobile Faceted Search: Part I</a> and <a href="http://www.uxmatters.com/mt/archives/2010/05/design-patterns-for-mobile-faceted-search-part-ii.php">Design Patterns for Mobile Faceted Search: Part II</a></li>
<li><a href="http://www.alistapart.com/articles/design-patterns-faceted-navigation/">Design Patterns for Faceted Navigation</a></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=IjRht47qDXE:WkRrEeOV7i0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=IjRht47qDXE:WkRrEeOV7i0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=IjRht47qDXE:WkRrEeOV7i0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=IjRht47qDXE:WkRrEeOV7i0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=IjRht47qDXE:WkRrEeOV7i0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=IjRht47qDXE:WkRrEeOV7i0:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/IjRht47qDXE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/1055/faceted-search-with-sphinx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/programming/1055/faceted-search-with-sphinx/</feedburner:origLink></item>
		<item>
		<title>How to Create iPad Formatted Videos Using HandBrake or FFMpeg</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/1oQDCbNAaKg/</link>
		<comments>http://www.ioncannon.net/meta/1040/how-to-create-ipad-formatted-videos-using-handbrake-or-ffmpeg/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 10:56:19 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[meta]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[handbrake]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1040</guid>
		<description><![CDATA[This is for those who may want to load a video onto their iPad with iTunes that isn&#039;t in the correct format. I needed to do this because I was trying to put an iTunes University video on my iPad a couple days ago and iTunes complained that it wasn&#039;t in the correct format for [...]]]></description>
			<content:encoded><![CDATA[<p>This is for those who may want to load a video onto their iPad with iTunes that isn&#039;t in the correct format. I needed to do this because I was trying to put an iTunes University video on my iPad a couple days ago and iTunes complained that it wasn&#039;t in the correct format for the iPad. I&#039;m not sure exactly how that could be but I decided to take the opportunity to see if I could use <a href="http://handbrake.fr/">HandBrake</a> to easily convert it to an iPad friendly format. There is currently no pre-loaded iPad configuration for HandBrake like there is for the iPhone and iPod Touch so I created a few profiles that can easily be imported into HandBrake to output different sizes for the iPad:</p>
<ul>
<li><a href="http://www.ioncannon.net/projects/ipadhandbrake/iPad-4x3.plist">iPad-4&#215;3.plist</a> &#8211; A 4&#215;3 aspect ratio at 640&#215;480</li>
<li><a href="http://www.ioncannon.net/projects/ipadhandbrake/iPad-16x9.plist">iPad-16&#215;9.plist</a> &#8211; A 16&#215;9 aspect ratio at 640&#215;360</li>
<li><a href="http://www.ioncannon.net/projects/ipadhandbrake/iPad-Full.plist">iPad-Full.plist</a> &#8211; A 4&#215;3 aspect ratio at 1024&#215;576</li>
</ul>
<p>Note that when you import videos using iTunes the iPad puts them in their own Videos app unlike the iPhone where they show up under the iPod app. You will want to find the Videos icon if you don&#039;t already know where it is:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-iPad-Videos.jpg"><img src="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-iPad-Videos-300x163.jpg" alt="iPad Videos Screenshot" title="iPad Videos Screenshot" width="300" height="163" class="alignnone size-medium wp-image-1043" /></a></p>
<p>After verifying that the above 4&#215;3 version worked for the iTunes University video I went about testing it on a couple other video formats. I tested the <a href="http://www.bigbuckbunny.org/">Big Buck Bunny</a> video that I also used for my post on <a href="http://www.ioncannon.net/programming/1015/ipad-streaming-video-and-more/">iPad video streaming</a> in both 640&#215;360 and 1024&#215;576 output formats. Both resolutions looked great. I also tried converting a DVD. If you decide to convert a DVD you will probably want to turn on de-interlacing in HandBrake. You do that by first selecting the &#034;Picture Settings&#034; option:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-HandBrake-PictureSettings.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-HandBrake-PictureSettings-300x81.png" alt="HandBrake Picture Settings Screenshot" title="HandBrake Picture Settings Screenshot" width="300" height="81" class="alignnone size-medium wp-image-1042" /></a></p>
<p>Then the filters tab and then select the type of de-interlace you want (fast, slow, slowest):</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-HandBrake-DeInterlaceSettings.png"><img src="http://www.ioncannon.net/wp-content/uploads/2010/04/Screenshot-HandBrake-DeInterlaceSettings-300x103.png" alt="HandBrake DeInterlace Settings Screenshot" title="HandBrake DeInterlace Settings Screenshot" width="300" height="103" class="alignnone size-medium wp-image-1041" /></a></p>
<p>If you want to use FFMpeg to do all this you can. The following is a slightly modified version of the streaming command I&#039;m using that will output a high bitrate version of the input video:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="kw2">ffmpeg</span> <span class="re5">-y</span> <span class="re5">-i</span> input.avi <span class="re5">-acodec</span> aac <span class="re5">-ar</span> 48000 <span class="re5">-ab</span> 128k <span class="re5">-ac</span> 2 <span class="re5">-s</span> 1024&#215;768 <span class="re5">-vcodec</span> libx264 <span class="re5">-b</span> 1200k <span class="re5">-flags</span> +loop+mv4 <span class="re5">-cmp</span> 256 <span class="re5">-partitions</span> +parti4x4+partp8x8+partb8x8 <span class="re5">-subq</span> 7 <span class="re5">-trellis</span> 1 <span class="re5">-refs</span> 5 <span class="re5">-coder</span> 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 <span class="re5">-bt</span> 1200k <span class="re5">-maxrate</span> 1200k <span class="re5">-bufsize</span> 1200k -rc_eq <span class="st_h">&#039;blurCplx^(1-qComp)&#039;</span> <span class="re5">-qcomp</span> 0.6 <span class="re5">-qmin</span> 10 <span class="re5">-qmax</span> 51 <span class="re5">-qdiff</span> 4 <span class="re5">-level</span> 30 <span class="re5">-aspect</span> 16:9 <span class="re5">-r</span> 30 <span class="re5">-g</span> 90 <span class="re5">-async</span> <span class="nu0">2</span> output.mp4</div>
</div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=1oQDCbNAaKg:mMyC7VTnQqo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=1oQDCbNAaKg:mMyC7VTnQqo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=1oQDCbNAaKg:mMyC7VTnQqo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=1oQDCbNAaKg:mMyC7VTnQqo:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=1oQDCbNAaKg:mMyC7VTnQqo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=1oQDCbNAaKg:mMyC7VTnQqo:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/1oQDCbNAaKg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/meta/1040/how-to-create-ipad-formatted-videos-using-handbrake-or-ffmpeg/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/meta/1040/how-to-create-ipad-formatted-videos-using-handbrake-or-ffmpeg/</feedburner:origLink></item>
		<item>
		<title>iPad Streaming Video and More</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/GP1k6TVqIA8/</link>
		<comments>http://www.ioncannon.net/programming/1015/ipad-streaming-video-and-more/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 11:01:33 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[segmenter]]></category>
		<category><![CDATA[Streaming Video]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1015</guid>
		<description><![CDATA[I&#039;ve updated the configuration examples in the open source segmenter project to reflect Apple&#039;s recommended stream bitrates for iPad video streaming, added a few fixes and a few new features. If you are interested in streaming video on the iPad, iPhone or iPod Touch and haven&#039;t done so yet you it may help to start [...]]]></description>
			<content:encoded><![CDATA[<p>I&#039;ve updated the configuration examples in the open source segmenter project to reflect <a href="http://developer.apple.com/iphone/library/technotes/tn2010/tn2224.html">Apple&#039;s recommended stream bitrates</a> for iPad video streaming, added a few fixes and a few new features. If you are interested in streaming video on the iPad, iPhone or iPod Touch and haven&#039;t done so yet you it may help to start with my post on <a href="http://www.ioncannon.net/meta/564/iphone-windowed-http-live-streaming-server/">windowed streaming on for the iPhone</a>, then read about <a href="http://www.ioncannon.net/programming/452/iphone-http-streaming-with-ffmpeg-and-an-open-source-segmenter/">iPhone HTTP streaming with FFMpeg and the open source segmenter</a> and finally check out the <a href="http://www.ioncannon.net/projects/http-live-video-stream-segmenter-and-distributor/">iPad, iPhone, and iPod Touch live video streaming project page</a>.</p>
<p>Here is a demo of the iPad streaming video created with the segmenter (I tried to show the progressive upgrade happening but it happens very quickly since the iPad is on WIFI, I also show that you can scrub without any issues and if you look in the background you can see the server log displaying entries as the segments are downloaded):</p>
<p><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/ydP51WxRDDk&#038;hl=en_US&#038;fs=1&#038;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/ydP51WxRDDk&#038;hl=en_US&#038;fs=1&#038;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
<p>If you want to view the demo yourself I&#039;ve created a demo for the <a href="http://www.ioncannon.net/projects/ivids/ipad/">iPad</a>, <a href="http://www.ioncannon.net/projects/ivids/iphone/">iPhone, and iPod Touch</a>. Note that those are two links, one for the iPad version and one for the iPhone/iPod Touch version. The main difference is the size of the video.</p>
<p>I used the open source video <a href="http://www.bigbuckbunny.org/">Big Buck Bunny</a> (the 1920&#215;1080 ogg version) for the above demos.</p>
<p>If you are interested in more details on what changed read on or skip to the bottom if you want to see what I&#039;ll be working towards in future versions of the segmenter.</p>
<p><span id="more-1015"></span></p>
<p>Over the past few weeks I learned that it is important that each segment starts with an <a href="http://avidemux.org/admWiki/index.php?title=H264#I-Frames">IDR frame</a>. To accomplish this I thought setting the gop so that the segment time % (gop size / frame rate) = 0 would work but I haven&#039;t completely convinced myself of this yet. An example of would be a segment size of 10 seconds % (300 gop size / 30 frame rate) = 0. This should insure that each segment starts with the correct i-frame and while I have looked over the resulting segments with a hex editor and believe it works I still get errors when using certain tools on the individual segments that makes me think it isn&#039;t working like I think it should. Either way I have included updates to the gop size in the example configuration files. The gop size is controlled by the -g option for FFMpeg and in the examples I have set it so that for a 10 second segment with the given frame rate the gop size makes sure each segment starts correctly. If you want to know more you can dig into the resulting segments and use this forum post on <a href="http://forum.digital-digest.com/showthread.php?t=89736">how to extract an i-frame</a>, this <a href="http://www.mpucoder.com/DVD/mpeghdrs.html">list of mpeg headers</a> to verify that each has the correct i-frame at the start.</p>
<p>The <a href="http://developer.apple.com/iphone/library/technotes/tn2010/tn2224.html">Apple streaming tech notes</a> where informative in a few other ways as well. The tech notes contain the supported h264 profiles for each device. For the iPhone/iPod Touch baseline level 3.0 is supported while the iPad supports baseline level 3.1. You can find out more about <a href="http://h264.code-shop.com/trac/wiki/Encoding">h264 encoding levels with FFMpeg</a> and also review <a href="http://rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide/">FFMpeg x264 encoding guide</a>, <a href="http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping">FFMpeg option mappings</a> and <a href="http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-x264.html">information on encoding with the x264 codec</a> for more information.</p>
<p>Another bit of information disclosed in the Apple tech notes is the existence of a media stream validation tool. This tool can be downloaded from the Apple iPhone developer site and has to be run on OS X. Apple recommends that you use this tool to validate any streams that you create.</p>
<p>One other note that I have recently ran across is that Apple seems to be <a href="http://techcrunch.com/2010/03/26/iphone-video-apps-downgrade-streaming-rates/">rejecting <i>native apps</i> that have video streams without a fall back audio stream</a>. The correct way of generating the fallback 64k audio only stream is something that is lacking in the current version of the segmenter but I hope to fix that soon. It won&#039;t matter for those using the HTML5 video tag however.</p>
<p>If you are using HTML5 video tags it is important not to use my older posts as a guide for the iPad since I use a now outdated example. Those examples still work on the iPhone but they do not work on the iPad. Here is an updated example that will work on both the iPhone and iPad:</p>
<pre class="brush: xml;">
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Video Test&lt;/title&gt;
  &lt;/head&gt;
  &lt;body style=&quot;background-color:#FFFFFF; &quot;&gt;
    &lt;center&gt;
      &lt;video controls&gt;
        &lt;source src=&quot;stream_multi.m3u8&quot;/&gt;
      &lt;/video&gt;
    &lt;/center&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Finally I am currently using the latest version of FFMpeg to do tests and it seems to have become more reliable for me. The current version in git seems to be pretty good at producing usable videos from a variety of source videos.</p>
<p>The following is a quick summary of the recent changes I have made:</p>
<ul>
<li>Applied an audio patch for the segmenter from Scott Kidder. This patch skips any video processing if there is no video stream.</li>
<li>Modified sample configs with newer FFMpeg string, gop sizes, frame rates and other parameters to match the Apple recomended values for iPhone/iPod Touch with aspect ratios of 4:3 and 6:9 on cell or wifi and iPad with aspect ratios of 4:3 and 6:9 on cell or wifi</li>
<li>Added configuration sanity checks</li>
<li>Made gems not required if not using those features that need them</li>
<li>Added fix for deprecation warning from newest version of libavformat</li>
<li>Made termination work better when killed with SIGINT/ctrl-c</li>
<li>Fixed some minor issues with index file format</li>
</ul>
<p>The following are enhancements I&#039;m planning on making:</p>
<ul>
<li>
I plan on creating a howto on getting everything set up on EC2.
</li>
<li>
Dig more into verification that each segment starts with the correct I-frame.
</li>
<li>
I&#039;m going to work on refactoring everything so that instead of creating files and then transferring them it streams them all. This makes more sense with doing encryption as just another part of the pipeline.
</li>
<li>
Add ability to do <a href="http://tools.ietf.org/html/draft-pantos-http-live-streaming-02#section-6.1.2">encryption</a>. I have a proof of concept working but I decided I need to get everything set up in one continuous stream before integrating encryption into the mix.
</li>
<li>
<a href="http://www.ioncannon.net/programming/941/using-daemon-kit-and-robustthread-to-build-ruby-daemons/">I had thoughtabout using the ruby daemon utils</a> to wrap the segmenter but I decided it probably isn&#039;t necessary at this point.
</li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=GP1k6TVqIA8:dlaMppi3EAo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=GP1k6TVqIA8:dlaMppi3EAo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=GP1k6TVqIA8:dlaMppi3EAo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=GP1k6TVqIA8:dlaMppi3EAo:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=GP1k6TVqIA8:dlaMppi3EAo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=GP1k6TVqIA8:dlaMppi3EAo:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/GP1k6TVqIA8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/1015/ipad-streaming-video-and-more/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/programming/1015/ipad-streaming-video-and-more/</feedburner:origLink></item>
		<item>
		<title>Using Cursors with PHP MySQLi and Multiple Prepared Statements</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/--KvmVxKSqU/</link>
		<comments>http://www.ioncannon.net/programming/998/using-cursors-with-php-mysqli-and-multiple-prepared-statements/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 11:37:41 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[cursor]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysqli]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=998</guid>
		<description><![CDATA[After my post on using PHP MySQLi and multiple prepared statements at the same time someone commented that using cursors could do the same thing. With that comment I dug some more and found that modifying the cursor type that is used under the covers will indeed let you execute multiple prepared statements concurrently on [...]]]></description>
			<content:encoded><![CDATA[<p>After my post on <a href="http://www.ioncannon.net/programming/889/php-mysqli-and-multiple-prepared-statements/">using PHP MySQLi and multiple prepared statements at the same time</a> someone commented that using <a href="http://dev.mysql.com/doc/refman/5.5/en/cursors.html">cursors</a> could do the same thing. With that comment I dug some more and found that modifying the cursor type that is used under the covers will indeed let you execute multiple prepared statements concurrently on the same connection.</p>
<p>First off you may ask yourself why you would want to use this. The best answer I have for that is that the solution in the other post loads the entire result set into memory from the very start while with this solution you can control just how many rows you load. To get started you will want to take a look at the <a href="http://php.net/manual/en/mysqli-stmt.attr-set.php">MySQLi statement set attribute</a> call. This call is will let you modify the underlying cursor type that is used with the prepared statement in two ways that are useful for this issue.</p>
<p><span id="more-998"></span></p>
<p>The MYSQLI_STMT_ATTR_CURSOR_TYPE attribute controls the type of cursor used for the results from the prepared statement. The default option is MYSQLI_CURSOR_TYPE_NO_CURSOR  which results in no cursor being used at all. The only other option is MYSQLI_CURSOR_TYPE_READ_ONLY and this is the one you will want to use.</p>
<p>The MYSQLI_STMT_ATTR_PREFETCH_ROWS attribute controls the number of rows that are fetched under the covers from the server as more data is needed. The default for this attribute is 1 which means that each fetch of the row causes a round trip to the server. Larger numbers for this attribute will cause more memory to be used to store the resulting rows but fewer round trips to the server. This is the attribute that gives this option more flexibility.</p>
<p>The following is a slightly modified example that was used in the previous post now using both the MYSQLI_STMT_ATTR_CURSOR_TYPE and MYSQLI_STMT_ATTR_PREFETCH_ROWS attributes to efficiently retrieve rows from two different prepared statements at the same time:</p>
<pre class="brush: php;">
&lt;?php

  $db_connection = new mysqli('127.0.0.1', 'user', '', 'test');

  $post_stmt = $db_connection-&gt;prepare(&quot;select id, title from post where id between 10000 and 10999&quot;);
  $post_stmt-&gt;attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY);
  $post_stmt-&gt;attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 100);
  $comment_stmt = $db_connection-&gt;prepare(&quot;select user_id from comment where post_id = ?&quot;);

  if ($post_stmt-&gt;execute())
  {
    $post_stmt-&gt;bind_result($post_id, $post_title);

    while ($post_stmt-&gt;fetch())
    {
      $comments = array();

      $comment_stmt-&gt;bind_param('i', $post_id);
      if ($comment_stmt-&gt;execute())
      {
        $comment_stmt-&gt;bind_result($user_id);
        while ($comment_stmt-&gt;fetch())
        {
          array_push($comments, array('user_id' =&gt; $user_id));
        }
      }
      else
      {
        printf(&quot;Comment statement error: %s\n&quot;, $comment_stmt-&gt;error);
      }

      printf(&quot;ID: %d -&gt; %s\n&quot;, $post_id, $post_title);
      print_r($comments);
    }
  }
  else
  {
    printf(&quot;Post statement error: %s\n&quot;, $post_stmt-&gt;error);
  }

  $post_stmt-&gt;close();
  $comment_stmt-&gt;close();

  $db_connection-&gt;close();
?&gt;
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=--KvmVxKSqU:E6VHmSNBVBM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=--KvmVxKSqU:E6VHmSNBVBM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=--KvmVxKSqU:E6VHmSNBVBM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=--KvmVxKSqU:E6VHmSNBVBM:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=--KvmVxKSqU:E6VHmSNBVBM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=--KvmVxKSqU:E6VHmSNBVBM:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/--KvmVxKSqU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/998/using-cursors-with-php-mysqli-and-multiple-prepared-statements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/programming/998/using-cursors-with-php-mysqli-and-multiple-prepared-statements/</feedburner:origLink></item>
		<item>
		<title>Spring 3 File Upload Example</title>
		<link>http://feedproxy.google.com/~r/ioncannon/~3/h6HJIGix_SY/</link>
		<comments>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 11:30:40 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=975</guid>
		<description><![CDATA[I had the opportunity to figure out how to do file uploads using Spring 3 the other day and I couldn&#039;t find anything that pulled it all together. What follows is a complete example of how to do MVC based file uploads with Spring 3. I&#039;m going to assume you know something about Spring and [...]]]></description>
			<content:encoded><![CDATA[<p>I had the opportunity to figure out how to do file uploads using Spring 3 the other day and I couldn&#039;t find anything that pulled it all together. What follows is a complete example of how to do MVC based file uploads with Spring 3.</p>
<p><span id="more-975"></span></p>
<p>I&#039;m going to assume you know something about <a href="http://www.springsource.org/">Spring</a> and their MVC configuration in general. If you want a simple MVC example to start with check out their <a href="https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/src/main/">SVN MVC-Basic sample</a>. There is a decent amount of boiler plate work so I&#039;ve created a <a href="http://www.ioncannon.net/examples/Spring3Upload.zip">project zip file</a> with all the code, a build file and configuration in it (you just need to add the libraries).</p>
<p>First lets start by gathering up all the libraries we are going to need (see the end of the post for the directory layout I used or just unzip the project). Grab a copy of the Spring 3 libraries, at this time the latest version is spring-framework-3.0.1.RELEASE-A.zip and that is what I used for the following example. For the file upload part there are two non-Spring dependencies as well: <a href="http://commons.apache.org/fileupload/">Apache Commons FileUpload</a> and <a href="http://commons.apache.org/io/">Apache Commons IO</a>. If you want to use the example project from the zip just copy all the jar files to the lib directory.</p>
<p>Next it is worth a quick look at the information provided in the Spring documentation about <a href="http://static.springsource.org/spring/docs/3.0.0.RELEASE/reference/html/mvc.html#mvc-multipart">MVC multipart</a>. It touches on what needs to be done but leaves out a full example. In documentation you will see that they talk about using a &#034;multipart resolver&#034; and that can be found at the end of <i>web/WEB-INF/spring/app-config.xml</i>:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
       xsi:schemaLocation=&quot;
		http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd&quot;&gt;

    &lt;!-- Scans the classpath of this application for @Components to deploy as beans --&gt;
    &lt;context:component-scan base-package=&quot;net.ioncannon&quot;/&gt;

    &lt;!-- Configures Spring MVC --&gt;
    &lt;import resource=&quot;mvc-config.xml&quot;/&gt;

    &lt;!-- Configure the multipart resolver --&gt;
    &lt;bean id=&quot;multipartResolver&quot; class=&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;&gt;
        &lt;!-- one of the properties available; the maximum file size in bytes --&gt;
        &lt;property name=&quot;maxUploadSize&quot; value=&quot;100000&quot;/&gt;
    &lt;/bean&gt;

&lt;/beans&gt;
</pre>
<p>The above app-config.xml configuration file is referenced from the mvc-config.xml configuration file. The mvc-config.xml configuration file doesn&#039;t need anything special for multipart uploads so I&#039;ll skip listing it here, have a look in the zip file if you are interested in its contents.</p>
<p>Now that the configuration is set the next step is to create the entry form for the upload. I&#039;ve done this in the view JSP found in <i>web/WEB-INF/views/upload/uploadForm.jsp</i>:</p>
<pre class="brush: xml;">
&lt;%@page contentType=&quot;text/html;charset=UTF-8&quot; %&gt;
&lt;%@page pageEncoding=&quot;UTF-8&quot; %&gt;
&lt;%@ page session=&quot;false&quot; %&gt;
&lt;%@ taglib prefix=&quot;form&quot; uri=&quot;http://www.springframework.org/tags/form&quot; %&gt;

&lt;html&gt;
    &lt;head&gt;
        &lt;META http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;
        &lt;title&gt;Upload Example&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;form:form modelAttribute=&quot;uploadItem&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
            &lt;fieldset&gt;
                &lt;legend&gt;Upload Fields&lt;/legend&gt;

                &lt;p&gt;
                    &lt;form:label for=&quot;name&quot; path=&quot;name&quot;&gt;Name&lt;/form:label&gt;&lt;br/&gt;
                    &lt;form:input path=&quot;name&quot;/&gt;
                &lt;/p&gt;

                &lt;p&gt;
                    &lt;form:label for=&quot;fileData&quot; path=&quot;fileData&quot;&gt;File&lt;/form:label&gt;&lt;br/&gt;
                    &lt;form:input path=&quot;fileData&quot; type=&quot;file&quot;/&gt;
                &lt;/p&gt;

                &lt;p&gt;
                    &lt;input type=&quot;submit&quot; /&gt;
                &lt;/p&gt;

            &lt;/fieldset&gt;
        &lt;/form:form&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>A few notes about this view JSP:</p>
<ul>
<li>The form needs to have the encoding type set correctly. Look for: enctype=&#034;multipart/form-data&#034;</li>
<li>The file input field needs to be set: type=&#034;file&#034;</li>
<li>In the above I&#039;ve included a Name field in the model as well as the File field just to show that you can mix fields in the same form</li>
<li>The definition of the model can be found next and I assume that it is introduced into the form as &#034;uploadItem&#034;</li>
</ul>
<p>The model is pretty simple and can be found in <i>src/net/ioncannon/model/UploadItem.java</i>:</p>
<pre class="brush: java;">
package net.ioncannon.model;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class UploadItem
{
  private String name;
  private CommonsMultipartFile fileData;

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

  public CommonsMultipartFile getFileData()
  {
    return fileData;
  }

  public void setFileData(CommonsMultipartFile fileData)
  {
    this.fileData = fileData;
  }
}
</pre>
<p>The Name attribute is just an extra input field and not the name of the file. Notice that the File attribute is of type CommonsMultipartFile. The CommonsMultipartFile type has a number of features that give you information about the uploaded file as well as access to its contents.</p>
<p>The controller brings everything together. The source can be found in the file <i>src/net/ioncannon/controller/UploadController.java</i>:</p>
<pre class="brush: java;">
package net.ioncannon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import net.ioncannon.model.UploadItem;

@Controller
@RequestMapping(value = &quot;/upload&quot;)
public class UploadController
{
  @RequestMapping(method = RequestMethod.GET)
  public String getUploadForm(Model model)
  {
    model.addAttribute(new UploadItem());
    return &quot;upload/uploadForm&quot;;
  }

  @RequestMapping(method = RequestMethod.POST)
  public String create(UploadItem uploadItem, BindingResult result)
  {
    if (result.hasErrors())
    {
      for(ObjectError error : result.getAllErrors())
      {
        System.err.println(&quot;Error: &quot; + error.getCode() +  &quot; - &quot; + error.getDefaultMessage());
      }
      return &quot;upload/uploadForm&quot;;
    }

    // Some type of file processing...
    System.err.println(&quot;-------------------------------------------&quot;);
    System.err.println(&quot;Test upload: &quot; + uploadItem.getName());
    System.err.println(&quot;Test upload: &quot; + uploadItem.getFileData().getOriginalFilename());
    System.err.println(&quot;-------------------------------------------&quot;);

    return &quot;redirect:/app/&quot;;
  }
}
</pre>
<p>Once the file is uploaded I&#039;m just dumping out part of the information. Doing something exciting with the file is up to you.</p>
<p>That is all there is to it. Here is a list of what the project structure looks like with everything pulled together including all the libraries, build file, source and configuration files:</p>
<div class="codesnip-container" >build/build.xml<br />
lib/commons-fileupload-1.2.1.jar<br />
lib/commons-io-1.4.jar<br />
lib/org.springframework.aop-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.asm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.aspects-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.beans-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.context-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.context.support-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.core-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.expression-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.instrument-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.instrument.tomcat-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.jdbc-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.jms-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.orm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.oxm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.spring-library-3.0.1.RELEASE-A.libd<br />
lib/org.springframework.test-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.transaction-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.portlet-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.servlet-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.struts-3.0.1.RELEASE-A.jar<br />
src/net/ioncannon/controller/UploadController.java<br />
src/net/ioncannon/model/UploadItem.java<br />
web/WEB-INF/web.xml<br />
web/WEB-INF/spring/app-config.xml<br />
web/WEB-INF/spring/mvc-config.xml<br />
web/WEB-INF/views/welcome.jsp<br />
web/WEB-INF/views/upload/uploadForm.jsp</div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ioncannon?a=h6HJIGix_SY:AvF0xNg6_lU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=h6HJIGix_SY:AvF0xNg6_lU:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ioncannon?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=h6HJIGix_SY:AvF0xNg6_lU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=h6HJIGix_SY:AvF0xNg6_lU:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ioncannon?a=h6HJIGix_SY:AvF0xNg6_lU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/ioncannon?i=h6HJIGix_SY:AvF0xNg6_lU:F7zBnMyn0Lo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ioncannon/~4/h6HJIGix_SY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.647 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-09-07 08:06:23 -->
