<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>Muranosoft Blog</title>
  <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/" />
  <link rel="self" href="http://www.muranosoft.com/Outsourcingblog/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2011-07-27T06:23:21.6461209-07:00</updated>
  <author>
    <name>Murano Software</name>
  </author>
  <subtitle>Coding etc</subtitle>
  <id>http://www.muranosoft.com/Outsourcingblog/</id>
  <generator uri="http://dasblog.info/" version="2.3.9074.18820">DasBlog</generator>
  <entry>
    <title>Hands on MongoDB–Part 4</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDBPart-4.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,88d5d2d4-6777-46ab-98af-44c463705f02.aspx</id>
    <published>2011-07-22T07:41:00-07:00</published>
    <updated>2011-07-27T06:23:21.6461209-07:00</updated>
    <category term="MongoDB" label="MongoDB" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,MongoDB.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Ivan, PhD., a <a href="http://www.muranosoft.com/Outsourcingblog/ct.ashx?id=9f5790d2-1eed-44fb-bd4e-e3e752e7fc29&amp;url=http%3a%2f%2fwww.muranosoft.com%2fservices%2fjava.aspx">Java
developer</a> at Murano Software’s team</em>
        </p>
        <p>
This is the last post from our series about <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-1.aspx">MongoDB</a>.
We have shown you the <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-2.aspx">features</a>,
the <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-3.aspx">drawbacks</a> and
now we will show you how it handles Java.
</p>
        <p>
As mentioned before, MongoDB supports a number of drivers for different platforms;
however, since it's mostly designed to operate in the Web's distributed environment,
it comes naturally along Java technology. But enough words said, instead let's jump <a name="__DdeLink__0_1595702071">straight</a> to
code and see what it really looks like from the inside. To make it even more exciting,
we put in some competition flavor by comparing MongoDB on Java with something very
common and widely used, something like MySQL. So, we are about to assemble some kind
of roughly made comparative performance test for MongoDB and MySQL with bulk inserts,
selects and updates. Before we move on, I beg you not to take this performance test
too seriously, since it's in no way a complete, redundant or ultimate performance
test, and it's not intended to say some heavy 'yes' or 'no' toward a specific solution.
It's merely an applied example to make your journey with MongoDB interesting and useful.
</p>
        <p>
There is plenty of detailed documentation for both MySQL’s and MongoDB’s installation
setup processes. They both are available as a binary distribution. If you are a Linux
user, I encourage you to use repository distributions. Let's assume we have our environment
set up and running, and we ready to start coding.
</p>
        <p>
We need some generic testing and reporting suite and service running our insert/select/update
routines for available database providers. You can download complete code to look
into and play with it using this <a href="http://www.muranosoft.com/downloads/MongoPerformanceTest.zip">link</a>:
</p>
        <p>
Let's take a closer look at MongoDB’s database service, MongoDbOpService.java:
</p>
        <p>
&lt;code&gt;
</p>
        <p>
...
</p>
        <p>
public class MongoDbOpService implements DatabaseOpService, InitializingBean { 
<br />
... 
<br />
    @Override 
<br />
    public void cleanUp() { 
<br />
        col.remove(BasicDBObjectBuilder.start().get()); 
<br />
        col.ensureIndex(BasicDBObjectBuilder.start().add("field1",
1).get()); 
<br />
    } 
<br />
  @Override 
<br />
   public void afterPropertiesSet() throws Exception { 
<br />
        Mongo mongo = new Mongo(host, port); 
<br />
        col = mongo.getDB("test").getCollection("test"); 
<br />
        cleanUp(); 
<br />
  } 
<br />
  @Override 
<br />
  public void select(int numOfOps) throws DatabaseOperationException { 
<br />
       for (int i = 0; i &lt; numOfOps; i++){ 
<br />
       col.find(BasicDBObjectBuilder.start() 
<br />
      .add("field1", new BasicDBObject("$gt",
i)).get()); 
<br />
  } 
<br />
  } 
<br />
  @Override 
<br />
  public void update(int numOfOps) throws DatabaseOperationException { 
<br />
       for (int i = 0; i &lt; numOfOps; i++) { 
<br />
      col.update(new BasicDBObject("field1", new
BasicDBObject("$gt", i)), 
<br />
      new BasicDBObject("$set", new BasicDBObject("field2",
1)), false, true); 
<br />
  } 
<br />
  } 
<br />
  @Override 
<br />
  public void insert(int numOfOps) throws DatabaseOperationException { 
<br />
      for (int i = 0; i &lt; numOfOps; i++) { 
<br />
          BasicDBObjectBuilder builder
= new BasicDBObjectBuilder(); 
<br />
          builder 
<br />
             .add("field1",
(int) (Math.random() * numOfOps)) 
<br />
             .add("field2",
(int) (Math.random() * numOfOps)) 
<br />
             .add("field3",
(int) (Math.random() * numOfOps)); 
<br />
         col.save(builder.get()); 
<br />
        } 
<br />
  } 
<br />
... 
<br />
}
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
We start by just creating Mongo instance, with its constructor accepting the host
address as a parameter. Then we want to create a test database and collect in it.
The trick is that we don't have to worry about whether the database with the given
name exists. getDB() will return existing names or create a new one for us, and the
same applies to getCollection(). Since we are going to run through our routines several
times, we want to ensure we have a clean collection for each pass, and we can do it
by calling the cleanUp() service method. It will remove all documents from the collection
in case this is not the first run and ensure (create) index on the field ('field1')
that we are going to query later on. If you did the same thing from a JavaScript console,
it would look something like this:
</p>
        <p>
&lt;code&gt;
</p>
        <p>
&gt; db.test.remove({}) 
<br />
&gt; db.test.ensureIndex({“field1”:1})
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
Where 'test' is the name of the collection, remove is given an empty JSON object as
a filter argument, and ensureIndex is given an object with only one name as an index
target field, while '1' indicates ascending indexing order. Worth mentioning is that
almost everything inside MongoDB uses json extensively for filtering, querying, update
operations, etc. Also note that there is nothing like data schema for the created
MongoDB collection.
</p>
        <p>
The next point of interest is the insert(int N) call that will insert N simple objects
into our test collection, which in json will look like this:
</p>
        <p>
&lt;code&gt;
</p>
        <p>
{ 
<br />
     “field1” : random_int, 
<br />
     “field2” : random_int, 
<br />
     “field3” : random_int 
<br />
}
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
Now, when we have N documents in our collection, we can start playing and selecting
them. The select(int N) call will make N queries to test the collection, trying to
fetch all documents that have their field2 value greater than some integer (0,N].
Note that such query returns the cursor, so it's usually a good idea to consider paging
and result limiting in your live application, especially on large data results. Otherwise
you will definitely hit a cursor timeout issue or some other nasty distributed environment
issues. The very same query in JS console would look like this: 
</p>
        <p>
&lt;code&gt;
</p>
        <p>
&gt; db.test.find({“field1”:{$gt:i}})
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
Note how we use the filter operator keyword '$gt' (greater than). There are two things
to note here. First, there are plenty of such keywords in mongodb query syntax used
for filtering, updating and some other cool stuff. You can find all the details in
manuals. What is more important to note is that we actually use json object as a value
for “field1.” So your documents can contain any number of nested documents in field
values, as well as arrays and functions. This can lead to very interesting applications,
including stored procedures. Just take a look at this example object:
</p>
        <p>
