manveru-ramaze 2008.12 → 2009.01

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # General Apache options
2
+ Options +FollowSymLinks +ExecCGI
3
+ AddHandler cgi-script cgi rb
4
+ <IfModule mod_fastcgi.c>
5
+ AddHandler fastcgi-script fcgi
6
+ </IfModule>
7
+ <IfModule mod_fcgid.c>
8
+ AddHandler fcgid-script fcgi
9
+ </IfModule>
10
+
11
+ # Redirect all requests not available on the filesystem to Ramaze.
12
+
13
+ RewriteEngine On
14
+ RewriteCond %{REQUEST_FILENAME} !-f
15
+ RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
16
+
17
+ # In case Ramaze experiences terminal errors.
18
+ # Instead of displaying this message you can supply a
19
+ # file here which will be rendered instead.
20
+ #
21
+ # Example:
22
+ # ErrorDocument 500 /500.html
23
+
24
+ ErrorDocument 500 "<h2>Application error</h2>Ramaze failed to start properly"
@@ -49,8 +49,8 @@ module Ramaze
49
49
  # true.
50
50
 
51
51
  def cached_render
52
- if Global.file_cache
53
- cached_render_file
52
+ if cache_root = Global.file_cache
53
+ cached_render_file(cache_root)
54
54
  else
55
55
  cached_render_memory
56
56
  end
@@ -59,12 +59,13 @@ module Ramaze
59
59
  # Uses files in the Global.public_root to provide a static ressource on
60
60
  # next request and returns the rendered action
61
61
 
62
- def cached_render_file
62
+ def cached_render_file(cache_root)
63
63
  rendered = uncached_render
64
64
 
65
- global_epath = Global.public_root/self.controller.mapping/extended_path
65
+ cr = cache_root.respond_to?(:to_str) ? cache_root.to_str : Global.public_root
66
+ global_epath = File.join(cr, self.controller.mapping, extended_path)
66
67
  FileUtils.mkdir_p(File.dirname(global_epath))
67
- File.open(global_epath, 'w+') {|fp| fp.print(rendered) }
68
+ File.open(global_epath, 'w+'){|fp| fp.print(rendered) }
68
69
 
69
70
  rendered
70
71
  end
@@ -16,7 +16,7 @@ module Ramaze
16
16
  # instead, in either case with path as argument.
17
17
 
18
18
  def resolve(path, routed = false)
19
- @routed = routed
19
+ Thread.current[:routed] = routed
20
20
 
21
21
  FILTER.each do |filter|
22
22
  answer = if filter.respond_to?(:call)
@@ -90,7 +90,7 @@ module Ramaze
90
90
  end
91
91
  end
92
92
 
93
- if !@routed and new_path = Route.resolve(path)
93
+ if !Thread.current[:routed] and new_path = Route.resolve(path)
94
94
  Log.dev("Routing from `#{path}' to `#{new_path}'")
95
95
  return resolve(new_path, true)
96
96
  end
@@ -196,9 +196,9 @@ module Ramaze
196
196
  # Example:
197
197
  # request.params
198
198
  # # => {'name' => 'jason', 'age' => '45', 'job' => 'lumberjack'}
199
- # request.sub('name')
199
+ # request.subset('name')
200
200
  # # => {'name' => 'jason'}
201
- # request.sub(:name, :job)
201
+ # request.subset(:name, :job)
202
202
  # # => {'name' => 'jason', 'job' => 'lumberjack'}
203
203
 
204
204
  def subset(*keys)
