knjrbfw 0.0.21 → 0.0.22

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.
@@ -288,7 +288,7 @@ class Knj::Objects
288
288
  if match[2] == "not"
289
289
  if val.is_a?(Array)
290
290
  if val.empty?
291
- sql_where << " AND false"
291
+ #ignore.
292
292
  else
293
293
  escape_sql = Knj::ArrayExt.join(
294
294
  :arr => val,
@@ -194,9 +194,13 @@ module Knj::Os
194
194
  if self.os == "linux"
195
195
  unix_proc = Knj::Unix_proc.find_self
196
196
  if unix_proc
197
- if match_cmd = unix_proc["cmd"].match(/^(\/usr\/bin\/|)((j|iron|)ruby([\d\.-]+))(\s+|$)/)
197
+ if match_cmd = unix_proc["cmd"].match(/^(\/usr\/bin\/|)((j|iron|)ruby([\d\.-]*))(\s+|$)/)
198
198
  return "#{match_cmd[1]}#{match_cmd[2]}"
199
+ else
200
+ raise "Could not match the executed command from the process."
199
201
  end
202
+ else
203
+ raise "Could not find the self-process."
200
204
  end
201
205
  end
202
206
 
@@ -966,6 +966,8 @@ module Knj::Php
966
966
  def empty(obj)
967
967
  if obj.respond_to?("empty?")
968
968
  return obj.empty?
969
+ elsif obj == nil
970
+ return true
969
971
  else
970
972
  raise "Dont know how to handle object on 'empty': '#{obj.class.name}'."
971
973
  end
@@ -7,7 +7,10 @@ class Knj::Process_meta
7
7
  def initialize(args = {})
8
8
  @args = args
9
9
  @objects = {}
10
+
11
+ #These variables are used to free memory in the subprocess, by using ObjectSpace#define_finalizer. The Mutex is the avoid problems when writing to the finalize-array multithreadded.
10
12
  @finalize = []
13
+ @finalize_mutex = Mutex.new
11
14
 
12
15
  if @args["exec_path"]
13
16
  exec_path = @args["exec_path"]
@@ -69,22 +72,32 @@ class Knj::Process_meta
69
72
  end
70
73
 
71
74
  def proxy_finalizer(id)
72
- @finalize << id
75
+ @finalize_mutex.synchronize do
76
+ @finalize << id
77
+ end
73
78
  end
74
79
 
75
80
  def check_finalizers
76
81
  return nil if @finalize.empty?
77
82
 
78
- remove = []
79
- @finalize.each do |id|
80
- @process.send("obj" => {
81
- "type" => "unset",
82
- "var_name" => id
83
- })
84
- remove << id
83
+ finalize = nil
84
+ @finalize_mutex.synchronize do
85
+ finalize = @finalize
86
+ @finalize = []
87
+
88
+ begin
89
+ @process.send("obj" => {
90
+ "type" => "unset_multiple",
91
+ "var_names" => finalize
92
+ })
93
+ rescue => e
94
+ if e.message.to_s.index("Var-name didnt exist when trying to unset:")
95
+ #ignore.
96
+ else
97
+ raise e
98
+ end
99
+ end
85
100
  end
86
-
87
- @finalize -= remove
88
101
  end
89
102
 
90
103
  #Parses the arguments given. Proxy-object-arguments will be their natural objects in the subprocess.
@@ -184,6 +197,10 @@ class Knj::Process_meta
184
197
 
185
198
  #Spawns a new object in the subprocess by that classname, with those arguments and with that block.
186
199
  def new(class_name, *args, &block)
200
+ #We need to check finalizers first, so we wont accidently reuse an ID, which will then be unset in the process.
201
+ self.check_finalizers
202
+
203
+ #Spawn and return the object.
187
204
  return self.spawn_object(class_name, nil, *args, &block)
188
205
  end
189
206
 
@@ -224,19 +241,23 @@ class Knj::Process_meta
224
241
 
225
242
  #Calls a method on an object and returns the result.
226
243
  def call_object(args, &block)
227
- self.check_finalizers
228
-
229
244
  if args.key?("capture_return")
230
245
  capture_return = args["capture_return"]
231
246
  else
232
247
  capture_return = true
233
248
  end
234
249
 
250
+ if args["buffered"]
251
+ type = "call_object_buffered"
252
+ else
253
+ type = "call_object_block"
254
+ end
255
+
235
256
  res = @process.send(
236
257
  {
237
258
  "buffer_use" => args["buffer_use"],
238
259
  "obj" => {
239
- "type" => "call_object_block",
260
+ "type" => type,
240
261
  "var_name" => args["var_name"],
241
262
  "method_name" => args["method_name"],
242
263
  "capture_return" => capture_return,
@@ -329,7 +350,12 @@ class Knj::Process_meta
329
350
  @process.send("obj" => {"type" => "exit"})
330
351
  @err_thread.kill if @err_thread
331
352
  @process.destroy
332
- Process.kill("TERM", @pid)
353
+
354
+ begin
355
+ Process.kill("TERM", @pid)
356
+ rescue Errno::ESRCH
357
+ #Process is already dead - ignore.
358
+ end
333
359
 
334
360
  begin
335
361
  sleep 0.1
@@ -410,4 +436,113 @@ class Knj::Process_meta::Proxy_obj
410
436
  &block
411
437
  )
412
438
  end
439
+
440
+ def _pm_buffered_caller(args)
441
+ return Knj::Process_meta::Proxy_obj::Buffered_caller.new({
442
+ :name => @args[:name],
443
+ :process_meta => @args[:process_meta]
444
+ }.merge(args))
445
+ end
446
+ end
447
+
448
+ class Knj::Process_meta::Proxy_obj::Buffered_caller
449
+ def initialize(args)
450
+ @args = args
451
+ @buffer = []
452
+ @mutex = Mutex.new
453
+ @mutex_write = Mutex.new
454
+ @count = 0
455
+ @debug = @args[:debug] if @args[:debug]
456
+
457
+ if @args[:count_to]
458
+ @count_to = @args[:count_to]
459
+ else
460
+ @count_to = 1000
461
+ end
462
+
463
+ @buffer_max = @count_to * 2
464
+ @threads = [] if @args[:async]
465
+ end
466
+
467
+ def method_missing(method_name, *args)
468
+ if method_name.to_s == @args[:method_name].to_s
469
+ self._pm_call(*args)
470
+ else
471
+ raise NoMethodError, "No such method: '#{method_name}'."
472
+ end
473
+ end
474
+
475
+ def _pm_call(*args)
476
+ raise @raise_error if @raise_error
477
+
478
+ @mutex.synchronize do
479
+ while @count >= @count_to and @buffer.length >= @buffer_max
480
+ STDOUT.print "Waiting for write to complete...\n" if @debug
481
+ sleep 0.1
482
+ end
483
+
484
+ STDOUT.print "Adding to buffer #{@buffer.length}...\n" if @debug
485
+ @buffer << args
486
+ @count += 1
487
+ end
488
+
489
+ self._pm_flush if @count >= @count_to and !@writing
490
+ return nil
491
+ end
492
+
493
+ def _pm_flush(*args)
494
+ raise @raise_error if @raise_error
495
+
496
+ buffer = nil
497
+ @mutex.synchronize do
498
+ buffer = @buffer
499
+ @buffer = []
500
+ @count = 0
501
+ end
502
+
503
+ if @args[:async]
504
+ begin
505
+ @threads << Thread.new do
506
+ self._pm_flush_real(buffer)
507
+ end
508
+ rescue => e
509
+ @raise_error = e
510
+ end
511
+
512
+ return nil
513
+ else
514
+ return self._pm_flush_real(buffer)
515
+ end
516
+ end
517
+
518
+ def _pm_flush_real(buffer)
519
+ @mutex_write.synchronize do
520
+ STDOUT.print "Writing...\n" if @debug
521
+ @writing = true
522
+
523
+ begin
524
+ return @args[:process_meta].call_object(
525
+ "var_name" => @args[:name],
526
+ "method_name" => @args[:method_name],
527
+ "args" => buffer,
528
+ "buffered" => true,
529
+ "capture_return" => false
530
+ )
531
+ ensure
532
+ @writing = false
533
+ end
534
+ end
535
+ end
536
+
537
+ def _pm_close
538
+ self._pm_flush
539
+
540
+ if @args[:async]
541
+ @threads.each do |thread|
542
+ thread.join
543
+ end
544
+ end
545
+
546
+ raise @raise_error if @raise_error
547
+ end
413
548
  end
@@ -22,6 +22,8 @@ objects = {}
22
22
 
23
23
  if obj.is_a?(Hash)
24
24
  if obj["type"] == "spawn_object"
25
+ raise "An object by that name already exists: '#{obj["var_name"]}'." if objects.key?(obj["var_name"])
26
+
25
27
  #Fix new integer.
26
28
  if obj["class_name"].to_s == "Integer" or obj["class_name"].to_s == "Fixnum"
27
29
  objects[obj["var_name"]] = obj["args"].first.to_i
@@ -35,7 +37,7 @@ objects = {}
35
37
  d.answer("type" => "success")
36
38
  elsif obj["type"] == "proxy_from_call"
37
39
  raise "No 'var_name' was given in arguments." if !obj["var_name"]
38
- raise "No object by that name: '#{obj["proxy_obj"]}' in '#{objects}'." if !objects.key?(obj["proxy_obj"])
40
+ raise "No object by that name when trying to do 'proxy_from_call': '#{obj["proxy_obj"]}' in '#{objects}'." if !objects.key?(obj["proxy_obj"])
39
41
  obj_to_call = objects[obj["proxy_obj"]]
40
42
  res = obj_to_call.__send__(obj["method_name"], *obj["args"])
41
43
  objects[obj["var_name"]] = res
@@ -57,6 +59,28 @@ objects = {}
57
59
  raise "No object by that name: '#{obj["var_name"]}'." if !obj
58
60
  res = obj_to_call.__send__(obj["method_name"], *obj["args"])
59
61
  res = nil if obj["capture_return"] == false
62
+ d.answer("type" => "call_object_success", "result" => res)
63
+ elsif obj["type"] == "call_object_buffered"
64
+ raise "Invalid var-name: '#{obj["var_name"]}'." if obj["var_name"].to_s.strip.length <= 0
65
+
66
+ obj_to_call = objects[obj["var_name"]]
67
+ raise "No object by that name: '#{obj["var_name"]}'." if !obj
68
+ capt_return = obj["capture_return"]
69
+
70
+ if capt_return != false
71
+ ret = []
72
+ else
73
+ ret = nil
74
+ end
75
+
76
+ obj["args"].each do |args|
77
+ if capt_return != false
78
+ ret << obj_to_call.__send__(obj["method_name"], *args)
79
+ else
80
+ obj_to_call.__send__(obj["method_name"], *args)
81
+ end
82
+ end
83
+
60
84
  d.answer("type" => "call_object_success", "result" => res)
61
85
  elsif obj["type"] == "call_object_block"
62
86
  raise "Invalid var-name: '#{obj["var_name"]}'." if obj["var_name"].to_s.strip.length <= 0
@@ -77,9 +101,19 @@ objects = {}
77
101
  end
78
102
  elsif obj["type"] == "unset"
79
103
  raise "Invalid var-name: '#{obj["var_name"]}'." if obj["var_name"].to_s.strip.length <= 0
80
- raise "Var-name doesnt exist: '#{obj["var_name"]}'." if !objects.key?(obj["var_name"])
104
+ raise Knj::Errors::NotFound, "Var-name didnt exist when trying to unset: '#{obj["var_name"]}'." if !objects.key?(obj["var_name"])
81
105
  objects.delete(obj["var_name"])
82
106
  d.answer("type" => "unset_success")
107
+ elsif obj["type"] == "unset_multiple"
108
+ err = nil
109
+ obj["var_names"].each do |var_name|
110
+ err = [Knj::Errors::InvalidData, "Invalid var-name: '#{var_name}'."] if var_name.to_s.strip.length <= 0
111
+ err = [Knj::Errors::NotFound, "Var-name didnt exist when trying to unset: '#{var_name}'."] if !objects.key?(var_name)
112
+ objects.delete(var_name)
113
+ end
114
+
115
+ raise err[0], err[1] if err
116
+ d.answer("type" => "unset_success")
83
117
  elsif obj["type"] == "static"
84
118
  const = Knj::Strings.const_get_full(obj["const"])
85
119
  res = const.__send__(obj["method_name"], *obj["args"], &block)
@@ -1,17 +1,23 @@
1
+ require "#{$knjpath}wref"
2
+
1
3
  class Knj::Unix_proc
2
4
  attr_reader :data
3
- @procs = {}
5
+
6
+ PROCS = Knj::Wref_map.new
7
+ MUTEX = Mutex.new
4
8
 
5
9
  def self.spawn(data)
6
- proc_ele = @procs[data["pid"]]
10
+ pid = data["pid"].to_i
7
11
 
8
- if proc_ele
12
+ begin
13
+ proc_ele = PROCS[pid]
9
14
  proc_ele.update_data(data)
10
- else
11
- @procs[data["pid"]] = Knj::Unix_proc.new(data)
15
+ rescue WeakRef::RefError
16
+ proc_ele = Knj::Unix_proc.new(data)
17
+ PROCS[pid] = proc_ele
12
18
  end
13
19
 
14
- return @procs[data["pid"]]
20
+ return proc_ele
15
21
  end
16
22
 
17
23
  def self.list(args = {})
@@ -23,40 +29,43 @@ class Knj::Unix_proc
23
29
  cmdstr << " | #{grepstr}"
24
30
  end
25
31
 
26
- ret = []
27
- res = Knj::Os.shellcmd(cmdstr)
28
-
29
- res.scan(/^(\S+)\s+([0-9]+)\s+([0-9.]+)\s+([0-9.]+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+ (.+)($|\n)/) do |match|
30
- pid = match[1]
31
-
32
- data = {
33
- "user" => match[0],
34
- "pid" => pid,
35
- "cpu_last" => match[2],
36
- "ram_last" => match[3],
37
- "cmd" => match[4],
38
- "app" => File.basename(match[4])
39
- }
40
-
41
- next if (!args.key?("ignore_self") or args["ignore_self"]) and match[1].to_i == $$.to_i
42
- next if grepstr.length > 0 and match[4].index(grepstr) != nil #dont return current process.
32
+ MUTEX.synchronize do
33
+ ret = []
34
+ res = Knj::Os.shellcmd(cmdstr)
43
35
 
44
- if args.key?("pids")
45
- found = false
46
- args["pids"].each do |pid_given|
47
- if pid_given.to_s == pid.to_s
48
- found = true
49
- break
36
+ res.scan(/^(\S+)\s+([0-9]+)\s+([0-9.]+)\s+([0-9.]+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+ (.+)($|\n)/) do |match|
37
+ pid = match[1]
38
+
39
+ data = {
40
+ "user" => match[0],
41
+ "pid" => pid,
42
+ "cpu_last" => match[2],
43
+ "ram_last" => match[3],
44
+ "cmd" => match[4],
45
+ "app" => File.basename(match[4])
46
+ }
47
+
48
+ next if (!args.key?("ignore_self") or args["ignore_self"]) and match[1].to_i == $$.to_i
49
+ next if grepstr.length > 0 and match[4].index(grepstr) != nil #dont return current process.
50
+
51
+ if args.key?("pids")
52
+ found = false
53
+ args["pids"].each do |pid_given|
54
+ if pid_given.to_s == pid.to_s
55
+ found = true
56
+ break
57
+ end
50
58
  end
59
+
60
+ next if !found
51
61
  end
52
62
 
53
- next if !found
63
+ ret << Knj::Unix_proc.spawn(data)
54
64
  end
55
65
 
56
- ret << Knj::Unix_proc.spawn(data)
66
+ PROCS.clean
67
+ return ret
57
68
  end
58
-
59
- return ret
60
69
  end
61
70
 
62
71
  def self.find_self
@@ -466,7 +466,7 @@ class Knj::Web
466
466
  Knj::ArrayExt.hash_sym(args)
467
467
 
468
468
  if args.key?(:value)
469
- if args[:value].is_a?(Array) and args[:value].first.is_a?(NilClass)
469
+ if args[:value].is_a?(Array) and (args[:value].first.is_a?(NilClass) or args[:value].first == false)
470
470
  value = nil
471
471
  elsif args[:value].is_a?(Array)
472
472
  if !args[:value][2] or args[:value][2] == :key
@@ -530,6 +530,7 @@ class Knj::Web
530
530
  }
531
531
  attr.merge!(args[:attr]) if args[:attr]
532
532
  attr["disabled"] = "disabled" if args[:disabled]
533
+ attr["maxlength"] = args[:maxlength] if args.key?(:maxlength)
533
534
 
534
535
  raise "No name given to the Web::input()-method." if !args[:name] and args[:type] != :info and args[:type] != :textshow and args[:type] != :plain and args[:type] != :spacer and args[:type] != :headline
535
536
 
@@ -553,6 +554,12 @@ class Knj::Web
553
554
  classes_tr_html = ""
554
555
  end
555
556
 
557
+ if args.key?(:title)
558
+ title_html = args[:title].to_s.html
559
+ elsif args.key?(:title_html)
560
+ title_html = args[:title_html]
561
+ end
562
+
556
563
  html = ""
557
564
 
558
565
  classes = ["input_#{args[:type]}"]
@@ -567,17 +574,17 @@ class Knj::Web
567
574
  html << "<tr#{classes_tr_html}>"
568
575
  html << "<td colspan=\"2\" class=\"tdcheck\">"
569
576
  html << "<input#{self.attr_html(attr)} />"
570
- html << "<label for=\"#{args[:id].html}\">#{args[:title].html}</label>"
577
+ html << "<label for=\"#{args[:id].html}\">#{title_html}</label>"
571
578
  html << "</td>"
572
579
  html << "</tr>"
573
580
  elsif args[:type] == :headline
574
- html << "<tr#{classes_tr_html}><td colspan=\"2\"><h2 class=\"input_headline\">#{args[:title].html}</h2></td></tr>"
581
+ html << "<tr#{classes_tr_html}><td colspan=\"2\"><h2 class=\"input_headline\">#{title_html}</h2></td></tr>"
575
582
  elsif args[:type] == :spacer
576
583
  html << "<tr#{classes_tr_html}><td colspan=\"2\">&nbsp;</td></tr>"
577
584
  else
578
585
  html << "<tr#{classes_tr_html}>"
579
586
  html << "<td class=\"tdt\">"
580
- html << args[:title].to_s.html
587
+ html << title_html
581
588
  html << "</td>"
582
589
  html << "<td#{self.style_html(css)} class=\"tdc\">"
583
590
 
@@ -671,12 +678,7 @@ class Knj::Web
671
678
 
672
679
  def self.opts(opthash, curvalue = nil, opts_args = {})
673
680
  opts_args = {} if !opts_args
674
- opts_args.each do |key, value|
675
- if !key.is_a?(Symbol)
676
- opts_args[key.to_sym] = value
677
- opts_args.delete(key)
678
- end
679
- end
681
+ Knj::ArrayExt.hash_sym(opts_args)
680
682
 
681
683
  return "" if !opthash
682
684
  cname = curvalue.class.name
@@ -739,7 +741,7 @@ class Knj::Web
739
741
  return "gecko"
740
742
  elsif agent.index("msie") != nil
741
743
  return "msie"
742
- elsif agent.index("w3c") != nil or agent.index("baiduspider") != nil or agent.index("googlebot") != nil
744
+ elsif agent.index("w3c") != nil or agent.index("baiduspider") != nil or agent.index("googlebot") != nil or agent.index("bot") != nil
743
745
  return "bot"
744
746
  else
745
747
  #print "Unknown agent: #{agent}"
@@ -887,16 +889,36 @@ class Knj::Web
887
889
  browser = "bot"
888
890
  title = "AhrefsBot"
889
891
  version = match[1]
892
+ elsif agent.index("sosospider") != nil
893
+ browser = "bot"
894
+ title = "Bot"
895
+ version = "Sosospider"
890
896
  else
891
897
  browser = "unknown"
892
898
  title = "(unknown browser)"
893
899
  version = "(unknown version)"
894
900
  end
895
901
 
902
+ os = nil
903
+ os_version = nil
904
+ if agent.index("linux") != nil
905
+ os = "linux"
906
+ elsif match = agent.match(/mac\s+os\s+x\s+([\d_+])/)
907
+ os = "mac"
908
+ elsif match = agent.match(/windows\s+nt\s+([\d\.]+)/)
909
+ os = "windows"
910
+
911
+ if match[1] == "5.1"
912
+ os_version = "xp"
913
+ end
914
+ end
915
+
896
916
  return {
897
917
  "browser" => browser,
898
918
  "title" => title,
899
- "version" => version
919
+ "version" => version,
920
+ "os" => os,
921
+ "os_version" => os_version
900
922
  }
901
923
  end
902
924