&lt;code&gt;
</p>
        <p>
{ 
<br />
     _id : ObjectID(“4e0a078e69fea677c91d3742”), 
<br />
     name: “John”, 
<br />
     address:{ 
<br />
                            
city:“Moscow”, 
<br />
                            
street:{ 
<br />
                                                    
name: ”Lenin”, 
<br />
                                                    
type: “Square” 
<br />
                                                
}, 
<br />
                            
zip: 12345 
<br />
                          
}, 
<br />
     sayHi : function(){print('Hello from function!');}, 
<br />
     some_list:[1245968390, 2859408375, 8756203941], 
<br />
     some_object_list:[ 
<br />
                                           
{field1:”something1”,field2:1}, 
<br />
                                           
{field1:”something2”,field2:-1} 
<br />
                                        
] 
<br />
} 
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
Even though it can look confusing, it turns out to be a very convenient way of making
things work. Also, since this is actually an object, you can use “dot notation” to
access any nested field. So if we match the object from the last example, we can do
the following:
</p>
        <p>
&lt;code&gt;
</p>
        <p>
&gt; a = db.test.findOne({name:”John”}) 
<br />
&gt; a.address.street.type 
<br />
Square 
<br />
&gt; a.sayHi() 
<br />
Hello from function!
</p>
        <p>
&gt; a.some_list[0] 
<br />
1245968390
</p>
        <p>
&lt;/code&gt;
</p>
        <p>
Finally, update(int N) call makes N update operations, trying to find objects with
the same query select() does, but this time we want to change 'field2' value of matched
objects. Note that we are using the '$set' atomic modifier here, so that this update
won't lock the object being changed, only the field value is to be updated.
</p>
        <p>
Here are the results I've got on my local machine. I have to mention that even the
simple and quick-made test we used shows how ridiculously slow bulk operation can
be with the traditional relational approach. I basically stopped on the 10k set because
it takes way too much time with little difference in results. In the meantime, using
MongoDB, I've had times when I generated millions of documents for the demo collection,
and it took a matter of minutes.
</p>
        <p>
Test: MongoDB vs MySQL quick performance test (insert/select/update) 
<br />
Environment: Ubuntu 11.04 Linux x86_64 2.6.38, i5-2400, RAM 8Gb
</p>
        <table border="0" cellspacing="0" cellpadding="2" width="419">
          <tbody>
            <tr>
              <td valign="top" width="55">
Service</td>
              <td valign="top" width="45">
OpNum</td>
              <td valign="top" width="64">
Ins</td>
              <td valign="top" width="49">
InsAvg</td>
              <td valign="top" width="53">
Sel</td>
              <td valign="top" width="43">
SelAvg</td>
              <td valign="top" width="50">
Upd</td>
              <td valign="top" width="58">
UpdAvg</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MongoDb</td>
              <td valign="top" width="45">
10</td>
              <td valign="top" width="64">
1</td>
              <td valign="top" width="49">
0.1</td>
              <td valign="top" width="53">
1</td>
              <td valign="top" width="43">
0.1</td>
              <td valign="top" width="50">
1</td>
              <td valign="top" width="58">
0.1 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MySQL</td>
              <td valign="top" width="45">
10</td>
              <td valign="top" width="64">
533</td>
              <td valign="top" width="49">
53.3</td>
              <td valign="top" width="53">
3</td>
              <td valign="top" width="43">
0.3</td>
              <td valign="top" width="50">
599</td>
              <td valign="top" width="58">
59.9 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MongoDb</td>
              <td valign="top" width="45">
100</td>
              <td valign="top" width="64">
19</td>
              <td valign="top" width="49">
0.19</td>
              <td valign="top" width="53">
0</td>
              <td valign="top" width="43">
0.0</td>
              <td valign="top" width="50">
8</td>
              <td valign="top" width="58">
0.08 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MySQL</td>
              <td valign="top" width="45">
100</td>
              <td valign="top" width="64">
5145</td>
              <td valign="top" width="49">
51.45</td>
              <td valign="top" width="53">
42</td>
              <td valign="top" width="43">
0.42</td>
              <td valign="top" width="50">
5866</td>
              <td valign="top" width="58">
58.66 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MongoDb</td>
              <td valign="top" width="45">
1000</td>
              <td valign="top" width="64">
79</td>
              <td valign="top" width="49">
0.079</td>
              <td valign="top" width="53">
5</td>
              <td valign="top" width="43">
0.0050</td>
              <td valign="top" width="50">
53</td>
              <td valign="top" width="58">
0.053 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MySQL</td>
              <td valign="top" width="45">
1000</td>
              <td valign="top" width="64">
49695</td>
              <td valign="top" width="49">
49.695</td>
              <td valign="top" width="53">
966</td>
              <td valign="top" width="43">
0.966</td>
              <td valign="top" width="50">
52245</td>
              <td valign="top" width="58">
52.245 
</td>
            </tr>
            <tr>
              <td valign="top" width="55">
MongoDb</td>
              <td valign="top" width="45">
10000</td>
              <td valign="top" width="64">
435</td>
              <td valign="top" width="49">
0.0435</td>
              <td valign="top" width="53">
18</td>
              <td valign="top" width="43">
0.0018</td>
              <td valign="top" width="50">
67182</td>
              <td valign="top" width="58">
6.7182 
</td>
            </tr>
          </tbody>
        </table>
        <table border="0" cellspacing="0" cellpadding="2" width="420">
          <tbody>
            <tr>
              <td valign="top" width="74">
MySQL</td>
              <td valign="top" width="50">
10000</td>
              <td valign="top" width="60">
490376</td>
              <td valign="top" width="44">
49.0376</td>
              <td valign="top" width="44">
40992</td>
              <td valign="top" width="43">
4.0992</td>
              <td valign="top" width="39">
863177</td>
              <td valign="top" width="64">
86.3177</td>
            </tr>
          </tbody>
        </table>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002_2.gif">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002_thumb.gif" width="582" height="354" />
          </a>
        </p>
        <blockquote>
          <p align="left">
                                  
Figure 2 - Average select time, ms/record
</p>
        </blockquote>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002%5B5%5D.gif">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002[5]" border="0" alt="clip_image002[5]" src="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002%5B5%5D_thumb.gif" width="484" height="274" />
          </a>
        </p>
        <blockquote>
          <p>
                                   
Figure 3 - Average update time, ms/record
</p>
        </blockquote>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002%5B9%5D.gif">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002[9]" border="0" alt="clip_image002[9]" src="http://www.muranosoft.com/Outsourcingblog/content/binary/Windows-Live-Writer/d50d22ef1343_901E/clip_image002%5B9%5D_thumb.gif" width="476" height="270" />
          </a>
        </p>
        <h4>Epilogue
</h4>
        <p>
After having a brief look at MongoDB's features and trade offs, one can ask oneself,
is this piece of technology production ready, and could I use it in my project? Well,
it's up to you, but my word is that you should give it a try. The test we were using
as an example cannot be taken to prove either MongoDB or MySQL is better. It just
shows how these two systems can handle one specific test. What is absolutely exciting
about MongoDB is that it's really easy to start working with. It's just a matter of
an hour to layout some basic configuration and client code. There are huge advantages
and yet a price to pay.
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=88d5d2d4-6777-46ab-98af-44c463705f02" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Hands on MongoDB–Part 3</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDBPart-3.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,255fb340-665e-43e2-8305-6624fc6f9fca.aspx</id>
    <published>2011-07-20T06:31:00-07:00</published>
    <updated>2011-07-25T23:31:49.1553972-07:00</updated>
    <category term="MongoDB" label="MongoDB" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,MongoDB.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
In our previous posts we <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-1.aspx">introduced
you to MongoDB</a> as well as it’s <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-2.aspx">features</a>.
In this part we will be talking about the 
</p>
        <h4>Trade offs
