fsdb 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- ### only use this if you can ensure Thread.critical is not already set!
4
- ### it mught be worth implementing a granular atomic-add-based mutex in
5
- ### place of Thread.critical
6
-
7
- # Make sure we use the fast definition, not the thread.rb one!
8
- class Thread # :nodoc:
9
- def self.exclusive
10
- old = critical
11
- self.critical = true
12
- yield
13
- ensure
14
- self.critical = old
15
- end
16
- end
17
-
18
- module FSDB
19
-
20
- # Mutex class based on standard thread.rb Mutex, which has some problems:
21
- #
22
- # - waiters are not a strict queue (try_lock can jump the queue, after
23
- # which the queue gets *rotated*). Race condition.
24
- #
25
- # - doesn't use Thread.exclusive in enough places
26
- #
27
- # - no way to make dead threads give up the mutex, which is crucial in a fork
28
- #
29
- # Note: neither this Mutex nor the one in thread.rb is nestable.
30
- #
31
- class Mutex
32
- def initialize
33
- @waiting = []
34
- @locked = nil
35
- end
36
-
37
- def locked?
38
- @locked
39
- end
40
-
41
- def try_lock
42
- Thread.critical = true
43
- if not @locked
44
- @locked = Thread.current
45
- rslt = true
46
- end
47
- Thread.critical = false
48
- rslt
49
- end
50
-
51
- def lock
52
- thread = Thread.current
53
- Thread.critical = true
54
- if @locked
55
- @waiting.push thread
56
- Thread.stop
57
- unless @locked == thread
58
- raise ThreadError, "queue was jumped"
59
- end
60
- else
61
- @locked = thread
62
- end
63
- Thread.critical = false
64
- self
65
- end
66
-
67
- def unlock
68
- return unless @locked
69
-
70
- Thread.critical = true; t = wake_next_waiter; Thread.critical = false
71
-
72
- begin
73
- t.run if t
74
- rescue ThreadError
75
- end
76
- self
77
- end
78
-
79
- def synchronize
80
- lock
81
- yield
82
- ensure
83
- unlock
84
- end
85
-
86
- def remove_dead # :nodoc:
87
- Thread.critical = true
88
- @waiting = @waiting.select {|t| t.alive?}
89
- wake_next_waiter if @locked and not @locked.alive?
90
- Thread.critical = false
91
- end
92
-
93
- private
94
- def wake_next_waiter
95
- t = @waiting.shift
96
- t.wakeup if t
97
- @locked = t
98
- rescue ThreadError
99
- retry
100
- end
101
-
102
- module ForkSafely
103
- def fork # :nodoc:
104
- super do
105
- ObjectSpace.each_object(Mutex) { |m| m.remove_dead }
106
- yield
107
- end
108
- end
109
- end
110
- end
111
-
112
- # FSDB users who fork should include ForkSafely or FSDB itself. If you use
113
- # mutexes (outside of those in FSDB), they should be FSDB::Mutexes.
114
- module ForkSafely
115
- include Mutex::ForkSafely
116
- end
117
- include ForkSafely
118
-
119
- end # module FSDB
120
-
121
-
122
- if __FILE__ == $0
123
- # Stress test is in fsdb/test/test-mutex.rb. This is just to show fork usage.
124
-
125
- include FSDB::ForkSafely
126
-
127
- m = FSDB::Mutex.new
128
-
129
- Thread.new { m.synchronize { sleep 1 } }
130
-
131
- fork do
132
- m.synchronize { puts "Didn't get here if you used standard mutex or fork." }
133
- end
134
-
135
- m.synchronize { puts "Got here." }
136
-
137
- Process.wait
138
- end
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- unless defined? Thread.exclusive
4
- class Thread # :nodoc:
5
- def self.exclusive
6
- old = critical
7
- self.critical = true
8
- yield
9
- ensure
10
- self.critical = old
11
- end
12
- end
13
- end
14
-
15
- module FSDB
16
-
17
- # Mutex class based on standard thread.rb Mutex, which has some problems:
18
- #
19
- # - waiters are not a strict queue (try_lock can jump the queue, after
20
- # which the queue gets *rotated*). Race condition.
21
- #
22
- # - doesn't use Thread.exclusive in enough places
23
- #
24
- # - no way to make dead threads give up the mutex, which is crucial in a fork
25
- #
26
- # Note: neither this Mutex nor the one in thread.rb is nestable.
27
- #
28
- class Mutex
29
- def initialize
30
- @waiting = []
31
- @locked = nil
32
- @waiting.taint # enable tainted comunication
33
- self.taint
34
- end
35
-
36
- def locked?
37
- @locked
38
- end
39
-
40
- def try_lock
41
- Thread.exclusive do
42
- if not @locked # and @waiting.empty? # not needed
43
- @locked = Thread.current
44
- true
45
- end
46
- end
47
- end
48
-
49
- def lock
50
- thread = Thread.current
51
- Thread.exclusive do
52
- if @locked
53
- @waiting.push thread
54
- Thread.stop
55
- unless @locked == thread
56
- raise ThreadError, "queue was jumped"
57
- end
58
- else
59
- @locked = thread
60
- end
61
- self
62
- end
63
- end
64
-
65
- def unlock
66
- return unless @locked
67
-
68
- t = Thread.exclusive { wake_next_waiter }
69
-
70
- begin
71
- t.run if t
72
- rescue ThreadError
73
- end
74
- self
75
- end
76
-
77
- def synchronize
78
- lock
79
- yield
80
- ensure
81
- unlock
82
- end
83
-
84
- def remove_dead # :nodoc:
85
- Thread.exclusive do
86
- @waiting = @waiting.select {|t| t.alive?}
87
- wake_next_waiter if @locked and not @locked.alive?
88
- ## what if @locked thread left the resource in an inconsistent state?
89
- end
90
- end
91
-
92
- private
93
- def wake_next_waiter
94
- t = @waiting.shift
95
- t.wakeup if t
96
- @locked = t
97
- rescue ThreadError
98
- retry
99
- end
100
-
101
- module ForkSafely
102
- def fork # :nodoc:
103
- super do
104
- ObjectSpace.each_object(Mutex) { |m| m.remove_dead }
105
- yield
106
- end
107
- end
108
- end
109
- end
110
-
111
- # FSDB users who fork should include ForkSafely or FSDB itself. If you use
112
- # mutexes (outside of those in FSDB), they should be FSDB::Mutexes.
113
- module ForkSafely
114
- include Mutex::ForkSafely
115
- end
116
- include ForkSafely
117
-
118
- end # module FSDB
119
-
120
-
121
- if __FILE__ == $0
122
- # Stress test is in fsdb/test/test-mutex.rb. This is just to show fork usage.
123
-
124
- include FSDB::ForkSafely
125
-
126
- m = FSDB::Mutex.new
127
-
128
- Thread.new { m.synchronize { sleep 1 } }
129
-
130
- fork do
131
- m.synchronize { puts "Didn't get here if you used standard mutex or fork." }
132
- end
133
-
134
- m.synchronize { puts "Got here." }
135
-
136
- Process.wait
137
- end
data/rakefile DELETED
@@ -1,41 +0,0 @@
1
- # Look in the tasks/setup.rb file for the various options that can be
2
- # configured in this Rakefile. The .rake files in the tasks directory
3
- # are where the options are used.
4
-
5
- begin
6
- require 'bones'
7
- Bones.setup
8
- rescue LoadError
9
- begin
10
- load 'tasks/setup.rb'
11
- rescue LoadError
12
- raise RuntimeError, '### please install the "bones" gem ###'
13
- end
14
- end
15
-
16
- ensure_in_path 'lib'
17
- require 'fsdb'
18
-
19
- #task :default => 'spec:run'
20
-
21
- PROJ.name = 'fsdb'
22
- PROJ.authors = 'Joel VanderWerf'
23
- PROJ.email = 'vjoel@users.sourceforge.net'
24
- PROJ.url = 'http://rubyforge.org/projects/fsdb/'
25
- PROJ.version = FSDB::VERSION
26
- PROJ.rubyforge.name = 'fsdb'
27
- PROJ.summary = "File System Database"
28
- PROJ.description = <<END
29
- A file system data base. Provides a thread-safe, process-safe Database class.
30
- Each entry is a separate file referenced by its relative path. Allows multiple
31
- file formats and serialization methods. Pure ruby and very light weight.
32
- END
33
- PROJ.changes = File.read(PROJ.history_file)[/^\w.*?(?=^\w)/m]
34
- PROJ.exclude << %w{ junk misc }
35
-
36
- PROJ.spec.opts << '--color'
37
- PROJ.test.files = Dir["test/*.rb"].select {|f| File.executable? f} ## ?
38
-
39
- task :release => ["gem:release", "doc:release"]
40
-
41
- # EOF
@@ -1,80 +0,0 @@
1
-
2
- begin
3
- require 'bones/smtp_tls'
4
- rescue LoadError
5
- require 'net/smtp'
6
- end
7
- require 'time'
8
-
9
- namespace :ann do
10
-
11
- # A prerequisites task that all other tasks depend upon
12
- task :prereqs
13
-
14
- file PROJ.ann.file do
15
- ann = PROJ.ann
16
- puts "Generating #{ann.file}"
17
- File.open(ann.file,'w') do |fd|
18
- fd.puts("#{PROJ.name} version #{PROJ.version}")
19
- fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
- fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
- fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
- fd.puts
23
- fd.puts("== DESCRIPTION")
24
- fd.puts
25
- fd.puts(PROJ.description)
26
- fd.puts
27
- fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
- fd.puts
29
- ann.paragraphs.each do |p|
30
- fd.puts "== #{p.upcase}"
31
- fd.puts
32
- fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
- fd.puts
34
- end
35
- fd.puts ann.text if ann.text
36
- end
37
- end
38
-
39
- desc "Create an announcement file"
40
- task :announcement => ['ann:prereqs', PROJ.ann.file]
41
-
42
- desc "Send an email announcement"
43
- task :email => ['ann:prereqs', PROJ.ann.file] do
44
- ann = PROJ.ann
45
- from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
46
- to = Array(ann.email[:to])
47
-
48
- ### build a mail header for RFC 822
49
- rfc822msg = "From: #{from}\n"
50
- rfc822msg << "To: #{to.join(',')}\n"
51
- rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
- rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
- rfc822msg << "\n"
54
- rfc822msg << "Date: #{Time.new.rfc822}\n"
55
- rfc822msg << "Message-Id: "
56
- rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
- rfc822msg << File.read(ann.file)
58
-
59
- params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
- ann.email[key]
61
- end
62
-
63
- params[3] = PROJ.email if params[3].nil?
64
-
65
- if params[4].nil?
66
- STDOUT.write "Please enter your e-mail password (#{params[3]}): "
67
- params[4] = STDIN.gets.chomp
68
- end
69
-
70
- ### send email
71
- Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
72
- end
73
- end # namespace :ann
74
-
75
- desc 'Alias to ann:announcement'
76
- task :ann => 'ann:announcement'
77
-
78
- CLOBBER << PROJ.ann.file
79
-
80
- # EOF
@@ -1,20 +0,0 @@
1
-
2
- if HAVE_BONES
3
-
4
- namespace :bones do
5
-
6
- desc 'Show the PROJ open struct'
7
- task :debug do |t|
8
- atr = if t.application.top_level_tasks.length == 2
9
- t.application.top_level_tasks.pop
10
- end
11
-
12
- if atr then Bones::Debug.show_attr(PROJ, atr)
13
- else Bones::Debug.show PROJ end
14
- end
15
-
16
- end # namespace :bones
17
-
18
- end # HAVE_BONES
19
-
20
- # EOF
@@ -1,201 +0,0 @@
1
-
2
- require 'find'
3
- require 'rake/packagetask'
4
- require 'rubygems/user_interaction'
5
- require 'rubygems/builder'
6
-
7
- module Bones
8
- class GemPackageTask < Rake::PackageTask
9
- # Ruby GEM spec containing the metadata for this package. The
10
- # name, version and package_files are automatically determined
11
- # from the GEM spec and don't need to be explicitly provided.
12
- #
13
- attr_accessor :gem_spec
14
-
15
- # Tasks from the Bones gem directory
16
- attr_reader :bones_files
17
-
18
- # Create a GEM Package task library. Automatically define the gem
19
- # if a block is given. If no block is supplied, then +define+
20
- # needs to be called to define the task.
21
- #
22
- def initialize(gem_spec)
23
- init(gem_spec)
24
- yield self if block_given?
25
- define if block_given?
26
- end
27
-
28
- # Initialization tasks without the "yield self" or define
29
- # operations.
30
- #
31
- def init(gem)
32
- super(gem.name, gem.version)
33
- @gem_spec = gem
34
- @package_files += gem_spec.files if gem_spec.files
35
- @bones_files = []
36
-
37
- local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
- if !test(?e, local_setup)
39
- Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
- end
41
- end
42
-
43
- # Create the Rake tasks and actions specified by this
44
- # GemPackageTask. (+define+ is automatically called if a block is
45
- # given to +new+).
46
- #
47
- def define
48
- super
49
- task :prereqs
50
- task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
51
- file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
52
- when_writing("Creating GEM") {
53
- chdir(package_dir_path) do
54
- Gem::Builder.new(gem_spec).build
55
- verbose(true) {
56
- mv gem_file, "../#{gem_file}"
57
- }
58
- end
59
- }
60
- end
61
-
62
- file package_dir_path => bones_files do
63
- mkdir_p package_dir rescue nil
64
-
65
- gem_spec.files = (gem_spec.files +
66
- bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
67
-
68
- bones_files.each do |fn|
69
- base_fn = File.join('tasks', File.basename(fn))
70
- f = File.join(package_dir_path, base_fn)
71
- fdir = File.dirname(f)
72
- mkdir_p(fdir) if !File.exist?(fdir)
73
- if File.directory?(fn)
74
- mkdir_p(f)
75
- else
76
- raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
77
- safe_ln(fn, f)
78
- end
79
- end
80
- end
81
- end
82
-
83
- def gem_file
84
- if @gem_spec.platform == Gem::Platform::RUBY
85
- "#{package_name}.gem"
86
- else
87
- "#{package_name}-#{@gem_spec.platform}.gem"
88
- end
89
- end
90
- end # class GemPackageTask
91
- end # module Bones
92
-
93
- namespace :gem do
94
-
95
- PROJ.gem._spec = Gem::Specification.new do |s|
96
- s.name = PROJ.name
97
- s.version = PROJ.version
98
- s.summary = PROJ.summary
99
- s.authors = Array(PROJ.authors)
100
- s.email = PROJ.email
101
- s.homepage = Array(PROJ.url).first
102
- s.rubyforge_project = PROJ.rubyforge.name
103
-
104
- s.description = PROJ.description
105
-
106
- PROJ.gem.dependencies.each do |dep|
107
- s.add_dependency(*dep)
108
- end
109
-
110
- PROJ.gem.development_dependencies.each do |dep|
111
- s.add_development_dependency(*dep)
112
- end
113
-
114
- s.files = PROJ.gem.files
115
- s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
116
- s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
117
-
118
- s.bindir = 'bin'
119
- dirs = Dir["{#{PROJ.libs.join(',')}}"]
120
- s.require_paths = dirs unless dirs.empty?
121
-
122
- incl = Regexp.new(PROJ.rdoc.include.join('|'))
123
- excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
124
- excl = Regexp.new(excl.join('|'))
125
- rdoc_files = PROJ.gem.files.find_all do |fn|
126
- case fn
127
- when excl; false
128
- when incl; true
129
- else false end
130
- end
131
- s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
132
- s.extra_rdoc_files = rdoc_files
133
- s.has_rdoc = true
134
-
135
- if test ?f, PROJ.test.file
136
- s.test_file = PROJ.test.file
137
- else
138
- s.test_files = PROJ.test.files.to_a
139
- end
140
-
141
- # Do any extra stuff the user wants
142
- PROJ.gem.extras.each do |msg, val|
143
- case val
144
- when Proc
145
- val.call(s.send(msg))
146
- else
147
- s.send "#{msg}=", val
148
- end
149
- end
150
- end # Gem::Specification.new
151
-
152
- Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
153
- pkg.need_tar = PROJ.gem.need_tar
154
- pkg.need_zip = PROJ.gem.need_zip
155
- end
156
-
157
- desc 'Show information about the gem'
158
- task :debug => 'gem:prereqs' do
159
- puts PROJ.gem._spec.to_ruby
160
- end
161
-
162
- desc 'Write the gemspec '
163
- task :spec => 'gem:prereqs' do
164
- File.open("#{PROJ.name}.gemspec", 'w') do |f|
165
- f.write PROJ.gem._spec.to_ruby
166
- end
167
- end
168
-
169
- desc 'Install the gem'
170
- task :install => [:clobber, 'gem:package'] do
171
- sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
172
-
173
- # use this version of the command for rubygems > 1.0.0
174
- #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
175
- end
176
-
177
- desc 'Uninstall the gem'
178
- task :uninstall do
179
- installed_list = Gem.source_index.find_name(PROJ.name)
180
- if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
181
- sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
182
- end
183
- end
184
-
185
- desc 'Reinstall the gem'
186
- task :reinstall => [:uninstall, :install]
187
-
188
- desc 'Cleanup the gem'
189
- task :cleanup do
190
- sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
191
- end
192
- end # namespace :gem
193
-
194
-
195
- desc 'Alias to gem:package'
196
- task :gem => 'gem:package'
197
-
198
- task :clobber => 'gem:clobber_package'
199
- remove_desc_for_task 'gem:clobber_package'
200
-
201
- # EOF