knjappserver 0.0.29 → 0.0.30

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.
data/Gemfile CHANGED
@@ -9,6 +9,7 @@ gem "mail"
9
9
  gem "tsafe"
10
10
  gem "datet"
11
11
  gem "http2"
12
+ gem "php4r"
12
13
 
13
14
  # Add dependencies to develop your gem here.
14
15
  # Include everything needed to run rake, tests, features, etc.
@@ -22,6 +22,9 @@ GEM
22
22
  mime-types (~> 1.16)
23
23
  treetop (~> 1.4.8)
24
24
  mime-types (1.19)
25
+ php4r (0.0.0)
26
+ datet
27
+ http2
25
28
  polyglot (0.3.3)
26
29
  rake (0.9.2.2)
27
30
  rspec (2.3.0)
@@ -51,6 +54,7 @@ DEPENDENCIES
51
54
  json
52
55
  knjrbfw
53
56
  mail
57
+ php4r
54
58
  rspec (~> 2.3.0)
55
59
  sqlite3
56
60
  tsafe
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.29
1
+ 0.0.30
@@ -50,7 +50,6 @@ if !options[:command]
50
50
  end
51
51
 
52
52
  require "#{options[:knjrbfw_path]}knjrbfw"
53
- require "knj/autoload"
54
53
 
55
54
  tmpdir = "#{Knj::Os.tmpdir}/knjappserver"