</h4>
        <p>
Finally, it’s payback time. Of course, we are not expecting to get a scalable and
high-performance database with little to no cost. Current MongoDB drawbacks should
be divided into two groups. The first group is caused by fundamental differences in
approach and the price we have to pay – consistency. This means that, as soon as MongoDB
is your weapon of choice, your application logic has to provide workarounds for concurrency
issues and consistency checks. It's good to know that MongoDB has two options to tackle
the last problem – write with concern (WriteConcern) allows you to go around the “save
now write later” issue, and it can be a powerful tool in skilled hands, while the
slaveOk setting allows you to force “read from primary only” behavior, so you are
no longer trapped with replication sync issues. And of course, versions and atomic
updates help with concurrency. 
</p>
        <p>
I should name the second group “age-related problems.” These are the drawbacks that
we are facing now, but they are more or less likely to go away in the future. Some
of these drawback fixes are harder to implement and/or have a lower priority. To name
a few:
</p>
        <p>
As mentioned before, queries in MongoDB work perfectly when the corresponding index
is there. But if your query filter has some not-indexed fields, you will end up with
a very long query time. There is a way to hint or force MongoDB to use the existing
query without that field, but you have to understand indexing mechanics and use this
feature carefully. Another thing is that MongoDB keeps all indexes in memory, and
even though memory size is usually quite large for servers, it’s still limited, and
you have to keep that in mind and make sure you are not creating too many indexes.
</p>
        <p>
Also when querying, you have to keep in mind that not all query types currently support
or use indexes; therefore, using something like MapReduce, where clause or some regular
expressions, you could end up with a long query time. Due to JavaScript engine limitations,
MapReduce queries are processed in a single thread and can lock down the whole database
instance. Eventually, indexes could be very productive for heavy-read applications
and could show up as counterproductive in applications with lots of writes.
</p>
        <p>
MongoDB is supposed to be operated from a secured/trusted environments and only has
basic authentication implemented. You have only two alternatives for user access rights:
it's either a read-only user or an admin user with all write/read privileges. The
user gets access database-wide, and it's not possible to set up different access per
collection. Also, the basic auth mechanism currently doesn't work for sharded configurations.
</p>
        <p>
Not a big deal, usually, but still a limitation of single document size. As for version
1.8, it’s 8Mb and assumed to increase in later releases.
</p>
        <p>
MongoDB returns the cursor as a query result. There is such a thing as a cursor timeout.
So, especially when operating in distributed configuration (shard + replicaset), you
should consider paging queries in a smaller chunks.
</p>
        <p>
Last but not least, even though there are a number of MongoDB drivers for all platforms,
they perform differently. Whether it's a platform or a driver implementation, it's
always a good idea to try and test-driver performance in your environment before making
a final decision.
</p>
        <p>
Stay tuned for our last posts where we will be talking about how <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDBPart-4.aspx">MongoDB
and Java</a></p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=255fb340-665e-43e2-8305-6624fc6f9fca" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Hands on MongoDB – Part 2</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-2.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,07150470-02a2-4480-adf3-e4181f3d1373.aspx</id>
    <published>2011-07-15T07:19:27.4413896-07:00</published>
    <updated>2011-07-15T07:21:54.1128473-07:00</updated>
    <category term="MongoDB" label="MongoDB" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,MongoDB.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <font size="2">By Ivan, a <a href="http://www.muranosoft.com/services/java.aspx">Java
Developer</a> at Murano software’s team.</font>
          </em>
        </p>
        <p>
          <font size="2">In our previous post we have <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-1.aspx">introduced
you to MongoDB</a> which has been getting quite the attention lately. We are continuing
our series about Mongo, and more precisely with..</font>
        </p>
        <p>
          <font size="3">
            <strong>MongoDB Features</strong>
          </font>
        </p>
        <strong>
          <font size="3">
          </font>
        </strong>
        <p>
          <font size="2">MongoDB distribution includes a JavaScript interactive shell that can
be used to access, query, update, configure and administer databases on local and
remote hosts. Having that JavaScript is the language of choice. All MongoDB shell
operations are JS calls, and JSON is the common way to define objects here.</font>
        </p>
        <p>
          <font size="2">MongoDB is fast, I mean really fast, when it comes to search and update
operations, as long as you have the corresponding index. It uses B-tree based indexes.
Each collection can have more than one index, and each can include as many fields
as you want (compound indexes supported).</font>
        </p>
        <p>
          <font size="2">MongoDB doesn't support transactions as most of the ACID-compliant
relational databases do, but it has its own way to tackle the concurrency problem
– atomic update operations on the document level. This basically means you can update
some of the document's fields without affecting the rest of them. There is a kind
of convention, called “update-if-current,” to make sure you're not saving an outdated
document using versions, or a filtering clause for the update operation. MongoDB also
supports the findAndModify operation that updates the value and immediately returns
to the previous or current value. This can be useful in many cases, like queues or
sequencers.</font>
        </p>
        <p>
          <font size="2">When it comes to aggregating queries, MongoDB has MapReduce support.
This distributed computation technique is another gift from Google to humanity. It
can look confusing to a common SQL-minded person at first glance, but a patient user
should have no problems mastering it quickly. Some people like it to the extent they
develop something like CoachDB, which is almost completely based on MapReduce and
definitely is a worthy piece of technology.</font>
        </p>
        <p>
          <font size="2">MongoDB was born with scalability in mind, so it implements replication
and sharding naturally. Replicas are organized into so-called ReplicaSets that consist
of one primary host (used for writes) and secondaries (currently up to 7). This is
a perfect choice for failover and redundancy. If the primary host goes down, the new
one will be “elected” automatically from the working secondaries.</font>
        </p>
        <p>
          <font size="2">MongoDB provides horizontal scalability with the sharding implementation.
MongoDB sharding configuration works on the collection level, evenly distributing
chunks of collection data among available cluster shards using the shard key. The
shard key can be one or more of the existing document fields or sometimes a specifically
generated field to ensure shallower load distribution among shards. Sharded and unsharded
collections feel exactly the same for the client application.</font>
        </p>
        <p>
          <font size="2">These two scaling techniques can and should be used simultaneously,
as when each shard for the sharded collection consists of a ReplicaSet.</font>
        </p>
        <p>
          <font size="2">Look forward to Part 3 of our Hands on MongoDB series! 
<br /></font>
        </p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=07150470-02a2-4480-adf3-e4181f3d1373" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Hands on MongoDB – Part 1</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-1.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,9f5790d2-1eed-44fb-bd4e-e3e752e7fc29.aspx</id>
    <published>2011-07-13T14:24:00-07:00</published>
    <updated>2011-07-15T07:24:58.3023708-07:00</updated>
    <category term="MongoDB" label="MongoDB" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,MongoDB.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Ivan, a <a href="http://www.muranosoft.com/services/java.aspx">Java developer</a> at
Murano Software’s team</em>
        </p>
        <p align="right">
«Why is it you're always 
<br />
too small or too tall?», 
<br />
The Mad Hatter, Alice in Wonderland
</p>
        <h4> <strong><font size="3">Prologue</font></strong></h4>
        <p>
Indeed, there is no such thing as an ultimate solution. Every time we face a problem,
even if we are lucky enough to have a precooked solution at our fingertips, we still
have to tweak, adjust and adapt it to a specific case's demands. Sometimes, the “adjustment”
part can take a while, and therefore putting the right tool in the right place has
a great impact on the overall project development efficiency.
</p>
        <p>
