knjrbfw 0.0.21 → 0.0.22

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