nitro 0.27.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG +276 -0
  2. data/ProjectInfo +4 -4
  3. data/README +9 -1
  4. data/Rakefile +1 -1
  5. data/doc/AUTHORS +30 -17
  6. data/doc/RELEASES +110 -23
  7. data/lib/glue/sweeper.rb +1 -1
  8. data/lib/glue/webfile.rb +1 -1
  9. data/lib/nitro.rb +1 -1
  10. data/lib/nitro/adapter/acgi.rb +5 -1
  11. data/lib/nitro/adapter/cgi.rb +4 -0
  12. data/lib/nitro/adapter/fastcgi.rb +12 -1
  13. data/lib/nitro/adapter/mongrel.rb +219 -0
  14. data/lib/nitro/adapter/scgi.rb +62 -69
  15. data/lib/nitro/caching.rb +6 -5
  16. data/lib/nitro/caching/actions.rb +14 -8
  17. data/lib/nitro/caching/fragments.rb +32 -17
  18. data/lib/nitro/caching/output.rb +10 -2
  19. data/lib/nitro/cgi.rb +7 -3
  20. data/lib/nitro/cgi/stream.rb +1 -3
  21. data/lib/nitro/compiler.rb +5 -4
  22. data/lib/nitro/compiler/errors.rb +1 -1
  23. data/lib/nitro/compiler/morphing.rb +2 -2
  24. data/lib/nitro/compiler/script.rb +1 -1
  25. data/lib/nitro/context.rb +8 -2
  26. data/lib/nitro/controller.rb +1 -1
  27. data/lib/nitro/dispatcher.rb +0 -2
  28. data/lib/nitro/element.rb +5 -5
  29. data/lib/nitro/flash.rb +1 -1
  30. data/lib/nitro/helper.rb +2 -2
  31. data/lib/nitro/helper/form.rb +1 -1
  32. data/lib/nitro/helper/form/controls.rb +2 -1
  33. data/lib/nitro/helper/javascript.rb +1 -1
  34. data/lib/nitro/helper/javascript/morphing.rb +1 -1
  35. data/lib/nitro/helper/layout.rb +1 -1
  36. data/lib/nitro/helper/pager.rb +7 -3
  37. data/lib/nitro/helper/rss.rb +1 -1
  38. data/lib/nitro/render.rb +1 -1
  39. data/lib/nitro/scaffolding.rb +26 -4
  40. data/lib/nitro/server/drb.rb +106 -0
  41. data/lib/nitro/server/runner.rb +23 -2
  42. data/lib/nitro/session.rb +33 -16
  43. data/lib/nitro/session/drb.rb +6 -20
  44. data/lib/nitro/session/file.rb +4 -49
  45. data/lib/nitro/session/memory.rb +16 -0
  46. data/lib/nitro/session/og.rb +4 -46
  47. data/src/part/admin/controller.rb +2 -3
  48. data/src/part/admin/template/index.xhtml +1 -1
  49. data/test/nitro/tc_cgi.rb +72 -3
  50. data/test/nitro/tc_render.rb +1 -1
  51. data/test/nitro/tc_session.rb +16 -15
  52. metadata +12 -14
  53. data/lib/nitro/caching/invalidation.rb +0 -25
  54. data/lib/nitro/caching/stores.rb +0 -94
  55. data/lib/nitro/helper/form/test.xhtml +0 -0
  56. data/lib/nitro/session/drbserver.rb +0 -84
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'drb'
4
+ require 'optparse'
5
+
6
+ require 'facet/synchash'
7
+
8
+ require 'glue'
9
+ require 'glue/cache/memory'
10
+
11
+ module Nitro
12
+
13
+ # A Drb server, typically used to host the application caches
14
+ # (sessions, application scoped variables, og cache, fragment
15
+ # cache, etc).
16
+ #
17
+ # === Example
18
+ #
19
+ # require 'nitro/server/drb
20
+ #
21
+ # class MyDrbServer < Nitro::DrbServer
22
+ # def setup_drb_objects
23
+ # ...
24
+ # end
25
+ # end
26
+ #
27
+ # MyDrbServer.start
28
+ #--
29
+ # FIXME: should probably move to another directory (scripts?)
30
+ # TODO: Add some debuging support (overload synchash).
31
+ # TODO: Implement MemcacheServer.
32
+ # TODO: Better start/stop functionality.
33
+ #++
34
+
35
+ class DrbServer
36
+
37
+ # Parse the command line arguments.
38
+
39
+ def parse_options
40
+ parser = OptionParser.new do |opts|
41
+ opts.banner = "Usage: #$0 [options]"
42
+ opts.separator ''
43
+ opts.separator 'Specific options:'
44
+
45
+ opts.on('-D', '--debug', 'Run in debug mode.') do |p|
46
+ @debug = true
47
+ end
48
+
49
+ opts.on('-d', '--daemon', 'Run as daemon.') do |p|
50
+ @daemon = true
51
+ end
52
+
53
+ opts.on_tail('-h', '--help', 'Show this message.') do
54
+ puts opts
55
+ exit
56
+ end
57
+ end
58
+
59
+ begin
60
+ parser.parse!(ARGV)
61
+ rescue OptionParser::InvalidOption
62
+ puts 'Invalid option, pass the --help parameter to get help!'
63
+ exit
64
+ end
65
+ end
66
+
67
+ # Override in your application to setup your custom objects.
68
+ # The default implementation only creates a session store.
69
+
70
+ def setup_drb_objects
71
+ require 'nitro/session'
72
+ @session_cache = SyncHash.new
73
+ DRb.start_service("druby://#{Session.cache_address}:#{Session.cache_port}", @session_cache)
74
+ puts "Drb session cache at druby://#{Session.cache_address}:#{Session.cache_port}."
75
+ end
76
+
77
+ def setup_drb
78
+ setup_drb_objects()
79
+ DRb.thread.join
80
+ end
81
+
82
+ # Start the DRb server.
83
+
84
+ def start
85
+ parse_options
86
+ if @daemon
87
+ require 'daemons/daemonize'
88
+ Daemonize.daemonize()
89
+ end
90
+ setup_drb()
91
+ end
92
+ alias_method :start!, :start
93
+
94
+ # A helper method to start the DRb server.
95
+
96
+ def self.start
97
+ self.new.start
98
+ end
99
+
100
+ end
101
+
102
+ DrbServer.start if __FILE__ == $0
103
+
104
+ end
105
+
106
+ # * George Moschovitis <gm@navel.gr>
@@ -3,7 +3,7 @@ require 'optparse'
3
3
  require 'glue/configuration'
