nanomsg 0.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/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:
|