ruby-iarm 0.0.2 → 0.0.3
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/CHANGELOG +3 -0
- data/Manifest +2 -1
- data/Rakefile +5 -2
- data/lib/iarm.rb +1 -1
- data/lib/iarm/channel.rb +29 -0
- data/lib/iarm/handle.rb +83 -0
- data/lib/iarm/msg.rb +1 -2
- data/lib/iarm/server.rb +69 -145
- data/lib/iarm/timer.rb +63 -24
- data/ruby-iarm.gemspec +8 -8
- data/test/performance_test.rb +26 -0
- data/test/test_iarm.rb +35 -3
- metadata +13 -9
data/CHANGELOG
CHANGED
data/Manifest
CHANGED
@@ -7,7 +7,9 @@ example/IARMserver.rb
|
|
7
7
|
example/chattest.rb
|
8
8
|
example/chattest_sniffer.rb
|
9
9
|
lib/iarm.rb
|
10
|
+
lib/iarm/channel.rb
|
10
11
|
lib/iarm/client.rb
|
12
|
+
lib/iarm/handle.rb
|
11
13
|
lib/iarm/msg.rb
|
12
14
|
lib/iarm/msg/channel_member.rb
|
13
15
|
lib/iarm/msg/join.rb
|
@@ -16,7 +18,6 @@ lib/iarm/msg/timeout.rb
|
|
16
18
|
lib/iarm/msg/topic.rb
|
17
19
|
lib/iarm/server.rb
|
18
20
|
lib/iarm/timer.rb
|
19
|
-
ruby-iarm.gemspec
|
20
21
|
test/performance_test.rb
|
21
22
|
test/test_iarm.rb
|
22
23
|
Manifest
|
data/Rakefile
CHANGED
data/lib/iarm.rb
CHANGED
data/lib/iarm/channel.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module Iarm
|
3
|
+
class Channel
|
4
|
+
|
5
|
+
|
6
|
+
attr_reader :created_at, :name
|
7
|
+
attr_accessor :members, :topic, :key
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@key = key
|
12
|
+
@members = {}
|
13
|
+
@created_at = Time.now.to_i
|
14
|
+
@topic = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(handle, msg)
|
18
|
+
handle.say(self, msg)
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
@members.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def members_by_name
|
26
|
+
@members.keys.inject({}) {|hash,handle| hash[handle.name] = @members[handle] ; hash }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/iarm/handle.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
module Iarm
|
3
|
+
class Handle
|
4
|
+
|
5
|
+
attr_reader :touched_at, :created_at, :name, :timer
|
6
|
+
attr_accessor :ttl, :channels
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@msg_mutex = Mutex.new
|
10
|
+
@channels = {}
|
11
|
+
@name = name
|
12
|
+
@timer = Iarm::Timer.new
|
13
|
+
@created_at = Time.now.to_i
|
14
|
+
@ttl = 90
|
15
|
+
@msgs = []
|
16
|
+
self.touch
|
17
|
+
end
|
18
|
+
|
19
|
+
def timed_out?
|
20
|
+
(@touched_at + @ttl) < Time.now.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_msg
|
24
|
+
@msg_mutex.synchronize { @msgs.shift }
|
25
|
+
end
|
26
|
+
|
27
|
+
def push_msg(msg)
|
28
|
+
@msg_mutex.synchronize { @msgs << msg }
|
29
|
+
end
|
30
|
+
|
31
|
+
def no_msgs?
|
32
|
+
@msgs.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def touch
|
36
|
+
@touched_at = Time.now.to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
def timeout # returns list of channels that this handle was a member of
|
40
|
+
@channels.keys.select do |channel|
|
41
|
+
channel.members.delete(self)
|
42
|
+
channel.post(self, Msg::Timeout.new(channel.name, self.name))
|
43
|
+
@channels.delete(channel)
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def depart(channel) # returns a list of channels that we departed
|
50
|
+
@channels.keys.select do |ch|
|
51
|
+
if channel.nil? || ch == channel
|
52
|
+
ch.members.delete(self)
|
53
|
+
@channels.delete(ch)
|
54
|
+
ch.post(self, Msg::Part.new(ch.name, self.name))
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def join(channel)
|
61
|
+
@channels[channel] = channel.members[self] = Time.now.to_i
|
62
|
+
send_msg(channel.topic) if channel.topic
|
63
|
+
channel.post(self, Msg::Join.new(channel.name, self.name, @channels[channel]))
|
64
|
+
end
|
65
|
+
|
66
|
+
def send_msg(msg)
|
67
|
+
if(msg.kind_of?(Msg::Topic) || @name != msg.from)
|
68
|
+
#puts "MSG[#{msg.class}] <##{msg.channel}:#{msg.from}> #{@name} : #{msg.data}"
|
69
|
+
self.push_msg(msg)
|
70
|
+
self.poke
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def poke
|
75
|
+
@timer.poke
|
76
|
+
end
|
77
|
+
|
78
|
+
def say(channel, msg)
|
79
|
+
channel.members.each_key {|member| member.send_msg(msg) }
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
data/lib/iarm/msg.rb
CHANGED
data/lib/iarm/server.rb
CHANGED
@@ -3,63 +3,51 @@ require 'thread'
|
|
3
3
|
require 'drb'
|
4
4
|
|
5
5
|
|
6
|
-
|
7
6
|
module Iarm
|
8
7
|
class Server
|
9
8
|
|
10
|
-
def ping
|
9
|
+
def ping(nickname=nil)
|
10
|
+
touch_nickname(nickname) if nickname
|
11
11
|
'pong'
|
12
12
|
end
|
13
|
-
|
14
|
-
|
13
|
+
|
14
|
+
def ttl(nickname, ttl_secs)
|
15
|
+
handle = touch_nickname(nickname)
|
16
|
+
handle.ttl = ttl_secs
|
15
17
|
end
|
16
18
|
|
17
19
|
def list(pattern=nil)
|
18
20
|
pattern ? @channels.keys.grep(pattern) : @channels.keys
|
19
21
|
end
|
20
22
|
|
21
|
-
def who(
|
22
|
-
|
23
|
-
@channel_members[channel] #.each {|w,time| post_msg(who, Msg::ChannelMember.new(channel, w, time)) }
|
24
|
-
else
|
25
|
-
{}
|
26
|
-
end
|
23
|
+
def who(channelname)
|
24
|
+
(ch = find_channel(channelname)) && ch.members_by_name || {}
|
27
25
|
end
|
28
26
|
|
29
|
-
def join(who,
|
27
|
+
def join(who, channelname, key=nil) # returns true if joined, false if denied, and nil if new channel formed
|
30
28
|
retval = nil
|
31
|
-
touch_nickname(who)
|
32
|
-
@
|
33
|
-
if(
|
34
|
-
retval =
|
29
|
+
handle = touch_nickname(who)
|
30
|
+
@channel_mutex.synchronize do
|
31
|
+
if(channel = find_channel(channelname))
|
32
|
+
retval = channel.key == key # verify password
|
35
33
|
else
|
36
|
-
@channels[
|
34
|
+
@channels[channelname].key = key # create the channel
|
37
35
|
end
|
38
36
|
|
39
37
|
if(retval != false) # if retval is true (joined existing) or nil (new channel formed)
|
40
|
-
if(
|
41
|
-
|
42
|
-
@channels_joined[who] << channel
|
43
|
-
send_msg(Msg::Join.new(channel, who, @channel_members[channel][who]))
|
44
|
-
post_msg(who, @topics[channel]) if @topics.has_key?(channel)
|
38
|
+
if(!(channel = @channels[channelname]).members.has_key?(handle)) # don't re-join them if they've already joined before
|
39
|
+
handle.join(channel)
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
48
43
|
retval
|
49
44
|
end
|
50
45
|
|
51
|
-
def depart(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
send_msg(Msg::Part.new(ch, who))
|
57
|
-
end
|
58
|
-
check_channel_empty(ch)
|
59
|
-
end
|
60
|
-
kill_client(who) if(channel.nil?)
|
61
|
-
end
|
62
|
-
|
46
|
+
def depart(nickname, channelname=nil) # nil=depart ALL channels and log out client
|
47
|
+
handle = touch_nickname(nickname)
|
48
|
+
channel = (find_channel(channelname) if channelname)
|
49
|
+
handle.depart(channel).each {|ch| check_channel_empty(ch) }
|
50
|
+
@handles.delete(nickname) if channelname.nil?
|
63
51
|
end
|
64
52
|
|
65
53
|
# getmsg(): NOTES
|
@@ -68,28 +56,15 @@ module Iarm
|
|
68
56
|
# if who=nil then it listens on all channels, but only one client can do this at once
|
69
57
|
# if another client is already listening with the same who-id, it has the effect of making them return immediately (before their timeout is up)
|
70
58
|
def getmsg(who, timeout=0)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
wait_existing = Iarm::Timer.poke(@listeners[who])
|
75
|
-
next_msg(who)
|
76
|
-
end
|
77
|
-
return msg if(msg)
|
78
|
-
|
79
|
-
if(wait_existing)
|
80
|
-
Thread.pass while(@mutex.synchronize { @listeners.has_key?(who) })
|
81
|
-
end
|
59
|
+
handle = touch_nickname(who)
|
60
|
+
if(timeout != 0 && handle.no_msgs?)
|
61
|
+
handle.poke
|
82
62
|
|
83
|
-
|
84
|
-
|
85
|
-
@mutex.synchronize do
|
86
|
-
mode ? @listeners[who] = Thread.current : @listeners.delete(who)
|
87
|
-
end
|
88
|
-
#puts "IARM getmsg: #{who} #{mode ? 'entering' : 'exiting'} wait with msgcount=#{@msgs[who].length}"
|
89
|
-
Iarm::Timer.poke(Thread.current) if mode && @msgs[who].length>0 # don't bother sleeping if we already have a new message waiting
|
63
|
+
handle.timer.wait(timeout) do |mode|
|
64
|
+
mode && handle.no_msgs?
|
90
65
|
end
|
91
66
|
end
|
92
|
-
|
67
|
+
handle.next_msg
|
93
68
|
end
|
94
69
|
|
95
70
|
def getmsgs(who, timeout=0)
|
@@ -100,30 +75,31 @@ module Iarm
|
|
100
75
|
res
|
101
76
|
end
|
102
77
|
|
103
|
-
def say(
|
104
|
-
|
78
|
+
def say(nickname, channelname, data)
|
79
|
+
handle = touch_nickname(nickname)
|
80
|
+
if(channel = find_channel(channelname))
|
81
|
+
channel.post(handle, Iarm::Msg.new(channelname, nickname, data))
|
82
|
+
end
|
105
83
|
end
|
106
84
|
|
107
|
-
def set_topic(
|
108
|
-
touch_nickname(
|
109
|
-
if
|
110
|
-
|
111
|
-
if(
|
112
|
-
|
113
|
-
post(
|
114
|
-
|
85
|
+
def set_topic(nickname, channelname, topic_data)
|
86
|
+
handle = touch_nickname(nickname)
|
87
|
+
if(channel = find_channel(channelname))
|
88
|
+
topic_data = Msg::Topic.new(channelname, nickname, topic_data) unless topic_data.kind_of?(Msg::Topic)
|
89
|
+
if(channel.topic != topic_data)
|
90
|
+
channel.topic = topic_data
|
91
|
+
channel.post(handle, topic_data)
|
92
|
+
topic_data
|
115
93
|
end
|
116
94
|
end
|
117
95
|
end
|
118
96
|
|
119
|
-
def get_topic(
|
120
|
-
|
97
|
+
def get_topic(channelname)
|
98
|
+
if(channel = find_channel(channelname))
|
99
|
+
channel.topic
|
100
|
+
end
|
121
101
|
end
|
122
102
|
|
123
|
-
def post(msg)
|
124
|
-
@mutex.synchronize { send_msg(msg) } if(msg.kind_of?(Msg))
|
125
|
-
end
|
126
|
-
|
127
103
|
def self.start(uri=nil)
|
128
104
|
DRb.start_service(uri, self.new)
|
129
105
|
DRb.thread
|
@@ -133,43 +109,30 @@ module Iarm
|
|
133
109
|
REAPER_GRANULARITY = 5 #seconds
|
134
110
|
|
135
111
|
def initialize
|
136
|
-
@
|
137
|
-
@
|
138
|
-
@
|
139
|
-
@
|
140
|
-
@msgs = Hash.new() {|hsh,key| hsh[key] = [ ] } # { who => [ msg1, msg2, ...] }
|
141
|
-
@clients = Hash.new() # { who => time_of_last_activity }
|
142
|
-
@channel_members = Hash.new() {|hsh,key| hsh[key] = { } } # { channelname => { who1 => join_time }, who2 => ...] }
|
143
|
-
@channels_joined = Hash.new() {|hsh,key| hsh[key] = [ ] } # { who => [ channel1, channel2 ] }
|
144
|
-
@channels = Hash.new() # { channelname => password }
|
145
|
-
@topics = Hash.new() # { channelname => topic }
|
112
|
+
@channel_mutex = Mutex.new()
|
113
|
+
@handle_mutex = Mutex.new()
|
114
|
+
@handles = Hash.new() # { nickname => Handle object }
|
115
|
+
@channels = Hash.new() {|hsh,key| hsh[key] = Iarm::Channel.new(key) }
|
146
116
|
@timeout_queue = []
|
147
117
|
reaper_thread
|
148
118
|
end
|
149
119
|
|
150
|
-
def touch_nickname(nickname) #
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
120
|
+
def touch_nickname(nickname, refresh=true) # returns Handle object
|
121
|
+
if !@handles.has_key?(nickname)
|
122
|
+
@handle_mutex.synchronize { @handles[nickname] ||= Iarm::Handle.new(nickname) }
|
123
|
+
end
|
124
|
+
handle = @handles[nickname]
|
125
|
+
handle.touch
|
126
|
+
if(refresh)
|
127
|
+
timeout_box = (handle.ttl.to_f / REAPER_GRANULARITY).ceil.to_i #/
|
128
|
+
@timeout_queue[timeout_box] ||= {}
|
129
|
+
@timeout_queue[timeout_box][handle] = true
|
157
130
|
end
|
131
|
+
handle
|
158
132
|
end
|
159
133
|
|
160
|
-
|
161
|
-
|
162
|
-
reaper ideas
|
163
|
-
------------
|
164
|
-
|
165
|
-
have a linked list which is in order of things to timeout
|
166
|
-
when taking something off the list, check its actual timeout value and put it back to sleep if needed
|
167
|
-
this could be a binary search down the track, for performance
|
168
|
-
|
169
|
-
=end
|
170
|
-
|
171
|
-
def timed_out?(nickname)
|
172
|
-
(tla = @clients[nickname]) && (tla + @ttl_secs) < clockval
|
134
|
+
def find_channel(channelname)
|
135
|
+
@channels[channelname] if @channels.has_key?(channelname)
|
173
136
|
end
|
174
137
|
|
175
138
|
def reaper_thread
|
@@ -177,25 +140,12 @@ module Iarm
|
|
177
140
|
loop do
|
178
141
|
kill_list = []
|
179
142
|
sleep REAPER_GRANULARITY
|
180
|
-
@
|
181
|
-
|
182
|
-
if timeoutlist
|
183
|
-
timeoutlist.each do |who|
|
184
|
-
kill_list << who if timed_out?(who)
|
185
|
-
end
|
186
|
-
end
|
143
|
+
if(timeoutlist = @timeout_queue.shift)
|
144
|
+
kill_list = timeoutlist.keys.select {|who| who.timed_out? }
|
187
145
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
@channels_joined[who].each do |ch|
|
192
|
-
@channel_members[ch].delete(who)
|
193
|
-
send_msg(Msg::Timeout.new(ch, who))
|
194
|
-
check_channel_empty(ch)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
kill_client(who)
|
198
|
-
end
|
146
|
+
kill_list.each do |who|
|
147
|
+
who.timeout.each {|ch| check_channel_empty(ch) }
|
148
|
+
@handles.delete(who.name)
|
199
149
|
end
|
200
150
|
end
|
201
151
|
end
|
@@ -204,37 +154,11 @@ module Iarm
|
|
204
154
|
def clockval
|
205
155
|
Time.new.to_i
|
206
156
|
end
|
207
|
-
|
208
|
-
def send_msg(msg)
|
209
|
-
@channel_members[msg.channel].each_key {|w| post_msg(w, msg) }
|
210
|
-
post_msg(nil, msg) if(@clients.has_key?(nil))
|
211
|
-
end
|
212
|
-
def post_msg(who, msg)
|
213
|
-
if(msg.kind_of?(Msg::Topic) || who != msg.from)
|
214
|
-
@msgs[who] << msg
|
215
|
-
Iarm::Timer.poke(@listeners[who]) if(@listeners.has_key?(who))
|
216
|
-
end
|
217
|
-
end
|
218
|
-
def next_msg(who) # returns msg or nil
|
219
|
-
touch_nickname(who)
|
220
|
-
@msgs[who].shift
|
221
|
-
end
|
157
|
+
|
222
158
|
def check_channel_empty(channel)
|
223
|
-
|
224
|
-
@channels.delete(channel)
|
225
|
-
@channel_members.delete(channel)
|
226
|
-
@topics.delete(channel)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
def kill_client(who)
|
230
|
-
@channels_joined[who].each do |ch|
|
231
|
-
@channel_members[ch].delete(who)
|
232
|
-
check_channel_empty(ch)
|
159
|
+
@channel_mutex.synchronize do
|
160
|
+
@channels.delete(channel.name) if channel.empty?
|
233
161
|
end
|
234
|
-
@channels_joined.delete(who)
|
235
|
-
@clients.delete(who)
|
236
|
-
@msgs.delete(who)
|
237
|
-
@listeners.delete(who)
|
238
162
|
end
|
239
163
|
|
240
164
|
end
|
data/lib/iarm/timer.rb
CHANGED
@@ -6,44 +6,83 @@ module Iarm
|
|
6
6
|
class Timeout < Exception; end
|
7
7
|
class Poke < Exception; end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
def initialize
|
10
|
+
@poked = false
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@resource = ConditionVariable.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def poke(timeout=false)
|
16
|
+
@mutex.synchronize do
|
17
|
+
@poked = true if timeout
|
18
|
+
@resource.signal
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
22
|
+
def wait(timeout)
|
21
23
|
timer = create_timer(timeout)
|
22
|
-
|
23
|
-
|
24
|
+
should_wait = true
|
25
|
+
should_wait = yield(true) if block_given?
|
26
|
+
if should_wait
|
27
|
+
@mutex.synchronize do
|
28
|
+
@resource.wait(@mutex)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
@poked
|
24
32
|
rescue Timeout
|
25
|
-
return false
|
26
|
-
rescue Poke
|
27
|
-
return true
|
28
33
|
ensure
|
29
34
|
Thread.kill(timer) if(timer && timer.alive?)
|
30
|
-
yield(false)
|
35
|
+
yield(false) if block_given?
|
31
36
|
end
|
32
37
|
|
33
|
-
def self.crit
|
34
|
-
yield
|
35
|
-
end
|
36
|
-
|
37
38
|
private
|
38
|
-
def
|
39
|
+
def create_timer(timeout)
|
39
40
|
return nil if(timeout.nil?)
|
40
|
-
|
41
41
|
waiter = Thread.current
|
42
42
|
Thread.start do
|
43
|
-
Thread.pass
|
44
43
|
sleep(timeout)
|
45
|
-
|
46
|
-
|
44
|
+
poke(true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def poke(thr)
|
50
|
+
if(thr)# && thr.stop?)
|
51
|
+
thr.raise(Poke.new)
|
52
|
+
true
|
53
|
+
else
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def wait(timeout)
|
59
|
+
timer = create_timer(timeout)
|
60
|
+
yield(true) if block_given?
|
61
|
+
Thread.stop
|
62
|
+
rescue Timeout
|
63
|
+
return false
|
64
|
+
rescue Poke
|
65
|
+
return true
|
66
|
+
ensure
|
67
|
+
Thread.kill(timer) if(timer && timer.alive?)
|
68
|
+
yield(false) if block_given?
|
69
|
+
end
|
70
|
+
|
71
|
+
def crit
|
72
|
+
(@mutex ||= Mutex.new).synchronize { yield }
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def create_timer(timeout)
|
77
|
+
return nil if(timeout.nil?)
|
78
|
+
|
79
|
+
waiter = Thread.current
|
80
|
+
Thread.start do
|
81
|
+
Thread.pass
|
82
|
+
sleep(timeout)
|
83
|
+
# Thread.critical = true
|
84
|
+
waiter.raise(Timeout.new)
|
85
|
+
end
|
47
86
|
end
|
48
87
|
end
|
49
88
|
end
|
data/ruby-iarm.gemspec
CHANGED
@@ -2,21 +2,21 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{ruby-iarm}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = [""]
|
9
|
-
s.date = %q{2010-
|
10
|
-
s.description = %q{}
|
11
|
-
s.email = %q{}
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "README.textile", "lib/iarm.rb", "lib/iarm/client.rb", "lib/iarm/msg.rb", "lib/iarm/msg/channel_member.rb", "lib/iarm/msg/join.rb", "lib/iarm/msg/part.rb", "lib/iarm/msg/timeout.rb", "lib/iarm/msg/topic.rb", "lib/iarm/server.rb", "lib/iarm/timer.rb"]
|
13
|
-
s.files = ["CHANGELOG", "LICENSE", "README", "README.textile", "Rakefile", "example/IARMserver.rb", "example/chattest.rb", "example/chattest_sniffer.rb", "lib/iarm.rb", "lib/iarm/client.rb", "lib/iarm/msg.rb", "lib/iarm/msg/channel_member.rb", "lib/iarm/msg/join.rb", "lib/iarm/msg/part.rb", "lib/iarm/msg/timeout.rb", "lib/iarm/msg/topic.rb", "lib/iarm/server.rb", "lib/iarm/timer.rb", "
|
8
|
+
s.authors = ["Andrew Snow"]
|
9
|
+
s.date = %q{2010-08-25}
|
10
|
+
s.description = %q{IRC-like Messaging Server for Ruby}
|
11
|
+
s.email = %q{andrew@modulus.org}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "README.textile", "lib/iarm.rb", "lib/iarm/channel.rb", "lib/iarm/client.rb", "lib/iarm/handle.rb", "lib/iarm/msg.rb", "lib/iarm/msg/channel_member.rb", "lib/iarm/msg/join.rb", "lib/iarm/msg/part.rb", "lib/iarm/msg/timeout.rb", "lib/iarm/msg/topic.rb", "lib/iarm/server.rb", "lib/iarm/timer.rb"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "README", "README.textile", "Rakefile", "example/IARMserver.rb", "example/chattest.rb", "example/chattest_sniffer.rb", "lib/iarm.rb", "lib/iarm/channel.rb", "lib/iarm/client.rb", "lib/iarm/handle.rb", "lib/iarm/msg.rb", "lib/iarm/msg/channel_member.rb", "lib/iarm/msg/join.rb", "lib/iarm/msg/part.rb", "lib/iarm/msg/timeout.rb", "lib/iarm/msg/topic.rb", "lib/iarm/server.rb", "lib/iarm/timer.rb", "test/performance_test.rb", "test/test_iarm.rb", "Manifest", "ruby-iarm.gemspec"]
|
14
14
|
s.homepage = %q{}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ruby-iarm", "--main", "README"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{ruby-iarm}
|
18
18
|
s.rubygems_version = %q{1.3.7}
|
19
|
-
s.summary = %q{}
|
19
|
+
s.summary = %q{IRC-like Messaging Server for Ruby}
|
20
20
|
s.test_files = ["test/test_iarm.rb", "test/performance_test.rb"]
|
21
21
|
|
22
22
|
if s.respond_to? :specification_version then
|
data/test/performance_test.rb
CHANGED
@@ -1 +1,27 @@
|
|
1
1
|
|
2
|
+
require "#{File.dirname(__FILE__)}/../lib/iarm"
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
|
5
|
+
socket_path = 'drbunix:/tmp/.s.perftestiarm'
|
6
|
+
num_clients = 4
|
7
|
+
|
8
|
+
server_pid = fork do
|
9
|
+
puts "#{$$} Starting server"
|
10
|
+
Iarm::Server.start(socket_path)
|
11
|
+
loop { sleep 10 }
|
12
|
+
end
|
13
|
+
|
14
|
+
client_pids = []
|
15
|
+
|
16
|
+
|
17
|
+
# handle sigpipe, check exit values, shutdown on any failures
|
18
|
+
|
19
|
+
|
20
|
+
num_clients.times do
|
21
|
+
Iarm::Client.connect(socket_path) or raise 'Cannot connect'
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
puts "Finished"
|
27
|
+
Process.kill(9, server_pid)
|
data/test/test_iarm.rb
CHANGED
@@ -36,7 +36,37 @@ end
|
|
36
36
|
class TestIarm < Test::Unit::TestCase
|
37
37
|
include TestIarmServer
|
38
38
|
|
39
|
-
def
|
39
|
+
def test_getmsg_with_timeout
|
40
|
+
@client1.join('client1', 'test_channel')
|
41
|
+
@client2.join('client2', 'test_channel')
|
42
|
+
|
43
|
+
# first test timeout with no messages
|
44
|
+
starttime = Time.now.to_f
|
45
|
+
msg = @client2.getmsg('client2', 2)
|
46
|
+
assert_nil msg
|
47
|
+
assert_in_delta(2, (Time.now.to_f - starttime), 0.5) # should have waited 2 seconds
|
48
|
+
|
49
|
+
testerthread = Thread.start do
|
50
|
+
sleep 1
|
51
|
+
new_connection = new_client
|
52
|
+
new_connection.say('client1', 'test_channel', 'TEST message!')
|
53
|
+
end
|
54
|
+
|
55
|
+
begin
|
56
|
+
starttime = Time.now.to_f
|
57
|
+
msg = @client2.getmsg('client2', 4)
|
58
|
+
|
59
|
+
assert_in_delta(1, (Time.now.to_f - starttime), 1) # make sure we didn't wait 4 seconds
|
60
|
+
assert_instance_of Iarm::Msg, msg
|
61
|
+
assert_equal 'client1', msg.from
|
62
|
+
assert_equal 'test_channel', msg.channel
|
63
|
+
assert_equal 'TEST message!', msg.data
|
64
|
+
ensure
|
65
|
+
testerthread.join
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_join
|
40
70
|
@client1.join('client1', 'test_channel')
|
41
71
|
@client2.join('client2', 'test_channel')
|
42
72
|
|
@@ -125,10 +155,12 @@ class TestIarm < Test::Unit::TestCase
|
|
125
155
|
end
|
126
156
|
|
127
157
|
def test_timeout
|
128
|
-
@client1.ttl(2)
|
129
158
|
@client1.join('client1', 'test_channel')
|
159
|
+
@client1.ttl('client1', 2)
|
130
160
|
assert_equal ['client1'], @client2.who('test_channel').keys
|
131
|
-
|
161
|
+
assert_equal 'pong', @client1.ping('client1')
|
162
|
+
countdown = Iarm::Server::REAPER_GRANULARITY * 2 + 1
|
163
|
+
sleep 1 while((countdown -= 1) >= 0 && !@client2.who('test_channel').empty?)
|
132
164
|
assert_equal [], @client2.who('test_channel').keys
|
133
165
|
end
|
134
166
|
end
|
metadata
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-iarm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
|
-
-
|
13
|
+
- Andrew Snow
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-08-25 00:00:00 +10:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
22
|
-
description:
|
23
|
-
email:
|
22
|
+
description: IRC-like Messaging Server for Ruby
|
23
|
+
email: andrew@modulus.org
|
24
24
|
executables: []
|
25
25
|
|
26
26
|
extensions: []
|
@@ -31,7 +31,9 @@ extra_rdoc_files:
|
|
31
31
|
- README
|
32
32
|
- README.textile
|
33
33
|
- lib/iarm.rb
|
34
|
+
- lib/iarm/channel.rb
|
34
35
|
- lib/iarm/client.rb
|
36
|
+
- lib/iarm/handle.rb
|
35
37
|
- lib/iarm/msg.rb
|
36
38
|
- lib/iarm/msg/channel_member.rb
|
37
39
|
- lib/iarm/msg/join.rb
|
@@ -50,7 +52,9 @@ files:
|
|
50
52
|
- example/chattest.rb
|
51
53
|
- example/chattest_sniffer.rb
|
52
54
|
- lib/iarm.rb
|
55
|
+
- lib/iarm/channel.rb
|
53
56
|
- lib/iarm/client.rb
|
57
|
+
- lib/iarm/handle.rb
|
54
58
|
- lib/iarm/msg.rb
|
55
59
|
- lib/iarm/msg/channel_member.rb
|
56
60
|
- lib/iarm/msg/join.rb
|
@@ -59,10 +63,10 @@ files:
|
|
59
63
|
- lib/iarm/msg/topic.rb
|
60
64
|
- lib/iarm/server.rb
|
61
65
|
- lib/iarm/timer.rb
|
62
|
-
- ruby-iarm.gemspec
|
63
66
|
- test/performance_test.rb
|
64
67
|
- test/test_iarm.rb
|
65
68
|
- Manifest
|
69
|
+
- ruby-iarm.gemspec
|
66
70
|
has_rdoc: true
|
67
71
|
homepage: ""
|
68
72
|
licenses: []
|
@@ -102,7 +106,7 @@ rubyforge_project: ruby-iarm
|
|
102
106
|
rubygems_version: 1.3.7
|
103
107
|
signing_key:
|
104
108
|
specification_version: 3
|
105
|
-
summary:
|
109
|
+
summary: IRC-like Messaging Server for Ruby
|
106
110
|
test_files:
|
107
111
|
- test/test_iarm.rb
|
108
112
|
- test/performance_test.rb
|