56
55
  tmppath = "#{tmpdir}/run_#{options[:title]}"
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{knjappserver}
8
- s.version = "0.0.29"
8
+ s.version = "0.0.30"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-07-20}
12
+ s.date = %q{2012-08-03}
13
13
  s.description = %q{Which supports a lot of undocumented stuff.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.executables = ["check_running.rb", "knjappserver_start.rb"]
@@ -73,6 +73,7 @@ Gem::Specification.new do |s|
73
73
  "lib/pages/benchmark_threadded_content.rhtml",
74
74
  "lib/pages/debug_database_connections.rhtml",
75
75
  "lib/pages/debug_http_sessions.rhtml",
76
+ "lib/pages/debug_memory_usage.rhtml",
76
77
  "lib/pages/error_notfound.rhtml",
77
78
  "lib/pages/logs_latest.rhtml",
78
79
  "lib/pages/logs_show.rhtml",
@@ -106,6 +107,7 @@ Gem::Specification.new do |s|
106
107
  s.add_runtime_dependency(%q<tsafe>, [">= 0"])
107
108
  s.add_runtime_dependency(%q<datet>, [">= 0"])
108
109
  s.add_runtime_dependency(%q<http2>, [">= 0"])
110
+ s.add_runtime_dependency(%q<php4r>, [">= 0"])
109
111
  s.add_development_dependency(%q<json>, [">= 0"])
110
112
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
111
113
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
@@ -118,6 +120,7 @@ Gem::Specification.new do |s|
118
120
  s.add_dependency(%q<tsafe>, [">= 0"])
119
121
  s.add_dependency(%q<datet>, [">= 0"])
120
122
  s.add_dependency(%q<http2>, [">= 0"])
123
+ s.add_dependency(%q<php4r>, [">= 0"])
121
124
  s.add_dependency(%q<json>, [">= 0"])
122
125
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
123
126
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -131,6 +134,7 @@ Gem::Specification.new do |s|
131
134
  s.add_dependency(%q<tsafe>, [">= 0"])
132
135
  s.add_dependency(%q<datet>, [">= 0"])
133
136
  s.add_dependency(%q<http2>, [">= 0"])
137
+ s.add_dependency(%q<php4r>, [">= 0"])
134
138
  s.add_dependency(%q<json>, [">= 0"])
135
139
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
136
140
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -7,10 +7,7 @@ class Knjappserver::ERBHandler
7
7
  eruby = httpsess.eruby
8
8
 
9
9
  if !@connected.key?(eruby.__id__)
10
- eruby.connect("error") do |e|
11
- _kas.handle_error(e)
12
- end
13
-
10
+ eruby.connect("error", &self.method(:on_error))
14
11
  @connected[eruby.__id__] = true
15
12
  end
16
13
 
@@ -22,4 +19,9 @@ class Knjappserver::ERBHandler
22
19
 
23
20
  httpsess.resp.status = 500 if eruby.error
24
21
  end
22
+
23
+ #Handels the event when an error in the eruby-instance occurs.
24
+ def on_error(e)
25
+ _kas.handle_error(e)
26
+ end
25
27
  end
@@ -82,15 +82,21 @@ class Knjappserver::Httpserver
82
82
  @http_sessions << Knjappserver::Httpsession.new(self, socket)
83
83
  end
84
84
 
85
- def count_add
86
- @mutex_count.synchronize do
87
- @working_count += 1 if @working_count
88
- end
89
- end
90
-
91
- def count_remove
92
- @mutex_count.synchronize do
93
- @working_count -= 1 if @working_count
85
+ def count_block
86
+ begin
87
+ added = false
88
+ @mutex_count.synchronize do
89
+ @working_count += 1 if @working_count != nil
90
+ added = true
91
+ end
92
+
93
+ yield
94
+ ensure
95
+ @kas.served += 1 if @kas
96
+
97
+ @mutex_count.synchronize do
98
+ @working_count -= 1 if @working_count != nil and added
99
+ end
94
100
  end
95
101
  end
96
102
  end
@@ -23,7 +23,7 @@ class Knjappserver::Httpsession
23
23
 
24
24
  @eruby = Knj::Eruby.new(
25
25
  :cache_hash => @kas.eruby_cache,
26
- :binding_callback => self.method("create_binding")
26
+ :binding_callback => self.method(:create_binding)
27
27
  )
28
28
 
29
29
  #Set socket stuff.
@@ -49,92 +49,86 @@ class Knjappserver::Httpsession
49
49
 
50
50
  @resp = Knjappserver::Httpsession::Http_response.new(:socket => @socket)
51
51
  @handler = Knjappserver::Httpsession::Http_request.new(:kas => @kas, :httpsession => self)
52
-
53
- @cgroup = Knjappserver::Httpsession::Contentgroup.new(
54
- :socket => @socket,
55
- :kas => @kas,
56
- :resp => @resp,
57
- :httpsession => self
58
- )
52
+ @cgroup = Knjappserver::Httpsession::Contentgroup.new(:socket => @socket, :kas => @kas, :resp => @resp, :httpsession => self)
59
53
  @resp.cgroup = @cgroup
60
54
 
61
55
  Dir.chdir(@config[:doc_root])
62
56
  ObjectSpace.define_finalizer(self, self.class.method(:finalize).to_proc) if @debug
63
57
  STDOUT.print "New httpsession #{self.__id__} (total: #{@httpserver.http_sessions.count}).\n" if @debug
64
58
 
65
- @thread_request = Thread.new do
66
- Thread.current[:knjappserver] = {} if !Thread.current[:knjappserver]
67
-
68
- begin
69
- while @active
70
- begin
71
- @cgroup.reset
72
- @written_size = 0
73
- @size_send = @config[:size_send]
74
- @alert_sent = false
75
- @working = false
76
- break if @kas.should_restart
77
-
78
- STDOUT.print "#{__id__} - Waiting to parse from socket.\n" if @debug
79
-
80
- #Timeout on sockets is currently broken in JRuby.
81
- if RUBY_ENGINE == "jruby"
82
- @handler.socket_parse(@socket)
83
- else
84
- Timeout.timeout(1800) do
85
- @handler.socket_parse(@socket)
86
- end
87
- end
88
-
89
- STDOUT.print "#{__id__} - Done parsing from socket.\n" if @debug
90
-
91
- while @kas.paused? #Check if we should be waiting with executing the pending request.
92
- STDOUT.print "#{__id__} - Paused! (#{@kas.paused}) - sleeping.\n" if @debug
59
+ @thread_request = Thread.new(&self.method(:thread_request_run))
60
+ end
61
+
62
+ def thread_request_run
63
+ Thread.current[:knjappserver] = {} if !Thread.current[:knjappserver]
64
+ Thread.current[:type] = :httpsession
65
+
66
+ if @config.key?(:max_requests_working)
67
+ max_requests_working = @config[:max_requests_working].to_i
68
+ else
69
+ max_requests_working = false
70
+ end
71
+
72
+ begin
73
+ while @active
74
+ begin
75
+ @cgroup.reset
76
+ @written_size = 0
77
+ @size_send = @config[:size_send]
78
+ @alert_sent = false
79
+ @working = false
80
+ break if @kas.should_restart
81
+
82
+ STDOUT.print "#{__id__} - Waiting to parse from socket.\n" if @debug
83
+ Timeout.timeout(1800) do
84
+ @handler.socket_parse(@socket)
85
+ end
86
+
87
+ STDOUT.print "#{__id__} - Done parsing from socket.\n" if @debug
88
+
89
+ while @kas.paused? #Check if we should be waiting with executing the pending request.
90
+ STDOUT.print "#{__id__} - Paused! (#{@kas.paused}) - sleeping.\n" if @debug
91
+ sleep 0.1
92
+ end
93
+
94
+ break if @kas.should_restart
95
+
96
+ if max_requests_working and @httpserver
97
+ while @httpserver.working_count.to_i >= max_requests_working
98
+ STDOUT.print "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{max_requests_working}) - sleeping.\n" if @debug
93
99
  sleep 0.1
94
100
  end
95
-
96
- break if @kas.should_restart
97
-
98
- if @config.key?(:max_requests_working)
99
- while @httpserver and @config and @httpserver.working_count.to_i >= @config[:max_requests_working].to_i
100
- STDOUT.print "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{@config[:max_requests_working]}) - sleeping.\n" if @debug
101
- sleep 0.1
102
- end
103
- end
104
-
105
- #Reserve database connections.
106
- @kas.db_handler.get_and_register_thread if @kas.db_handler.opts[:threadsafe]
107
- @kas.ob.db.get_and_register_thread if @kas.ob.db.opts[:threadsafe]
108
-
109
- @httpserver.count_add
110
- @working = true
111
- STDOUT.print "#{__id__} - Serving.\n" if @debug
112
-
113
- begin
114
- self.serve
115
- ensure
116
- @httpserver.count_remove
117
- @kas.served += 1 if @kas
118
- @working = false
119
- end
120
- ensure
121
- STDOUT.print "#{__id__} - Closing request.\n" if @debug
122
- #Free reserved database-connections.
123
- @kas.db_handler.free_thread if @kas and @kas.db_handler.opts[:threadsafe]
124
- @kas.ob.db.free_thread if @kas and @kas.ob.db.opts[:threadsafe]
125
101
  end
102
+
103
+ #Reserve database connections.
104
+ @kas.db_handler.get_and_register_thread if @kas.db_handler.opts[:threadsafe]
105
+ @kas.ob.db.get_and_register_thread if @kas.ob.db.opts[:threadsafe]
106
+
107
+ @working = true
108
+ STDOUT.print "#{__id__} - Serving.\n" if @debug
109
+
110
+ @httpserver.count_block do
111
+ self.serve
112
+ end
113
+ ensure
114
+ STDOUT.print "#{__id__} - Closing request.\n" if @debug
115
+ @working = false
116
+
117
+ #Free reserved database-connections.
118
+ @kas.db_handler.free_thread if @kas and @kas.db_handler.opts[:threadsafe]
119
+ @kas.ob.db.free_thread if @kas and @kas.ob.db.opts[:threadsafe]
126
120
  end
127
- rescue Timeout::Error
128
- STDOUT.print "#{__id__} - Closing httpsession because of timeout.\n" if @debug
129
- rescue Errno::ECONNRESET, Errno::ENOTCONN, Errno::EPIPE => e
130
- STDOUT.print "#{__id__} - Connection error (#{e.inspect})...\n" if @debug
131
- rescue Interrupt => e
132
- raise e
133
- rescue Exception => e
134
- STDOUT.puts Knj::Errors.error_str(e)
135
- ensure
136
- self.destruct
137
121
  end
122
+ rescue Timeout::Error
123
+ STDOUT.print "#{__id__} - Closing httpsession because of timeout.\n" if @debug
124
+ rescue Errno::ECONNRESET, Errno::ENOTCONN, Errno::EPIPE => e
125
+ STDOUT.print "#{__id__} - Connection error (#{e.inspect})...\n" if @debug
126
+ rescue Interrupt => e
127
+ raise e
128
+ rescue Exception => e
129
+ STDOUT.puts Knj::Errors.error_str(e)
130
+ ensure
131
+ self.destruct
138
132
  end
139
133
  end
140
134
 
@@ -1,9 +1,10 @@
1
- require "timeout"
1
+ require "base64"
2
2
  require "digest"
3
3
  require "erubis"
4
- require "base64"
4
+ require "monitor"
5
5
  require "stringio"
6
6
  require "socket"
7
+ require "timeout"
7
8
  require "tsafe" if !Kernel.const_defined?(:Tsafe)
8
9
 
9
10
  #The class that stands for the whole appserver / webserver.
@@ -44,7 +45,7 @@ class Knjappserver
44
45
 
45
46
 
46
47
  #Require gems.
47
- gems = %w[datet]
48
+ gems = %w[datet php4r]
48
49
  gems.each do |gem|
49
50
  puts "Loading gem: '#{gem}'." if @debug
50
51
  require gem
@@ -67,9 +68,7 @@ class Knjappserver
67
68
 
68
69
 
69
70
  #Add extra handlers if given.
70
- if @config[:handlers_extra]
71
- @config[:handlers] += @config[:handlers_extra]
72
- end
71
+ @config[:handlers] += @config[:handlers_extra] if @config[:handlers_extra]
73
72
 
74
73
 
75
74
  #Setup cache to make .rhtml-calls faster.
@@ -108,11 +107,7 @@ class Knjappserver
108
107
  ]
