vuf 1.0.1 → 1.1.0
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.
- 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
|