nitro 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>