109
108
 
110
109
  print "Auto restarting.\n" if @debug
111
- @mod_event = Knj::Event_filemod.new(:wait => 2, :paths => paths) do |event, path|
112
- print "File changed - restart server: #{path}\n"
113
- @should_restart = true
114
- @mod_event.destroy if @mod_event
115
- end
110
+ @mod_event = Knj::Event_filemod.new(:wait => 2, :paths => paths, &self.method(:on_event_filemod))
116
111
  end
117
112
 
118
113
 
@@ -166,15 +161,15 @@ class Knjappserver
166
161
 
167
162
  if !@config.key?(:dbrev) or @config[:dbrev]
168
163
  print "Updating database.\n" if @debug
169
- require "knj/knjdb/revision.rb"
170
164
 
171
165
  dbschemapath = "#{File.dirname(__FILE__)}/../files/database_schema.rb"
172
166
  raise "'#{dbschemapath}' did not exist." if !File.exists?(dbschemapath)
173
167
  require dbschemapath
174
168
  raise "No schema-variable was spawned." if !Knjappserver::DATABASE_SCHEMA
175
-
176
- dbrev = Knj::Db::Revision.new
177
- dbrev.init_db("schema" => Knjappserver::DATABASE_SCHEMA, "db" => @db)
169
+ dbrev_args = {"schema" => Knjappserver::DATABASE_SCHEMA, "db" => @db}
170
+ dbrev_args.merge!(@config[:dbrev_args]) if @config.key?(:dbrev_args)
171
+ Knj::Db::Revision.new.init_db(dbrev_args)
172
+ dbrev_args = nil
178
173
  end
179
174
 
180
175
 
@@ -186,9 +181,7 @@ class Knjappserver
186
181
  :datarow => true,
187
182
  :knjappserver => self
188
183
  )
189
- @ob.events.connect(:no_date) do |event, classname|
190
- "[no date]"
191
- end
184
+ @ob.events.connect(:no_date, &self.method(:no_date))
192
185
 
193
186
 
194
187
  if @config[:httpsession_db_args]
@@ -312,14 +305,22 @@ class Knjappserver
312
305
 
313
306
 
314
307
  #Clear memory at exit.
315
- Kernel.at_exit do
316
- self.stop
317
- end
308
+ Kernel.at_exit(&self.method(:stop))
318
309
 
319
310
 
320
311
  print "Appserver spawned.\n" if @debug
321
312
  end
322
313
 
314
+ def no_date(event, classname)
315
+ return "[no date]"
316
+ end
317
+
318
+ def on_event_filemod(event, path)
319
+ print "File changed - restart server: #{path}\n"
320
+ @should_restart = true
321
+ @mod_event.destroy if @mod_event
322
+ end
323
+
323
324
  #If you want to use auto-restart, every file reloaded through loadfile will be watched for changes. When changed the server will do a restart to reflect that.