From the day the Web was born, it never stopped growing in both size and quality.
Whether you are developing an online shop, developing a news portal or trying to get
to your customer with a company site, databases are always going to be a major building
block for your solution. In terms of maturity and functional completeness, nothing
can compare to relational databases. Of course, there are plenty of RDBMS, each with
its own advantages and flaws, but they have proved that their strict rules and functionality
can give a rock-solid basis for any web project.
</p>
        <p>
However, in some cases, the relational approach can be too “tall.” Schema limitations
and weak scalability support can be a decisive factor leading you to look for another
solution. And object-oriented databases  are among the alternatives here. So,
without further delay, let's get our hands on MongoDB – an object-oriented database
that’s gaining popularity recently. 
<br /></p>
        <h4>Essentials
</h4>
        <p>
MongoDB is an open (GNU AGPL 3.0 license), schema-less, non-SQL, document-oriented
database management system developed by a 10gen. It has been developed since 2007
with the first public release in 2009. It's available for download from <a href="http://www.mongodb.org">http://www.mongodb.org</a>.
MongoDB has a variety of drivers to work with both officially supported (Java, C#,
CPP, Python, PHP, Ruby, Scala, Erlang, Perl and others) and community developed. And,
of course, MongoDB is available for all Mac, Solaris, Windows and Linux users, with
sources available so you basically could try building it yourself for any platform.
</p>
        <p>
So what is “schema-less” all about? The deal is that MongoDB does not have any schema
or any other kind of user-defined restrictions for data storage. When using a relational
database, you have plenty of work to do in order to prepare your domain entities for
storage in tables and rows. You define each field type, add restrictions, sometimes
even put some logic in triggers and stored procedures. 
</p>
        <p>
This is not the case with MongoDB.  What once was a record in a relational table
(usually more than one table) now becomes a document. Each document can have an unlimited
number of fields. A field is a pair of key (unique string identifier) and value. A
value can be of any supported type as well as an object (document) or array itself.
You can use dot notation to access values at any field level. Documents are stored
in collections. But since you don't have any schema, every document in a single collection
can have any set of different fields. Of course, it's a good practice to put different
objects in separate collections.
</p>
        <p>
Obviously, this kind of unrestrained storage is hardly compatible with SQL, and there
is no such thing as “joint” operations in object-oriented databases. So, let's see
what MongoDB has to offer instead.
</p>
        <h4>BASE vs. ACID
</h4>
        <p>
While most, if not all, relational databases offer their prayers to ACID (Atomicity,
Consistency, Isolation, Durability), this evil god demands sacrifices. According to
Eric Brewer's CAP theorem, there are at most two of three properties a shared data
system can have: Consistency, Availability and Partition tolerance. And while RDBMS
strive hard for Consistency and tolerance, Availability is left behind.
</p>
        <p>
An object-oriented database’s logic instead declares that, in the cases where this
is applicable, consistency can be given up in favor of high availability and scalability.
This is sometimes referred to as a BASE acronym, which stands for Basically Available,
Soft state, Eventually available. It means it's okay to go on without locks and transactions.
It's okay to have data in a soft state (we can consider write operation as complete
before the data is actually written to disk).The data will eventually become consistent,
and in most cases, there are plenty of other ways to work around concurrency.
</p>
        <p>
Now we will make a small break. Have we piqued your interest? Look out for Part 2,
where we will be introducing the <a href="http://www.muranosoft.com/Outsourcingblog/Hands-On-MongoDB-Part-2.aspx">Features
of MongoDB</a></p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=9f5790d2-1eed-44fb-bd4e-e3e752e7fc29" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Video: Murano’s Expertise in Windows Azure</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Video-Muranos-Expertise-In-Windows-Azure.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,25673ba3-7a20-45bb-9c33-98e2e573d186.aspx</id>
    <published>2010-09-07T08:12:00-07:00</published>
    <updated>2010-10-06T09:09:33.770219-07:00</updated>
    <category term="Azure" label="Azure" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Azure.aspx" />
    <category term="Cloud Computing" label="Cloud Computing" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,CloudComputing.aspx" />
    <category term="Silverlight" label="Silverlight" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Silverlight.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
In one of our previous posts, we already <a href="http://muranosoft.com/outsourcingblog/default.aspx#a00a85692-e300-4a4d-af31-38de8d35e1ca">described
the technical details of Multidraw</a>, our rich cloud application that showed how
Windows Azure cloud computing works. The solution was generalized into an open source
framework, which has been <a href="http://code.msdn.microsoft.com/rca/Wiki/View.aspx?title=Home&amp;version=19">released
to the Microsoft Developer Network</a>. This significant event highlights how Murano
Software is a leading expert in Windows Azure on the global arena. To see Multidraw
in action and learn more about Murano’s expertise in Azure, check out our new video:
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:7ac36c7c-9274-4b2f-9463-6be0a27eb535" class="wlWriterEditableSmartContent">
          <div id="f3054a62-52ed-4e51-bc0d-53054df01ed8" style="margin: 0px; padding: 0px; display: inline;">
            <div>
              <a href="http://www.youtube.com/watch?v=0XkOy9dTot0?fs=1&amp;hl=en_US" target="_new">
                <img src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoMuranosExpertiseinWindowsAzure_AC04/videocd3c0f35740b.jpg" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('f3054a62-52ed-4e51-bc0d-53054df01ed8'); downlevelDiv.innerHTML = &quot;&lt;div&gt;&lt;object width=\&quot;425\&quot; height=\&quot;355\&quot;&gt;&lt;param name=\&quot;movie\&quot; value=\&quot;http://www.youtube.com/v/0XkOy9dTot0?fs=1&amp;hl=en_US&amp;hl=en\&quot;&gt;&lt;\/param&gt;&lt;embed src=\&quot;http://www.youtube.com/v/0XkOy9dTot0?fs=1&amp;hl=en_US&amp;hl=en\&quot; type=\&quot;application/x-shockwave-flash\&quot; width=\&quot;425\&quot; height=\&quot;355\&quot;&gt;&lt;\/embed&gt;&lt;\/object&gt;&lt;\/div&gt;&quot;;" alt="" />
              </a>
            </div>
          </div>
        </div>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=25673ba3-7a20-45bb-9c33-98e2e573d186" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Printing support in Silverlight 4 RC</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Printing-Support-In-Silverlight-4-RC.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,189440d7-9bd0-415e-a2b2-02d7cbae18b8.aspx</id>
    <published>2010-05-25T04:47:15.2367639-07:00</published>
    <updated>2010-05-25T04:47:15.2367639-07:00</updated>
    <category term="Silverlight" label="Silverlight" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Silverlight.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <category term="Visual Studio" label="Visual Studio" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,VisualStudio.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Pavel, a <a href="http://www.muranosoft.com/services/microsoftnet.aspx">.NET
Developer</a> on Murano Software’s team</em>
        </p>
        <p>
One of the new, pleasant features of Silverlight 4 RC is comprehensive printing support,
enabling hardcopy reports and documents, as well as a virtual print view, independent
of screen content. We used this feature while updating <a href="http://www.muranosoft.com/Outsourcingblog/Rich-Cloud-Application-Phase-2-Is-Released.aspx">RCA
POC project phase 2</a>, and we want to give a little overview of how to use this
feature.
</p>
        <p>
          <b>Printing API</b>
        </p>
        <p>
The PrintDocument class provides printing capabilities from a Silverlight application.
A developer can handle three events of this class: StartPrint, EndPrint and PrintPage.
The StartPrint event is used for special handling or setting up before printing begins.
The EndPrint event is used for clean up or other operations after printing is complete.
Use the PrintPage event to generate page content for printing by setting the <strong>PrintPageEventArgs</strong> argument.
</p>
        <p>
