<?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>Jayway Team Blog &#187; network</title>
	<atom:link href="http://blog.jayway.com/tag/network/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jayway.com</link>
	<description>Sharing Experience</description>
	<lastBuildDate>Sat, 28 Jan 2012 15:53:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Host Specific Routing Via the iPhone on OSX</title>
		<link>http://blog.jayway.com/2011/03/01/host-specific-routing-via-the-iphone-on-osx/</link>
		<comments>http://blog.jayway.com/2011/03/01/host-specific-routing-via-the-iphone-on-osx/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 19:59:39 +0000</pubDate>
		<dc:creator>Anders Janmyr</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[routing]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=7243</guid>
		<description><![CDATA[If you are working as a consultant, it is sometimes not easy to get proper network access when you are using your customer's network. The easiest way to solve this problem is to connect via your mobile phone. But, the 3G network is not always the fastest and it would be nice to use the [...]]]></description>
			<content:encoded><![CDATA[
<p>If you are working as a consultant, it is sometimes not easy to get<br />
proper network access when you are using your customer's network. The<br />
easiest way to solve this problem is to connect via your mobile phone.<br />
But, the 3G network is not always the fastest and it would be nice to<br />
use the normal network for certain tasks and the 3G network for others.</p>
<p>The problem in my case was that I wanted to connect to Github but, SSH<br />
traffic was blocked on the network where I was working. So what to do?<br />
I quick mail to the Jayway tech mailing list, lets me know that in Linux<br />
there is a <code>route</code> command, that can solve this problem. (Un)Fortunately<br />
I am not using Linux on my development machine, but it turns out there<br />
is a <code>route(8)</code> command in BSD too, with slightly different syntax.</p>
<h3>Find the IP-address of the host I wish to connect to</h3>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt><i><font color="#9A1900"># Find the IP-address of the host I wish to connect to</font></i>
$ nslookup github<font color="#990000">.</font>com
Server<font color="#990000">:</font>		<font color="#993399">195.58</font><font color="#990000">.</font><font color="#993399">103.21</font>
Address<font color="#990000">:</font>	<font color="#993399">195.58</font><font color="#990000">.</font><font color="#993399">103.21</font><i><font color="#9A1900">#53</font></i> 

Non-authoritative answer<font color="#990000">:</font>
Name<font color="#990000">:</font>	github<font color="#990000">.</font>com
Address<font color="#990000">:</font> <font color="#993399">207.97</font><font color="#990000">.</font><font color="#993399">227.239</font> 

</tt></pre>
<h3>Find out the gateway of the interface of the cell phone</h3>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt><i><font color="#9A1900"># Find out the gateway of the interface of the cell phone</font></i>
$ ifconfig
lo0<font color="#990000">:</font> <font color="#009900">flags</font><font color="#990000">=</font><font color="#993399">8049</font><font color="#990000">&lt;</font>UP<font color="#990000">,</font>LOOPBACK<font color="#990000">,</font>RUNNING<font color="#990000">,</font>MULTICAST<font color="#990000">&gt;</font> mtu <font color="#993399">16384</font>
	inet <font color="#993399">127.0</font><font color="#990000">.</font><font color="#993399">0.1</font> netmask <font color="#993399">0xff000000</font>
	inet6 <font color="#990000">::</font><font color="#993399">1</font> prefixlen <font color="#993399">128</font>
	inet6 fe80<font color="#990000">::</font><font color="#993399">1</font><font color="#990000">%</font>lo0 prefixlen <font color="#993399">64</font> scopeid <font color="#993399">0x1</font>
<font color="#990000">...</font>
vmnet8<font color="#990000">:</font> <font color="#009900">flags</font><font color="#990000">=</font><font color="#993399">8863</font><font color="#990000">&lt;</font>UP<font color="#990000">,</font>BROADCAST<font color="#990000">,</font>SMART<font color="#990000">,</font>RUNNING<font color="#990000">,</font>SIMPLEX<font color="#990000">,</font>MULTICAST<font color="#990000">&gt;</font> mtu <font color="#993399">1500</font>
	ether <font color="#993399">00</font><font color="#990000">:</font><font color="#993399">50</font><font color="#990000">:</font><font color="#993399">56</font><font color="#990000">:</font>c0<font color="#990000">:</font><font color="#993399">00</font><font color="#990000">:</font><font color="#993399">08</font>
	inet <font color="#993399">192.168</font><font color="#990000">.</font><font color="#993399">105.1</font> netmask <font color="#993399">0xffffff00</font> broadcast <font color="#993399">192.168</font><font color="#990000">.</font><font color="#993399">105.255</font>
en3<font color="#990000">:</font> <font color="#009900">flags</font><font color="#990000">=</font><font color="#993399">8863</font><font color="#990000">&lt;</font>UP<font color="#990000">,</font>BROADCAST<font color="#990000">,</font>SMART<font color="#990000">,</font>RUNNING<font color="#990000">,</font>SIMPLEX<font color="#990000">,</font>MULTICAST<font color="#990000">&gt;</font> mtu <font color="#993399">1500</font>
	ether <font color="#993399">06</font><font color="#990000">:</font>1e<font color="#990000">:</font><font color="#993399">64</font><font color="#990000">:</font><font color="#993399">00</font><font color="#990000">:</font><font color="#993399">34</font><font color="#990000">:</font>1a
	inet6 fe80<font color="#990000">::</font>41e<font color="#990000">:</font>64ff<font color="#990000">:</font>fe00<font color="#990000">:</font>341a<font color="#990000">%</font>en3 prefixlen <font color="#993399">64</font> scopeid <font color="#993399">0xa</font>
	inet <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.3</font> netmask <font color="#993399">0xfffffff0</font> broadcast <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.15</font>
	media<font color="#990000">:</font> 10baseT/UTP
	status<font color="#990000">:</font> active
</tt></pre>
<p>In my case the interface I want to use is the last one, <strong>en3</strong> with <strong>inet<br />
172.20.10.3</strong> but if you are unsure, you can open the network preference<br />
pane and look it up there.</p>
<p>Now I need to find out what the gateway for this interface is. I can<br />
do this with <code>netstat -r</code>.</p>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt><i><font color="#9A1900"># Show the routing table</font></i>
$ netstat -r
Routing tables

Internet<font color="#990000">:</font>
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            <font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.254</font>       UGSc           <font color="#993399">10</font>        <font color="#993399">0</font>     en1
default            <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font>        UGScI           <font color="#993399">0</font>        <font color="#993399">0</font>     en3
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10</font><font color="#990000">/</font><font color="#993399">24</font>        link<i><font color="#9A1900">#5             UCS             3        0     en1</font></i>
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.88</font>        localhost          UHS             <font color="#993399">1</font>      <font color="#993399">811</font>     lo0
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.254</font>       <font color="#993399">0</font><font color="#990000">:</font><font color="#993399">14</font><font color="#990000">:</font>4f<font color="#990000">:</font><font color="#993399">69</font><font color="#990000">:</font>da<font color="#990000">:</font><font color="#993399">13</font>   UHLWI          <font color="#993399">10</font>       <font color="#993399">41</font>     en1    <font color="#993399">661</font>
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.255</font>       link<i><font color="#9A1900">#5             UHLWbI          1       78     en1</font></i>
<font color="#993399">127</font>                localhost          UCS             <font color="#993399">0</font>        <font color="#993399">0</font>     lo0
<font color="#990000">...</font> 

Internet6<font color="#990000">:</font>
Destination        Gateway            Flags         Netif Expire
localhost          localhost          UH              lo0
fe80<font color="#990000">::%</font>lo0         localhost          Uc              lo0
localhost          link<i><font color="#9A1900">#1             UHL             lo0</font></i>
<font color="#990000">...</font> 

</tt></pre>
<p>Close to the top we find the entry for our interface <strong>en3</strong>.</p>
<pre><code>default            172.20.10.1        UGScI           0        0     en3
</code></pre>
<p>Now we have the ip to the gateway that we wanted. So now the last step<br />
is to make sure that access to github.com is routed via this gateway.</p>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt><i><font color="#9A1900">#route command -host destination gateway</font></i>
$ sudo route add -host <font color="#993399">207.97</font><font color="#990000">.</font><font color="#993399">227.239</font> <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font>
add host <font color="#993399">207.97</font><font color="#990000">.</font><font color="#993399">227.239</font><font color="#990000">:</font> gateway <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font> 

</tt></pre>
<p>That's it, I'm done. To make sure the routing is changed I check the<br />
routing table with <code>netstat -r</code> again, to make sure the new entry is in it.</p>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt>$ netstat -r
Routing tables

Internet<font color="#990000">:</font>
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            <font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.254</font>       UGSc           <font color="#993399">30</font>        <font color="#993399">0</font>     en1
default            <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font>        UGScI           <font color="#993399">0</font>        <font color="#993399">0</font>     en3
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10</font><font color="#990000">/</font><font color="#993399">24</font>        link<i><font color="#9A1900">#5             UCS             4        0     en1</font></i>
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.88</font>        localhost          UHS             <font color="#993399">0</font>      <font color="#993399">973</font>     lo0
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.254</font>       <font color="#993399">0</font><font color="#990000">:</font><font color="#993399">14</font><font color="#990000">:</font>4f<font color="#990000">:</font><font color="#993399">69</font><font color="#990000">:</font>da<font color="#990000">:</font><font color="#993399">13</font>   UHLWI          <font color="#993399">27</font>       <font color="#993399">11</font>     en1    <font color="#993399">708</font>
<font color="#993399">10.67</font><font color="#990000">.</font><font color="#993399">10.255</font>       ff<font color="#990000">:</font>ff<font color="#990000">:</font>ff<font color="#990000">:</font>ff<font color="#990000">:</font>ff<font color="#990000">:</font>ff  UHLWbI          <font color="#993399">1</font>       <font color="#993399">14</font>     en1
<font color="#993399">127</font>                localhost          UCS             <font color="#993399">0</font>        <font color="#993399">0</font>     lo0
<font color="#990000">...</font>
github<font color="#990000">.</font>com         <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font>        UGHS            <font color="#993399">0</font>       <font color="#993399">43</font>     en3

Internet6<font color="#990000">:</font>
Destination        Gateway            Flags         Netif Expire
localhost          localhost          UH              lo0
fe80<font color="#990000">::%</font>lo0         localhost          Uc              lo0
localhost          link<i><font color="#9A1900">#1             UHL             lo0</font></i>
fe80<font color="#990000">::%</font>en0         link<i><font color="#9A1900">#4             UC              en0</font></i> 

</tt></pre>
<p>Sure enough, there it is, <code>github.com</code>. Finally I can now <code>git pull</code><br />
and everything works <img src='http://blog.jayway.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>If I want to remove the entry, when I'm working elsewhere, I do that with</p>
<p><!-- Generator: GNU source-highlight 3.1.4<br />
by Lorenzo Bettini</p>
<p>http://www.lorenzobettini.it</p>
<p>http://www.gnu.org/software/src-highlite --> </p>
<pre><tt>
$ sudo route delete -host <font color="#993399">207.97</font><font color="#990000">.</font><font color="#993399">227.239</font> <font color="#993399">172.20</font><font color="#990000">.</font><font color="#993399">10.1</font> 

</tt></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2011/03/01/host-specific-routing-via-the-iphone-on-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Future Cocoa Operation</title>
		<link>http://blog.jayway.com/2010/08/19/future-cocoa-operation/</link>
		<comments>http://blog.jayway.com/2010/08/19/future-cocoa-operation/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 17:51:30 +0000</pubDate>
		<dc:creator>Fredrik Olsson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=6051</guid>
		<description><![CDATA[In Java you have for quite some time had the Future interface for encapsulating an asynchronous calculation. Cocoa has had the abstract NSOperation class to encapsulate asynchronous operations. NSOperation do not have any facilities for returning a result when done as the Future do, you are left to implement this on your own. Which I [...]]]></description>
			<content:encoded><![CDATA[<p>In Java you have for quite some time had the <code><a href="http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html">Future</a></code> interface for encapsulating an asynchronous calculation. Cocoa has had the abstract <code><a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html">NSOperation</a></code> class to encapsulate asynchronous operations.</p>
<p><code>NSOperation</code> do not have any facilities for returning a result when done as the <code>Future</code> do, you are left to implement this on your own. Which I have done a few times, and as a rule of thumb, make the solution generic when needed for the third time.</p>
<p>Operations works perfectly for background network activities. One common network activity is search-as-you-type, in this case you need to also cancel the previous operation if it has not yet been completed, so lets built this behavior into the generic solution as well.</p>
<h3>API Design</h3>
<p>What we want is an subclass of <code>NSOperation</code> that provides a future result, lets call this class <code>CWFutureOperation</code>. It is abstract, so users are supposed to subclass and implement <code>main</code> method just as for <code>NSOperation</code>, only difference is that the main method implementation must call <code>setResult:</code> before exiting.</p>
<p>The result that is set in the main method implementation can then be fetched using the blocking method <code>result</code>, equivalent to <code>get()</code> from the Java <code>Future</code>. As an alternative we would also like to be handed the method upon completion via a target-action pair. If the target-action pair is only called for finished operations that are not cancelled, then we get the search-as-you-type behavior for free.</p>
<p>It is also nice to be able to wrap up any method returning an object in a future operation as a convenience, so lets add that as well to our class interface:</p>
<pre class="brush:objc">@interface CWFutureOperation : NSOperation {
@private
    id _result;
    BOOL _isResultSet;
    id _completionTarget;
    SEL _completionSelector;
}

-(id)result;
-(void)setCompletionTarget:(id)target selector:(SEL)selector;
-(void)setResult:(id)result;

+(CWFutureOperation*)operationWithTarget:(id)target
                                selector:(SEL)selector
                                  object:(id)object;

+(CWFutureOperation*)operationWithInvocation:(NSInvocation*)invocation;

@end</pre>
<h3>Implementation</h3>
<p>The client of the code must be able to fetch the result and the <code>CWFutureOperation</code> subclass must be able to set the result. The <code>result</code> method should block until the operation is finished if needed, and must properly return a result that can survive the operation that might be in a release pool. The implementation for this is straight forward, only minor complexity added in order to allow the result to be set multiple times:</p>
<pre class="brush:objc">-(id)result;
{
    if (![self isFinished]) {
        [self waitUntilFinished];
    }
    if ([self isCancelled]) {
        return nil;
    }
    return [[_result retain] autorelease];
}

-(void)setResult:(id)result;
{
    _isResultSet = YES;
    if (_result != result) {
        [_result autorelease];
        _result = [result retain];
    }
}</pre>
<p>The reason that we flag if the result has been set is because we want to throw an exception if the subclass implementation of the main method failes to set the result before exiting, we add this behavior by overriding the start method in <code>CWFutureOperation</code>.</p>
<p>The <code>start</code> method will also call the target-action pair upon completion if the operation has not been cancelled. The target selector is always called on the main thread, this is so that we safely can update any UI using the calculated result without adding even more threading code.</p>
<pre class="brush:objc">-(void)start;
{
    [super start];
    if (![self isCancelled]) {
        if (!_isResultSet) {
            [NSException raise:NSInternalInconsistencyException
                        format:@"%@ did not set result.", self];
        }
        [_completionTarget performSelectorOnMainThread:_completionSelector
                                            withObject:self
                                         waitUntilDone:NO];
    }
}</pre>
<h3>Conclusion</h3>
<p>The total amount of code is not mu<a href='http://blog.jayway.com/wordpress/wp-content/uploads/2010/08/Futures.zip'>Futures</a>ch, but this generic class adds a pattern to follow making design decisions for new application easy and consistent.</p>
<p>Solving the age old search-as-you-type problem can be as simple as this (Many assumptions, but you get the idea):</p>
<pre class="brush:objc">-(NSArray*)performSearchWithString:(NSString*)str;
{
    NSMutableArray* searchResults = nil;
    // Do actual search over the interwebz.
    return searchResults;
}

-(void)searchOperationDidComplete:(CWFutureOperation*)op;
{
    self.currentSearchOperation = nil;
    self.currentSearchResult = [op result];
    [self.searchDisplayController.searchResultsTableView reloadData];
}

-(BOOL)searchDisplayController:(UISearchDisplayController*)controller
  shouldReloadTableForSearchString:(NSString*)searchString;
{
	CWFutureOperation* op = [CWFutureOperation operationWithTarget:self
                                                          selector:@selector(performSearchWithString:) object:searchString];
    [op setCompletionTarget:self
                   selector:@selector(searchOperationDidComplete:)];
    [[NSOperationQueue defaultQueue]
    		replaceOperation:self.currentSearchOperation
               withOperation:op];
    self.currentSearchOperation = op;
    return NO;
}</pre>
<p>The full source code including unit tests, and some additional categories for making operation queue life easier, can be <a href="http://blog.jayway.com/wordpress/wp-content/uploads/2010/08/Futures.zip">downloaded here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2010/08/19/future-cocoa-operation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Queued Background Tasks for Cocoa</title>
		<link>http://blog.jayway.com/2009/05/09/queued-background-tasks-for-cocoa/</link>
		<comments>http://blog.jayway.com/2009/05/09/queued-background-tasks-for-cocoa/#comments</comments>
		<pubDate>Sat, 09 May 2009 12:42:04 +0000</pubDate>
		<dc:creator>Fredrik Olsson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=1665</guid>
		<description><![CDATA[The megahertz race is over, and instead we get more execution cores. This means that we as developers must make our applications parallel, in order to take advantage of the new performance. The easiest way to be parallel is to execute tasks in new threads, something that is useful also for lengthy but not resource [...]]]></description>
			<content:encoded><![CDATA[<p>The megahertz race is over, and instead we get more execution cores. This means that we as developers must make our applications parallel, in order to take advantage of the new performance. The easiest way to be parallel is to execute tasks in new threads, something that is useful also for lengthy but not resource intensive tasks such as network access.</p>
<p>Any sane developer avoids premature optimization, so the task we later want to execute in a separate thread is almost always available in our current context. I am sure all Java-developers has seen something like this:</p>
<pre class="java"> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AThread+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #aaaadd; font-weight: bold;">Thread</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> run<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        OuterClass.<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006600;">someMethod</span><span style="color: #66cc66;">&#40;</span>arg<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>.<span style="color: #006600;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre>
<p>And often an anonymous <code>Runnable</code> is involved as well. Executing a task in a separate thread with Cocoa and Cocoa Touch is ridiculously easy given the dynamic nature of Objective-C. This is done with Cocoa with this one-liner:</p>
<pre class="objc"><span style="color: #002200;">&#91;</span>self performSelectorInBackground:<span style="color: #0000ff;">@selector</span><span style="color: #002200;">&#40;</span>someMethod:<span style="color: #002200;">&#41;</span> withObject:arg<span style="color: #002200;">&#93;</span>;</pre>
<p>The <code>performSelectorInBackground:withObject:</code> is a companion method for <code>performSelector:withObject:</code>, and will create a new <code>NSThread</code> instance, and execute the specified method there. There are more companions such as <code>performSelectorOnMainThread:withObject:</code> that is used to execute a method on the main UI thread.</p>
<p>This easy access to executing in new threads often can result in code that spawns too many threads. In Cocoa on Mac OS X this is seldom a problem, not for Cocoa Touch applications under development when running in the iPhone simulator either. But on the more resource constrained iPhone and iPod Touch devices this will be a problem. Spawning a dozen background threads to download images will bring the iPhone OS to a staggering mess.</p>
<p><em><strong>Update: </strong>I have removed <code>CWSelectorOperation</code> from this post, since using <code>NSInvocationOperation</code> is preferred.</em></p>
<h3>Operation Queues</h3>
<p>The solution is to use a <code>NSOperationQueue</code>, that as the name implies handles a queue of operations. The max number of concurrent operations can be set, as well as dependencies and priority. The downside is that <code>NSOperationQueue</code> can only handle instances of <code>NSOperation</code>.</p>
<p><code>NSOperation</code> is an abstract class, where you as a developer override the <code>main</code> method to execute your task. In short <code>NSOperation</code> is programatically the equivalent of the Java <code>Runnable</code> interface. It is even worse as Objective-C do not support anonymous classes, so we will be required to actually implement our queued tasks as separate classes.</p>
<p>Not as neat as one would like, and definitely not even very Cocoa-like.</p>
<h3>What is Missing</h3>
<p>As a Cocoa developer I expect that executing a task on background queue, would be just as easy as executing a task on a background thread. The expected needed code is something like this:</p>
<pre class="objc"><span style="color: #002200;">&#91;</span>self performSelectorOnBackgroundQueue:<span style="color: #0000ff;">@selector</span><span style="color: #002200;">&#40;</span>someMethod:<span style="color: #002200;">&#41;</span> withObject:arg<span style="color: #002200;">&#93;</span>;</pre>
<p>To make this work we need:</p>
<ol>
<li>A category on <code>NSObject</code> to add <code>performSelectorOnBackgroundQueue:withObject:</code>.</li>
<li><del datetime="2009-05-13T10:47:35+00:00">Implement a concrete subclass of <code>NSOperation</code> to support execution of a selector on any target.</del>Use <code>NSInvocationOperation</code> to perform selector.</li>
<li>A category on <code>NSOperationQueue</code> to add a shared operation queue.</li>
</ol>
<p>This is in the order of how a client developer would see it (most developers will only care for the <code>NSObject</code> category). For us this is the reverse order when implement this functionality.</p>
<h3>A Shared Operation Queue</h3>
<p>Cocoa and Cocoa Touch used many shared instances, for example a shared <code>UIAccelerometer</code> instance, and a shared <code>NSURLCache</code> instance. So this pattern of single point dependency injection is common in Cocoa and works very well. So let us follow suit by introducing an interface like this:</p>
<pre class="objc"><span style="color: #0000ff;">@interface</span> NSOperationQueue <span style="color: #002200;">&#40;</span>CWSharedQueue<span style="color: #002200;">&#41;</span>
+<span style="color: #002200;">&#40;</span>NSOperationQueue*<span style="color: #002200;">&#41;</span>sharedOperationQueue;
+<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #002200;">&#41;</span>setSharedOperationQueue:<span style="color: #002200;">&#40;</span>NSOperationQueue*<span style="color: #002200;">&#41;</span>operationQueue;
<span style="color: #0000ff;">@end</span></pre>
<p>The shared operation queue will be created lazily if it do not exist, and the client can easily swap it out at startup if needed. The implementation is very small, and a good example of how we should implement class variables with proper memory handling.</p>
<pre class="objc"><span style="color: #0000ff;">@implementation</span> NSOperationQueue <span style="color: #002200;">&#40;</span>CWSharedQueue<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #0000ff;">static</span> NSOperationQueue* cw_sharedOperationQueue = <span style="color: #0000ff;">nil</span>;
&nbsp;
+<span style="color: #002200;">&#40;</span>NSOperationQueue*<span style="color: #002200;">&#41;</span>sharedOperationQueue;
<span style="color: #002200;">&#123;</span>
  <span style="color: #0000ff;">if</span> <span style="color: #002200;">&#40;</span>cw_sharedOperationQueue == <span style="color: #0000ff;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    cw_sharedOperationQueue = <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSOperationQueue alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>cw_sharedOperationQueue setMaxConcurrentOperationCount:<span style="color: #0000dd;">3</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #0000ff;">return</span> cw_sharedOperationQueue;
<span style="color: #002200;">&#125;</span>
&nbsp;
+<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #002200;">&#41;</span>setSharedOperationQueue:<span style="color: #002200;">&#40;</span>NSOperationQueue*<span style="color: #002200;">&#41;</span>operationQueue;
<span style="color: #002200;">&#123;</span>
  <span style="color: #0000ff;">if</span> <span style="color: #002200;">&#40;</span>operationQueue != cw_sharedOperationQueue<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>cw_sharedOperationQueue release<span style="color: #002200;">&#93;</span>;
    cw_sharedOperationQueue = <span style="color: #002200;">&#91;</span>operationQueue retain<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">@end</span></pre>
<h3><del datetime="2009-05-13T10:47:35+00:00">Enter <code>CWSelectorOperation</code></del></h3>
<p><em><strong>Update: </strong><code>CWSelectorOperation</code> is no longer needed, our implementation instead uses <code>NSInvocationOperation</code>.</em></p>
<h3>Wrapping up <code>NSObject</code></h3>
<p>And at last we reach the category on <code>NSObject</code>, that is what we initially wanted, and what 95% of all use cases will be limited to.</p>
<pre class="objc"><span style="color: #0000ff;">@interface</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSObject.html"><span style="color: #0000ff;">NSObject</span></a> <span style="color: #002200;">&#40;</span>CWSharedQueue<span style="color: #002200;">&#41;</span>
&nbsp;
-<span style="color: #002200;">&#40;</span>NSInvocationOperation*<span style="color: #002200;">&#41;</span>performSelectorInBackgroundQueue:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">SEL</span><span style="color: #002200;">&#41;</span>aSelector
    withObject:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">id</span><span style="color: #002200;">&#41;</span>arg;
-<span style="color: #002200;">&#40;</span>NSInvocationOperation*<span style="color: #002200;">&#41;</span>performSelectorInBackgroundQueue:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">SEL</span><span style="color: #002200;">&#41;</span>aSelector
    withObject:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">id</span><span style="color: #002200;">&#41;</span>arg dependencies:<span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSArray.html"><span style="color: #0000ff;">NSArray</span></a>*<span style="color: #002200;">&#41;</span>dependencies
    priority:<span style="color: #002200;">&#40;</span>NSOperationQueuePriority<span style="color: #002200;">&#41;</span>priority;
&nbsp;
<span style="color: #0000ff;">@end</span></pre>
<p>Most <code>performSelector*</code> methods do not have a return value, I have chosen to return the resulting <code> NSInvocationOperation </code> so that it can be used to setup dependencies for future queued operations. I have also added a second method <code>performSelectorInBackgroundQueue:withObject:dependencies:priority:</code> so that such dependencies can easily be setup, as well as prioritisation of operations.</p>
<p>The actual implementation is a simple wrapper around the <code> NSInvocationOperation </code> class, and category on <code>NSOperationQueue</code> that we implemented above:</p>
<pre class="objc"><span style="color: #0000ff;">@implementation</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSObject.html"><span style="color: #0000ff;">NSObject</span></a> <span style="color: #002200;">&#40;</span>CWSharedQueue<span style="color: #002200;">&#41;</span>
&nbsp;
-<span style="color: #002200;">&#40;</span>NSInvocationOperation*<span style="color: #002200;">&#41;</span>performSelectorInBackgroundQueue:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">SEL</span><span style="color: #002200;">&#41;</span>aSelector
    withObject:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">id</span><span style="color: #002200;">&#41;</span>arg;
<span style="color: #002200;">&#123;</span>
  NSInvocationOperation* operation = <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSInvocationOperation alloc<span style="color: #002200;">&#93;</span>
      initWithTarget:self selector:aSelector object:arg<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSOperationQueue sharedOperationQueue<span style="color: #002200;">&#93;</span> addOperation:operation<span style="color: #002200;">&#93;</span>;
  <span style="color: #0000ff;">return</span> <span style="color: #002200;">&#91;</span>operation autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
-<span style="color: #002200;">&#40;</span>NSInvocationOperation*<span style="color: #002200;">&#41;</span>performSelectorInBackgroundQueue:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">SEL</span><span style="color: #002200;">&#41;</span>aSelector
    withObject:<span style="color: #002200;">&#40;</span><span style="color: #0000ff;">id</span><span style="color: #002200;">&#41;</span>arg dependencies:<span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSArray.html"><span style="color: #0000ff;">NSArray</span></a>*<span style="color: #002200;">&#41;</span>dependencies
    priority:<span style="color: #002200;">&#40;</span>NSOperationQueuePriority<span style="color: #002200;">&#41;</span>priority;
<span style="color: #002200;">&#123;</span>
  NSInvocationOperation* operation = <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSInvocationOperation alloc<span style="color: #002200;">&#93;</span>
      initWithTarget:self selector:aSelector object:arg<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>operation setQueuePriority:priority<span style="color: #002200;">&#93;</span>;
  <span style="color: #0000ff;">for</span> <span style="color: #002200;">&#40;</span>NSOperation* dependency in dependencies<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>operation addDependency:dependency<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>NSOperationQueue sharedOperationQueue<span style="color: #002200;">&#93;</span> addOperation:operation<span style="color: #002200;">&#93;</span>;
  <span style="color: #0000ff;">return</span> <span style="color: #002200;">&#91;</span>operation autorelease<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">@end</span></pre>
<p>And that is it, if you want to avoid cut and paste of all this code to your own project just <a href='http://blog.jayway.com/wordpress/wp-content/uploads/2009/05/nsoperationqueuecwsharedqueue.zip'>download the source code here</a>. And happy concurrent hacking.</p>
<p>Download the <a href='http://blog.jayway.com/wordpress/wp-content/uploads/2009/05/cwselectoroperation.zip'>older source code here</a>, with a concrete subclass of <code>NSOperation</code> called <code>CWSelectorOperation</code>. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2009/05/09/queued-background-tasks-for-cocoa/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Squid, the caching proxy</title>
		<link>http://blog.jayway.com/2008/06/06/squid-the-caching-proxy/</link>
		<comments>http://blog.jayway.com/2008/06/06/squid-the-caching-proxy/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 18:37:34 +0000</pubDate>
		<dc:creator>Ulrik Sandberg</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=85</guid>
		<description><![CDATA[I just checked out the old Squid again, the worlds most famous caching proxy. If you direct all your web access through the Squid proxy server, it will cache stuff after the first access. This would simplify for example for labs where fifty people simultaneously begin retrieving stuff from a Maven repo somewhere or downloading [...]]]></description>
			<content:encoded><![CDATA[<p>I just checked out the old <a href="http://www.squid-cache.org/">Squid</a> again, the worlds most famous caching proxy. If you direct all your web access through the Squid proxy server, it will cache stuff after the first access. This would simplify for example for labs where fifty people simultaneously begin retrieving stuff from a Maven repo somewhere or downloading required libraries, and we have a very limited bandwidth.</p>
<p>On the Mac it was easy to get running (if you have <a href="http://www.macports.org/">MacPorts</a>):</p>
<pre>% sudo port install squid
% sudo squid -z (initialize stuff if you never ran Squid before)
% sudo squid -N -d 1 (no daemon, debug level 1)</pre>
<p>Then it was running on the console, and you could test it like this:</p>
<pre>% squidclient http://google.com
...
X-Cache: MISS from myhostname
Via: 1.0 myhostname:3128 (squid/2.7.STABLE2)</pre>
<p>And again, this time fetching from the cache:</p>
<pre>% squidclient http://google.com
...
X-Cache: HIT from myhostname
Via: 1.0 myhostname:3128 (squid/2.7.STABLE2)</pre>
<p>You configure your browser by simply setting proxy server to <code>localhost:3128</code>, if you are running your Squid locally, that is.</p>
<p>Maven is probably best configured in <code>~/.m2/settings.xml</code>:</p>
<pre>&lt;settings xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/xmlSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/settings-1.0.0.xsd"&gt;
  &lt;proxies&gt;
    &lt;proxy&gt;
      &lt;active&gt;true&lt;/active&gt;
      &lt;protocol&gt;http&lt;/protocol&gt;
      &lt;host&gt;localhost&lt;/host&gt;
      &lt;port&gt;3128&lt;/port&gt;
    &lt;/proxy&gt;
  &lt;/proxies&gt;
&lt;/settings&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2008/06/06/squid-the-caching-proxy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Amazon S3 for backup</title>
		<link>http://blog.jayway.com/2007/09/02/using-amazon-s3-for-backup/</link>
		<comments>http://blog.jayway.com/2007/09/02/using-amazon-s3-for-backup/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 22:50:20 +0000</pubDate>
		<dc:creator>Ulrik Sandberg</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=162</guid>
		<description><![CDATA[Amazon Simple Storage Service (S3) is cheap on-line storage with a Web Service interface. You just log in with your Amazon id, sign up for S3, designate a credit card, and that's it. You now have access to pretty much unlimited storage space, managed by Amazon. The price is $0.15 per GB-Month of storage used [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://aws.amazon.com/s3">Amazon Simple Storage Service (S3)</a> is cheap on-line storage with a Web Service interface. You just log in with your Amazon id, sign up for S3, designate a credit card, and that's it. You now have access to pretty much unlimited storage space, managed by Amazon. The price is $0.15 per GB-Month of storage used (plus transfer costs). It was too tempting; I simply had to test it.</p>
<p>I used the <a href="http://jungledisk.com/">Jungle Disk</a> software to provide the mapping from the S3 web service interface to a network drive. You give Jungle Disk your S3 account information, and it provides a network disk which you can use as the backup device. I first tried my existing backup software (<a href="http://www.qdea.com/pages/pages-sprox/sprox1.html">Synchronize! Pro X</a>) and it happily began creating directories and copying files. I then tried the backup feature built into Jungle Disk, and it works fine too. It's not fast compared to a local FireWire disk. It's limited to your upload bandwidth, which often is substantially smaller than the download bandwidth.</p>
<p>Anyway, it has been tugging along today storing 5 GB of by digital photos. It feels pretty good to know that my photos are now stored encrypted and with 99.99% availability somewhere far far away, costing me only 75 cents per month after the initial $2 for the transfer.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2007/09/02/using-amazon-s3-for-backup/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Sharing a Mac Internet Connection Through Airport</title>
		<link>http://blog.jayway.com/2007/01/20/sharing-a-mac-internet-connection-through-airport/</link>
		<comments>http://blog.jayway.com/2007/01/20/sharing-a-mac-internet-connection-through-airport/#comments</comments>
		<pubDate>Sat, 20 Jan 2007 22:02:03 +0000</pubDate>
		<dc:creator>Ulrik Sandberg</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=183</guid>
		<description><![CDATA[I just solved a networking problem on my Macs after hours of trying. For the benefit of others, I'll describe here the problem and the solution. Setup Cable modem from ISP, network cable to a firewall, the private end of the firewall via network cable on to a switch. Pretty basic, I guess. No wireless [...]]]></description>
			<content:encoded><![CDATA[<p>I just solved a networking problem on my Macs after hours of trying. For the benefit of others, I'll describe here the problem and the solution.</p>
<h3>Setup</h3>
<p>Cable modem from ISP, network cable to a firewall, the private end of the firewall via network cable on to a switch. Pretty basic, I guess. No wireless base stations or anything. Just an iMac connected via network cable to the switch.</p>
<h3>Problem</h3>
<p>Share the iMac's network cable connection through its Airport wireless capability. The client is a MacBook Pro. Basically, I just want to get Internet access on my laptop via the iMac. Sounds simple, but hey, it took me half a day and plenty of research to figure out.</p>
<h4>Useful pieces of information gathered during this adventure</h4>
<ol>
<li>Turning on Internet Connection Sharing (ICS) will start a DHCP server.</li>
<li>Turning on ICS will create a full Airport network (not a computer-to-computer network).</li>
<li>Turning on ICS will create a new network configuration for 10.0.2.1, which I understand is the same address as the Airport base stations use.</li>
</ol>
<h3>Solution</h3>
<ol>
<li>On the iMac, set the Airport network to "Use DHCP with manual address" and set the IP to 10.0.2.1. Set the DNS servers to the ones recommended by your ISP. Apply.</li>
<li>On the iMac, go to Sharing|Internet and choose AirPort Options. Enable WEP encryption (I chose 40-bit with a 5 character password). The default network name is your computer name. I added a postfix to the network name ("-ics") so I can distinguish it from the computer-to-computer network. Apply.</li>
<li>Now start sharing your Built-in Ethernet connection to computers using Airport. As I mentioned previously, this will create the new network and also start a DHCP server.</li>
<li>On the MacBook, set the Airport network to "Use DHCP". Leave all fields blank.</li>
<li>On the MacBook, connect to the newly created network, which should be named "hostname-ics" if you followed my naming advice earlier. Watch the network configuration. Eventually it shows the IP 10.0.2.2.</li>
</ol>
<p>That's it. You should now have access to your other machines on your private network, but also to Internet.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2007/01/20/sharing-a-mac-internet-connection-through-airport/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Solving 403 problems with Sourceforge Subversion</title>
		<link>http://blog.jayway.com/2007/01/13/solving-403-problems-with-sourceforge-subversion/</link>
		<comments>http://blog.jayway.com/2007/01/13/solving-403-problems-with-sourceforge-subversion/#comments</comments>
		<pubDate>Sat, 13 Jan 2007 16:54:42 +0000</pubDate>
		<dc:creator>Ulrik Sandberg</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[sourceforge]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=177</guid>
		<description><![CDATA[After having had severe problems when committing to the Sourceforge Subversion repos, I stumbled upon what appears to be the solution. The problem was that in the middle of a commit, one file or directory would fail with a 403 (permission denied). In desperation, I would chop up the change set and commit little pieces [...]]]></description>
			<content:encoded><![CDATA[<p>After having had severe problems when committing to the Sourceforge Subversion repos, I stumbled upon what appears to be the solution. The problem was that in the middle of a commit, one file or directory would fail with a 403 (permission denied). In desperation, I would chop up the change set and commit little pieces at the time, until only the ones with problems remained. I would then perform desperate unnamed actions with these until they eventually were committed. Pretty nerve-wrecking, time-consuming, and unproductive stuff. The worst part is that if you split the change set, you could end up splitting a move operation, which is basically a copy and a delete. Say that you commit the delete operation successfully first. Then you try to commit the copy, which will fail with a 404 (not found), since the stuff it tries to copy has been deleted. There are ways around it, but I won't describe them here. Horrible stuff.</p>
<p>I had seen somewhere that you could get the 403 error if you were using SSL (which I was) and the Sourceforge server <tt>svn.sourceforge.net</tt>. The correct server is the <tt>PROJECTNAME.svn.sourceforge.net</tt>, where <tt>PROJECTNAME</tt> in my case was <tt>springframework</tt>. So <b>the correct URL to use is <tt>https://springframework.svn.sourceforge.net/svnroot/springframework/</tt>.</b> This meant changing the checkout URL, which Subversion can do on an already checked-out working copy, using the <tt>switch</tt> command. Cool. When I tried this, it failed because it couldn't find the new server. The problem was that the DNS servers I was using at some point didn't find this server, and probably cached this negative hit. Eventually I found a DNS that could locate this server and performed the switch. Things have been working much better since.</p>
<p>Using the incorrect server, which most likely is a proxy server of some sort, could possibly have resulted in different physical servers being used for different requests during the Subversion transaction. It's not allowed to perform a <tt>svn copy</tt> operation between repositories. You'll get a 403 if you try it. Perhaps that rule applied to my situation as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2007/01/13/solving-403-problems-with-sourceforge-subversion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A cool GMail feature</title>
		<link>http://blog.jayway.com/2007/01/03/a-cool-gmail-feature/</link>
		<comments>http://blog.jayway.com/2007/01/03/a-cool-gmail-feature/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 16:34:37 +0000</pubDate>
		<dc:creator>Ulrik Sandberg</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=172</guid>
		<description><![CDATA[Google Mail will deliver a mail even though the recipient address ends with '+' and some more text, like john.doe+msn@gmail.com for example. This feature can be used to create an unlimited number of mail addresses that can be used for registration purposes. For example, say that the MSN web site requires your email address for [...]]]></description>
			<content:encoded><![CDATA[<p>Google Mail will deliver a mail even though the recipient address ends with '+' and some more text, like <tt>john.doe+msn@gmail.com</tt> for example. This feature can be used to create an unlimited number of mail addresses that can be used for registration purposes. For example, say that the MSN web site requires your email address for you to download some stuff you need. You don't want to give up your real email, since you're afraid you'll be spammed. Yet you need to give a valid email since they might send registration information to it, like the password. The solution is to use <tt>john.doe+msn@gmail.com</tt> and the mails will still be delivered to the <tt>john.doe</tt> mailbox. However, you can now quickly identify if the address you gave when you registered at MSN has been used for spam, and create a filter to handle them. GMail filters allow you to perform any or all of the following actions: archive, delete, label, forward, mark with a star.</p>
<p>Note that although this follows the Internet standard for email addresses (<a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>), some sites simply ignore this and incorrectly disallows addresses with plus signs.</p>
<p>Read more <a href="http://21st.blogspot.com/2006/09/use-gmail-generate-unlimited-e-mail.html">here</a>. More cool mail tips can be found <a href="http://www.howtohut.com/tag/email">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2007/01/03/a-cool-gmail-feature/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