324
325
  def loadfile(fpath)
325
326
  if !@config[:autorestart]
@@ -1,101 +1,108 @@
1
1
  class Knjappserver
2
2
  def initialize_cleaner
3
- if @config[:autorestart]
4
- time = 1
5
- else
6
- time = 15
7
- end
8
-
9
3
  #This should not be runned via _kas.timeout because timeout wont run when @should_restart is true! - knj
10
- Thread.new do
11
- begin
12
- loop do
13
- sleep time
4
+ Thread.new(&self.method(:clean_autorestart))
5
+
6
+ #This flushes (writes) all session-data to the server and deletes old unused sessions from the database.
7
+ self.timeout(:time => @config[:cleaner_timeout], &self.method(:clean_sessions))
8
+ end
9
+
10
+ def clean
11
+ self.clean_sessions
12
+ self.clean_autorestart
13
+ end
14
+
15
+ def clean_autorestart
16
+ begin
17
+ if @config[:autorestart]
18
+ time = 1
19
+ else
20
+ time = 15
21
+ end
22
+
23
+ loop do
24
+ sleep time
25
+
26
+ if @config.has_key?(:restart_when_used_memory) and !@should_restart
27
+ mbs_used = (Php4r.memory_get_usage / 1024) / 1024
28
+ STDOUT.print "Restart when over #{@config[:restart_when_used_memory]}mb\n" if @config[:debug]
29
+ STDOUT.print "Used: #{mbs_used}mb\n" if @config[:debug]
14
30
 
15
- if @config.has_key?(:restart_when_used_memory) and !@should_restart
16
- mbs_used = (Knj::Php.memory_get_usage / 1024) / 1024
17
- STDOUT.print "Restart when over #{@config[:restart_when_used_memory]}mb\n" if @config[:debug]
18
- STDOUT.print "Used: #{mbs_used}mb\n" if @config[:debug]
19
-
20
- if mbs_used.to_i >= @config[:restart_when_used_memory].to_i
21
- STDOUT.print "Memory is over #{@config[:restart_when_used_memory]} - restarting.\n"
22
- @should_restart = true
23
- end
31
+ if mbs_used.to_i >= @config[:restart_when_used_memory].to_i
32
+ STDOUT.print "Memory is over #{@config[:restart_when_used_memory]} - restarting.\n"
33
+ @should_restart = true
24
34
  end
25
-
26
- if @should_restart and !@should_restart_done and !@should_restart_runnning
35
+ end
36
+
37
+ if @should_restart and !@should_restart_done and !@should_restart_runnning
38
+ begin
39
+ @should_restart_runnning = true
40
+
41
+ #When we begin to restart it should go as fast as possible - so start by flushing out any emails waiting so it goes faster the last time...
42
+ STDOUT.print "Flushing mails.\n"
43
+ self.mail_flush
44
+
45
+ #Lets try to find a time where no thread is working within the next 30 seconds. If we cant - we interrupt after 10 seconds and restart the server.
27
46
  begin
28
- @should_restart_runnning = true
29
-
30
- #When we begin to restart it should go as fast as possible - so start by flushing out any emails waiting so it goes faster the last time...
31
- STDOUT.print "Flushing mails.\n"
32
- self.mail_flush
33
-
34
- #Lets try to find a time where no thread is working within the next 30 seconds. If we cant - we interrupt after 10 seconds and restart the server.
35
- begin
36
- Timeout.timeout(30) do
37
- loop do
38
- working_count = self.httpserv.working_count
39
- working = false
40
-
41
- if working_count and working_count > 0
42
- working = true
43
- STDOUT.print "Someone is working - wait two sec and try to restart again!\n"
44
- end
45
-
46
- if !working
47
- STDOUT.print "Found window where no sessions were active - restarting!\n"
48
- break
49
- else
50
- sleep 0.2
51
- end
52
-
53
- STDOUT.print "Trying to find window with no active sessions to restart...\n"
47
+ Timeout.timeout(30) do
48
+ loop do
49
+ working_count = self.httpserv.working_count
50
+ working = false
51
+
52
+ if working_count and working_count > 0
53
+ working = true
54
+ STDOUT.print "Someone is working - wait two sec and try to restart again!\n"
55
+ end
56
+
57
+ if !working
58
+ STDOUT.print "Found window where no sessions were active - restarting!\n"
59
+ break
60
+ else
61
+ sleep 0.2
54
62
  end
63
+
64
+ STDOUT.print "Trying to find window with no active sessions to restart...\n"
55
65
  end
56
- rescue Timeout::Error
57
- STDOUT.print "Could not find a timing window for restarting... Forcing restart!\n"
58
- end
59
-
60
- #Flush emails again if any are pending (while we tried to find a window to restart)...
61
- STDOUT.print "Flushing mails.\n"
62
- self.mail_flush
63
-
64
- STDOUT.print "Stopping appserver.\n"
65
- self.stop
66
-
67
- STDOUT.print "Figuring out restart-command.\n"
68
- mycmd = @config[:restart_cmd]
69
-
70
- if !mycmd or mycmd.to_s.strip.length <= 0
71
- fpath = File.realpath("#{File.dirname(__FILE__)}/../knjappserver.rb")
72
- mycmd = Knj::Os.executed_cmd
73
-
74
- STDOUT.print "Previous cmd: #{mycmd}\n"
75
- mycmd = mycmd.gsub(/\s+knjappserver.rb/, " #{Knj::Strings.unixsafe(fpath)}")
76
66
  end