The PrintPageEventArgs class contains three main properties: PageVisual, HasMorePages
and PrintableArea. The PageVisual property sets the element for printing. It can be
the layout root of Silverlight content or the name of UIElement. The PrintableArea
gets the size of the printable area. You can use the HasMorePages property for printing
multiple pages. If HasMorePages = true, then the PrintPage event is called again to
print the next page.
</p>
        <p>
Sample:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; border-top: silver 1px solid; border-right: silver 1px solid">
          <pre class="brush: csharp; toolbar: true; gutter: false; bloggerMode:true;">
private void PrintAll_Click(object sender, RoutedEventArgs e)
{
	PrintDocument docToPrint = new PrintDocument();
	// prepare to print
	docToPrint.BeginPrint += (s, args) =&gt;
	{
		// do something
	};
	// set UIElement
	docToPrint.PrintPage += (s, args) =&gt;
	{
		args.PageVisual = this.StackOfStuff;
		args.HasMorePages = true;
	};
	// ending prepare to print
	docToPrint.EndPrint += (s, args) =&gt;
	{
		// do something
	};
	// start print
	docToPrint.Print("Entire Screen Sample";);
}</pre>
        </div>
        <p>
          <b>Print Preview</b>
        </p>
        <p>
We reviewed the main features of Printing API. Now let's look at how to implement
a preview of the printed content. It’s easy. You have to create a User control where
your printable data will be showed in the way you need. Then you set this control
to the PageVisual property of the PrintPageEventArgs and print it.
</p>
        <p>
          <b>Examples</b>
        </p>
        <p>
The following code example shows a PrintPage event handler in <a href="http://code.msdn.microsoft.com/rca">RCA
POC project</a>, where stPage is a grid in the PrintPreviewBox control and the <i>document</i> is
an instance of the PrintDocument class:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; border-top: silver 1px solid; border-right: silver 1px solid">
          <pre class="brush: csharp; toolbar: true; gutter: false; bloggerMode:true;">
document.PrintPage += (sender1, args) =&gt;
	{
		((Grid)stPage.Children[pagesPrinted]).Width = args.PrintableArea.Width;
		((Grid)stPage.Children[pagesPrinted]).Height = args.PrintableArea.Height;
		args.PageVisual = stPage.Children[pagesPrinted];
		pagesPrinted++;
		args.HasMorePages = stPage.Children.Count &gt; pagesPrinted;
	};</pre>
        </div>
        <p>
Then we invoke the method Print() of <i>document</i> object. This will show a print
dialog, where we can select a printer. After that, Silverlight will generate the document
and send it to the printer. You can see a preview page from <a href="http://code.msdn.microsoft.com/rca">RCA
POC project</a> on figure below.
</p>
        <p>
 <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/PrintingsupportinSilverlight4RC_CFE7/SL4_PrintPreview_5.jpg"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Preview of report with comments" border="0" alt="Preview of report with comments" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/PrintingsupportinSilverlight4RC_CFE7/SL4_PrintPreview_thumb_1.jpg" width="638" height="510" /></a> 
</p>
        <p>
          <b>Conclusion</b>
        </p>
        <p>
As you can see, Silverlight 4 RC allows a developer to print documents with any content,
whether photos, charts or text.
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=189440d7-9bd0-415e-a2b2-02d7cbae18b8" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Porting database from Azure storage to Azure SQL</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Porting-Database-From-Azure-Storage-To-Azure-SQL.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,af8bb2a4-a405-408a-8059-4b07a0d40dcc.aspx</id>
    <published>2010-05-24T14:33:13.3854926-07:00</published>
    <updated>2010-05-24T14:33:13.3854926-07:00</updated>
    <category term="Azure" label="Azure" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Azure.aspx" />
    <category term="Cloud Computing" label="Cloud Computing" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,CloudComputing.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <category term="Visual Studio" label="Visual Studio" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,VisualStudio.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Denis, a <a href="http://www.muranosoft.com/services/microsoftnet.aspx">.NET
Developer</a> on Murano Software’s team</em>
        </p>
        <p>
One of the updates in the <a href="http://www.muranosoft.com/Outsourcingblog/Rich-Cloud-Application-Phase-2-Is-Released.aspx">RCA
phase 2</a> was a porting our database from Azure storage to Azure SQL. Minimal changes
we needed to make were on the server (Azure web/web role) and Azure SQL. We also changed
some scripts on the client to increase performance. Let’s look at the changes in the
main two steps:
</p>
        <p>
          <strong>Changes in the Azure SQL</strong>
        </p>
        <p>
The main differences between Azure storage and Azure SQL are: 
</p>
        <ol>
          <li>
Each table in Azure storage has two key fields: RowKey and PartitionKey.</li>
          <li>
A database in Azure storage is not relational, so no joins, group by and order by.</li>
          <li>
Windows Azure storage can return either 1,000 rows or 4 Kbytes.</li>
          <li>
Two key fields must be properly designed for good performance. 
</li>
        </ol>
        <p>
We also want to note that Azure SQL has some <a href="http://msdn.microsoft.com/en-us/library/ee336245.aspx">limitations</a> as
compared to traditional RDBMS. We couldn’t make a connection to Azure SQL from Visual
studio before version 2010 RC, and we had to create copy of the Azure SQL database
on the local SQL Server, make a model and change the connection string to the database
in Azure SQL. But this problem was resolved in VS 2010 RC, and we can work with Azure
SQL directly. 
</p>
        <p>
Thus, we removed PartitionKey and RowKey, as well as TimeStamp, from the structure
of each table because these keys can’t be used as primary keys in relational database.
Then we formed primary keys and relations between tables. We didn’t find any tool
to migrate the database from Azure storage to Azure SQL. So we implemented sql-script
to create our database structure by hand.
</p>
        <p>
We want to note that you can work with Azure SQL, as well as the traditional SQL Server,
using <a href="http://blogs.msdn.com/ssds/archive/2009/11/11/9921041.aspx">SQL Server
2008 R2 Management Studio CTP</a>. One of the most pleasant features of this tool
is the script generator that can generate script from an existing database. A generated
script is adapted to Azure SQL and can create a database in Azure SQL. So you can
create a database in the local SQL Server and use it in your Rich Internet Application
before releasing and generating the database in Azure SQL only for the production
version. 
</p>
        <p>
          <strong>Changes on the server (Web role / Azure Web)</strong>
        </p>
        <p>
We used the data access layer described in this blog (<a href="http://blogs.msdn.com/ales/archive/2009/06/17/porting-silverlight-ria-to-windows-azure-part-1.aspx">Porting
Silverlight RIA to Windows Azure</a>) to work with Azure storage. The next step was
to decide what kind of technology we would use to work with Azure SQL. We chose the
LINQ to SQL technology. So we changed the previous model to a model generated by the
DBML Code Generator. Our new model has to be inherited from the IUpdatable interface,
so we implemented a partial class of our model that inherits from the IUpdatable interface.
A generic implementation of the IUpdatable interface for LINQ to SQL is provided under
MS-PL license. You can find it <a href="http://code.msdn.microsoft.com/IUpdateableLinqToSql/Release/ProjectReleases.aspx?ReleaseId=1753">here</a> and
use it in the partial class of your model.
</p>
        <p>