4
4
  require 'nitro/compiler'
5
5
 
6
- #require 'nano/kernel/autoreload'
6
+ #require 'facet/kernel/autoreload'
7
7
  require 'glue/autoreload'
8
8
 
9
9
  module Nitro
@@ -128,6 +128,11 @@ class Runner
128
128
  @server = :webrick
129
129
  end
130
130
 
131
+ opts.on('-m', '--mongrel', 'Use the Mongrel Ruby server.') do
132
+ @server = :mongrel
133
+ # FIXME: handle logging.
134
+ end
135
+
131
136
  opts.on('-l', '--lhttpd', 'Use a lighttpd server (FastCGI).') do
132
137
  @server = :lhttpd
133
138
  Logger.set(Logger.new('log/app.log'))
@@ -147,6 +152,10 @@ class Runner
147
152
  @server = :cgi
148
153
  Logger.set(Logger.new('log/app.log'))
149
154
  end
155
+
156
+ opts.on('--scgi', 'Use the generic SCGI adapter') do
157
+ @server = :scgi
158
+ end
150
159
 
151
160
  opts.on('-C', '--console', 'Start a console attached to an instance of the application.') do
152
161
  if RUBY_PLATFORM =~ /mswin32/
@@ -307,10 +316,17 @@ class Runner
307
316
  case @server
308
317
  when :webrick
309
318
  require 'nitro/adapter/webrick'
310
- puts "==> Listening at #{server.address}:#{server.port}."
319
+ puts "==> Listening at #{server.address}:#{server.port}. [WEBRICK]"
311
320
  puts "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
312
321
  Webrick.start(server)
313
322
 
323
+ when :mongrel
324
+ require 'nitro/adapter/mongrel'
325
+ puts "==> Listening at #{server.address}:#{server.port}. [MONGREL]"
326
+ puts "==> Press Ctrl-C to shutdown; Run with --help for options.\n\n"
327
+
328
+ Mongrel.start(server)
329
+
314
330
  when :lhttpd
315
331
  require 'nitro/adapter/fastcgi'
316
332
  puts "==> Launching lighttpd (FastCGI)."
@@ -329,6 +345,11 @@ class Runner
329
345
  when :cgi
330
346
  require 'nitro/adapter/cgi'
331
347
  puts "==> Using standard CGI. Please look into using Fast/Scgi"
348
+
349
+
350
+ when :scgi
351
+ require 'nitro/adapter/scgi'
352
+ SCGI.start(server)
332
353
 
333
354
  when :acgi
334
355
  require 'nitro/adapter/acgi'
@@ -1,9 +1,10 @@
1
1
  require 'md5'
2
2
  require 'webrick'
3
3
 
4
- require 'mega/synchash'
5
- require 'mega/time_in_english'
4
+ require 'facet/synchash'
5
+ require 'facet/times'
6
6
 
7
+ require 'glue'
7
8
  require 'glue/attribute'
8
9
  require 'glue/configuration'
9
10
  require 'glue/logger'