67
+ rescue Timeout::Error
68
+ STDOUT.print "Could not find a timing window for restarting... Forcing restart!\n"
69
+ end
70
+
71
+ #Flush emails again if any are pending (while we tried to find a window to restart)...
72
+ STDOUT.print "Flushing mails.\n"
73
+ self.mail_flush
74
+
75
+ STDOUT.print "Stopping appserver.\n"
76
+ self.stop
77
+
78
+ STDOUT.print "Figuring out restart-command.\n"
79
+ mycmd = @config[:restart_cmd]
80
+
81
+ if !mycmd or mycmd.to_s.strip.length <= 0
82
+ fpath = File.realpath("#{File.dirname(__FILE__)}/../knjappserver.rb")
83
+ mycmd = Knj::Os.executed_cmd
77
84
 
78
- STDOUT.print "Restarting knjAppServer with command: #{mycmd}\n"
79
- @should_restart_done = true
80
- print exec(mycmd)
81
- exit
82
- rescue => e
83
- STDOUT.puts e.inspect
84
- STDOUT.puts e.backtrace
85
+ STDOUT.print "Previous cmd: #{mycmd}\n"
86
+ mycmd = mycmd.gsub(/\s+knjappserver.rb/, " #{Knj::Strings.unixsafe(fpath)}")
85
87
  end
88
+
89
+ STDOUT.print "Restarting knjAppServer with command: #{mycmd}\n"
90
+ @should_restart_done = true
91
+ print exec(mycmd)
92
+ exit
93
+ rescue => e
94
+ STDOUT.puts e.inspect
95
+ STDOUT.puts e.backtrace
86
96
  end
87
97
  end
88
- rescue => e
89
- self.handle_error(e)
90
98
  end
99
+ rescue => e
100
+ self.handle_error(e)
91
101
  end
92
-
93
- #This flushes (writes) all session-data to the server and deletes old unused sessions from the database.
94
- self.timeout(:time => @config[:cleaner_timeout], &self.method("clean"))
95
102
  end
96
103
 
97
104
  #This method can be used to clean the appserver. Dont call this from a HTTP-request.
98
- def clean
105
+ def clean_sessions
99
106
  STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
100
107
 
101
108
  #Clean up various inactive sessions.
@@ -30,15 +30,18 @@ class Knjappserver
30
30
  end
31
31
  end
32
32
 
33
- self.cmd_connect(/^\s*restart\s*$/i) do |data|
34
- print "Restart will begin shortly.\n"
35
- self.should_restart = true
36
- end
37
-
38
- self.cmd_connect(/^\s*stop\s*$/i) do |data|
39
- print "Stopping appserver.\n"
40
- self.stop
41
- end
33
+ self.cmd_connect(/^\s*restart\s*$/i, &self.method(:cmdline_on_restart_cmd))
34
+ self.cmd_connect(/^\s*stop\s*$/i, &self.method(:cmdline_on_stop_cmd))
35
+ end
36
+
37
+ def cmdline_on_restart_cmd(data)
38
+ print "Restart will begin shortly.\n"
39
+ self.should_restart = true
40
+ end
41
+
42
+ def cmdline_on_stop_cmd(data)
43
+ print "Stopping appserver.\n"
44
+ self.stop
42
45
  end
43
46
 
44
47
  #Connects a proc to a specific command in the command-line (key should be a regex).
@@ -13,9 +13,7 @@ class Knjappserver
13
13
  @error_emails_time = 180
14
14
  end
15
15
 
16
- self.timeout(:time => @error_emails_time) do
17
- self.flush_error_emails
18
- end
16
+ self.timeout(:time => @error_emails_time, &self.method(:flush_error_emails))
19
17
  end
20
18
 
21
19
  #Send error-emails based on error-emails-cache (cached so the same error isnt send out every time it occurrs to prevent spamming).
@@ -99,12 +97,12 @@ class Knjappserver
99
97
  html << "#{Knj::Web.html(line)}<br />"
100
98
  end
101
99
 
102
- html << "<br /><b>Post:</b><br /><pre>#{Knj::Php.print_r(_post, true)}</pre>" if _post
103
- html << "<br /><b>Get:</b><br /><pre>#{Knj::Php.print_r(_get, true)}</pre>" if _get
104
- html << "<br /><b>Server:</b><br /><pre>#{Knj::Php.print_r(_server, true).html}</pre>" if _server
105
- html << "<br /><b>Cookie:</b><br /><pre>#{Knj::Php.print_r(_cookie, true).html}</pre>" if _meta
106
- html << "<br /><b>Session:</b><br /><pre>#{Knj::Php.print_r(_session, true).html}</pre>" if _session
107
- html << "<br /><b>Session hash:</b><br /><pre>#{Knj::Php.print_r(_session_hash, true).html}</pre>" if _session_hash
100
+ html << "<br /><b>Post:</b><br /><pre>#{Php4r.print_r(_post, true)}</pre>" if _post
101
+ html << "<br /><b>Get:</b><br /><pre>#{Php4r.print_r(_get, true)}</pre>" if _get
102
+ html << "<br /><b>Server:</b><br /><pre>#{Php4r.print_r(_server, true).html}</pre>" if _server
103
+ html << "<br /><b>Cookie:</b><br /><pre>#{Php4r.print_r(_cookie, true).html}</pre>" if _meta
104
+ html << "<br /><b>Session:</b><br /><pre>#{Php4r.print_r(_session, true).html}</pre>" if _session
105
+ html << "<br /><b>Session hash:</b><br /><pre>#{Php4r.print_r(_session_hash, true).html}</pre>" if _session_hash
108
106
 
109
107
  error_hash = @error_emails_pending[backtrace_hash]
110
108
  error_hash[:last_time] = Time.new