These are all minimal changes you need to make to port your Azure storage to Azure
SQL. Good luck.
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=af8bb2a4-a405-408a-8059-4b07a0d40dcc" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Video in Silverlight 4</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Video-In-Silverlight-4.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,3cb21155-dcd3-4316-ad47-2e2452e72b68.aspx</id>
    <published>2010-04-21T15:13:52.4001053-07:00</published>
    <updated>2010-04-21T15:24:47.0115015-07:00</updated>
    <category term="Azure" label="Azure" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Azure.aspx" />
    <category term="Cloud Computing" label="Cloud Computing" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,CloudComputing.aspx" />
    <category term="Silverlight" label="Silverlight" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Silverlight.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <category term="Visual Studio" label="Visual Studio" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,VisualStudio.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Stanislav, a <a href="http://www.muranosoft.com/services/microsoftnet.aspx">Senior
.NET Developer</a> on Murano Software’s team</em>
        </p>
        <p>
The latest version of Silverlight delivers hundreds of features, such as a full set
of form controls, enhanced data-binding support, printing API, UDP, webcam and microphone
support, full trust in out-of-browser, and so on. But it doesn't have an out-of-box
solution to stream video or audio captured from a microphone and Web camera via a
network. Current API allows you to capture video/audio data from media devices, and
it has a way to play back media information using MediaStreamSource and MediaElement
control. Also, API has the UdpAnySourceMulticastClient class, which is a client receiver
for multicast traffic from any source, also known as Any Source Multicast (ASM) or
Internet Standard Multicast (ISM).
</p>
        <p>
Silverlight 4 gets support for microphones and webcams. It allows us to have access
to the raw streams. The added support opens a lot of opportunities for new types of
applications. 
</p>
        <p>
During our work on <a href="http://code.msdn.microsoft.com/rca">http://code.msdn.microsoft.com/rca</a> (source
code is available under the MS-PL license), we created an application that allows
users to communicate over the local network and to establish video/audio conferencing.
</p>
        <p>
The classes that expose this functionality live in the System.Windows.Media namespace. 
</p>
        <p>
There are two classes that give us access to audio and video (<a href="http://msdn.microsoft.com/en-us/library/system.windows.media.audiosink(VS.96).aspx">AudioSink</a>, <a href="http://msdn.microsoft.com/en-us/library/system.windows.media.videosink(VS.96).aspx">VideoSink</a>).
</p>
        <p>
To obtain video information from a video input device in Silverlight, you have to
derive a custom video sink from VideoSink, which exposes several virtual callbacks:
</p>
        <ul>
          <li>
OnCaptureStarted 
</li>
          <li>
OnCaptureStopped 
</li>
          <li>
OnFormatChange 
</li>
          <li>
OnSamples 
</li>
        </ul>
        <p>
When you derive from VideoSink, you must provide overrides for the callbacks in order
to compile.
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; border-top: silver 1px solid; border-right: silver 1px solid">
          <pre class="brush: csharp; toolbar: true; gutter: false; bloggerMode:true;">protected override void OnSamples(long sampleTime, long frameDuration, byte[] sampleData)
{
	// Some code here...
}</pre>
        </div>
        <p>
The idea was to split data related to the particular frame into a set of packets,
renumber them, add additional information and send them over the network.
</p>
        <p>
On the client side, the application receives the mentioned packets, orders them, recovers
the frame structure and passes frames to MediaElement, using MediaStreamSource.
</p>
        <p>
The sources can be downloaded <a href="http://code.msdn.microsoft.com/rca">here</a>.
All logic related to the media chat is located in the PSO.Client.UDPMediaChat project
(see Figure 1). It contains the following classes:
</p>
        <p>
          <table border="1" cellspacing="0" cellpadding="2">
            <tbody>
              <tr>
                <td valign="top">
                  <strong>Class name</strong>
                </td>
                <td valign="top">
                  <strong>Description</strong>
                </td>
              </tr>
              <tr>
                <td valign="top">
MediaFrame 
</td>
                <td valign="top">
Contains all related data to the media sample 
</td>
              </tr>
              <tr>
                <td valign="top">
UdpAudioSink, 
<br />
UdpVideoSink 
</td>
                <td valign="top">
These classes are responsible for the capturing raw media data and passing it to the
appropriate media channel. 
</td>
              </tr>
              <tr>
                <td valign="top">
VideoPacketChannel, 
<br />
AudioPacketChannel 
</td>
                <td valign="top">
These classes are responsible for the preparing data for the transmission. They split
media samples into a set of packets and pass them to the transmitter. 
</td>
              </tr>
              <tr>
                <td valign="top">
NetPacketTransmitter 
</td>
                <td valign="top">
It contains the logic of the transmission and receives NetPackets over the network. 
</td>
              </tr>
              <tr>
                <td valign="top">
NetAudioPacketSerializer, 
<br />
NetVideoPacketSerializer 
</td>
                <td valign="top">
These classes are responsible for the logic of packet serialization and de-serialization. 
</td>
              </tr>
              <tr>
                <td valign="top">
NetVideoPacket, 
<br />
NetAudioPacket 
</td>
                <td valign="top">
Stores all necessary media data that is prepared to send over the network. 
</td>
              </tr>
              <tr>
                <td valign="top">
StreamingServer 
</td>
                <td valign="top">
Contains logic that allows users to organize raw media data transmission over the
network. 
</td>
              </tr>
              <tr>
                <td valign="top">
MediaFrameSource 
</td>
                <td valign="top">
Contains media buffering logic. 
</td>
              </tr>
              <tr>
                <td valign="top">
RawMediaStreamSource 
</td>
                <td valign="top">
Contains the logic of the prepared media samples for the playback by MediaElement 
</td>
              </tr>
            </tbody>
          </table>
        </p>
        <p>
          <b>Table 1. The description of the most important classes.</b>
        </p>
        <p>
          <img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="Solution structure" border="0" alt="Solution structure" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard02_3.png" width="367" height="747" />
        </p>
        <p>
          <b>Figure 1. Solution explorer</b>
        </p>
        <p>
Sequence diagrams show how the application processes media samples before sending
them over a network.
</p>
        <p>
We streamed raw data without any compression. Unfortunately, Silverlight doesn't supply
codecs yet, but we suppose that it's possible to compress media streams using COM
Object Access in Trusted Applications.
</p>
        <p>
Figure 2 shows that we have two media data sources (VideoSink and AudioSink). They
pass media data to the corresponding media packet channel, which is responsible for
the media frames’ (samples’) processing and further transmission. We want to note
that these sinks work separately in different threads. Also, the media channel contains
frames splitting logic into a pile of packets. Each packet is sent over the network
separately.
</p>
        <p>
 <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard01_4.png" target="_blank"><img style="display: inline" title="Sequence diagram shows simplified algorithm of raw media streaming" alt="Sequence diagram shows simplified algorithm of raw media streaming" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard01_thumb_1.png" width="750" height="512" /></a></p>
        <p>
          <b>Figure 2. Sequence diagram shows simplified algorithm of raw media streaming.</b>
        </p>
        <p>
When you use a multicast client, the first thing you have to do is to join the group,
using the known multicast IP address (ex: 224.0.0.1 - The All Hosts multicast group
that contains all systems on the same network segment) and the port (ex: 9999). The
address block 224.0.0.0/24 (224.0.0.0 to 224.0.0.255) is designated for multicasting
on the local subnetwork only. When the connection has been made, you can start send
and/or receive from the group. 
</p>
        <p>
There are several security restrictions on connecting to multicast groups in Silverlight.
</p>
        <p>
The security policy checks included in the Silverlight runtime are designed to prevent
networking threats like DoS attacks, DNS rebinding, reverse tunnel attack, etc. Currently,
it's not possible to connect to remote ports less then 1024. Before a multicast client
is allowed to join a group, the Silverlight runtime implements a protocol check to
verify that the client has been granted permission to join the group and receive datagrams.
</p>
        <p>
