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

<channel>
	<title>Adam Frisby &#187; s3</title>
	<atom:link href="http://www.adamfrisby.com/blog/tag/s3/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.adamfrisby.com/blog</link>
	<description>ZOMGWTFHAI</description>
	<lastBuildDate>Sat, 26 Dec 2009 07:02:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Prototyping with OpenSim: Testing out Amazon S3 as a Grid-Mode Asset Server</title>
		<link>http://www.adamfrisby.com/blog/2008/07/prototyping-with-opensim-testing-out-amazon-s3-as-a-grid-mode-asset-server/</link>
		<comments>http://www.adamfrisby.com/blog/2008/07/prototyping-with-opensim-testing-out-amazon-s3-as-a-grid-mode-asset-server/#comments</comments>
		<pubDate>Fri, 25 Jul 2008 05:54:18 +0000</pubDate>
		<dc:creator>Adam Frisby</dc:creator>
				<category><![CDATA[OpenSim]]></category>
		<category><![CDATA[Technical]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[assets]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[prototyping]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://gwala.net/blog/?p=16</guid>
		<description><![CDATA[Disclaimer: This is probably a bad idea in motion, I make no claims as to how well this could hold up in the long run or real world &#8211; I have some personal concerns about how Amazon is able to scale their S3 service effectively, and the recent downtime should give cause to think first [...]]]></description>
			<content:encoded><![CDATA[<p><em>Disclaimer: This is probably a bad idea in motion, I make no claims as to how well this could hold up in the long run or real world &#8211; I have some personal concerns about how Amazon is able to scale their S3 service effectively, and the recent downtime should give cause to think first before putting this into production.</em></p>
<p>If you want to be a cool geek these days, you absolutely have to insert the words &#8216;cloud computing&#8217; into every other sentence. It&#8217;s no suprise then that one of the more adopted and interesting toys in the last year or two has been the Amazon Simple Storage Service (S3 for short).</p>
<p>It&#8217;s a &#8220;cloud&#8221; based storage solution, where you can upload files onto the cloud relatively cheaply. It&#8217;s being used in places Akamai used to be used for mirroring and proxying of frequently accessed files. (Even Linden Lab uses it for distrobuting their updates.)</p>
<p>The price is right, and the solution is fully programmable via a convenient web API, so it&#8217;s snuck itself into all sorts of places. What I&#8217;d like to experiment here is using it as a complete grid asset server, for those who havnt toyed much with the OpenSim asset server under the hood &#8211; it&#8217;s effectively a webserver with two supported operations: &#8220;PUT&#8221; and &#8220;GET&#8221; &#8211; funnily enough this overlaps nicely with any network accessible storage system, S3 included.</p>
<h3>Building a new asset storage module from scratch</h3>
<p>First thing we need to do is go hunting for another asset storage module in OpenSim so we can take a look at the interface we are required to implement. After a quick hunt for &#8220;asset_database&#8221; (the OpenSim.ini setting) it turns up that we need to create a class that derives from <span style="color: #3366ff;">AssetServerBase </span>which in turn derives from <span style="color: #3366ff;">IAssetServer</span>.</p>
<textarea name="code" class="csharp:nocontrols" cols="60" rows="10">
public interface IAssetServer
{
void SetReceiver(IAssetReceiver receiver);
void RequestAsset(LLUUID assetID, bool isTexture);
void StoreAsset(AssetBase asset);
void UpdateAsset(AssetBase asset);
void Close();
}
</textarea>
<p>This looks relatively painless so far, we need to make a class which implements all five of these functions. The next step is to go take a look around and see if there is a decent .NET library for interfacing with S3. Turns out there is &#8211; <a href="http://sourceforge.net/projects/nets3client/">.NET S3</a>. (<em>Post-authoring note: Apparently Amazon have an official library which looks easier to use, for one it doesn&#8217;t require the delegate hackery seen in the GetAsset function</em>)</p>
<p>This library, while not fantastically documented does seem to do the job quickly and easily.</p>
<h3>Implementing the asset client</h3>
<p>Now we are at the point where we can actually write our class, using the above library, I&#8217;ve skipped ahead and written the class as presented below:</p>
<textarea name="code" class="csharp:nocontrols" cols="60" rows="10">
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using log4net;
using S3Client;

namespace OpenSim.Framework.Communications.Cache
{
public class S3AssetClient : AssetServerBase
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private S3Connection con;
private string dir;

// For converting assets to/from XML
// (convenient for us, although a binary serialiser will be cheaper storage-space wise)
private XmlSerializer xs = new XmlSerializer(typeof(AssetBase));

public S3AssetClient(string s3id, string s3key, string s3dir)
{
m_log.Info("[S3 Asset Store] Initialising Amazon Asset Client");
con = new S3Connection(s3id, s3key, true);
dir = s3dir;

// Find our directory. (I CAN HAZ MY BUKKIT?)
List x = con.ListAllBuckets();
bool found = false;
foreach (BucketInfo info in x)
{
if(info.Name == dir)
{
found = true;
}
}

// No luck? Create a new bucket/directory.
if (!found)
con.CreateBucket(dir);
}

public override void StoreAsset(AssetBase asset)
{
m_log.Info("[S3 Asset Store] Saving asset...");

MemoryStream tw = new MemoryStream();

// Convert the asset to XML and throw it into memory.
xs.Serialize(tw, asset);

string xml = tw.ToString();
string md5 = Util.Md5Hash(xml);

con.PutObject(dir, asset.FullID.ToString(), xml.Length, "text/xml", md5, null, delegate(Stream s)
{
tw.WriteTo(s);
return null;
});

}

protected override AssetBase GetAsset(AssetRequest req)
{
Stream v = null;
bool done = false;
m_log.Info("[S3 Asset Store] Retrieving asset...");
con.GetObject(dir, req.AssetID.UUID.ToString(), delegate(Stream s)
{
v = s;
done = true;
return null;
});
while(!done)
{
System.Threading.Thread.Sleep(500);
}

return (AssetBase) xs.Deserialize(v);
}
}
}
</textarea>
<p>As you can see, the meat of the function sits in the StoreAsset and GetAsset functions, in this case we&#8217;ve overridden them to save to an EC2 Bucket (&#8221;directory&#8221;). We&#8217;ve made the directory a parameter of the constructor, as long as each region on the &#8220;grid&#8221; uses the same directory, they will act as one giant asset database.</p>
<h3>Final Steps: Hooking it up</h3>
<p>If we head back to OpenSimBase.cs where we first went looking for &#8220;m_assetStorage&#8221; originally, on line 412 we see:</p>
<textarea name="code" class="csharp:nocontrols" cols="60" rows="10">
IAssetServer assetServer;
if (m_assetStorage == "grid")
{
assetServer = new GridAssetClient(m_networkServersInfo.AssetURL);
}
</textarea>
<p>Below this, let&#8217;s add a new statement</p>
<textarea name="code" class="csharp:nocontrols" cols="60" rows="10">
else if (m_assetStorage == "s3")
{
assetServer = new S3AssetClient("id", "key", "directory");
}
</textarea>
<p>Now, if we change the ini setting to read &#8220;s3&#8243; our brand spanking new S3 client should fire up.</p>
<h3>In Conclusion</h3>
<p>I need to make some notes here, first hard coding classes like the above is a bad idea. We shouldnt be doing it for the grid asset server (and instead should be loading a class via reflection). Second we shouldnt be hard-coding the login keys &#8211; moving that up to an ini setting is preffered (and not too difficult to do properly). <strong>Third this is a untested bit of code, use it at your own risk, this was done as an experiment in approximately 45 minutes.</strong></p>
<p>However, for all the above warts &#8211; this shows off the power of OpenSim for rapid prototyping, one of the great features of OpenSim is just how flexible it can be, and how little work is needed to do something completely crazy with it quickly and relatively easily.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamfrisby.com/blog/2008/07/prototyping-with-opensim-testing-out-amazon-s3-as-a-grid-mode-asset-server/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