@@ -124,7 +122,7 @@ class Knjappserver
124
122
 
125
123
  #Prints a detailed overview of the object in the terminal from where the appserver was started. This can be used for debugging.
126
124
  def dprint(obj)
127
- STDOUT.print Knj::Php.print_r(obj, true)
125
+ STDOUT.print Php4r.print_r(obj, true)
128
126
  end
129
127
 
130
128
  #Prints a string with a single file-line-backtrace prepended which is useful for debugging.
@@ -44,7 +44,7 @@ class Knjappserver::Leakproxy_server
44
44
  STDOUT.print obj["str"]
45
45
  end
46
46
  else
47
- STDOUT.print Knj::Php.print_r(obj, true)
47
+ STDOUT.print Php4r.print_r(obj, true)
48
48
  end
49
49
  }
50
50
  )
@@ -4,16 +4,14 @@ class Knjappserver
4
4
  @logs_mutex = Mutex.new
5
5
 
6
6
  if @config[:logging] and @config[:logging][:access_db]
7
- self.timeout(:time => 30) do
8
- if @logs_access_pending.length > 0
9
- flush_access_log
10
- end
11
- end
7
+ self.timeout(:time => 30, &self.method(:flush_access_log))
12
8
  end
13
9
  end
14
10
 
15
11
  #Writes all queued access-logs to the database.
16
12
  def flush_access_log
13
+ return nil if @logs_access_pending.empty?
14
+
17
15
  @logs_mutex.synchronize do
18
16
  ins_arr = @logs_access_pending
19
17
  @logs_access_pending = []
@@ -306,7 +304,9 @@ class Knjappserver
306
304
  def logs_table(obj, args = {})
307
305
  links = @ob.list(:Log_link, {"object_class" => obj.class.name, "object_id" => obj.id, "limit" => 500, "orderby" => [["id", "desc"]]})
308
306
 
309
- html = "<table class=\"list knjappserver_log_table\">"
307
+ html = ""
308
+
309
+ html << "<table class=\"list knjappserver_log_table\">"
310
310
  html << "<thead>"
311
311
  html << "<tr>"
312
312
  html << "<th>ID</th>"
@@ -8,10 +8,7 @@ class Knjappserver
8
8
  @mails_waiting = []
9
9
  @mails_mutex = Monitor.new
10
10
  @mails_queue_mutex = Monitor.new
11
- @mails_timeout = self.timeout(:time => 30) do
12
- STDOUT.print "Flushing mails.\n" if @debug
13
- self.mail_flush
14
- end
11
+ @mails_timeout = self.timeout(:time => 30, &self.method(:mail_flush))
15
12
  end
16
13
 
17
14
  #Queue a mail for sending. Possible keys are: :subject, :from, :to, :text and :html.
@@ -40,6 +37,8 @@ class Knjappserver
40
37
  #Sends all queued mails to the respective servers, if we are online.
41
38
  def mail_flush
42
39
  @mails_mutex.synchronize do
40
+ STDOUT.print "Flushing mails.\n" if @debug
41
+
43
42
  if @mails_waiting.length <= 0
44
43
  STDOUT.print "No mails to flush - skipping.\n" if @debug
45
44
  return false
@@ -83,6 +82,8 @@ class Knjappserver
83
82
  subproc.destroy if subproc
84
83
  subproc = nil
85
84
  end
85
+
86
+ return nil
86
87
  end
87
88
  end
88
89
 
@@ -4,9 +4,12 @@ class Knjappserver
4
4
  @config[:threadding][:max_running] = 8 if !@config[:threadding].has_key?(:max_running)
5
5
 
6
6
  @threadpool = Knj::Threadpool.new(:threads => @config[:threadding][:max_running], :sleep => 0.1)
7
- @threadpool.events.connect(:on_error) do |event, error|
8
- self.handle_error(error)
9
- end
7
+ @threadpool.events.connect(:on_error, &self.method(:threadpool_on_error))
8
+ end
9
+
10
+ #Callback for when an error occurs in the threadpool.
11
+ def threadpool_on_error(event, error)
12
+ self.handle_error(error)
10
13
  end
11
14
 
12
15
  #Inits the thread so it has access to the appserver and various magic methods can be used.
@@ -71,6 +74,7 @@ class Knjappserver
71
74
  #Spawns a thread to run the given proc and add the output of that block in the correct order to the HTML.
72
75
  def threadded_content(&block)
73
76
  _httpsession.threadded_content(block)
77
+ return nil
74
78
  end
75
79
  end
76
80
 
@@ -1,15 +1,15 @@
1
1
  class Knjappserver
2
+ #Translates a given key for a given object.
3
+ #===Examples
4
+ # print _kas.trans(obj, :title) #=> "Trala"
2
5
  def trans(obj, key, args = {})
3
6
  args[:locale] = self.trans_locale if !args[:locale]
4
7
  trans_val = @translations.get(obj, key, args).to_s
5
-
6
- if trans_val.length <= 0
7
- trans_val = @events.call(:trans_no_str, {:obj => obj, :key => key, :args => args})
8
- end
9
-
8
+ trans_val = @events.call(:trans_no_str, {:obj => obj, :key => key, :args => args}) if trans_val.length <= 0
10
9
  return trans_val
11
10
  end
12
11
 
12
+ #Returns the locale for the current thread.
13
13
  def trans_locale(args = {})
14
14
  if args.is_a?(Hash) and args[:locale]
15
15
  return args[:locale]
@@ -26,11 +26,17 @@ class Knjappserver
26
26
  raise "Could not figure out locale."
27
27
  end
28
28
 