Sink produces raw media data by the callback:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; border-top: silver 1px solid; border-right: silver 1px solid">
          <pre class="brush: csharp; toolbar: true; gutter: false; bloggerMode:true;">protected override void OnSamples(long sampleTime, long frameDuration, byte[] sampleData)
{
	// Some code here...
}</pre>
        </div>
        <p>
These data are packed in a media frame and passed to the corresponding media channel.
The channel splits the media frame into a set of packets because UdpAnySourceMulticastClient
restricts the amount of data that can be sent at once. So the application cuts huge
media frames that contain raw media data into small pieces and sends them over the
network. 
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard04_2.png" target="_blank">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sequence diagram shows simplified playback algorithm of the raw media stream" border="0" alt="Sequence diagram shows simplified playback algorithm of the raw media stream" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard04_thumb.png" width="750" height="641" />
          </a>
        </p>
        <p>
          <b>Figure 3. Sequence diagram shows simplified playback algorithm of the raw media
stream.</b>
        </p>
        <p>
On the client side, UdpAnySourceMulticastClient receives raw bytes. It passes them
to NetPacketTransmitter. The transmitter verifies the destination address and “unpacks”
the packet.
</p>
        <p>
Then the transmitter notifies the media channels that the packet with media data has
been received.
</p>
        <p>
Each channel verifies the ability to process the incoming packet. The logic of the
channels could vary drastically, depending on the nature of the received data. For
instance, VideoChannel uses a special mechanism for the video frames recovery from
a set of packets. When the media channel decides that a subsequent frame is received
completely, it passes it to the MediaFrameSource.
</p>
        <p>
This class manages media frame queues for both audio and video frames. Each received
frame is added to the particular queue. The frames from the queues are pulled by the
MediaStreamSource.
</p>
        <p>
If the queue is empty, the thread that serves MediaStreamSource is suspended until
the queue receives at least one frame.
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard05_2.png" target="_blank">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Audio chat window" border="0" alt="Audio chat window" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard05_thumb.png" width="615" height="480" />
          </a>
        </p>
        <p>
          <b>Figure 5. Audio chat window</b>
        </p>
        <p>
A user can perform a call to other user by clicking on the phone icon at the left-side
of the main window. The other participant has to confirm the call. If the call is
confirmed, the special media control will be displayed (see Figure 5). By default
PSO establishes an audio conference. If you want to perform a video call you have
to press the film icon. In this case your application instance will start a video
transmission and the other participant will be able to see you. The video chat window
is displayed on figure 6.
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard06_2.png" target="_blank">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Video chat window" border="0" alt="Video chat window" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/VideoinSilverlight4_B3A/Clipboard06_thumb.png" width="611" height="480" />
          </a>
        </p>
        <p>
          <b>Figure 6. Video chat window</b>
        </p>
        <p>
We successfully realized a proof of concept that shows the possibility of video conference
software development on the Silverlight 4 technology. Also, we built a universal extensible
framework that allows users to transmit data in the local network.
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=3cb21155-dcd3-4316-ad47-2e2452e72b68" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Rich Cloud Application Phase 2 is released!</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Rich-Cloud-Application-Phase-2-Is-Released.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,4acdc401-94af-49ec-b97e-3b5dffc40ca7.aspx</id>
    <published>2010-04-21T14:38:50.6922329-07:00</published>
    <updated>2010-05-25T04:53:34.022792-07:00</updated>
    <category term="Azure" label="Azure" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Azure.aspx" />
    <category term="Cloud Computing" label="Cloud Computing" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,CloudComputing.aspx" />
    <category term="Silverlight" label="Silverlight" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Silverlight.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <category term="Visual Studio" label="Visual Studio" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,VisualStudio.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Denis, a <a href="http://www.muranosoft.com/services/microsoftnet.aspx">.NET
Developer</a> on Murano Software’s team</em>
        </p>
        <p>
We are glad to present the release of the new extended version of <a href="http://blogs.msdn.com/ales/archive/2010/02/05/rich-cloud-application-architecture-in-more-detail.aspx">Rich
Cloud Application</a> (RCA) that was announced in the last Rich Cloud Application
blog post. The main enhancements of this version are using Silverlight 4 RC features,
SQL Azure and Microsoft SyncFx:
</p>
        <ol>
          <li>
Using Silverlight’s comprehensive <a href="http://www.muranosoft.com/Outsourcingblog/Printing-Support-In-Silverlight-4-RC.aspx">printing
support</a>. Any registered user can make a hard copy, as well as a virtual printing
view, of any report in the system. 
</li>
          <li>
Using a microphone and Web camera in the world of today is the standard de facto of
user collaboration on the Internet. We extended the private chat with the possibility
of using a microphone and a Webcam for more effective cooperation. 
</li>
          <li>
Another cool feature of Silverlight 4 RC is multicast networking, enabling enterprises
to lower the cost of streaming broadcast events. We implemented <a href="http://www.muranosoft.com/Outsourcingblog/Video-In-Silverlight-4.aspx">video/audio
stream broadcasting</a> for video chat in the system by using UDP multicast. 
</li>
          <li>
Implementation of a new, complex rating system requires us to move the database from
Azure storage to Azure SQL. All changes that are needed to move the application from
Azure storage to Azure SQL will be described in the next blog post. 
</li>
          <li>
We implemented the possibility of comfortably working with our system in off-line
mode. The user can run the application in out-of-browser mode and work with cached
data. Any changes in cache will be synchronized with storage in Azure SQL by Microsoft
SyncFX while online. 
</li>
        </ol>
        <p>
Click below to take a look at screenshots of the application in action or try it online
at <a href="http://pso.cloudapp.net">http://pso.cloudapp.net</a>!
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:66721397-FF69-4ca6-AEC4-17E6B3208830:b4859f59-9f1d-41d8-8463-798f375b435d" class="wlWriterSmartContent">
          <a style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" href="http://cid-f279fbd2c1838cbf.skydrive.live.com/redir.aspx?page=browse&amp;resid=F279FBD2C1838CBF!147&amp;ct=photos">
            <img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="View PSO v2 Screenshots" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/RichCloudApplicationPhase2isreleased_8DB/InlineRepresentation0a28ee78-e482-4c95-b36b-d78aed7bc61a.jpg" />
          </a>
          <div style="text-align: right; width: 400px">
            <a href="http://cid-f279fbd2c1838cbf.skydrive.live.com/redir.aspx?page=browse&amp;resid=F279FBD2C1838CBF!147&amp;ct=photos">View
Full Album</a>
          </div>
        </div>
        <p>
The full source of code, except synchronization, is available for download at the
MSDN Code Gallery under the MS-PL license. You can find some interesting solutions
and work-arounds for creating peer-to-peer video chat and printing support.
</p>
        <p>
So stay tuned and subscribe to our blog to get fresh news about Rich Cloud Application!
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=4acdc401-94af-49ec-b97e-3b5dffc40ca7" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Microsoft Azure Sharding</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Microsoft-Azure-Sharding.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,baf1c62f-e4eb-4037-99ca-1c9e7d670678.aspx</id>
    <published>2010-03-31T02:16:38.0279643-07:00</published>
    <updated>2010-03-31T02:24:55.9051558-07:00</updated>
    <category term="Azure" label="Azure" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Azure.aspx" />
    <category term="Cloud Computing" label="Cloud Computing" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,CloudComputing.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>By Alex, a <a href="http://www.muranosoft.com/services/microsoftnet.aspx">Senior
.NET Developer</a> on Murano Software’s team</em>
        </p>
        <p>
