nanomsg 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +0 -0
- data/LICENSE +23 -0
- data/README +47 -0
- data/examples/pair.rb +16 -0
- data/examples/roundtrip_latency.rb +140 -0
- data/ext/Makefile +218 -0
- data/ext/extconf.rb +5 -0
- data/ext/init.c +271 -0
- data/ext/init.o +0 -0
- data/ext/mkmf.log +22 -0
- data/ext/nanomsg.bundle +0 -0
- data/ext/nanomsg.o +0 -0
- data/lib/nanomsg.rb +10 -0
- data/lib/nanomsg/pair_socket.rb +6 -0
- data/spec/lib/nanomsg/pair_socket_spec.rb +27 -0
- data/spec/spec_helper.rb +4 -0
- metadata +77 -0
data/HISTORY
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2013 Kaspar Schiess
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person
|
5
|
+
obtaining a copy of this software and associated documentation
|
6
|
+
files (the "Software"), to deal in the Software without
|
7
|
+
restriction, including without limitation the rights to use,
|
8
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the
|
10
|
+
Software is furnished to do so, subject to the following
|
11
|
+
conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
TLDR
|
3
|
+
|
4
|
+
An idiomatic nanomsg wrapper for Ruby. (http://nanomsg.org/)
|
5
|
+
|
6
|
+
NANOMSG
|
7
|
+
|
8
|
+
nanomsg library is a high-performance implementation of several "scalability
|
9
|
+
protocols". Scalability protocol's job is to define how multiple applications
|
10
|
+
communicate to form a single distributed application. Implementation of
|
11
|
+
following scalability protocols is available at the moment:
|
12
|
+
|
13
|
+
* PAIR - simple one-to-one communication
|
14
|
+
* BUS - simple many-to-many communication
|
15
|
+
* REQREP - allows to build clusters of stateless services to process user requests
|
16
|
+
* PUBSUB - distributes messages to large sets of interested subscribers
|
17
|
+
* FANIN - aggregates messages from multiple sources
|
18
|
+
* FANOUT - load balances messages among many destinations
|
19
|
+
* SURVEY - allows to query state of multiple applications in a single go
|
20
|
+
|
21
|
+
Scalability protocols are layered on top of transport layer in the network
|
22
|
+
stack. At the moment, nanomsg library supports following transports:
|
23
|
+
|
24
|
+
* INPROC - transport within a process (between threads, modules etc.)
|
25
|
+
* IPC - transport between processes on a single machine
|
26
|
+
* TCP - network transport via TCP
|
27
|
+
|
28
|
+
SYNOPSIS
|
29
|
+
|
30
|
+
require 'nanomsg'
|
31
|
+
|
32
|
+
socket1 = NanoMsg::PairSocket.new
|
33
|
+
socket1.bind('inproc://test')
|
34
|
+
|
35
|
+
socket1.send('test')
|
36
|
+
socket1.recv
|
37
|
+
|
38
|
+
STATUS
|
39
|
+
|
40
|
+
Very early alpha, not much testing has been done. Only the PAIR communication
|
41
|
+
type works. Nonblocking mode doesn't even begin to work. This will break your
|
42
|
+
application.
|
43
|
+
|
44
|
+
LICENSE
|
45
|
+
|
46
|
+
MIT, 2013, Kaspar Schiess
|
47
|
+
|
data/examples/pair.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'nanomsg'
|
4
|
+
|
5
|
+
sock1 = NanoMsg::PairSocket.new(NanoMsg::AF_SP)
|
6
|
+
sock1.bind("ipc:///tmp/test.ipc")
|
7
|
+
|
8
|
+
sock2 = NanoMsg::PairSocket.new(NanoMsg::AF_SP)
|
9
|
+
sock2.connect("ipc:///tmp/test.ipc")
|
10
|
+
|
11
|
+
sock1.send 'test'
|
12
|
+
sock1.send 'nanomsg'
|
13
|
+
|
14
|
+
puts sock2.recv
|
15
|
+
puts sock2.recv
|
16
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
|
2
|
+
# Example adapted from nn-cores roundtrip_latency.
|
3
|
+
# (https://raw.github.com/chuckremes/nn-core/master/examples/roundtrip_latency.rb)
|
4
|
+
|
5
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
6
|
+
require 'nanomsg'
|
7
|
+
|
8
|
+
# Within a single process, we start up two threads. One thread has a REQ (request)
|
9
|
+
# socket and the second thread has a REP (reply) socket. We measure the
|
10
|
+
# *round-trip* latency between these sockets. Only *one* message is in flight at
|
11
|
+
# any given moment.
|
12
|
+
#
|
13
|
+
# % ruby roundtrip_latency.rb tcp://127.0.0.1:5555 1024 1_000_000
|
14
|
+
#
|
15
|
+
# % ruby roundtrip_latency.rb inproc://lm_sock 1024 1_000_000
|
16
|
+
#
|
17
|
+
|
18
|
+
if ARGV.length < 3
|
19
|
+
puts "usage: ruby roundtrip_latency.rb <connect-to> <message-size> <roundtrip-count>"
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
|
23
|
+
link = ARGV[0]
|
24
|
+
message_size = ARGV[1].to_i
|
25
|
+
roundtrip_count = ARGV[2].to_i
|
26
|
+
|
27
|
+
def set_signal_handler(receiver, transmitter)
|
28
|
+
trap(:INT) do
|
29
|
+
puts "got ctrl-c"
|
30
|
+
receiver.terminate
|
31
|
+
transmitter.terminate
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Node
|
36
|
+
def initialize(endpoint, size, count)
|
37
|
+
@endpoint = endpoint
|
38
|
+
@size = size
|
39
|
+
@count = count
|
40
|
+
@msg = 'a' * @size
|
41
|
+
|
42
|
+
setup_socket
|
43
|
+
set_endpoint
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup_socket
|
47
|
+
@socket = NanoMsg::PairSocket.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def send_msg
|
51
|
+
nbytes = @socket.send(@msg)
|
52
|
+
assert(nbytes)
|
53
|
+
nbytes
|
54
|
+
end
|
55
|
+
|
56
|
+
def recv_msg
|
57
|
+
msg = @socket.recv
|
58
|
+
nbytes = msg.bytesize
|
59
|
+
assert(nbytes)
|
60
|
+
nbytes
|
61
|
+
end
|
62
|
+
|
63
|
+
def terminate
|
64
|
+
# TODO
|
65
|
+
# assert(NNCore::LibNanomsg.nn_close(@socket))
|
66
|
+
end
|
67
|
+
|
68
|
+
def assert(rc)
|
69
|
+
raise "Last API call failed at #{caller(1)}" unless rc >= 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Receiver < Node
|
74
|
+
def set_endpoint
|
75
|
+
@socket.bind(@endpoint)
|
76
|
+
end
|
77
|
+
|
78
|
+
def run
|
79
|
+
@count.times do
|
80
|
+
nbytes = recv_msg
|
81
|
+
|
82
|
+
raise "Message size doesn't match, expected [#{@size}] but received [#{string.size}]" if @size != nbytes
|
83
|
+
|
84
|
+
send_msg
|
85
|
+
end
|
86
|
+
|
87
|
+
terminate
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Transmitter < Node
|
92
|
+
def set_endpoint
|
93
|
+
@socket.connect(@endpoint)
|
94
|
+
end
|
95
|
+
|
96
|
+
def run
|
97
|
+
elapsed = elapsed_microseconds do
|
98
|
+
@count.times do
|
99
|
+
send_msg
|
100
|
+
|
101
|
+
nbytes = recv_msg
|
102
|
+
|
103
|
+
raise "Message size doesn't match, expected [#{@size}] but received [#{nbytes}]" if @size != nbytes
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
latency = elapsed / @count / 2
|
108
|
+
|
109
|
+
puts "message size: %i [B]" % @size
|
110
|
+
puts "roundtrip count: %i" % @count
|
111
|
+
puts "throughput (msgs/s): %i" % (@count / (elapsed / 1_000_000))
|
112
|
+
puts "mean latency: %.3f [us]" % latency
|
113
|
+
terminate
|
114
|
+
end
|
115
|
+
|
116
|
+
def elapsed_microseconds(&blk)
|
117
|
+
start = Time.now
|
118
|
+
yield
|
119
|
+
value = ((Time.now - start) * 1_000_000)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
threads = []
|
124
|
+
receiver = transmitter = nil
|
125
|
+
|
126
|
+
threads << Thread.new do
|
127
|
+
receiver = Receiver.new(link, message_size, roundtrip_count)
|
128
|
+
receiver.run
|
129
|
+
end
|
130
|
+
|
131
|
+
sleep 1
|
132
|
+
|
133
|
+
threads << Thread.new do
|
134
|
+
transmitter = Transmitter.new(link, message_size, roundtrip_count)
|
135
|
+
transmitter.run
|
136
|
+
end
|
137
|
+
|
138
|
+
set_signal_handler(receiver, transmitter)
|
139
|
+
|
140
|
+
threads.each {|t| t.join}
|
data/ext/Makefile
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
# V=0 quiet, V=1 verbose. other values don't work.
|
5
|
+
V = 0
|
6
|
+
Q1 = $(V:1=)
|
7
|
+
Q = $(Q1:0=@)
|
8
|
+
n=$(NULLCMD)
|
9
|
+
ECHO1 = $(V:1=@$n)
|
10
|
+
ECHO = $(ECHO1:0=@echo)
|
11
|
+
|
12
|
+
#### Start of system configuration section. ####
|
13
|
+
|
14
|
+
srcdir = .
|
15
|
+
topdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1
|
16
|
+
hdrdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1
|
17
|
+
arch_hdrdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/$(arch)
|
18
|
+
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
|
19
|
+
prefix = $(DESTDIR)/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo
|
20
|
+
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
21
|
+
exec_prefix = $(prefix)
|
22
|
+
vendorhdrdir = $(rubyhdrdir)/vendor_ruby
|
23
|
+
sitehdrdir = $(rubyhdrdir)/site_ruby
|
24
|
+
rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
|
25
|
+
vendordir = $(rubylibprefix)/vendor_ruby
|
26
|
+
sitedir = $(rubylibprefix)/site_ruby
|
27
|
+
ridir = $(datarootdir)/$(RI_BASE_NAME)
|
28
|
+
mandir = $(datarootdir)/man
|
29
|
+
localedir = $(datarootdir)/locale
|
30
|
+
libdir = $(exec_prefix)/lib
|
31
|
+
psdir = $(docdir)
|
32
|
+
pdfdir = $(docdir)
|
33
|
+
dvidir = $(docdir)
|
34
|
+
htmldir = $(docdir)
|
35
|
+
infodir = $(datarootdir)/info
|
36
|
+
docdir = $(datarootdir)/doc/$(PACKAGE)
|
37
|
+
oldincludedir = $(DESTDIR)/usr/include
|
38
|
+
includedir = $(prefix)/include
|
39
|
+
localstatedir = $(prefix)/var
|
40
|
+
sharedstatedir = $(prefix)/com
|
41
|
+
sysconfdir = $(prefix)/etc
|
42
|
+
datadir = $(datarootdir)
|
43
|
+
datarootdir = $(prefix)/share
|
44
|
+
libexecdir = $(exec_prefix)/libexec
|
45
|
+
sbindir = $(exec_prefix)/sbin
|
46
|
+
bindir = $(exec_prefix)/bin
|
47
|
+
rubylibdir = $(rubylibprefix)/$(ruby_version)
|
48
|
+
archdir = $(rubylibdir)/$(arch)
|
49
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
50
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
51
|
+
vendorlibdir = $(vendordir)/$(ruby_version)
|
52
|
+
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
53
|
+
|
54
|
+
NULLCMD = :
|
55
|
+
|
56
|
+
CC = /usr/local/bin/gcc-4.2
|
57
|
+
CXX = g++
|
58
|
+
LIBRUBY = $(LIBRUBY_SO)
|
59
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
60
|
+
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
|
61
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
62
|
+
empty =
|
63
|
+
OUTFLAG = -o $(empty)
|
64
|
+
COUTFLAG = -o $(empty)
|
65
|
+
|
66
|
+
RUBY_EXTCONF_H =
|
67
|
+
cflags = $(optflags) $(debugflags) $(warnflags)
|
68
|
+
optflags = -O3
|
69
|
+
debugflags = -ggdb
|
70
|
+
warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration
|
71
|
+
CFLAGS = -fno-common $(cflags) -fno-common -pipe $(ARCH_FLAG)
|
72
|
+
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
73
|
+
DEFS =
|
74
|
+
CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags) -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include
|
75
|
+
CXXFLAGS = $(CFLAGS) $(cxxflags)
|
76
|
+
ldflags = -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
|
77
|
+
dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
|
78
|
+
ARCH_FLAG =
|
79
|
+
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
|
80
|
+
LDSHARED = $(CC) -dynamic -bundle
|
81
|
+
LDSHAREDXX = $(CXX) -dynamic -bundle
|
82
|
+
AR = ar
|
83
|
+
EXEEXT =
|
84
|
+
|
85
|
+
RUBY_BASE_NAME = ruby
|
86
|
+
RUBY_INSTALL_NAME = ruby
|
87
|
+
RUBY_SO_NAME = ruby.1.9.1
|
88
|
+
arch = x86_64-darwin12.3.0
|
89
|
+
sitearch = $(arch)
|
90
|
+
ruby_version = 1.9.1
|
91
|
+
ruby = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/bin/ruby
|
92
|
+
RUBY = $(ruby)
|
93
|
+
RM = rm -f
|
94
|
+
RM_RF = $(RUBY) -run -e rm -- -rf
|
95
|
+
RMDIRS = rmdir -p
|
96
|
+
MAKEDIRS = mkdir -p
|
97
|
+
INSTALL = /usr/bin/install -c
|
98
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
99
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
100
|
+
COPY = cp
|
101
|
+
TOUCH = exit >
|
102
|
+
|
103
|
+
#### End of system configuration section. ####
|
104
|
+
|
105
|
+
preload =
|
106
|
+
|
107
|
+
libpath = . $(libdir) /usr/local/opt/libyaml/lib /usr/local/opt/readline/lib /usr/local/opt/libxml2/lib /usr/local/opt/libxslt/lib /usr/local/opt/libksba/lib /usr/local/opt/openssl/lib /usr/local/opt/sqlite/lib
|
108
|
+
LIBPATH = -L. -L$(libdir) -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
|
109
|
+
DEFFILE =
|
110
|
+
|
111
|
+
CLEANFILES = mkmf.log
|
112
|
+
DISTCLEANFILES =
|
113
|
+
DISTCLEANDIRS =
|
114
|
+
|
115
|
+
extout =
|
116
|
+
extout_prefix =
|
117
|
+
target_prefix =
|
118
|
+
LOCAL_LIBS =
|
119
|
+
LIBS = $(LIBRUBYARG_SHARED) -lnanomsg -lpthread -ldl -lobjc
|
120
|
+
SRCS = init.c
|
121
|
+
OBJS = init.o
|
122
|
+
TARGET = nanomsg
|
123
|
+
DLLIB = $(TARGET).bundle
|
124
|
+
EXTSTATIC =
|
125
|
+
STATIC_LIB =
|
126
|
+
|
127
|
+
BINDIR = $(bindir)
|
128
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
129
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
130
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
131
|
+
HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
|
132
|
+
ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
|
133
|
+
|
134
|
+
TARGET_SO = $(DLLIB)
|
135
|
+
CLEANLIBS = $(TARGET).bundle
|
136
|
+
CLEANOBJS = *.o *.bak
|
137
|
+
|
138
|
+
all: $(DLLIB)
|
139
|
+
static: $(STATIC_LIB)
|
140
|
+
.PHONY: all install static install-so install-rb
|
141
|
+
.PHONY: clean clean-so clean-rb
|
142
|
+
|
143
|
+
clean-static::
|
144
|
+
clean-rb-default::
|
145
|
+
clean-rb::
|
146
|
+
clean-so::
|
147
|
+
clean: clean-so clean-static clean-rb-default clean-rb
|
148
|
+
-$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
|
149
|
+
|
150
|
+
distclean-rb-default::
|
151
|
+
distclean-rb::
|
152
|
+
distclean-so::
|
153
|
+
distclean: clean distclean-so distclean-rb-default distclean-rb
|
154
|
+
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
155
|
+
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
156
|
+
@-$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
|
157
|
+
|
158
|
+
realclean: distclean
|
159
|
+
install: install-so install-rb
|
160
|
+
|
161
|
+
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
162
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
163
|
+
-$(Q)$(MAKEDIRS) $(@D)
|
164
|
+
$(INSTALL_PROG) $(DLLIB) $(@D)
|
165
|
+
clean-static::
|
166
|
+
-$(Q)$(RM) $(STATIC_LIB)
|
167
|
+
install-rb: pre-install-rb install-rb-default
|
168
|
+
install-rb-default: pre-install-rb-default
|
169
|
+
pre-install-rb: Makefile
|
170
|
+
pre-install-rb-default: Makefile
|
171
|
+
pre-install-rb-default:
|
172
|
+
$(ECHO) installing default nanomsg libraries
|
173
|
+
./.RUBYARCHDIR.time:
|
174
|
+
$(Q) $(MAKEDIRS) $(RUBYARCHDIR)
|
175
|
+
$(Q) $(TOUCH) $@
|
176
|
+
|
177
|
+
site-install: site-install-so site-install-rb
|
178
|
+
site-install-so: install-so
|
179
|
+
site-install-rb: install-rb
|
180
|
+
|
181
|
+
.SUFFIXES: .c .m .cc .mm .cxx .cpp .C .o
|
182
|
+
|
183
|
+
.cc.o:
|
184
|
+
$(ECHO) compiling $(<)
|
185
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
186
|
+
|
187
|
+
.mm.o:
|
188
|
+
$(ECHO) compiling $(<)
|
189
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
190
|
+
|
191
|
+
.cxx.o:
|
192
|
+
$(ECHO) compiling $(<)
|
193
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
194
|
+
|
195
|
+
.cpp.o:
|
196
|
+
$(ECHO) compiling $(<)
|
197
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
198
|
+
|
199
|
+
.C.o:
|
200
|
+
$(ECHO) compiling $(<)
|
201
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
202
|
+
|
203
|
+
.c.o:
|
204
|
+
$(ECHO) compiling $(<)
|
205
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
206
|
+
|
207
|
+
.m.o:
|
208
|
+
$(ECHO) compiling $(<)
|
209
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
210
|
+
|
211
|
+
$(DLLIB): $(OBJS) Makefile
|
212
|
+
$(ECHO) linking shared-object $(DLLIB)
|
213
|
+
-$(Q)$(RM) $(@)
|
214
|
+
$(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
$(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
|
data/ext/extconf.rb
ADDED
data/ext/init.c
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
|
2
|
+
#include "ruby/ruby.h"
|
3
|
+
|
4
|
+
#include <nanomsg/nn.h>
|
5
|
+
#include <nanomsg/pair.h>
|
6
|
+
|
7
|
+
static VALUE cNanoMsg;
|
8
|
+
static VALUE cSocket;
|
9
|
+
static VALUE cPairSocket;
|
10
|
+
static VALUE ceSocketError;
|
11
|
+
|
12
|
+
struct nmsg_socket {
|
13
|
+
int socket;
|
14
|
+
};
|
15
|
+
|
16
|
+
|
17
|
+
static void
|
18
|
+
sock_mark(void *ptr)
|
19
|
+
{
|
20
|
+
// struct nmsg_socket *sock = ptr;
|
21
|
+
}
|
22
|
+
|
23
|
+
static void
|
24
|
+
sock_free(void *ptr)
|
25
|
+
{
|
26
|
+
struct nmsg_socket *sock = ptr;
|
27
|
+
xfree(sock);
|
28
|
+
}
|
29
|
+
|
30
|
+
static size_t
|
31
|
+
sock_memsize(const void *ptr)
|
32
|
+
{
|
33
|
+
return ptr ? sizeof(struct nmsg_socket) : 0;
|
34
|
+
}
|
35
|
+
|
36
|
+
static const rb_data_type_t socket_data_type = {
|
37
|
+
"nanomsg_socket",
|
38
|
+
{sock_mark, sock_free, sock_memsize,},
|
39
|
+
};
|
40
|
+
|
41
|
+
static struct nmsg_socket*
|
42
|
+
sock_get_ptr(VALUE socket)
|
43
|
+
{
|
44
|
+
struct nmsg_socket *psock;
|
45
|
+
TypedData_Get_Struct(socket, struct nmsg_socket, &socket_data_type, psock);
|
46
|
+
|
47
|
+
return psock;
|
48
|
+
}
|
49
|
+
|
50
|
+
static int
|
51
|
+
sock_get(VALUE socket)
|
52
|
+
{
|
53
|
+
struct nmsg_socket *psock = sock_get_ptr(socket);
|
54
|
+
return psock->socket;
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE
|
58
|
+
sock_alloc(VALUE klass)
|
59
|
+
{
|
60
|
+
VALUE obj;
|
61
|
+
struct nmsg_socket *psock;
|
62
|
+
|
63
|
+
obj = TypedData_Make_Struct(klass, struct nmsg_socket, &socket_data_type, psock);
|
64
|
+
return obj;
|
65
|
+
}
|
66
|
+
|
67
|
+
static void
|
68
|
+
sock_raise_error(int code)
|
69
|
+
{
|
70
|
+
printf("socket error %d errno %d\n", code, errno);
|
71
|
+
|
72
|
+
// TODO allow querying of the errno at the very least.
|
73
|
+
switch (errno) {
|
74
|
+
case EBADF:
|
75
|
+
rb_raise(ceSocketError, "The provided socket is invalid.");
|
76
|
+
break;
|
77
|
+
case ENOTSUP:
|
78
|
+
rb_raise(ceSocketError, "The operation is not supported by this socket type.");
|
79
|
+
break;
|
80
|
+
case EFSM:
|
81
|
+
rb_raise(ceSocketError, "The operation cannot be performed on this socket at the moment because the socket is not in the appropriate state.");
|
82
|
+
break;
|
83
|
+
case EAGAIN:
|
84
|
+
rb_raise(ceSocketError, "Non-blocking mode was requested and the message cannot be sent at the moment.");
|
85
|
+
break;
|
86
|
+
case EINTR:
|
87
|
+
rb_raise(ceSocketError, "The operation was interrupted by delivery of a signal before the message was sent.");
|
88
|
+
break;
|
89
|
+
case ETIMEDOUT:
|
90
|
+
rb_raise(ceSocketError, "Individual socket types may define their own specific timeouts. If such timeout is hit, this error will be returned.");
|
91
|
+
break;
|
92
|
+
case EAFNOSUPPORT:
|
93
|
+
rb_raise(ceSocketError, "Specified address family is not supported.");
|
94
|
+
break;
|
95
|
+
case EINVAL:
|
96
|
+
rb_raise(ceSocketError, "Unknown protocol.");
|
97
|
+
break;
|
98
|
+
case EMFILE:
|
99
|
+
rb_raise(ceSocketError, "The limit on the total number of open SP sockets or OS limit for file descriptors has been reached.");
|
100
|
+
break;
|
101
|
+
case ETERM:
|
102
|
+
rb_raise(ceSocketError, "The library is terminating.");
|
103
|
+
break;
|
104
|
+
default:
|
105
|
+
rb_raise(ceSocketError, "Unknown error code %d", errno);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE
|
110
|
+
sock_bind(VALUE socket, VALUE bind)
|
111
|
+
{
|
112
|
+
int sock = sock_get(socket);
|
113
|
+
int endpoint;
|
114
|
+
|
115
|
+
endpoint = nn_bind(sock, StringValueCStr(bind));
|
116
|
+
if (endpoint < 0)
|
117
|
+
sock_raise_error(endpoint);
|
118
|
+
|
119
|
+
// TODO do something with the endpoint, returning it in a class for example.
|
120
|
+
return Qnil;
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE
|
124
|
+
sock_connect(VALUE socket, VALUE connect)
|
125
|
+
{
|
126
|
+
int sock = sock_get(socket);
|
127
|
+
int endpoint;
|
128
|
+
|
129
|
+
endpoint = nn_connect(sock, StringValueCStr(connect));
|
130
|
+
if (endpoint < 0)
|
131
|
+
sock_raise_error(endpoint);
|
132
|
+
|
133
|
+
// TODO do something with the endpoint, returning it in a class for example.
|
134
|
+
return Qnil;
|
135
|
+
}
|
136
|
+
|
137
|
+
struct ioop {
|
138
|
+
int last_code;
|
139
|
+
int sock;
|
140
|
+
char* buffer;
|
141
|
+
long len;
|
142
|
+
int abort;
|
143
|
+
};
|
144
|
+
|
145
|
+
static VALUE
|
146
|
+
sock_send_no_gvl(void* data)
|
147
|
+
{
|
148
|
+
struct ioop *pio = data;
|
149
|
+
|
150
|
+
while (pio->last_code == EAGAIN && !pio->abort) {
|
151
|
+
pio->last_code = nn_send(pio->sock, pio->buffer, pio->len, NN_DONTWAIT /* flags */);
|
152
|
+
|
153
|
+
if (pio->last_code < 0)
|
154
|
+
pio->last_code = errno;
|
155
|
+
}
|
156
|
+
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
|
160
|
+
static void
|
161
|
+
sock_send_abort(void* data)
|
162
|
+
{
|
163
|
+
struct ioop *pio = data;
|
164
|
+
pio->abort = Qtrue;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE
|
168
|
+
sock_send(VALUE socket, VALUE buffer)
|
169
|
+
{
|
170
|
+
struct ioop io;
|
171
|
+
|
172
|
+
io.sock = sock_get(socket);
|
173
|
+
io.last_code = EAGAIN;
|
174
|
+
io.buffer = StringValuePtr(buffer);
|
175
|
+
io.len = RSTRING_LEN(buffer);
|
176
|
+
io.abort = Qfalse;
|
177
|
+
|
178
|
+
rb_thread_blocking_region(sock_send_no_gvl, &io, sock_send_abort, &io);
|
179
|
+
|
180
|
+
// Unclear what to do in this situation, but we'll simply return nil,
|
181
|
+
// leaving Ruby to handle the abort.
|
182
|
+
if (io.abort)
|
183
|
+
return Qnil;
|
184
|
+
|
185
|
+
if (io.last_code < 0)
|
186
|
+
sock_raise_error(io.last_code);
|
187
|
+
|
188
|
+
return INT2NUM(io.last_code);
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE
|
192
|
+
sock_recv_no_gvl(void* data)
|
193
|
+
{
|
194
|
+
struct ioop *pio = data;
|
195
|
+
|
196
|
+
while (pio->last_code == EAGAIN && !pio->abort) {
|
197
|
+
pio->last_code = nn_recv(pio->sock, &pio->buffer, NN_MSG, NN_DONTWAIT /* flags */);
|
198
|
+
|
199
|
+
if (pio->last_code < 0)
|
200
|
+
pio->last_code = errno;
|
201
|
+
}
|
202
|
+
|
203
|
+
return Qnil;
|
204
|
+
}
|
205
|
+
|
206
|
+
static void
|
207
|
+
sock_recv_abort(void* data)
|
208
|
+
{
|
209
|
+
struct ioop *pio = data;
|
210
|
+
|
211
|
+
pio->abort = Qtrue;
|
212
|
+
}
|
213
|
+
|
214
|
+
static VALUE
|
215
|
+
sock_recv(VALUE socket)
|
216
|
+
{
|
217
|
+
VALUE result;
|
218
|
+
struct ioop io;
|
219
|
+
|
220
|
+
io.sock = sock_get(socket);
|
221
|
+
io.buffer = (char*) 0;
|
222
|
+
io.abort = Qfalse;
|
223
|
+
io.last_code = EAGAIN;
|
224
|
+
|
225
|
+
rb_thread_blocking_region(sock_recv_no_gvl, &io, sock_recv_abort, &io);
|
226
|
+
|
227
|
+
if (io.abort)
|
228
|
+
return Qnil;
|
229
|
+
|
230
|
+
if (io.last_code < 0)
|
231
|
+
sock_raise_error(io.last_code);
|
232
|
+
|
233
|
+
result = rb_str_new(io.buffer, io.last_code);
|
234
|
+
nn_freemsg(io.buffer); io.buffer = (char*) 0;
|
235
|
+
|
236
|
+
return result;
|
237
|
+
}
|
238
|
+
|
239
|
+
static VALUE
|
240
|
+
pair_sock_init(VALUE socket)
|
241
|
+
{
|
242
|
+
struct nmsg_socket *psock = sock_get_ptr(socket);
|
243
|
+
|
244
|
+
psock->socket = nn_socket(AF_SP, NN_PAIR);
|
245
|
+
if (psock->socket < 0) {
|
246
|
+
sock_raise_error(psock->socket);
|
247
|
+
}
|
248
|
+
|
249
|
+
return socket;
|
250
|
+
}
|
251
|
+
|
252
|
+
void
|
253
|
+
Init_nanomsg(void)
|
254
|
+
{
|
255
|
+
printf("loading nanomsg extension\n");
|
256
|
+
|
257
|
+
cNanoMsg = rb_define_module("NanoMsg");
|
258
|
+
cSocket = rb_define_class_under(cNanoMsg, "Socket", rb_cObject);
|
259
|
+
cPairSocket = rb_define_class_under(cNanoMsg, "PairSocket", cSocket);
|
260
|
+
|
261
|
+
ceSocketError = rb_define_class_under(cNanoMsg, "SocketError", rb_eIOError);
|
262
|
+
|
263
|
+
rb_define_method(cSocket, "bind", sock_bind, 1);
|
264
|
+
rb_define_method(cSocket, "connect", sock_connect, 1);
|
265
|
+
rb_define_method(cSocket, "send", sock_send, 1);
|
266
|
+
rb_define_method(cSocket, "recv", sock_recv, 0);
|
267
|
+
|
268
|
+
rb_define_alloc_func(cPairSocket, sock_alloc);
|
269
|
+
rb_define_method(cPairSocket, "initialize", pair_sock_init, 0);
|
270
|
+
}
|
271
|
+
|
data/ext/init.o
ADDED
Binary file
|
data/ext/mkmf.log
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
have_library: checking for main() in -lnanomsg... -------------------- yes
|
2
|
+
|
3
|
+
"/usr/local/bin/gcc-4.2 -o conftest -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/x86_64-darwin12.3.0 -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/ruby/backward -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -O3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -fno-common -pipe conftest.c -L. -L/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -lruby.1.9.1 -lpthread -ldl -lobjc "
|
4
|
+
checked program was:
|
5
|
+
/* begin */
|
6
|
+
1: #include "ruby.h"
|
7
|
+
2:
|
8
|
+
3: int main() {return 0;}
|
9
|
+
/* end */
|
10
|
+
|
11
|
+
"/usr/local/bin/gcc-4.2 -o conftest -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/x86_64-darwin12.3.0 -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/ruby/backward -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -O3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -fno-common -pipe conftest.c -L. -L/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -lruby.1.9.1 -lnanomsg -lpthread -ldl -lobjc "
|
12
|
+
checked program was:
|
13
|
+
/* begin */
|
14
|
+
1: #include "ruby.h"
|
15
|
+
2:
|
16
|
+
3: /*top*/
|
17
|
+
4: int main() {return 0;}
|
18
|
+
5: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
|
19
|
+
/* end */
|
20
|
+
|
21
|
+
--------------------
|
22
|
+
|
data/ext/nanomsg.bundle
ADDED
Binary file
|
data/ext/nanomsg.o
ADDED
Binary file
|
data/lib/nanomsg.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NanoMsg::PairSocket do
|
4
|
+
let(:sock1) { NanoMsg::PairSocket.new }
|
5
|
+
let(:sock2) { NanoMsg::PairSocket.new }
|
6
|
+
|
7
|
+
def self.examples_for_transport tbind
|
8
|
+
name = tbind.split('://').first
|
9
|
+
|
10
|
+
describe "transport #{name}" do
|
11
|
+
it 'allows simple send/recv' do
|
12
|
+
sock1.bind(tbind)
|
13
|
+
sock2.connect(tbind)
|
14
|
+
|
15
|
+
sock1.send('1234').should == 4
|
16
|
+
sock2.recv.should == '1234'
|
17
|
+
|
18
|
+
sock2.send('5678').should == 4
|
19
|
+
sock1.recv.should == '5678'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
examples_for_transport "ipc:///tmp/test.ipc"
|
25
|
+
examples_for_transport "tcp://127.0.0.1:5555"
|
26
|
+
examples_for_transport "inproc://test"
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nanomsg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kaspar Schiess
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-22 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! " nanomsg provides idiomatic Ruby bindings to the C library nanomsg
|
15
|
+
(nanomsg.org)\n\n nanomsg library is a high-performance implementation of several
|
16
|
+
\"scalability \n protocols\". Scalability protocol's job is to define how multiple
|
17
|
+
applications \n communicate to form a single distributed application. Implementation
|
18
|
+
of \n following scalability protocols is available at the moment:\n\n PAIR
|
19
|
+
- simple one-to-one communication\n BUS - simple many-to-many communication\n
|
20
|
+
\ REQREP - allows to build clusters of stateless services to process user requests\n
|
21
|
+
\ PUBSUB - distributes messages to large sets of interested subscribers\n FANIN
|
22
|
+
- aggregates messages from multiple sources\n FANOUT - load balances messages
|
23
|
+
among many destinations\n SURVEY - allows to query state of multiple applications
|
24
|
+
in a single go\n\n WARNING: nanomsg is still in alpha stage!\n"
|
25
|
+
email: kaspar.schiess@absurd.li
|
26
|
+
executables: []
|
27
|
+
extensions:
|
28
|
+
- ext/extconf.rb
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README
|
31
|
+
files:
|
32
|
+
- HISTORY
|
33
|
+
- LICENSE
|
34
|
+
- README
|
35
|
+
- lib/nanomsg/pair_socket.rb
|
36
|
+
- lib/nanomsg.rb
|
37
|
+
- ext/extconf.rb
|
38
|
+
- ext/init.c
|
39
|
+
- ext/init.o
|
40
|
+
- ext/Makefile
|
41
|
+
- ext/mkmf.log
|
42
|
+
- ext/nanomsg.bundle
|
43
|
+
- ext/nanomsg.o
|
44
|
+
- examples/pair.rb
|
45
|
+
- examples/roundtrip_latency.rb
|
46
|
+
- spec/lib/nanomsg/pair_socket_spec.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
homepage: https://bitbucket.org/kschiess/nanomsg
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --main
|
53
|
+
- README
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
- ext
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.25
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Ruby binding for nanomsg. nanomsg library is a high-performance implementation
|
75
|
+
of several "scalability protocols".
|
76
|
+
test_files: []
|
77
|
+
has_rdoc:
|