knjappserver 0.0.15 → 0.0.16

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 (44) hide show
  1. data/Gemfile +4 -2
  2. data/Gemfile.lock +24 -10
  3. data/README.rdoc +298 -1
  4. data/VERSION +1 -1
  5. data/bin/check_running.rb +2 -2
  6. data/knjappserver.gemspec +23 -5
  7. data/lib/files/database_schema.rb +124 -111
  8. data/lib/include/class_customio.rb +19 -5
  9. data/lib/include/class_erbhandler.rb +5 -22
  10. data/lib/include/class_httpresp.rb +66 -28
  11. data/lib/include/class_httpserver.rb +27 -14
  12. data/lib/include/class_httpsession.rb +161 -212
  13. data/lib/include/class_httpsession_contentgroup.rb +144 -0
  14. data/lib/include/class_httpsession_knjengine.rb +33 -68
  15. data/lib/include/class_httpsession_mongrel.rb +1 -1
  16. data/lib/include/class_httpsession_webrick.rb +1 -1
  17. data/lib/include/class_knjappserver.rb +105 -130
  18. data/lib/include/class_knjappserver_cleaner.rb +20 -13
  19. data/lib/include/class_knjappserver_cmdline.rb +44 -0
  20. data/lib/include/class_knjappserver_errors.rb +4 -1
  21. data/lib/include/class_knjappserver_logging.rb +48 -8
  22. data/lib/include/class_knjappserver_mailing.rb +36 -14
  23. data/lib/include/class_knjappserver_sessions.rb +78 -0
  24. data/lib/include/class_knjappserver_threadding.rb +18 -45
  25. data/lib/include/class_knjappserver_threadding_timeout.rb +78 -0
  26. data/lib/include/class_knjappserver_translations.rb +30 -0
  27. data/lib/include/class_knjappserver_web.rb +55 -3
  28. data/lib/include/class_log.rb +31 -3
  29. data/lib/include/class_log_access.rb +0 -15
  30. data/lib/include/class_log_data.rb +0 -15
  31. data/lib/include/class_log_data_link.rb +1 -14
  32. data/lib/include/class_log_data_value.rb +5 -17
  33. data/lib/include/class_session.rb +6 -18
  34. data/lib/include/magic_methods.rb +12 -14
  35. data/lib/pages/benchmark.rhtml +0 -0
  36. data/lib/pages/benchmark_print.rhtml +14 -0
  37. data/lib/pages/benchmark_simple.rhtml +3 -0
  38. data/lib/pages/benchmark_threadded_content.rhtml +21 -0
  39. data/lib/pages/spec.rhtml +26 -0
  40. data/lib/pages/spec_test_multiple_clients.rhtml +3 -0
  41. data/lib/pages/spec_threadded_content.rhtml +38 -0
  42. data/lib/scripts/benchmark.rb +65 -0
  43. data/spec/knjappserver_spec.rb +87 -43
  44. metadata +54 -20
