knjappserver 0.0.29 → 0.0.30

Sign up to get free protection for your applications and to get access to all the features.
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"