29
+ #Sets new translations for the given object.
30
+ #===Examples
31
+ # _kas.trans_set(obj, {:title => "Trala"})
29
32
  def trans_set(obj, values, args = {})
30
33
  args[:locale] = self.trans_locale if !args[:locale]
31
34
  @translations.set(obj, values, args)
32
35
  end
33
36
 
37
+ #Deletes all translations for the given object.
38
+ #===Examples
39
+ # _kas.trans_del(obj)
34
40
  def trans_del(obj)
35
41
  @translations.delete(obj)
36
42
  end
@@ -1,7 +1,7 @@
1
1
  class Knjappserver
2
2
  #Imports a .rhtml-file and executes it.
3
3
  #===Examples
4
- # _kas.import("/some/path/page.rhtml")
4
+ # _kas.import("/some/path/page.rhtml")
5
5
  def import(filepath)
6
6
  if filepath.to_s.index("../proc/self") != nil
7
7
  raise Errno::EACCES, "Possible attempt to hack the appserver."
@@ -12,8 +12,8 @@ class Knjappserver
12
12
 
13
13
  #Redirects to another URL.
14
14
  #===Examples
15
- # _kas.redirect("someotherpage.rhtml")
16
- # _kas.redirect("newpage.rhtml", :perm => true)
15
+ # _kas.redirect("someotherpage.rhtml")
16
+ # _kas.redirect("newpage.rhtml", :perm => true)
17
17
  def redirect(url, args = {})
18
18
  #Header way
19
19
  if !_httpsession.alert_sent and !self.headers_sent?
@@ -32,7 +32,7 @@ class Knjappserver
32
32
 
33
33
  #Sends a javascript-alert to the HTML.
34
34
  #===Examples
35
- # _kas.alert("Hello world!")
35
+ # _kas.alert("Hello world!")
36
36
  def alert(msg)
37
37
  _httpsession.alert_sent = true
38
38
  Knj::Web.alert(msg)
@@ -41,33 +41,36 @@ class Knjappserver
41
41
 
42
42
  #Define a cookies in the clients browser.
43
43
  #===Examples
44
- # _kas.cookie(:name => "MyCookie", :value => "Trala")
44
+ # _kas.cookie(:name => "MyCookie", :value => "Trala")
45
45
  def cookie(cookie)
46
46
  raise "No HTTP-session attached to this thread." if !_httpsession
47
47
  raise "HTTP-session not active." if !_httpsession.resp
48
48
  raise "Not a hash: '#{cookie.class.name}', '#{cookie}'." unless cookie.is_a?(Hash)
49
49
  _httpsession.resp.cookie(cookie)
50
+ return nil
50
51
  end
51
52
 
52
53
  #Sends a header to the clients browser.
53
54
  #===Examples
54
- # _kas.header("Content-Type", "text/javascript")
55
+ # _kas.header("Content-Type", "text/javascript")
55
56
  def header(key, val)
56
57
  raise "No HTTP-session attached to this thread." if !_httpsession
57
58
  raise "HTTP-session not active." if !_httpsession.resp
58
59
  _httpsession.resp.header(key, val)
60
+ return nil
59
61
  end
60
62
 
61
63
  #Sends a raw header-line to the clients browser.
62
64
  def header_raw(str)
63
65
  raise "No HTTP-session attached to this thread." if !_httpsession
64
66
  raise "HTTP-session not active." if !_httpsession.resp
65
- Knj::Php.header(str)
67
+ Php4r.header(str)
68
+ return nil
66
69
  end
67
70
 
68
71
  #Returns true if the headers are already sent.
69
72
  #===Examples
70
- # _kas.headers_sent? #=> true
73
+ # _kas.headers_sent? #=> true
71
74
  def headers_sent?
72
75
  return true if _httpsession.resp.headers_sent
73
76
  return false
@@ -76,16 +79,17 @@ class Knjappserver
76
79
  #Define the size for when to automatically send headers. If you want to send hundres of kilobytes and then a header, you can use this method to do so.
77
80
  #===Examples
78
81
  #Set the size to 200 kb.
79
- # _kas.headers_send_size = (1024 * 200)
82
+ # _kas.headers_send_size = (1024 * 200)
80
83
  def headers_send_size=(newsize)
81
84
  raise "The headers are already sent and you cannot modify the send-size any more." if self.headers_sent?
82
85
  _httpsession.size_send = newsize.to_i
86
+ return nil
83
87
  end
84
88
 
85
89
  #Serves the given filepath and enables caching for it. No other content should be written to the page when using this method.
86
90
  #===Examples
87
- # _kas.header("Content-Type", "text/javascript")
88
- # _kas.serve_file("somefile.js")
91
+ # _kas.header("Content-Type", "text/javascript")
92
+ # _kas.serve_file("somefile.js")
89
93
  def serve_file(filepath)
90
94
  raise "File doesnt exist: '#{filepath}'." if !File.exists?(filepath)
91
95
  httpsess = _httpsession
@@ -115,6 +119,7 @@ class Knjappserver
115
119
  end
116
120
 
117
121
  httpsess.force_content(:type => :file, :path => filepath)
122
+ return nil
118
123
  end
119
124
 
120
125
  #Sends a javascript back to the browser and exits.
@@ -129,7 +134,7 @@ class Knjappserver
129
134
 
130
135
  #Urlencodes a string.
131
136
  #===Examples
132
- # _kas.redirect("mypage.rhtml?arg=#{_kas.urlenc(value_variable)}")
137
+ # _kas.redirect("mypage.rhtml?arg=#{_kas.urlenc(value_variable)}")
133
138
  def urlenc(str)