@@ -24,7 +25,10 @@ module Nitro
24
25
  # The session should be persistable to survive server
25
26
  # shutdowns.
26
27
  #
27
- # TODO rehash of the session cookie
28
+ #--
29
+ # TODO: rehash of the session cookie
30
+ # TODO: store -> cache, reimplement helpers.
31
+ #++
28
32
 
29
33
  class Session < Hash
30
34
  include Expirable
@@ -45,15 +49,23 @@ class Session < Hash
45
49
  # garbage collection after this time passes.
46
50
 
47
51
  setting :keepalive, :default => 30.minutes, :doc => 'The session keepalive time'
52
+
53
+ # The address of the Session cache / store (if distibuted).
54
+
55
+ setting :cache_address, :default => '127.0.0.1', :doc => 'The address of the Session cache'
48
56
 
49
- # The sessions store.
57
+ # The port of the Session DRb cache / store (if distributed).
58
+
59
+ setting :cache_port, :default => 9069, :doc => 'The port of the Session cache'
50
60
 
51
- cattr_accessor :store
61
+ # The sessions cache (store).
62
+
63
+ cattr_accessor :cache
52
64
 
53
65
  class << self
54
66
 
55
- # Set the session store. The following options are
56
- # available:
67
+ # Set the session cache. The generalized caching system in
68
+ # Glue is used. The following options are available:
57
69
  #
58
70
  # * :memory [default]
59
71
  # * :drb
@@ -61,20 +73,22 @@ class Session < Hash
61
73
  # * :file (not safe yet with multiple process as in fastcgi)
62
74
  # * :memcached (not available yet)
63
75
 
64
- def store_type=(store_type)
76
+ def cache_type=(cache_type)
65
77
  # gmosx: RDoc friendly.
66
- require 'nitro/session/' + store_type.to_s
78
+ require 'nitro/session/' + cache_type.to_s
67
79
  end
68
- alias_method :set_store_type, :store_type=
80
+ alias_method :set_cache_type, :cache_type=
81
+ alias_method :store_type=, :cache_type=
82
+ alias_method :set_store_type, :cache_type=
69
83
 
70
- # Lookup the session in the store by using the session
84
+ # Lookup the session in the cache by using the session
71
85
  # cookie value as a key. If the session does not exist
72
- # creates a new session, inserts it in the store and
86
+ # creates a new session, inserts it in the cache and
73
87
  # appends a new session cookie in the response.
74
88
 
75
89
  def lookup(context)
76
90
  if session_id = context.cookies[Session.cookie_name]
77
- session = Session.store[session_id]
91
+ session = Session.cache[session_id]
78
92
  end
79
93
 
80
94
  unless session
@@ -85,7 +99,7 @@ class Session < Hash
85
99
  cookie.expires = Time.now + Session.keepalive
86
100
  end
87
101
  context.add_cookie(cookie)
88
- Session.store[session.session_id] = session
102
+ Session.cache[session.session_id] = session
89
103
  else
90
104
  # Access ('touch') the existing session.
91
105
  session.touch!
@@ -101,7 +115,7 @@ class Session < Hash
101
115
  # gmosx: should be placed here.
102
116
  #++
103
117
 
104
- set_store_type(:memory)
118
+ set_cache_type(:memory)
105
119
 
106
120
  # The unique id of this session.
107
121
 
@@ -123,7 +137,7 @@ class Session < Hash
123
137
  # in distributed and/or multiprocess setups.
124
138
 
125
139
  def sync
126
- Session.store[@session_id] = self
140
+ Session.cache[@session_id] = self
127
141
  end
128
142
  alias_method :restore, :sync
129
143
 
@@ -139,6 +153,9 @@ protected
139
153
  # increasing function like time is appropriate.
140
154
  # Random may produce equal ids? add a prefix
141
155
  # (SALT) to stop hackers from creating session_ids.
156
+ #--
157
+ # THINK: Is MD5 slow???
158
+ #++
142
159
 
143
160
  def create_id
144
161
  now = Time.now
@@ -1,28 +1,14 @@
1
- require 'drb'
2
-
3
- require 'glue/configuration'
1
+ require 'glue/cache/drb'
4
2
  require 'nitro/session'
5
3
 
6
- Logger.debug 'Using Drb sessions.'
7
-
8
4
  module Nitro
9
5
 
10
- class Session
11
-
12
- # The address of the Session DRb server.
13
-
14
- setting :drb_address, :default => '127.0.0.1', :doc => 'The address of the Session DRb server'
15
-
16
- # The port of the Session DRb server.
17
-
18
- setting :drb_port, :default => 9069, :doc => 'The port of the Session DRb server'
19
-
20
- end
6
+ Logger.debug "Using DRb sessions at #{Session.cache_address}:#{Session.cache_port}."
21
7
 