@@ -0,0 +1,43 @@
1
+ require 'benchmark'
2
+
3
+ module Ramaze
4
+ module Helper
5
+
6
+ # Little helper to give you a hand when benching parts of actions
7
+
8
+ module Bench
9
+
10
+ # Will first run an empty loop to determine the overhead it imposes, then
11
+ # goes on to yield your block +iterations+ times.
12
+ #
13
+ # The last yielded return value will be returned upon completion of the
14
+ # benchmark and the result of the benchmark itself will be sent to
15
+ # Log.info
16
+ #
17
+ # Example:
18
+ #
19
+ # class MainController < Ramaze::Controller
20
+ # def index
21
+ # @users = bench{ User.all }
22
+ # @tags = bench{ Article.tags }
23
+ # end
24
+ # end
25
+ #
26
+ # This will show something like following in your log:
27
+ # [..] INFO Bench ./start.rb:3:in `index': 0.121163845062256
28
+ # [..] INFO Bench ./start.rb:4:in `index': 2.234987235098341
29
+ #
30
+ # So now we know that the Article.tags call takes the most time and
31
+ # should be improved.
32
+
33
+ def bench(iterations = 1)
34
+ result = nil
35
+ from = caller[0]
36
+ delta = Benchmark.realtime{ iterations.times{ nil }}
37
+ taken = Benchmark.realtime{ iterations.times{ result = yield }}
38
+ Log.info "Bench #{from}: #{taken - delta}"
39
+ return result
40
+ end
41
+ end
42
+ end
43
+ end
@@ -15,7 +15,7 @@ module Ramaze
15
15
  def markaby(ivs = {}, helpers = nil, &block)
16
16
  builder = ::Markaby::Builder
17
17
  builder.extend(Ramaze::Helper::Methods)
18
- builder.send(:helper, :link)
18
+ builder.send(:helper, :redirect, :link, :sendfile, :flash, :cgi, :partial)
19
19
 
20
20
  iv_hash = {}
21
21
  instance_variables.each do |iv|
@@ -165,7 +165,7 @@ module Ramaze
165
165
  text = h(text.to_s)
166
166
 
167
167
  params = Ramaze::Request.current.params.merge(@var.to_s => n)
168
- name = Ramaze::Request.current.request_path
168
+ name = Ramaze::Request.current.path_info
169
169
  hash[:href] = R(name, params)
170
170
 
171
171
  g.a(hash){ text }
data/lib/ramaze/option.rb CHANGED
@@ -78,7 +78,7 @@ module Ramaze
78
78
  o "Turn on customized error pages. Use Rack::ShowException otherwise.",
79
79
  :error_page, true, :cli => true
80
80
 
81
- o "Caching actions to the filesystem in Global.public_root",
81
+ o "Cache actions to filesystem, uses String as directory name or Global.public_root if other truism",
82
82
  :file_cache, false, :cli => false
83
83
 
84
84
  o "Specify what IP Ramaze will respond to - 0.0.0.0 for all",
@@ -1,57 +1,62 @@
1
1
  module Ramaze
2
2
  class Reloader
3
+ # TODO:
4
+ # * There seems to be a problem somewhere that I couldn't identify yet, a
5
+ # file has to be modified twice initially to make it show up as
6
+ # modified here, subsequent changes work just fine.
7
+ # The only workaround I could find right now would be to read/write
8
+ # every single file, but that would be unexpected, irresponsible, and
9
+ # error-prone.
10
+ #
11
+ # NOTE:
12
+ # * I have changed from using a Mutex to using a Queue, which uses a
13
+ # Mutex internally.
14
+
3
15
  class WatchInotify
4
16
  POLL_INTERVAL = 2 # seconds
17
+ NOTIFY_MASK = RInotify::MODIFY | RInotify::IN_ONESHOT
5
18
 
6
19
  def initialize
7
20
  @watcher = RInotify.new
8
- @changed = []
9
- @mutex = Mutex.new
21
+ @changed = Queue.new
10
22
  @watcher_thread = start_watcher
11
23
  end
12
24
 
13
25
  def call(cooldown)
14
- yield if @changed.any?
26
+ yield
15
27
  end
16
28
 
17
29
  # TODO: define a finalizer to cleanup? -- reloader never calls #close
18
30
 
19
31
  def start_watcher