@@ -1,111 +1,124 @@
1
- $tables = {
2
- "tables" => {
3
- "Session" => {
4
- "columns" => [
5
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
6
- {"name" => "idhash", "type" => "varchar"},
7
- {"name" => "sess_data", "type" => "text"},
8
- {"name" => "date_added", "type" => "datetime"},
9
- {"name" => "ip", "type" => "varchar", "maxlength" => 15}
10
- ],
11
- "indexes" => [
12
- {"name" => "date_added", "columns" => ["date_added"]},
13
- {"name" => "idhash", "columns" => ["idhash"]}
14
- ],
15
- "renames" => ["sessions"]
16
- },
17
- "Translation" => {
18
- "columns" => [
19
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
20
- {"name" => "object_class", "type" => "varchar", "maxlength" => 50},
21
- {"name" => "object_id", "type" => "bigint"},
22
- {"name" => "key", "type" => "varchar", "maxlength" => 50},
23
- {"name" => "locale", "type" => "varchar", "maxlength" => 5},
24
- {"name" => "value", "type" => "text"}
25
- ],
26
- "indexes" => [
27
- {"name" => "lookup", "columns" => ["object_class", "object_id", "key", "locale"]}
28
- ],
29
- "indexes_remove" => {
30
- "object_class" => true
31
- },
32
- "renames" => ["translations"]
33
- },
34
- "Log" => {
35
- "columns" => [
36
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
37
- {"name" => "text_value_id", "type" => "bigint"},
38
- {"name" => "date_saved", "type" => "datetime"},
39
- {"name" => "get_keys_data_id", "type" => "bigint"},
40
- {"name" => "get_values_data_id", "type" => "bigint"},
41
- {"name" => "post_keys_data_id", "type" => "bigint"},
42
- {"name" => "post_values_data_id", "type" => "bigint"}
43
- ],
44
- "indexes" => [
45
- {"name" => "text_value_id", "columns" => ["text_value_id"]}
46
- ]
47
- },
48
- "Log_access" => {
49
- "columns" => [
50
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
51
- {"name" => "session_id", "type" => "bigint"},
52
- {"name" => "date_request", "type" => "datetime"},
53
- {"name" => "ip_data_id", "type" => "bigint"},
54
- {"name" => "get_keys_data_id", "type" => "bigint"},
55
- {"name" => "get_values_data_id", "type" => "bigint"},
56
- {"name" => "post_keys_data_id", "type" => "bigint"},
57
- {"name" => "post_values_data_id", "type" => "bigint"},
58
- {"name" => "cookie_keys_data_id", "type" => "bigint"},
59
- {"name" => "cookie_values_data_id", "type" => "bigint"},
60
- {"name" => "meta_keys_data_id", "type" => "bigint"},
61
- {"name" => "meta_values_data_id", "type" => "bigint"}
62
- ],
63
- "indexes" => [
64
- {"name" => "session_id", "columns" => ["session_id"]},
65
- {"name" => "date_request", "columns" => ["date_request"]}
66
- ]
67
- },
68
- "Log_data" => {
69
- "columns" => [
70
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
71
- {"name" => "id_hash", "type" => "varchar"}
72
- ],
73
- "indexes" => [
74
- {"name" => "id_hash", "columns" => ["id_hash"]}
75
- ]
76
- },
77
- "Log_data_link" => {
78
- "columns" => [
79
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
80
- {"name" => "no", "type" => "int"},
81
- {"name" => "data_id", "type" => "bigint"},
82
- {"name" => "value_id", "type" => "bigint"}
83
- ],
84
- "indexes" => [
85
- {"name" => "data_id", "columns" => ["data_id"]},
86
- {"name" => "value_id", "columns" => ["value_id"]}
87
- ]
88
- },
89
- "Log_data_value" => {
90
- "columns" => [
91
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
92
- {"name" => "value", "type" => "text"}
93
- ]
94
- },
95
- "Log_link" => {
96
- "columns" => [
97
- {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
98
- {"name" => "log_id", "type" => "bigint"},
99
- {"name" => "object_class_value_id", "type" => "bigint"},
100
- {"name" => "object_id", "type" => "bigint"}
101
- ],
102
- "indexes" => [
103
- {"name" => "log_id", "columns" => ["log_id"]},
104
- {"name" => "object_id", "columns" => ["object_id"]},
105
- {"name" => "object_class_value_id", "columns" => ["object_class_value_id"]},
106
- {"name" => "object_lookup", "columns" => ["object_class_value_id", "object_id"]},
107
- {"name" => "log_lookup", "columns" => ["object_class_value_id", "object_id", "log_id"]}
108
- ]
109
- }
110
- }
111
- }
1
+ class Knjappserver
2
+ DATABASE_SCHEMA = {
3
+ "tables" => {
4
+ "Log" => {
5
+ "columns" => [
6
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
7
+ {"name" => "text_value_id", "type" => "bigint"},
8
+ {"name" => "date_saved", "type" => "datetime"},
9
+ {"name" => "get_keys_data_id", "type" => "bigint"},
10
+ {"name" => "get_values_data_id", "type" => "bigint"},
11
+ {"name" => "post_keys_data_id", "type" => "bigint"},
12
+ {"name" => "post_values_data_id", "type" => "bigint"},
13
+ {"name" => "cookie_keys_data_id", "type" => "bigint"},
14
+ {"name" => "cookie_values_data_id", "type" => "bigint"},
15
+ {"name" => "meta_keys_data_id", "type" => "bigint"},
16
+ {"name" => "meta_values_data_id", "type" => "bigint"},
17
+ {"name" => "tag_data_id", "type" => "bigint"},
18
+ {"name" => "comment_data_id", "type" => "bigint"}
19
+ ],
20
+ "indexes" => [
21
+ {"name" => "text_value_id", "columns" => ["text_value_id"]},
22
+ {"name" => "tag_data_id", "columns" => ["tag_data_id"]},
23
+ {"name" => "comment_data_id", "columns" => ["comment_data_id"]}
24
+ ]
25
+ },
26
+ "Log_access" => {
27
+ "columns" => [
28
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
29
+ {"name" => "session_id", "type" => "bigint"},
30
+ {"name" => "date_request", "type" => "datetime"},
31
+ {"name" => "ip_data_id", "type" => "bigint"},
32
+ {"name" => "get_keys_data_id", "type" => "bigint"},
33
+ {"name" => "get_values_data_id", "type" => "bigint"},
34
+ {"name" => "post_keys_data_id", "type" => "bigint"},
35
+ {"name" => "post_values_data_id", "type" => "bigint"},
36
+ {"name" => "cookie_keys_data_id", "type" => "bigint"},
37
+ {"name" => "cookie_values_data_id", "type" => "bigint"},
38
+ {"name" => "meta_keys_data_id", "type" => "bigint"},
39
+ {"name" => "meta_values_data_id", "type" => "bigint"}
40
+ ],
41
+ "indexes" => [
42
+ {"name" => "session_id", "columns" => ["session_id"]},
43
+ {"name" => "date_request", "columns" => ["date_request"]}
44
+ ]
45
+ },
46
+ "Log_data" => {
47
+ "columns" => [
48
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
49
+ {"name" => "id_hash", "type" => "varchar"}
50
+ ],
51
+ "indexes" => [
52
+ {"name" => "id_hash", "columns" => ["id_hash"]}
53
+ ]
54
+ },
55
+ "Log_data_link" => {
56
+ "columns" => [
57
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
58
+ {"name" => "no", "type" => "int"},
59
+ {"name" => "data_id", "type" => "bigint"},
60
+ {"name" => "value_id", "type" => "bigint"}
61
+ ],
62
+ "indexes" => [
63
+ {"name" => "data_id", "columns" => ["data_id"]},
64
+ {"name" => "value_id", "columns" => ["value_id"]}
65
+ ]
66
+ },
67
+ "Log_data_value" => {
68
+ "columns" => [
69
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
70
+ {"name" => "value", "type" => "text"}
71
+ ]
72
+ },
73
+ "Log_link" => {
74
+ "columns" => [
75
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
76
+ {"name" => "log_id", "type" => "bigint"},
77
+ {"name" => "object_class_value_id", "type" => "bigint"},
78
+ {"name" => "object_id", "type" => "bigint"}
79
+ ],
80
+ "indexes" => [
81
+ {"name" => "log_id", "columns" => ["log_id"]},
82
+ {"name" => "object_id", "columns" => ["object_id"]},
83
+ {"name" => "object_class_value_id", "columns" => ["object_class_value_id"]},
84
+ {"name" => "object_lookup", "columns" => ["object_class_value_id", "object_id"]},
85
+ {"name" => "log_lookup", "columns" => ["object_class_value_id", "object_id", "log_id"]}
86
+ ]
87
+ },
88
+ "Session" => {
89
+ "columns" => [
90
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
91
+ {"name" => "idhash", "type" => "varchar"},
92
+ {"name" => "sess_data", "type" => "text"},
93
+ {"name" => "date_added", "type" => "datetime"},
94
+ {"name" => "date_lastused", "type" => "datetime", "on_created" => proc{|d| d["db"].query("UPDATE Session SET date_lastused = '#{Knj::Datet.new.dbstr}")}},
95
+ {"name" => "ip", "type" => "varchar", "maxlength" => 15},
96
+ {"name" => "user_agent", "type" => "text"},
97
+ {"name" => "remember", "type" => "enum", "maxlength" => "'0','1'", "default" => 0, "comment" => "If the session should be remembered or not."}
98
+ ],
99
+ "indexes" => [
100
+ {"name" => "date_added", "columns" => ["date_added"]},
101
+ {"name" => "idhash", "columns" => ["idhash"]}
102
+ ],
103
+ "renames" => ["sessions"]
104
+ },
105
+ "Translation" => {
106
+ "columns" => [
107
+ {"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
108
+ {"name" => "object_class", "type" => "varchar", "maxlength" => 50},
109
+ {"name" => "object_id", "type" => "bigint"},
110
+ {"name" => "key", "type" => "varchar", "maxlength" => 50},
111
+ {"name" => "locale", "type" => "varchar", "maxlength" => 5},
112
+ {"name" => "value", "type" => "text"}
113
+ ],
114
+ "indexes" => [
115
+ {"name" => "lookup", "columns" => ["object_class", "object_id", "key", "locale"]}
116
+ ],
117
+ "indexes_remove" => {
118
+ "object_class" => true
119
+ },
120
+ "renames" => ["translations"]
121
+ }
122
+ }
123
+ }
124
+ end
@@ -1,13 +1,23 @@
1
1
  class Knjappserver::CustomIO < StringIO
2
2
  def print(str)
3
3
  thread = Thread.current
4
+ str = str.to_s
4
5
 
5
- if thread and thread[:knjappserver] and thread[:knjappserver][:stringio] and !thread[:knjappserver][:stringio].closed?
6
- return thread[:knjappserver][:stringio].print(str)
7
- elsif thread and thread[:knjappserver] and thread[:knjappserver][:httpsession] and thread[:knjappserver][:httpsession].out and !thread[:knjappserver][:httpsession].out.closed?
8
- return thread[:knjappserver][:httpsession].out.print(str)
6
+ if thread and thread[:knjappserver] and thread[:knjappserver][:contentgroup]
7
+ httpsession = thread[:knjappserver][:httpsession]
8
+
9
+ if httpsession
10
+ wsize = httpsession.written_size
11
+ wsize += str.size
12
+
13
+ if wsize >= httpsession.size_send
14
+ httpsession.cgroup.write_output
15
+ end
16
+ end
17
+
18
+ thread[:knjappserver][:contentgroup].write(str)
9
19
  else
10
- return STDOUT.print(str) if !STDOUT.closed?
20
+ STDOUT.print(str) if !STDOUT.closed?
11
21
  end
12
22
  end
13
23
 
@@ -18,4 +28,8 @@ class Knjappserver::CustomIO < StringIO
18
28
  def write(str)
19
29
  self.print(str)
20
30
  end
31
+
32
+ def p(str)
33
+ self.print(str)
34
+ end
21
35
  end
@@ -3,12 +3,10 @@ class Knjappserver::ERBHandler
3
3
  @connected = {}
4
4
  end
5
5
 
6
- def erb_handler(data)
7
- #Hack the Knj::Thread to accept data - this is how get, post and etc. are set.
8
- Thread.current[:knjappserver] = data
9
- eruby = data[:httpsession].eruby
10
-
11
- if !@connected[eruby.__id__]
6
+ def erb_handler(httpsess)
7
+ eruby = httpsess.eruby
8
+
9
+ if !@connected.key?(eruby.__id__)
12
10
  eruby.connect("error") do |e|
13
11
  _kas.handle_error(e)
14
12
  end
@@ -16,21 +14,6 @@ class Knjappserver::ERBHandler
16
14
  @connected[eruby.__id__] = true
17
15
  end
18
16
 
19
- cont = eruby.load_return(data[:filepath], {
20
- :with_headers => false,
21
- :custom_io => true
22
- })
23
- headers = eruby.headers
24
- eruby.reset_headers
25
-
26
- headers_ret = {}
27
- headers.each do |header|
28
- headers_ret[header[0]] = [header[1]]
29
- end
30
-
31
- Thread.current[:knjappserver].clear
32
- Thread.current[:knjappserver] = nil
33
-
34
- return {:headers => headers}
17
+ eruby.import(httpsess.page_path)
35
18
  end
36
19
  end
@@ -1,7 +1,7 @@
1
1
  require "time"
2
2
 
3
3
  class Knjappserver::Httpresp
4
- attr_accessor :body, :nl, :status
4
+ attr_accessor :nl, :status, :http_version, :headers, :headers_trailing, :headers_sent
5
5
 
6
6
  STATUS_CODES = {
7
7
  100 => "Continue",
@@ -24,20 +24,41 @@ class Knjappserver::Httpresp
24
24
  }
25
25
  NL = "\r\n"
26
26
 
27
- def initialize
27
+ def initialize(args)
28
+ @cgroup = args[:cgroup]
29
+ end
30
+
31
+ def reset(args)
28
32
  @status = 200
33
+ @http_version = args[:http_version]
34
+ @close = args[:close]
35
+ @fileobj = nil
36
+ @close = true if @http_version == "1.0"
37
+ @trailers = []
38
+
39
+ @headers_sent = false
40
+ @headers_trailing = {}
41
+
29
42
  @headers = {
30
- "Content-Type" => "text/html",
31
- "Date" => Time.now.httpdate,
43
+ "date" => ["Date", Time.now.httpdate]
44
+ }
45
+
46
+ @headers_11 = {
32
47
  "Connection" => "Keep-Alive",
33
48
  "Transfer-Encoding" => "chunked",
34
- "Keep-Alive" => "timeout=30, max=100"
49
+ "Keep-Alive" => "timeout=15, max=30"
35
50
  }
51
+
36
52
  @cookies = []
37
53
  end
38
54
 
39
55
  def header(key, val)
40
- @headers[key] = val
56
+ if !@headers_sent
57
+ @headers[key.to_s.downcase] = [key, val]
58
+ else
59
+ raise "Headers already sent and given header was not in trailing headers: '#{key}'." if @trailers.index(key) == nil
60
+ @headers_trailing[key.to_s.downcase] = [key, val]
61
+ end
41
62
  end
42
63
 
43
64
  def cookie(cookie)
@@ -45,18 +66,32 @@ class Knjappserver::Httpresp
45
66
  end
46
67
 
47
68
  def header_str
48
- res = "HTTP/1.1 #{@status}"
69
+ if @http_version == "1.0"
70
+ res = "HTTP/1.0 #{@status}"
71
+ else
72
+ res = "HTTP/1.1 #{@status}"
73
+ end
74
+
49
75
  code = STATUS_CODES[@status]
50
76
  res += " #{code}" if code
51
77
  res += NL
52
- #res += "Content-Length: #{@body.length}#{NL}"
53
78
 
54
79
  @headers.each do |key, val|
55
- res += "#{key}: #{val}#{NL}"
80
+ res += "#{val[0]}: #{val[1]}#{NL}"
81
+ end
82
+
83
+ if @http_version == "1.1"
84
+ @headers_11.each do |key, val|
85
+ res += "#{key}: #{val}#{NL}"
86
+ end
87
+
88
+ @trailers.each do |trailer|
89
+ res += "Trailer: #{trailer}#{NL}"
90
+ end
56
91
  end
57
92
 
58
93
  @cookies.each do |cookie|
59
- res += "Set-Cookie: #{cookie}#{NL}"
94
+ res += "Set-Cookie: #{Knj::Web.cookie_str(cookie)}#{NL}"
60
95
  end
61
96
 
62
97
  res += NL
@@ -64,28 +99,31 @@ class Knjappserver::Httpresp
64
99
  return res
65
100
  end
66
101
 
67
- def write_chunked(socket)
102
+ def write(socket)
103
+ @headers_sent = true
68
104
  socket.write(self.header_str)
69
105
 
70
- @body.each do |part|
71
- while buf = part.read(1024)
72
- next if buf.empty?
73
- socket.write("#{format("%x", buf.bytesize)}#{NL}#{buf}#{NL}")
106
+ if @status == 304
107
+ #do nothing.
108
+ else
109
+ case @http_version
110
+ when "1.0"
111
+ @cgroup.write_to_socket
112
+ socket.write("#{NL}#{NL}")
113
+ when "1.1"
114
+ @cgroup.write_to_socket
115
+ socket.write("0#{NL}")
116
+
117
+ @headers_trailing.each do |header_id_str, header|
118
+ socket.write("#{header[0]}: #{header[1]}#{NL}")
119
+ end
120
+
121
+ socket.write(NL)
122
+ else
123
+ raise "Could not figure out of HTTP version: '#{@http_version}'."
74
124
  end
75
125
  end
76
126
 
77
- socket.write("0#{NL}#{NL}")
78
- end
79
-
80
- def content
81
- str = self.header_str + @body.string + "\n\n"
82
- end
83
-
84
- def destroy
85
- @status = nil
86
- @status_codes = nil
87
- @body = nil
88
- @cookies = nil
89
- @headers = nil
127
+ socket.close if @close
90
128
  end
91
129
  end