ipc_transit 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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, serverless message queueing
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
- ret = mq.snd(1, pack_message(args), flags)
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
- ret = "#{l}:#{args['serialized_wire_meta_data']}#{args['serialized_message']}"
201
- return ret
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.1
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-11 00:00:00.000000000 Z
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: Serverless Message Queue
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: Serverless, cross-language, fast message queue library
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