<?xml version="1.0" encoding="UTF-8"?><rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
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/"
> <channel><title>Comments on: Wanna Review My Code?</title> <atom:link href="http://davybrion.com/blog/2010/02/wanna-review-my-code/feed/" rel="self" type="application/rss+xml" /><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/</link> <description>inquisitive: adjective. given to inquiry, research, or asking questions; eager for knowledge; intellectually curious</description> <lastBuildDate>Tue, 22 May 2012 17:40:00 +0000</lastBuildDate> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <item><title>By: Davy Brion</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29863</link> <dc:creator>Davy Brion</dc:creator> <pubDate>Fri, 26 Feb 2010 07:26:02 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29863</guid> <description>@Adamtrue... but it also falls under the &quot; they’re no longer a paying customer so i no longer care about them&quot; category ;)</description> <content:encoded><![CDATA[<p>@Adam</p><p>true&#8230; but it also falls under the &#8221; they’re no longer a paying customer so i no longer care about them&#8221; category <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p> ]]></content:encoded> </item> <item><title>By: Adam</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29813</link> <dc:creator>Adam</dc:creator> <pubDate>Thu, 25 Feb 2010 19:30:43 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29813</guid> <description>If CreateSessionForCurrentTenant and RemoveSessionFactoryForTenant execute at the same time with an unreasonable amount of bad luck it&#039;s possible that Dispose gets called on the sessionfactory right before OpenSession.
I don&#039;t see how that can be avoided without using the same lock for reading the dictionary as well.</description> <content:encoded><![CDATA[<p>If CreateSessionForCurrentTenant and RemoveSessionFactoryForTenant execute at the same time with an unreasonable amount of bad luck it&#8217;s possible that Dispose gets called on the sessionfactory right before OpenSession.<br
/> I don&#8217;t see how that can be avoided without using the same lock for reading the dictionary as well.</p> ]]></content:encoded> </item> <item><title>By: Tiendq</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29760</link> <dc:creator>Tiendq</dc:creator> <pubDate>Thu, 25 Feb 2010 05:20:53 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29760</guid> <description>I will use IDictionary and will not use {} for single IF statement.</description> <content:encoded><![CDATA[<p>I will use IDictionary and will not use {} for single IF statement.</p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29691</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Wed, 24 Feb 2010 12:31:39 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29691</guid> <description>I blame notepad :)</description> <content:encoded><![CDATA[<p>I blame notepad <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p> ]]></content:encoded> </item> <item><title>By: Davy Brion</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29688</link> <dc:creator>Davy Brion</dc:creator> <pubDate>Wed, 24 Feb 2010 12:05:04 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29688</guid> <description>@Awkwardi think you got something mixed up there because that either returns an ISession or an ISessionFactory ;)</description> <content:encoded><![CDATA[<p>@Awkward</p><p>i think you got something mixed up there because that either returns an ISession or an ISessionFactory <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29687</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Wed, 24 Feb 2010 11:57:43 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29687</guid> <description>plus I would change the CreateSessionForCurrentTenant to remove the other race condition...private ISession CreateSessionFactoryForCurrentTenant()
{
lock (writeLock)
{
var tenantId = tenantContext.CurrentTenantId;
if (sessionFactories.ContainsKey(tenantId))
{
return sessionFactories[tenantId].OpenSession();
}
var connectionString = tenantInfoHolder.GetDatabaseConnectionString(tenantId);
var sessionFactory = new Configuration()
.Configure()
.AddProperties(new Dictionary
{{ \connection.connection_string\, connectionString },{ \cache.region_prefix\, \Tenant_\ + tenantId }})
.AddAssembly(mappingAssemblyName)
.BuildSessionFactory();
var newDictionary = new Dictionary(sessionFactories);
newDictionary[tenantId] = sessionFactory;
sessionFactories = newDictionary;return sessionFactory;
}
}</description> <content:encoded><![CDATA[<p>plus I would change the CreateSessionForCurrentTenant to remove the other race condition&#8230;</p><p>private ISession CreateSessionFactoryForCurrentTenant()<br
/> {<br
/> lock (writeLock)<br
/> {<br
/> var tenantId = tenantContext.CurrentTenantId;<br
/> if (sessionFactories.ContainsKey(tenantId))<br
/> {<br
/> return sessionFactories[tenantId].OpenSession();<br
/> }</p><p> var connectionString = tenantInfoHolder.GetDatabaseConnectionString(tenantId);<br
/> var sessionFactory = new Configuration()<br
/> .Configure()<br
/> .AddProperties(new Dictionary<br
/> {</p><p> { \connection.connection_string\, connectionString },</p><p> { \cache.region_prefix\, \Tenant_\ + tenantId }</p><p> })<br
/> .AddAssembly(mappingAssemblyName)<br
/> .BuildSessionFactory();<br
/> var newDictionary = new Dictionary(sessionFactories);<br
/> newDictionary[tenantId] = sessionFactory;<br
/> sessionFactories = newDictionary;</p><p> return sessionFactory;<br
/> }<br
/> }</p> ]]></content:encoded> </item> <item><title>By: Davy Brion</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29682</link> <dc:creator>Davy Brion</dc:creator> <pubDate>Wed, 24 Feb 2010 11:23:27 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29682</guid> <description>@Awkward Coderaha, that is indeed technically possible :)</description> <content:encoded><![CDATA[<p>@Awkward Coder</p><p>aha, that is indeed technically possible <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29681</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Wed, 24 Feb 2010 11:21:03 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29681</guid> <description>if one thread is in the middle of executing CreateSessionFactoryForCurrentTenant - inside the lock and hasn&#039;t yet updated the dictionary and another thread executes RemoveSessionFactoryForTenant for the same tenant id then the first if statement outside of the lock statement will return true and exit the method, whilst the other thread completes and updates the dictionary with the new SessionFactory.Chances of this actually happening are zero though.or I could be complete wrong, it&#039;s been known :)</description> <content:encoded><![CDATA[<p>if one thread is in the middle of executing CreateSessionFactoryForCurrentTenant &#8211; inside the lock and hasn&#8217;t yet updated the dictionary and another thread executes RemoveSessionFactoryForTenant for the same tenant id then the first if statement outside of the lock statement will return true and exit the method, whilst the other thread completes and updates the dictionary with the new SessionFactory.</p><p>Chances of this actually happening are zero though.</p><p>or I could be complete wrong, it&#8217;s been known <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p> ]]></content:encoded> </item> <item><title>By: Davy Brion</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29674</link> <dc:creator>Davy Brion</dc:creator> <pubDate>Wed, 24 Feb 2010 08:59:50 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29674</guid> <description>@Kenif i use the SyncRoot, i have to use it for each access to the dictionary@JeroenHit&#039;s a copy-on-write implementation... reading from the dictionary is thread-safe, as long as no other thread mutates the state of the dictionary.  when a ISessionFactory needs to be added to or removed from the dictionary, i create a new one, add the new sessionfactory to it or remove the old one from it, and then replace the field that holds the dictionary.  during this entire operation, any other thread can still safely perform the read since the field that is used by the thread always references a dictionary that is never mutated.@Awkward Codersessions aren&#039;t stored in the dictionary... they&#039;re sessionfactories.  i don&#039;t _think_ there&#039;s a race condition between creating a new one, and removing one from the dictionary but i definitly could be wrong... creating and removing is both done within a lock on the same object, so i think it&#039;s safe... if i&#039;m wrong there, i&#039;d really appreciate you pointing out what i missed :)@Phoyou are correct about the bug :)
normally, it shouldn&#039;t occur because by the time we need to remove a tenant, the users of that tenant shouldn&#039;t even have access to the application anymore.  and even if they did still have access, they&#039;re no longer a paying customer (hence the removal of the tenant) so any exception they run into isn&#039;t really something i&#039;d be worried about</description> <content:encoded><![CDATA[<p>@Ken</p><p>if i use the SyncRoot, i have to use it for each access to the dictionary</p><p>@JeroenH</p><p>it&#8217;s a copy-on-write implementation&#8230; reading from the dictionary is thread-safe, as long as no other thread mutates the state of the dictionary.  when a ISessionFactory needs to be added to or removed from the dictionary, i create a new one, add the new sessionfactory to it or remove the old one from it, and then replace the field that holds the dictionary.  during this entire operation, any other thread can still safely perform the read since the field that is used by the thread always references a dictionary that is never mutated.</p><p>@Awkward Coder</p><p>sessions aren&#8217;t stored in the dictionary&#8230; they&#8217;re sessionfactories.  i don&#8217;t _think_ there&#8217;s a race condition between creating a new one, and removing one from the dictionary but i definitly could be wrong&#8230; creating and removing is both done within a lock on the same object, so i think it&#8217;s safe&#8230; if i&#8217;m wrong there, i&#8217;d really appreciate you pointing out what i missed <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>@Pho</p><p>you are correct about the bug <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br
/> normally, it shouldn&#8217;t occur because by the time we need to remove a tenant, the users of that tenant shouldn&#8217;t even have access to the application anymore.  and even if they did still have access, they&#8217;re no longer a paying customer (hence the removal of the tenant) so any exception they run into isn&#8217;t really something i&#8217;d be worried about</p> ]]></content:encoded> </item> <item><title>By: pho</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29617</link> <dc:creator>pho</dc:creator> <pubDate>Tue, 23 Feb 2010 20:19:00 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29617</guid> <description>my refactorings based on 2 minutes of apathically staring at this code:
1. rename method CreateSessionFactoryForCurrentTenant() to EnsureSessionFactoryForCurrentTenantExists() because you&#039;re only conditionally creating a new session factory.
2. remove the contains check in CreateSessionForCurrentTenant(). if you did this to avoid writelocks as much as possible, move the check to the method that does the actual lock. in both cases --&gt; remove the temp variable in the public method
3. (this one is on the extremely subjective side and purely to improve readability) i&#039;m not really a fan of implicitly adding new key value pairs and prefer using the Add(K,V) method, especially if contexts like this where you know you are adding and are certain a keyvaluepair for a given key does not yet exist.you probably have your reasons why this isn&#039;t already the case i guess :-)as for the known bug, i guess theoretically it could be that between CreateSessionFactoryForCurrentTenant() and the actual dictionary lookup, the key value pair for the current tenantid is already removed? won&#039;t happen though.</description> <content:encoded><![CDATA[<p>my refactorings based on 2 minutes of apathically staring at this code:<br
/> 1. rename method CreateSessionFactoryForCurrentTenant() to EnsureSessionFactoryForCurrentTenantExists() because you&#8217;re only conditionally creating a new session factory.<br
/> 2. remove the contains check in CreateSessionForCurrentTenant(). if you did this to avoid writelocks as much as possible, move the check to the method that does the actual lock. in both cases &#8211;&gt; remove the temp variable in the public method<br
/> 3. (this one is on the extremely subjective side and purely to improve readability) i&#8217;m not really a fan of implicitly adding new key value pairs and prefer using the Add(K,V) method, especially if contexts like this where you know you are adding and are certain a keyvaluepair for a given key does not yet exist.</p><p>you probably have your reasons why this isn&#8217;t already the case i guess <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p><p>as for the known bug, i guess theoretically it could be that between CreateSessionFactoryForCurrentTenant() and the actual dictionary lookup, the key value pair for the current tenantid is already removed? won&#8217;t happen though.</p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29615</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Tue, 23 Feb 2010 19:33:26 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29615</guid> <description>@Stefan - that&#039;s not the problem...</description> <content:encoded><![CDATA[<p>@Stefan &#8211; that&#8217;s not the problem&#8230;</p> ]]></content:encoded> </item> <item><title>By: Stefan</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29595</link> <dc:creator>Stefan</dc:creator> <pubDate>Tue, 23 Feb 2010 17:50:35 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29595</guid> <description>@Akward,He repeats the check inside of the lock also...</description> <content:encoded><![CDATA[<p>@Akward,</p><p>He repeats the check inside of the lock also&#8230;</p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29594</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Tue, 23 Feb 2010 17:50:32 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29594</guid> <description>Not that I think the it would happen in reality...</description> <content:encoded><![CDATA[<p>Not that I think the it would happen in reality&#8230;</p> ]]></content:encoded> </item> <item><title>By: Awkward Coder</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29592</link> <dc:creator>Awkward Coder</dc:creator> <pubDate>Tue, 23 Feb 2010 17:28:35 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29592</guid> <description>Isn&#039;t there a race condition between creating &amp; removing a session?You could be in the middle of assigning the new session into the dictionary (which you replace everytime) and you request the (new) session be removed but it won&#039;t be cos you&#039;re checking outside of the lock in the remove...</description> <content:encoded><![CDATA[<p>Isn&#8217;t there a race condition between creating &amp; removing a session?</p><p>You could be in the middle of assigning the new session into the dictionary (which you replace everytime) and you request the (new) session be removed but it won&#8217;t be cos you&#8217;re checking outside of the lock in the remove&#8230;</p> ]]></content:encoded> </item> <item><title>By: JeroenH</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29589</link> <dc:creator>JeroenH</dc:creator> <pubDate>Tue, 23 Feb 2010 16:54:30 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29589</guid> <description>Why do you replace the sessionFactories dictionary with a new copy every time you need to add or remove a new SessionFactory?</description> <content:encoded><![CDATA[<p>Why do you replace the sessionFactories dictionary with a new copy every time you need to add or remove a new SessionFactory?</p> ]]></content:encoded> </item> <item><title>By: Ken Egozi</title><link>http://davybrion.com/blog/2010/02/wanna-review-my-code/comment-page-1/#comment-29588</link> <dc:creator>Ken Egozi</dc:creator> <pubDate>Tue, 23 Feb 2010 16:24:27 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/2010/02/wanna-review-my-code/#comment-29588</guid> <description>just a couple of points:
1. in RemoveSessionFactoryForTenant() you do a &quot;reverse if&quot; - return if the post-condition is ok, otherwise do the work, while in CreateSessionFactoryForCurrentTenant() you go the other way around, which adds an annoying nesting level. I&#039;d reverse the if on CreateSessionFactoryForCurrentTenant() also
2. I&#039;d also move the first Contains check into CreateSessionFactoryForCurrentTenant(), for two reasons:
i) will make the main method clearer
ii) will make it clear that we follow the two-phase check
3. question: why use an external lock object, and not the .SyncLock of the dictionary?</description> <content:encoded><![CDATA[<p>just a couple of points:<br
/> 1. in RemoveSessionFactoryForTenant() you do a &#8220;reverse if&#8221; &#8211; return if the post-condition is ok, otherwise do the work, while in CreateSessionFactoryForCurrentTenant() you go the other way around, which adds an annoying nesting level. I&#8217;d reverse the if on CreateSessionFactoryForCurrentTenant() also<br
/> 2. I&#8217;d also move the first Contains check into CreateSessionFactoryForCurrentTenant(), for two reasons:<br
/> i) will make the main method clearer<br
/> ii) will make it clear that we follow the two-phase check<br
/> 3. question: why use an external lock object, and not the .SyncLock of the dictionary?</p> ]]></content:encoded> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching using disk: basic
Object Caching 605/681 objects using disk: basic
Content Delivery Network via Amazon Web Services: CloudFront: d18sni7re4ly7f.cloudfront.net

Served from: davybrion.com @ 2012-05-23 02:49:32 -->
