From: Jason Mayer Date: 2007-01-30T12:31:27+09:00 Subject: Re: Is my code using the Ruby way? ------=_Part_117440_19578574.1170127884902 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline On 1/29/07, ara.t.howard@noaa.gov wrote: > > hopefully you realize this code contains a race condition. if you use a > two > step process to check that the database is created and, if not, to create > it - > you risk that another process might create it in between those two > steps. a > cleaner way to do it is to use execptions: > > harp:~ > cat a.rb > require 'sqlite' > > class Database > SCHEMA = <<-SCHEMA > create table t( > id int, > data string > ); > SCHEMA > > def initialize path > @path = path > @db = SQLite::Database.new @path > setup > end > > def setup > @db.execute SCHEMA rescue nil > ensure > validate_schema > end > > def validate_schema > @db.execute 'select * from t limit 1' > end > end > > Database.new 'db' > > here, the db is always created and initialized with the SCHEMA. normally > trying to create the table twice would throw an error, which is ingored. > because ignoring this error might mask a real failure to set the db a > simplistic method, in this case, is used to make sure the database looks > like > it's supposed to. note that this whole thing is based on the knowledge > that > sqlite uses it's own locking to ensure atmoicity. > > in any case, the pattern of > > "try it and recover if it blows up" > > is often a good solution where testing a condition and then acting on it > cannot be done in one step to avoid a race condition. > > btw. sqlite and ruby are a good combination - i use them heavily in my > own > work. Just a general thank you for this detailed explanation - now I understand better how to avoid race conditions (and I'm much more certain of what exactly they are now). ------=_Part_117440_19578574.1170127884902--