134
139
  return Knj::Web.urlenc(str)
135
140
  end
@@ -1,3 +1,3 @@
1
1
  <%
2
- Knj::Php.print_r([_get, _post, _meta])
2
+ Php4r.print_r([_get, _post, _meta])
3
3
  %>
@@ -0,0 +1,16 @@
1
+ <%
2
+ if _get["choice"] == "dogarbagecollect"
3
+ GC.start
4
+ _kas.redirect("?show=debug_memory_usage")
5
+ end
6
+ %>
7
+
8
+ <h1>Memory usage</h1>
9
+
10
+ <div style="padding-bottom: 15px;">
11
+ <input type="button" value="Garbage collect" onclick="location.href='?show=debug_memory_usage&amp;choice=dogarbagecollect';" />
12
+ </div>
13
+
14
+ <%
15
+ Knj::Memory_analyzer.new.write
16
+ %>
@@ -107,7 +107,7 @@ begin
107
107
 
108
108
  #cgi.print "Content-Type: text/html\r\n"
109
109
  #cgi.print "\r\n"
110
- #cgi.print Knj::Php.print_r(cgi.params, true)
110
+ #cgi.print Php4r.print_r(cgi.params, true)
111
111
 
112
112
  if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
113
113
  count = 0
@@ -74,7 +74,7 @@ FCGI.each_cgi do |cgi|
74
74
  headers = {}
75
75
  cgi.env_table.each do |key, val|
76
76
  if key[0, 5] == "HTTP_" and key != "HTTP_KNJAPPSERVER_CGI_CONFIG"
77
- key = Knj::Php.ucwords(key[5, key.length].gsub("_", " ")).gsub(" ", "-")
77
+ key = Php4r.ucwords(key[5, key.length].gsub("_", " ")).gsub(" ", "-")
78
78
  headers[key] = val
79
79
  end
80
80
  end
@@ -92,7 +92,7 @@ FCGI.each_cgi do |cgi|
92
92
 
93
93
  #cgi.print "Content-Type: text/html\r\n"
94
94
  #cgi.print "\r\n"
95
- #cgi.print Knj::Php.print_r(cgi.params, true)
95
+ #cgi.print Php4r.print_r(cgi.params, true)
96
96
 
97
97
  if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
98
98
  count = 0
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: knjappserver
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.29
5
+ version: 0.0.30
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kasper Johansen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-07-20 00:00:00 +02:00
13
+ date: 2012-08-03 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -80,19 +80,30 @@ dependencies:
80
80
  prerelease: false
81
81
  version_requirements: *id006
82
82
  - !ruby/object:Gem::Dependency
83
- name: json
83
+ name: php4r
84
84
  requirement: &id007 !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: "0"
90
- type: :development
90
+ type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: *id007
93
93
  - !ruby/object:Gem::Dependency
94
- name: rspec
94
+ name: json
95
95
  requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: rspec
106
+ requirement: &id009 !ruby/object:Gem::Requirement
96
107
  none: false
97
108
  requirements:
98
109
  - - ~>
@@ -100,10 +111,10 @@ dependencies:
100
111
  version: 2.3.0
101
112
  type: :development
102
113
  prerelease: false
103
- version_requirements: *id008
114
+ version_requirements: *id009
104
115
  - !ruby/object:Gem::Dependency
105
116
  name: bundler
106
- requirement: &id009 !ruby/object:Gem::Requirement
117
+ requirement: &id010 !ruby/object:Gem::Requirement
107
118
  none: false
108
119
  requirements:
109
120
  - - ">="
@@ -111,10 +122,10 @@ dependencies:
111
122
  version: 1.0.0
112
123
  type: :development
113
124
  prerelease: false
114
- version_requirements: *id009
125
+ version_requirements: *id010
115
126
  - !ruby/object:Gem::Dependency
116
127
  name: jeweler
117
- requirement: &id010 !ruby/object:Gem::Requirement
128
+ requirement: &id011 !ruby/object:Gem::Requirement
118
129
  none: false
119
130
  requirements:
120
131
  - - ~>
@@ -122,10 +133,10 @@ dependencies:
122
133
  version: 1.6.3
123
134
  type: :development
124
135
  prerelease: false
125
- version_requirements: *id010
136
+ version_requirements: *id011
126
137
  - !ruby/object:Gem::Dependency
127
138
  name: sqlite3
128
- requirement: &id011 !ruby/object:Gem::Requirement
139
+ requirement: &id012 !ruby/object:Gem::Requirement
129
140
  none: false
130
141
  requirements:
131
142
  - - ">="
@@ -133,7 +144,7 @@ dependencies:
133
144
  version: "0"
134
145
  type: :development
135
146
  prerelease: false
136
- version_requirements: *id011
147
+ version_requirements: *id012
137
148
  description: Which supports a lot of undocumented stuff.
138
149
  email: k@spernj.org
139
150
  executables:
@@ -200,6 +211,7 @@ files:
200
211
  - lib/pages/benchmark_threadded_content.rhtml
201
212
  - lib/pages/debug_database_connections.rhtml
202
213
  - lib/pages/debug_http_sessions.rhtml
214
+ - lib/pages/debug_memory_usage.rhtml
203
215
  - lib/pages/error_notfound.rhtml
204
216
  - lib/pages/logs_latest.rhtml
205
217
  - lib/pages/logs_show.rhtml
@@ -230,7 +242,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
230
242
  requirements:
231
243
  - - ">="
232
244
  - !ruby/object:Gem::Version
233
- hash: 4291663965426138445
245
+ hash: 676583393387932093
234
246
  segments:
235
247
  - 0
236
248
  version: "0"