22
- Session.store = DRbObject.new(
23
- nil,
24
- "druby://#{Session.drb_address}:#{Session.drb_port}"
25
- )
8
+ Session.cache = DrbCache.new(
9
+ :address => Session.cache_address,
10
+ :port => Session.cache_port
11
+ )
26
12
 
27
13
  end
28
14
 
@@ -1,59 +1,14 @@
1
- #!/usr/bin/env ruby
2
-
1
+ require 'glue/cache/file'
3
2
  require 'nitro/session'
4
- require 'fileutils'
5
- require 'tmpdir'
6
3
 
7
4
  module Nitro
8
5
 
9
- # A Session manager that persists sessions on disk.
10
- #
11
- # TODO: safe locking of files, because Nitro can be multiprocess
12
-
13
- class FileSessionStore
14
- setting :path, :default => "#{Dir.tmpdir}/nitro_session_#{Session.cookie_name}", :doc => 'The directory to store file session'
15
-
16
- def initialize
17
- @path = FileSessionStore.path
18
- FileUtils.mkdir_p(@path)
19
- end
20
-
21
- def []=(k,v)
22
- fn = File.join(@path, k.to_s)
23
- encode_file(fn, v)
24
- end
25
-
26
- def [](k)
27
- fn = File.join(@path, k.to_s)
28
- return nil unless File.exists?(fn)
29
- decode_file(fn)
30
- end
31
-
32
- def gc!
33
- now = Time.now
34
- all.each do |fn|
35
- expire_time = File.stat(fn).atime + Session.keepalive
36
- File.delete(fn) if now > expire_time
37
- end
38
- end
39
-
40
- def all
41
- Dir.glob( File.join(@path, '*' ) )
42
- end
43
-
44
- private
45
-
46
- def decode_file(fn)
47
- Marshal.load( File.read(fn) )
48
- end
6
+ # A Session manager that persists sessions on disk.
49
7
 
50
- def encode_file(fn, value)
51
- File.open(fn, "w") { |f| f.write(Marshal.dump(value)) }
52
- end
8
+ Logger.debug "Using File sessions."
53
9
 
54
- end
10
+ Session.cache = FileCache.new("session_#{Session.cookie_name}", Session.keepalive)
55
11
 
56
- Session.store = FileSessionStore.new
57
12
  end
58
13
 
59
14
  # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
@@ -1,3 +1,18 @@
1
+ require 'glue/cache/memory'
2
+ require 'nitro/session'
3
+
4
+ module Nitro
5
+
6
+ Logger.debug "Using Memory sessions."
7
+
8
+ Session.cache = MemoryCache.new
9
+
10
+ end
11
+
12
+ # * George Moschovitis <gm@navel.gr>
13
+
14
+ =begin
15
+
1
16
  module Nitro
2
17
 
3
18
  class MemorySessionStore < SyncHash
@@ -18,3 +33,4 @@ module Nitro
18
33
  end
19
34
 
20
35
  # * George Moschovitis <gm@navel.gr>
36
+ =end
@@ -1,56 +1,14 @@
1
- require 'og'
1
+ require 'glue/cache/og'
2
2
  require 'nitro/session'
3
- require 'base64'
4
3
 
5
4
  module Nitro
6
5
 
7
- class OgSession < Session
8
- prop_accessor :sessionid, String
9
- prop_accessor :expires, Time
10
- prop_accessor :content
11
- end
6
+ # A Session manager that persists sessions on an Og store.
12
7
 
13
- # A Session manager that persists sessions on an Og store.
14
-
15
- class OgSessionStore
8
+ Logger.debug "Using Og sessions."
16
9
 
17
- def []=(k,v)
18
- unless s = OgSession.find_by_sessionid(k.to_s)
19
- s = OgSession.new
20
- s.sessionid = k.to_s
21
- end
22
- #s.content = v.to_yaml
23
- s.content = encode(v)
24
- s.save
25
- end
10
+ Session.cache = OgCache.new("session_#{Session.cookie_name}", Session.keepalive)
26
11
 
27
- def [](k)
28
- s = OgSession.find_by_sessionid(k.to_s) and decode(s.content)
29
- end
30
-
31
- def gc!
32
- now = Og.manager.store.quote(Time.now)
33
- OgSession.find(:condition => "expires < #{now}").each {|s| s.delete }
34
- end
35
-
36
- def all
37
- OgSession.all
38
- end
39
-
40
- private
41
-
42
- def encode(c)
43
- Base64.encode64(Marshal.dump(c))
44
- end
45
-
46
- def decode(c)
47
- Marshal::load(Base64.decode64(c))
48
- #s.content = YAML::load(s.content)
49
- end
50
-
51
- end
52
-
53
- Session.store = OgSessionStore.new
54
12
  end
55
13
 
56
14
  # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>