As Microsoft Azure spreads, the cloud computing and scaling technologies are getting
more and more familiar among the software developers. This is very essential, since
nowadays startups <i>scale fast or fail fast</i>.
</p>
        <p>
One of the advanced scaling techniques is <i>sharding</i>, which is horizontal data
partitioning, when large and scalability-sensitive data (e.g., a person's profiles
and his or her messages) are split into several <i>shards</i> by certain criteria
(regional, alphabetical and so on). You can add a new shard at any time to scale out
with less cost due to its smaller size and hardware requirements. All giants like
Flickr and Google are using <i>shards</i> in their architecture. There is a good amount
of network resources concerning <i>sharding</i> — e.g., at <a href="http://highscalability.com/unorthodox-approach-database-design-coming-shard">highscalability.com</a> or <a href="http://www.25hoursaday.com/weblog/2009/01/16/BuildingScalableDatabasesProsAndConsOfVariousDatabaseShardingSchemes.aspx">here</a>.
You can look at the <i>discussion</i><a href="http://www.mysqlperformanceblog.com/2009/08/06/why-you-dont-want-to-shard/">in
this blog</a> as a great example of sharding pros and cons from a practical angle.<i> Sharding</i> has
many difficult aspects and requires superior expertise in architecture and a large
investment in the design of your system.
</p>
        <p>
What concerns SQL Azure is that there are <a href="http://msdn.microsoft.com/en-us/library/ee336245.aspx#dcasl">size
limitations</a> for the databases (originally they were up to 10Gb for a single database).
Although Microsoft <a href="http://blogs.msdn.com/cbiyikoglu/archive/2010/03/18/in-future-with-sql-azure.aspx">announced
50Gb databases</a>, the problem is still present for rapidly growing startups, and
Microsoft considers <i>sharding</i> one of the recommended solutions. Previously, <i>sharding</i> was
a high-end technology, but now it is knocking at the door of an average software development
team.
</p>
        <p>
Our company is going to develop an architectural guideline and software extensibility
kit, providing implementations for common sharding tasks, such as shard location service,
and using all the benefits of Microsoft Azure as a platform.
</p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=baf1c62f-e4eb-4037-99ca-1c9e7d670678" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Using Amazon to speed-up development</title>
    <link rel="alternate" type="text/html" href="http://www.muranosoft.com/Outsourcingblog/Using-Amazon-To-Speedup-Development.aspx" />
    <id>http://www.muranosoft.com/Outsourcingblog/PermaLink,guid,3ee4540e-0202-4502-abc9-f4cd5319402d.aspx</id>
    <published>2010-03-19T07:45:00-07:00</published>
    <updated>2010-03-19T00:45:44.9051976-07:00</updated>
    <category term="ASP.NET" label="ASP.NET" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,ASPNET.aspx" />
    <category term="Microsoft SharePoint" label="Microsoft SharePoint" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,MicrosoftSharePoint.aspx" />
    <category term="Software Development" label="Software Development" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,SoftwareDevelopment.aspx" />
    <category term="Virtual" label="Virtual" scheme="http://www.muranosoft.com/Outsourcingblog/CategoryView,category,Virtual.aspx" />
    <author>
      <name>Muranosoft admin</name>
    </author>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <h3>Our goal
</h3>
        <p>
During the <a href="http://www.muranosoft.com/Outsourcingblog/Murano-Software-At-Microsoft-SharePoint-2010-Social-Fest.aspx">Microsoft
SharePoint 2010 Social Fest</a>, Murano’s programmers had to create seven applications
for the new SharePoint Server 2010. This article will show how Amazon Web Services
helped us to get results in just seven days.
</p>
        <h3>Why did we choose Amazon?
</h3>
        <p>
We had few days before the Microsoft SharePoint 2010 Social Fest to test the new SharePoint
server. Microsoft’s SharePoint Server 2010 is in beta status and has strict hardware
requirements. You must have 4GB of RAM to start working with it. Also, the best way
to use SharePoint Server 2010 is to install it on a Windows Server 2008 or Windows
Server 2008 R2 operating system. 
</p>
        <p>
So we had to upgrade some of the developers’ PC hardware and OS or find another solution.
There also was another problem – how to prepare the environment for the new developers
on SharePoint Social Fest’s team very quickly. We decided to check Amazon services. 
</p>
        <p>
Amazon Elastic Compute Cloud (Amazon EC2) is a Web-based service that provides compute
capacity in the cloud. Amazon EC2 presents a virtual computing environment, allowing
you to use Web service interfaces to launch instances with selected operating systems.
Fortunately, MS Windows Server 2008 is available to use on Amazon. We chose “Large
Instance” with 8GB RAM and 4 EC2 Compute Units to handle our tasks.
</p>
        <h3>How to start using Amazon Web Services
</h3>
        <p>
Getting to Amazon’s cloud is simple. You have to go to <a href="http://aws.amazon.com/ec2/">http://aws.amazon.com/ec2</a> and
register a new account if you don’t have one. After registering for service and filling
out your card data, you can create a new instance by wizard in EC2 AWS console:
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image002_2.gif">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image002_thumb.gif" width="468" height="305" />
          </a>
        </p>
        <p>
After passing several steps, you will get new instances in the console:
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image004_2.gif">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image004_thumb.gif" width="648" height="180" />
          </a>
        </p>
        <p>
Now instances on Amazon EC2 use ELASTIC BLOCK STORE (EBS) to store data volumes. This
is good news because your data will stay alive after instance shutdown. 
</p>
        <h3>Our results
</h3>
        <p>
Virtual servers on Amazon have a good performance level. We used Visual Studio 2010
on it with hosted SharePoint 2010 sites, and the machines worked very promptly.
</p>
        <p>
As we selected Amazon EC2 as our platform for the SharePoint 2010 Social Fest, we
had to find out how to multiply the development environment in a short time. 
</p>
        <p>
The “Snapshot” function could help. It will take a snapshot from the selected data
volume. Then you can create a new volume from the snapshot and attach it to the instance.
But I found that instance’s Amazon Machine Image (AMI) creation is more applicable
for our task. 
</p>
        <p>
You can install any software you need, make your changes to the system configuration
and then create an image of your instance. Then you can use this image for creating
new instances. Using AMIs instead of snapshots gives you an advantage in time because
you will already get a configured instance right after the launch.
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image006_2.gif">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image006_thumb.gif" width="428" height="298" />
          </a>
        </p>
        <p>
Thus we prepared AMI with Visual Studio 2010 beta and SharePoint Server 2010 beta
installed on it, and we used it any time our developer needed a new environment.
</p>
        <h3>Benefits of using Amazon
</h3>
        <p>
Using Amazon Elastic Compute Cloud gives all our programmers the possibility of working
with the demanding SharePoint Server 2010 without OS reinstallation and hardware upgrade.
</p>
        <p>
Also, we find that Amazon EC2 is very convenient if you need to increase the quantity
of servers very quickly.
</p>
        <p>
You could use Command Line Tools to automate some tasks with EC2 instances. We used
it to enable programmers to shut down and start their instances.
</p>
        <p>
          <a href="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image008_2.gif">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://www.muranosoft.com/Outsourcingblog/content/binary/WindowsLiveWriter/UsingAmazontospeedupdevelopment_8873/clip_image008_thumb.gif" width="650" height="457" />
          </a>
        </p>
        <img width="0" height="0" src="http://www.muranosoft.com/Outsourcingblog/aggbug.ashx?id=3ee4540e-0202-4502-abc9-f4cd5319402d" />
      </div>
    </content>
  </entry>
</feed>