20
- Thread.new do
21
- loop do
22
- watcher_cycle
23
- sleep POLL_INTERVAL
24
- end
25
- end
32
+ Thread.new{ loop{ watcher_cycle }}
26
33
  end
27
34
 
35
+ # Not much work here, we just have to empty the event queue and push the
36
+ # descriptors for reloading on next request.
28
37
  def watcher_cycle
29
- return unless @watcher.wait_for_events(0)
30
- changed_descriptors = []
38
+ return unless @watcher.wait_for_events(POLL_INTERVAL)
31
39
 
32
40
  @watcher.each_event do |event|
33
- changed_descriptors << event.watch_descriptor
34
- end
35
-
36
- @mutex.synchronize do
37
- changed_descriptors.each do |descriptor|
38
- @changed << @watcher.watch_descriptors[descriptor]
39
- end
41
+ @changed.push(event.watch_descriptor)
40
42
  end
41
43
  end
42
44
 
43
45
  def watch(file)
44
- return false if @watcher.watch_descriptors.has_value?(file)
45
- return false unless File.exist?(file)
46
+ return if @watcher.watch_descriptors.has_value?(file)
47
+ return unless File.exist?(file)
46
48
 
47
- @mutex.synchronize{ @watcher.add_watch(file, RInotify::MODIFY) }
48
-
49
- true
49
+ @watcher.add_watch(file, NOTIFY_MASK)
50
+ rescue Errno::ENOENT
51
+ retry
50
52
  end
51
53
 
54
+ # FIXME:
55
+ # Seems like this won't work due to some bug in the rinotify library.
56
+ # Would be cool if someone could make a FFI version.
57
+
52
58
  def remove_watch(file)
53
- @mutex.synchronize{ @watcher.rm_watch(file) }
54
- true
59
+ @watcher.rm_watch(file)
55
60
  end
56
61
 
57
62
  def close
@@ -60,13 +65,20 @@ module Ramaze
60
65
  true
61
66
  end
62
67
 
68
+ # NOTE:
69
+ # We have to add the changed file again after we got a notification, I
70
+ # have no idea why, but using IN_ONESHOT should make sure that there is
71
+ # no memory leak in the C level even if we add a file again.
72
+ # There is a memory leak however in the watch_descriptors hash, since
73
+ # rinotify won't synchronize the contents properly and will only add to
74
+ # the hash, so we have to clean up ourselves.
63
75
  def changed_files
64
- @mutex.synchronize do
65
- @tmp = @changed
66
- @changed = []
76
+ until @changed.empty?
77
+ descriptor = @changed.shift
78
+ file = @watcher.watch_descriptors.delete(descriptor)
79
+ watch(file)
80
+ yield(file)
67
81
  end
68
- @tmp.uniq!
69
- @tmp
70
82
  end
71
83
  end
72
84
  end
@@ -38,18 +38,14 @@ module Ramaze
38
38
 
39
39
  # return files changed since last call
40
40
  def changed_files
41
- changed = []
42
-
43
41
  @files.each do |file, stat|
44
42
  if new_stat = safe_stat(file)
45
43
  if new_stat.mtime > stat.mtime
46
- changed << file
47
44
  @files[file] = new_stat
45
+ yield(file)
48
46
  end
49
47
  end
50
48
  end
51
-
52
- changed
53
49
  end
54
50
 
55
51
  def safe_stat(file)
@@ -88,7 +88,7 @@ module Ramaze
88
88
  before_cycle
89
89
 
90
90
  rotation{|file| @watcher.watch(file) }
91
- @watcher.changed_files.each{|f| safe_load(f) }
91
+ @watcher.changed_files{|f| safe_load(f) }
92
92
 
93
93
  after_cycle
94
94
  end
@@ -2,5 +2,5 @@
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
4
  module Ramaze
5
- VERSION = "2008.10"
5
+ VERSION = "2009.01"
6
6
  end