vuf 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vuf.rb +2 -0
- data/lib/vuf/profiler.rb +21 -8
- data/lib/vuf/server.rb +85 -0
- data/lib/vuf/version.rb +1 -1
- data/lib/vuf/working_pool.rb +7 -2
- data/test/lib/vuf/pool_test.rb +27 -21
- data/test/lib/vuf/profiler_test.rb +2 -0
- data/test/lib/vuf/server_test.rb +100 -0
- metadata +5 -2
data/lib/vuf.rb
CHANGED
data/lib/vuf/profiler.rb
CHANGED
@@ -17,27 +17,33 @@ module Vuf
|
|
17
17
|
@stats[:counter][label] += 1
|
18
18
|
}
|
19
19
|
end
|
20
|
-
def start(label)
|
21
|
-
@mutex.synchronize { @timers[[Thread.current,label]] = Time.new }
|
20
|
+
def start(label,limit=nil)
|
21
|
+
@mutex.synchronize { @timers[[Thread.current,label]] = [Time.new,limit] }
|
22
22
|
end
|
23
23
|
|
24
24
|
def stop(label)
|
25
|
+
Logger.error "Invalid label #{label}" unless label.instance_of?(String) || label.instance_of?(Symbol)
|
25
26
|
new_time = Time.new
|
26
27
|
@mutex.synchronize {
|
27
|
-
time = @timers.delete([Thread.current,label])
|
28
|
+
time,limit = @timers.delete([Thread.current,label])
|
28
29
|
if time
|
29
30
|
@stats[:time][label] ||= []
|
30
|
-
|
31
|
+
t = new_time - time
|
32
|
+
if limit && t > limit
|
33
|
+
Logger.warn "Time limit exceeds for #{label} : #{t} s"
|
34
|
+
end
|
35
|
+
@stats[:time][label] << t
|
31
36
|
end
|
32
37
|
}
|
33
38
|
end
|
34
39
|
|
35
40
|
def result
|
36
|
-
counter_stat = [] ; time_stat = []
|
41
|
+
counter_stat = [] ; time_stat = [] ; current_time = Time.new
|
37
42
|
error = nil
|
38
43
|
@mutex.synchronize {
|
39
44
|
begin
|
40
|
-
@stats[:counter].each{|k,v| counter_stat << "#{k} => #{v.to_s.rjust(10,' ')}" }
|
45
|
+
@stats[:counter].each{|k,v| counter_stat << [k, "#{k} => #{v.to_s.rjust(10,' ')}"] }
|
46
|
+
counter_stat = counter_stat.sort{|a,b| a.first <=> b.first}.collect{|a| a.last}
|
41
47
|
@stats[:time].each{ |k,v|
|
42
48
|
# retrieve previous av_time and number of mesures (nbdata)
|
43
49
|
av_time,nbdata = @stats[:avtime][k]
|
@@ -52,10 +58,17 @@ module Vuf
|
|
52
58
|
end
|
53
59
|
av_time = cumul_time / nbdata
|
54
60
|
time_stat << "#{k.to_s.rjust(20,' ')} => #{av_time.round(8).to_s.rjust(12,' ')} s/op " +
|
55
|
-
|
61
|
+
"[#{nbdata.to_s.rjust(12,' ')} op| #{(nbdata*av_time).round(2).to_s.rjust(8,' ')} s]"
|
56
62
|
@stats[:avtime][k] = [av_time,nbdata]
|
57
63
|
@stats[:time][k] = nil
|
58
|
-
}
|
64
|
+
}
|
65
|
+
@timers.each{|k,v|
|
66
|
+
t = current_time - v.first
|
67
|
+
if v.last && ( t > v.last)
|
68
|
+
time_stat << "Timeout on #{k.last} : #{t} s"
|
69
|
+
end
|
70
|
+
}
|
71
|
+
# time_stat = time_stat.sort{|a,b| a.first <=> b.first}.collect{|a| a.last}
|
59
72
|
rescue => e
|
60
73
|
Logger.error {"Error in statistic #{e.message}\n#{e.backtrace.join("\n")}"}
|
61
74
|
error = e
|
data/lib/vuf/server.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Vuf
|
2
|
+
class Server
|
3
|
+
|
4
|
+
def initialize(port, session_klass)
|
5
|
+
@port = port
|
6
|
+
@sessions_ctx = {}
|
7
|
+
@server_thread = nil
|
8
|
+
@closing_q = Queue.new
|
9
|
+
@session_klass = session_klass
|
10
|
+
@wp = Vuf::WorkingPool.new(4)
|
11
|
+
@wp.run
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
if @server_thread.nil?
|
16
|
+
@running = true
|
17
|
+
@server_thread = Thread.new do
|
18
|
+
Logger.debug "Server Starting"
|
19
|
+
begin
|
20
|
+
@server = TCPServer.new @port
|
21
|
+
@s_list = [@server]
|
22
|
+
while @running
|
23
|
+
close_ended_sessions
|
24
|
+
rsl, = IO.select(@s_list,[],[],1)
|
25
|
+
next if rsl.nil? # Timeout
|
26
|
+
accept(rsl) # Handle acceptance of new incoming session
|
27
|
+
rsl.each { |s| serve s }
|
28
|
+
end
|
29
|
+
rescue => e
|
30
|
+
Logger.error "Server Error [#{e}]
|
31
|
+
#{e.message}
|
32
|
+
#{e.backtrace.join("\n")}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def shutdown
|
39
|
+
@running = false
|
40
|
+
@server_thread.join unless @server_thread.nil?
|
41
|
+
@server_thread = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def accept(selected)
|
47
|
+
serv = selected.delete(@server)
|
48
|
+
if serv
|
49
|
+
sock = serv.accept
|
50
|
+
@s_list << sock
|
51
|
+
@sessions_ctx[sock] = @session_klass.new(sock)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def serve(sock)
|
56
|
+
msg_recv = sock.recv_nonblock(1024)
|
57
|
+
if msg_recv.empty?
|
58
|
+
@closing_q << sock
|
59
|
+
else
|
60
|
+
session = @sessions_ctx[sock]
|
61
|
+
@wp.do(session,session,msg_recv) do |sess,msg|
|
62
|
+
ret = sess.handle(msg)
|
63
|
+
if ret.nil?
|
64
|
+
Logger.error "Handle return nil on msg #{msg} at step #{sess.step}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def close_ended_sessions
|
71
|
+
until @closing_q.empty?
|
72
|
+
s = @closing_q.pop
|
73
|
+
session = @sessions_ctx.delete(s)
|
74
|
+
if session
|
75
|
+
@wp.do(session,session,s) do |sess,sock|
|
76
|
+
sess.finalize
|
77
|
+
sock.close
|
78
|
+
end
|
79
|
+
end
|
80
|
+
@s_list.delete(s)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
data/lib/vuf/version.rb
CHANGED
data/lib/vuf/working_pool.rb
CHANGED
@@ -44,14 +44,19 @@ module Vuf
|
|
44
44
|
|
45
45
|
def try_lock_channel(channel,task, args)
|
46
46
|
new_channel_q = nil
|
47
|
+
error = nil
|
47
48
|
@channels_mutex.synchronize {
|
48
49
|
if @channels[channel].nil?
|
49
50
|
new_channel_q = @channelsQ.shift
|
50
|
-
raise "Missing queue in working pool" unless new_channel_q.instance_of?(Queue)
|
51
51
|
@channels[channel]=new_channel_q
|
52
52
|
end
|
53
|
-
@channels[channel].
|
53
|
+
if @channels[channel].instance_of?(Queue)
|
54
|
+
@channels[channel].push([task, args])
|
55
|
+
else
|
56
|
+
error = "Missing queue in working pool"
|
57
|
+
end
|
54
58
|
}
|
59
|
+
raise error unless error.nil?
|
55
60
|
return new_channel_q
|
56
61
|
end
|
57
62
|
|
data/test/lib/vuf/pool_test.rb
CHANGED
@@ -1,4 +1,19 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
|
+
class PoolKlass
|
3
|
+
include Vuf::Pool
|
4
|
+
attr_reader :i_index
|
5
|
+
def initialize
|
6
|
+
@@index ||= 0
|
7
|
+
@@index += 1
|
8
|
+
@i_index = @@index
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(msg)
|
12
|
+
@f = File.open(File.join("test", "tmp", "file_#{@i_index}.txt"),"w+")
|
13
|
+
@f.write(msg)
|
14
|
+
@f.close
|
15
|
+
end
|
16
|
+
end
|
2
17
|
|
3
18
|
describe Vuf::Pool do
|
4
19
|
subject {
|
@@ -23,34 +38,25 @@ describe Vuf::Pool do
|
|
23
38
|
end
|
24
39
|
end
|
25
40
|
|
41
|
+
|
26
42
|
describe Vuf::Pool do
|
27
|
-
class PoolKlass
|
28
|
-
include Vuf::Pool
|
29
|
-
attr_reader :i_index
|
30
|
-
def initialize
|
31
|
-
@@index ||= 0
|
32
|
-
@@index += 1
|
33
|
-
@i_index = @@index
|
34
|
-
@f = File.open(File.join("test", "tmp", "file_#{@@index}.txt"),"w+")
|
35
|
-
end
|
36
|
-
|
37
|
-
def write(msg)
|
38
|
-
@f.write(msg)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
43
|
|
43
44
|
subject { 5 }
|
44
45
|
|
45
46
|
it "must create 5 Files" do
|
46
47
|
wp = Vuf::WorkingPool.new(subject)
|
47
48
|
wp.run
|
48
|
-
|
49
|
-
wp.do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
100.times do |i|
|
50
|
+
wp.do(i,i) { |i|
|
51
|
+
begin
|
52
|
+
writer = PoolKlass.instance
|
53
|
+
writer.write("Message #{i.to_s}\n")
|
54
|
+
sleep 0.01
|
55
|
+
PoolKlass.release
|
56
|
+
rescue => e
|
57
|
+
Vuf::Logger.error "#{e}\n#{e.message}\n#{e.backtrace.join("\n")}"
|
58
|
+
end
|
59
|
+
}
|
54
60
|
end
|
55
61
|
wp.finalize
|
56
62
|
Dir[File.join("test", "tmp","file_*.txt")].size.must_equal(subject)
|
@@ -4,6 +4,7 @@ describe Vuf::Profiler do
|
|
4
4
|
subject { Vuf::Profiler.new }
|
5
5
|
|
6
6
|
it "must parse options without errors" do
|
7
|
+
Vuf::Logger.outputters = Log4r::FileOutputter.new("profile_logger", {:filename => "test/tmp/log_profiler.log"})
|
7
8
|
subject.run(0.1)
|
8
9
|
10000.times do
|
9
10
|
subject.start('test')
|
@@ -11,5 +12,6 @@ describe Vuf::Profiler do
|
|
11
12
|
subject.stop('test')
|
12
13
|
end
|
13
14
|
subject.finalize
|
15
|
+
Vuf::Logger.outputters = Log4r::Outputter.stderr
|
14
16
|
end
|
15
17
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
STEPS = ["IPDU_CN", "IPDU_AC", "MSG_804", "MSG_814", "MSG_306", "MSG_316",
|
4
|
+
"MSG_246", "MSG_256", "MSG_506", "MSG_516", nil]
|
5
|
+
|
6
|
+
|
7
|
+
class TestSession
|
8
|
+
attr_reader :step
|
9
|
+
def initialize(socket)
|
10
|
+
@sock = socket
|
11
|
+
@step = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
@sock.send STEPS.first, 0
|
16
|
+
@step += 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle(msg)
|
20
|
+
curr_step = STEPS.index(msg)
|
21
|
+
if @step != curr_step
|
22
|
+
Vuf::Logger.error "Error received #{msg} on step #{@step}"
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
@step += 1
|
26
|
+
reply = STEPS[@step]
|
27
|
+
return nil if reply.nil?
|
28
|
+
no_reply = true
|
29
|
+
begin
|
30
|
+
@sock.send reply,0
|
31
|
+
no_reply = false
|
32
|
+
rescue => e
|
33
|
+
Vuf::Logger.error "Error on send #{reply} for #{@sock} => [#{e}]
|
34
|
+
#{e.message}
|
35
|
+
#{e.backtrace.join("\n")}"
|
36
|
+
ensure
|
37
|
+
if no_reply
|
38
|
+
Vuf::Logger.error "No reply send on session #{@sock} for msg #{msg} / reply #{reply} on step #{@step}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@step += 1
|
42
|
+
return @step
|
43
|
+
end
|
44
|
+
|
45
|
+
def finalize
|
46
|
+
if @step != (STEPS.size - 1)
|
47
|
+
Vuf::Logger.error "Error finalize on step #{@step}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
class TestClient
|
54
|
+
def initialize(nb_req)
|
55
|
+
@nb_req = nb_req
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
sockets = []
|
60
|
+
sessions = {}
|
61
|
+
done = 0 ; done_mutex = Mutex.new
|
62
|
+
nb_run=0
|
63
|
+
until done == @nb_req
|
64
|
+
while sockets.size < 20 && nb_run < @nb_req
|
65
|
+
nb_run += 1
|
66
|
+
s = TCPSocket.open('localhost',3527)
|
67
|
+
sockets << s
|
68
|
+
sessions[s] = TestSession.new(s)
|
69
|
+
sessions[s].start
|
70
|
+
end
|
71
|
+
|
72
|
+
rsl, = IO.select(sockets,[],[],1)
|
73
|
+
|
74
|
+
unless rsl.nil?
|
75
|
+
rsl.each do |s|
|
76
|
+
reply = s.recv(1024)
|
77
|
+
sess = sessions[s]
|
78
|
+
ret = sess.handle(reply)
|
79
|
+
if ret.nil?
|
80
|
+
s.close
|
81
|
+
done_mutex.synchronize { done += 1}
|
82
|
+
sockets.delete(s)
|
83
|
+
sessions.delete(s)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe Vuf::Server do
|
92
|
+
subject { Vuf::Server.new(3527,TestSession) }
|
93
|
+
|
94
|
+
it "must parse options without errors" do
|
95
|
+
# Run the server with logging enabled (it's a separate thread).
|
96
|
+
subject.start
|
97
|
+
TestClient.new(100).run
|
98
|
+
subject.shutdown
|
99
|
+
end
|
100
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -60,11 +60,13 @@ files:
|
|
60
60
|
- lib/vuf/logger.rb
|
61
61
|
- lib/vuf/pool.rb
|
62
62
|
- lib/vuf/profiler.rb
|
63
|
+
- lib/vuf/server.rb
|
63
64
|
- lib/vuf/version.rb
|
64
65
|
- lib/vuf/working_pool.rb
|
65
66
|
- test/lib/vuf/batch_test.rb
|
66
67
|
- test/lib/vuf/pool_test.rb
|
67
68
|
- test/lib/vuf/profiler_test.rb
|
69
|
+
- test/lib/vuf/server_test.rb
|
68
70
|
- test/lib/vuf/wp_test.rb
|
69
71
|
- test/test_helper.rb
|
70
72
|
- test/tmp/.gitignore
|
@@ -99,6 +101,7 @@ test_files:
|
|
99
101
|
- test/lib/vuf/batch_test.rb
|
100
102
|
- test/lib/vuf/pool_test.rb
|
101
103
|
- test/lib/vuf/profiler_test.rb
|
104
|
+
- test/lib/vuf/server_test.rb
|
102
105
|
- test/lib/vuf/wp_test.rb
|
103
106
|
- test/test_helper.rb
|
104
107
|
- test/tmp/.gitignore
|