ipc_transit 0.0.1 → 0.0.2
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/bin/transitd +31 -0
- data/bin/trsend +7 -2
- data/bin/trserver +41 -0
- data/lib/ipc_transit.rb +65 -25
- data/test/tc_transit_remote.rb +51 -0
- metadata +10 -4
data/bin/transitd
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'ipc_transit'
|
5
|
+
|
6
|
+
$url = 'http://127.0.0.1:8726/transit_data'
|
7
|
+
|
8
|
+
|
9
|
+
def one_message
|
10
|
+
message = IPCTransit.receive('qname' => 'transitd', 'raw' => 1)
|
11
|
+
if not (serialized_message = message['serialized_wire_data'])
|
12
|
+
raise 'Message did not contain serialized_wire_data'
|
13
|
+
end
|
14
|
+
if not (wire_headers = message['wire_headers'])
|
15
|
+
raise 'Message did not contain wire_headers'
|
16
|
+
end
|
17
|
+
if not (d = wire_headers['d'])
|
18
|
+
raise 'Message did not contain required wire attribite "d"'
|
19
|
+
end
|
20
|
+
postData = Net::HTTP.post_form(URI.parse($url),
|
21
|
+
{'data'=>serialized_message})
|
22
|
+
puts postData.body
|
23
|
+
end
|
24
|
+
while 1
|
25
|
+
begin
|
26
|
+
one_message()
|
27
|
+
rescue Exception => e
|
28
|
+
puts "Exception: #{e}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/bin/trsend
CHANGED
@@ -2,9 +2,14 @@
|
|
2
2
|
require 'ipc_transit'
|
3
3
|
require 'json'
|
4
4
|
|
5
|
+
|
5
6
|
qname = ARGV[0]
|
6
7
|
message = JSON.parse(ARGV[1])
|
8
|
+
dest = ARGV[2]
|
7
9
|
|
8
|
-
|
9
|
-
ret = IPCTransit.send('message' => message, 'qname' => qname)
|
10
|
+
if dest.nil?
|
11
|
+
ret = IPCTransit.send('message' => message, 'qname' => qname)
|
12
|
+
else
|
13
|
+
ret = IPCTransit.send('message' => message, 'qname' => qname, 'd' => dest)
|
14
|
+
end
|
10
15
|
puts ret
|
data/bin/trserver
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'webrick'
|
3
|
+
require 'ipc_transit'
|
4
|
+
|
5
|
+
|
6
|
+
class PersistAnswers < WEBrick::HTTPServlet::AbstractServlet
|
7
|
+
def do_POST(request, response)
|
8
|
+
status, content_type, body = handle_data(request)
|
9
|
+
|
10
|
+
response.status = status
|
11
|
+
response['Content-Type'] = content_type
|
12
|
+
response.body = body
|
13
|
+
end
|
14
|
+
|
15
|
+
def handle_data(request)
|
16
|
+
if (data = request.query['data'])
|
17
|
+
qname = handle_message({ 'serialized_wire_data' => data })
|
18
|
+
end
|
19
|
+
return 200, 'text/plain', "Forwarding message to queue '#{qname}'"
|
20
|
+
end
|
21
|
+
def handle_message(args)
|
22
|
+
IPCTransit.unpack_data(args)
|
23
|
+
if not (wire_headers = args['wire_headers'])
|
24
|
+
raise 'Message did not contain wire_headers'
|
25
|
+
end
|
26
|
+
if not (args['qname'] = wire_headers['q'])
|
27
|
+
raise 'Message did not contain required wire attribite "q"'
|
28
|
+
end
|
29
|
+
#at this point we should make sure the message we received
|
30
|
+
#is truly destined for this box
|
31
|
+
#we should also decrement the TTL
|
32
|
+
puts "Forwarding message to queue '#{args['qname']}'"
|
33
|
+
IPCTransit.send(args)
|
34
|
+
return args['qname']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
server = WEBrick::HTTPServer.new(:Port => 8726)
|
39
|
+
server.mount '/transit_data', PersistAnswers
|
40
|
+
trap "INT" do server.shutdown end
|
41
|
+
server.start
|
data/lib/ipc_transit.rb
CHANGED
@@ -3,7 +3,7 @@ require 'SysVIPC'
|
|
3
3
|
include SysVIPC
|
4
4
|
|
5
5
|
##
|
6
|
-
# Fast,
|
6
|
+
# Fast, brokerless message queueing
|
7
7
|
#
|
8
8
|
# Author:: Dana M. Diederich (diederich@gmail.com)
|
9
9
|
# Copyright:: Copyright (c) 2012 Dana M. Diederich
|
@@ -13,15 +13,18 @@ class IPCTransit
|
|
13
13
|
@@queues = {}
|
14
14
|
|
15
15
|
@@ipc_transit_wire_header_args = {
|
16
|
-
'e' => {
|
16
|
+
'e' => { #encoding
|
17
17
|
'json' => 1,
|
18
18
|
'yaml' => 1,
|
19
19
|
},
|
20
|
-
'c' => {
|
20
|
+
'c' => { #compression
|
21
21
|
'zlib' => 1,
|
22
22
|
'snappy' => 1,
|
23
23
|
'none' => 1,
|
24
24
|
},
|
25
|
+
'd' => 1, #destination address
|
26
|
+
't' => 1, #hop TTL
|
27
|
+
'q' => 1, #destination qname
|
25
28
|
}
|
26
29
|
@@ipc_transit_std_args = {
|
27
30
|
'message' => 1,
|
@@ -42,14 +45,25 @@ class IPCTransit
|
|
42
45
|
ret = nil
|
43
46
|
flags = IPC_NOWAIT
|
44
47
|
begin
|
48
|
+
if args['d']
|
49
|
+
args['q'] = args['qname']
|
50
|
+
args['qname'] = 'transitd'
|
51
|
+
if not args['t']
|
52
|
+
args['t'] = 9
|
53
|
+
end
|
54
|
+
end
|
45
55
|
key = self.get_queue_id(args)
|
46
56
|
mq = MessageQueue.new(key, IPC_CREAT | 0666)
|
47
|
-
|
57
|
+
if args['serialized_wire_data'].nil?
|
58
|
+
pack_message(args)
|
59
|
+
end
|
60
|
+
ret = mq.snd(1, args['serialized_wire_data'], flags)
|
48
61
|
rescue Exception => msg
|
49
62
|
puts "Exception: #{msg}"
|
50
63
|
end
|
51
64
|
return ret
|
52
65
|
end
|
66
|
+
|
53
67
|
##
|
54
68
|
# Receive a message from a queue
|
55
69
|
#
|
@@ -73,8 +87,12 @@ class IPCTransit
|
|
73
87
|
mq = MessageQueue.new(key, IPC_CREAT | 0666)
|
74
88
|
args['serialized_wire_data'] = mq.receive(0, 10000, flags)
|
75
89
|
self.unpack_data(args)
|
90
|
+
#at this point I need to see if this is a remote transit
|
91
|
+
#if it is, then do not thaw the message proper
|
92
|
+
args['message'] = self.transit_thaw(args)
|
76
93
|
rescue Exception => msg
|
77
94
|
# puts "Exception: #{msg}"
|
95
|
+
# need to do something smarter with this
|
78
96
|
end
|
79
97
|
if args['raw']
|
80
98
|
ret = args;
|
@@ -83,11 +101,21 @@ class IPCTransit
|
|
83
101
|
end
|
84
102
|
return ret
|
85
103
|
end
|
104
|
+
|
86
105
|
def self.all_queue_info()
|
87
106
|
self.gather_queue_info()
|
88
107
|
return @@queues
|
89
108
|
end
|
90
109
|
|
110
|
+
##
|
111
|
+
# Return info about all of the queues on the system
|
112
|
+
#
|
113
|
+
# Arguments: none
|
114
|
+
#
|
115
|
+
# Returns: hash. key is qname, value contains:
|
116
|
+
# qid - integer queue ID
|
117
|
+
# count - number of messages in this queue
|
118
|
+
|
91
119
|
def self.all_queues()
|
92
120
|
ret = {}
|
93
121
|
self.all_queue_info().each_pair do |qname,v|
|
@@ -103,7 +131,38 @@ class IPCTransit
|
|
103
131
|
return ret
|
104
132
|
end
|
105
133
|
|
134
|
+
##
|
135
|
+
# Unpack the wire meta data from a message
|
136
|
+
#
|
137
|
+
# Arguments:
|
138
|
+
# serialized_wire_data - the serialized message
|
139
|
+
#
|
140
|
+
# Returns: (in the passed args)
|
141
|
+
# wire_headers - all of the wire headers
|
142
|
+
# serialized_message - the message itself, still serialized
|
143
|
+
|
144
|
+
def self.unpack_data(args)
|
145
|
+
stuff = args['serialized_wire_data'].split(':')
|
146
|
+
offset = Integer(stuff.shift)
|
147
|
+
header_and_message = stuff.join(':')
|
148
|
+
if offset == 0
|
149
|
+
args['serialized_header'] = ''
|
150
|
+
else
|
151
|
+
args['serialized_header'] = header_and_message[0..offset-1]
|
152
|
+
self.thaw_wire_headers(args)
|
153
|
+
end
|
154
|
+
args['serialized_message'] = header_and_message[offset..header_and_message.length]
|
155
|
+
return true
|
156
|
+
end
|
157
|
+
#NB: I know this is all hideously inefficient. I'm still learning Ruby,
|
158
|
+
#and I'm focusing on getting this correct first.
|
159
|
+
#
|
160
|
+
#returns a serialized_message and wire_meta_data
|
161
|
+
#takes serialized_wire_data
|
162
|
+
|
163
|
+
|
106
164
|
private
|
165
|
+
|
107
166
|
def self.get_next_id
|
108
167
|
new_id = 1
|
109
168
|
@@queues.each_pair do |k,v|
|
@@ -197,8 +256,8 @@ class IPCTransit
|
|
197
256
|
args['serialized_message'] = self.transit_freeze(args)
|
198
257
|
self.serialize_wire_meta(args)
|
199
258
|
l = args['serialized_wire_meta_data'].length
|
200
|
-
|
201
|
-
return
|
259
|
+
args['serialized_wire_data'] = "#{l}:#{args['serialized_wire_meta_data']}#{args['serialized_message']}"
|
260
|
+
return args['serialized_wire_data']
|
202
261
|
end
|
203
262
|
|
204
263
|
def self.serialize_wire_meta(args)
|
@@ -221,25 +280,6 @@ class IPCTransit
|
|
221
280
|
args['serialized_wire_meta_data'] = s
|
222
281
|
end
|
223
282
|
|
224
|
-
#NB: I know this is all hideously inefficient. I'm still learning Ruby,
|
225
|
-
#and I'm focusing on getting this correct first.
|
226
|
-
#
|
227
|
-
#returns a serialized_message and wire_meta_data
|
228
|
-
#takes serialized_wire_data
|
229
|
-
def self.unpack_data(args)
|
230
|
-
stuff = args['serialized_wire_data'].split(':')
|
231
|
-
offset = Integer(stuff.shift)
|
232
|
-
header_and_message = stuff.join(':')
|
233
|
-
if offset == 0
|
234
|
-
args['serialized_header'] = ''
|
235
|
-
else
|
236
|
-
args['serialized_header'] = header_and_message[0..offset-1]
|
237
|
-
self.thaw_wire_headers(args)
|
238
|
-
end
|
239
|
-
args['serialized_message'] = header_and_message[offset..header_and_message.length]
|
240
|
-
args['message'] = self.transit_thaw(args)
|
241
|
-
return true
|
242
|
-
end
|
243
283
|
|
244
284
|
def self.thaw_wire_headers(args)
|
245
285
|
h = args['serialized_header']
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'ipc_transit'
|
3
|
+
|
4
|
+
#kind of ghetto, but I don't have a better way right now
|
5
|
+
def drain_test_queue
|
6
|
+
begin
|
7
|
+
while ret = IPCTransit.receive('qname' => 'test_qname', 'nowait' => 1)
|
8
|
+
end
|
9
|
+
rescue Exception => msg
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_daemon(prog)
|
14
|
+
pid = fork
|
15
|
+
if pid.nil? #child
|
16
|
+
exec "bin/#{prog}"
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
return pid
|
20
|
+
end
|
21
|
+
def kill_daemon(pid)
|
22
|
+
Process.kill(9, pid)
|
23
|
+
end
|
24
|
+
|
25
|
+
class TestIPCTransit < Test::Unit::TestCase
|
26
|
+
def test_basic_remote
|
27
|
+
drain_test_queue()
|
28
|
+
IPCTransit.send('message' => { 'foo' => 'bar' }, 'qname' => 'test_qname', 'd' => '127.0.0.1')
|
29
|
+
ret = IPCTransit.receive('qname' => 'transitd', 'nowait' => 1)
|
30
|
+
assert(ret, 'IPCTransit.receive returned true')
|
31
|
+
assert_equal(ret['foo'], 'bar')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_full_remote
|
35
|
+
drain_test_queue()
|
36
|
+
begin
|
37
|
+
trserver_pid = run_daemon('trserver')
|
38
|
+
transitd_pid = run_daemon('transitd')
|
39
|
+
sleep 1
|
40
|
+
IPCTransit.send('message' => { 'foo' => 'bar' }, 'qname' => 'test_qname', 'd' => '127.0.0.1')
|
41
|
+
ret = IPCTransit.receive('qname' => 'test_qname', 'nowait' => 1)
|
42
|
+
assert(ret, 'IPCTransit.receive returned true')
|
43
|
+
assert_equal(ret['foo'], 'bar')
|
44
|
+
rescue Exception => msg
|
45
|
+
puts "Exception: #{msg}"
|
46
|
+
end
|
47
|
+
kill_daemon(transitd_pid)
|
48
|
+
kill_daemon(trserver_pid)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ipc_transit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
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: 2012-11-
|
12
|
+
date: 2012-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -43,12 +43,14 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description:
|
46
|
+
description: Brokerless Message Queue
|
47
47
|
email: diederich@gmail.com
|
48
48
|
executables:
|
49
49
|
- trrecv
|
50
50
|
- trsend
|
51
51
|
- trlist
|
52
|
+
- transitd
|
53
|
+
- trserver
|
52
54
|
extensions: []
|
53
55
|
extra_rdoc_files: []
|
54
56
|
files:
|
@@ -57,7 +59,10 @@ files:
|
|
57
59
|
- bin/trrecv
|
58
60
|
- bin/trsend
|
59
61
|
- bin/trlist
|
62
|
+
- bin/transitd
|
63
|
+
- bin/trserver
|
60
64
|
- test/tc_transit_simple.rb
|
65
|
+
- test/tc_transit_remote.rb
|
61
66
|
homepage: http://rubygems.org/gems/ipc_transit
|
62
67
|
licenses: []
|
63
68
|
post_install_message:
|
@@ -81,6 +86,7 @@ rubyforge_project:
|
|
81
86
|
rubygems_version: 1.8.24
|
82
87
|
signing_key:
|
83
88
|
specification_version: 3
|
84
|
-
summary:
|
89
|
+
summary: Brokerless, cross-language, fast message queue library
|
85
90
|
test_files:
|
86
91
|
- test/tc_transit_simple.rb
|
92
|
+
- test/tc_transit_remote.rb
|