Commit 6a5120b1 authored by Martin Sustrik's avatar Martin Sustrik

python extension & perf tests

parent 72fdf47d
...@@ -111,7 +111,7 @@ ZMQ_EXPORT int zmq_msg_init (struct zmq_msg_t *msg); ...@@ -111,7 +111,7 @@ ZMQ_EXPORT int zmq_msg_init (struct zmq_msg_t *msg);
ZMQ_EXPORT int zmq_msg_init_size (struct zmq_msg_t *msg, size_t size); ZMQ_EXPORT int zmq_msg_init_size (struct zmq_msg_t *msg, size_t size);
// Initialise a message from an existing buffer. Message isn't copied, // Initialise a message from an existing buffer. Message isn't copied,
// instead 0SOCKETS infrastructure take ownership of the buffer and call // instead 0MQ infrastructure take ownership of the buffer and call
// deallocation functio (ffn) once it's not needed anymore. // deallocation functio (ffn) once it's not needed anymore.
ZMQ_EXPORT int zmq_msg_init_data (struct zmq_msg_t *msg, void *data, ZMQ_EXPORT int zmq_msg_init_data (struct zmq_msg_t *msg, void *data,
size_t size, zmq_free_fn *ffn); size_t size, zmq_free_fn *ffn);
...@@ -139,7 +139,7 @@ ZMQ_EXPORT size_t zmq_msg_size (struct zmq_msg_t *msg); ...@@ -139,7 +139,7 @@ ZMQ_EXPORT size_t zmq_msg_size (struct zmq_msg_t *msg);
// Returns type of the message. // Returns type of the message.
ZMQ_EXPORT int zmq_msg_type (struct zmq_msg_t *msg); ZMQ_EXPORT int zmq_msg_type (struct zmq_msg_t *msg);
// Initialise 0SOCKETS context. 'app_threads' specifies maximal number // Initialise 0MQ context. 'app_threads' specifies maximal number
// of application threads that can have open sockets at the same time. // of application threads that can have open sockets at the same time.
// 'io_threads' specifies the size of thread pool to handle I/O operations. // 'io_threads' specifies the size of thread pool to handle I/O operations.
// //
...@@ -147,7 +147,7 @@ ZMQ_EXPORT int zmq_msg_type (struct zmq_msg_t *msg); ...@@ -147,7 +147,7 @@ ZMQ_EXPORT int zmq_msg_type (struct zmq_msg_t *msg);
// threads declared at all. // threads declared at all.
ZMQ_EXPORT void *zmq_init (int app_threads, int io_threads); ZMQ_EXPORT void *zmq_init (int app_threads, int io_threads);
// Deinitialise 0SOCKETS context including all the open sockets. Closing // Deinitialise 0MQ context including all the open sockets. Closing
// sockets after zmq_term has been called will result in undefined behaviour. // sockets after zmq_term has been called will result in undefined behaviour.
ZMQ_EXPORT int zmq_term (void *context); ZMQ_EXPORT int zmq_term (void *context);
......
...@@ -38,6 +38,7 @@ int main (int argc, char *argv []) ...@@ -38,6 +38,7 @@ int main (int argc, char *argv [])
struct timeval end; struct timeval end;
uint64_t elapsed; uint64_t elapsed;
uint64_t throughput; uint64_t throughput;
double megabits;
if (argc != 4) { if (argc != 4) {
printf ("usage: local_thr <bind-to> <message-count> " printf ("usage: local_thr <bind-to> <message-count> "
...@@ -81,12 +82,15 @@ int main (int argc, char *argv []) ...@@ -81,12 +82,15 @@ int main (int argc, char *argv [])
elapsed = ((uint64_t) end.tv_sec * 1000000 + end.tv_usec) - elapsed = ((uint64_t) end.tv_sec * 1000000 + end.tv_usec) -
((uint64_t) start.tv_sec * 1000000 + start.tv_usec); ((uint64_t) start.tv_sec * 1000000 + start.tv_usec);
if (elapsed == 0)
elapsed = 1;
throughput = (uint64_t) message_count * 1000000 / elapsed; throughput = (uint64_t) message_count * 1000000 / elapsed;
megabits = (double) (throughput * message_size * 8) / 1000000;
printf ("message size: %d [B]\n", (int) message_size); printf ("message size: %d [B]\n", (int) message_size);
printf ("message count: %d\n", (int) message_count); printf ("message count: %d\n", (int) message_count);
printf ("mean throughput: %d [msg/s]\n", (int) throughput); printf ("mean throughput: %d [msg/s]\n", (int) throughput);
printf ("mean throughput: %3f [Mb/s]\n", (double) megabits);
return 0; return 0;
} }
...@@ -63,12 +63,15 @@ int main (int argc, char *argv []) ...@@ -63,12 +63,15 @@ int main (int argc, char *argv [])
uint64_t elapsed = ((uint64_t) end.tv_sec * 1000000 + end.tv_usec) - uint64_t elapsed = ((uint64_t) end.tv_sec * 1000000 + end.tv_usec) -
((uint64_t) start.tv_sec * 1000000 + start.tv_usec); ((uint64_t) start.tv_sec * 1000000 + start.tv_usec);
if (elapsed == 0)
elapsed = 1;
uint64_t throughput = (uint64_t) message_count * 1000000 / elapsed; uint64_t throughput = (uint64_t) message_count * 1000000 / elapsed;
double megabits = (double) (throughput * message_size * 8) / 1000000;
printf ("message size: %d [B]\n", (int) message_size); printf ("message size: %d [B]\n", (int) message_size);
printf ("message count: %d\n", (int) message_count); printf ("message count: %d\n", (int) message_count);
printf ("mean throughput: %d [msg/s]\n", (int) throughput); printf ("mean throughput: %d [msg/s]\n", (int) throughput);
printf ("mean throughput: %3f [Mb/s]\n", (double) megabits);
return 0; return 0;
} }
...@@ -18,50 +18,32 @@ ...@@ -18,50 +18,32 @@
# #
import sys import sys
from datetime import datetime
import libpyzmq
import time import time
import libpyzmq
def main (): def main ():
if len (sys.argv) != 5: if len (sys.argv) != 4:
print 'usage: py_local_lat <in-interface> <out-interface> <message-size> <roundtrip-count>' print 'usage: local_lat <bind-to> <roundtrip-count> <message-size>'
sys.exit (1) sys.exit (1)
try: try:
in_interface = sys.argv [1] bind_to = sys.argv [1]
out_interface = sys.argv [2] roundtrip_count = int (sys.argv [2])
message_size = int (sys.argv [3]) message_size = int (sys.argv [3])
roundtrip_count = int (sys.argv [4])
except (ValueError, OverflowError), e: except (ValueError, OverflowError), e:
print 'message-size and roundtrip-count must be integers' print 'message-size and roundtrip-count must be integers'
sys.exit (1) sys.exit (1)
print "message size:", message_size, "[B]" ctx = libpyzmq.Context (1, 1);
print "roundtrip count:", roundtrip_count s = libpyzmq.Socket (ctx, libpyzmq.REP)
s.bind (bind_to)
z = libpyzmq.Zmq ()
context = z.context (1,1);
in_socket = z.socket (context, libpyzmq.ZMQ_SUB)
out_socket = z.socket (context, libpyzmq.ZMQ_PUB)
z.bind (in_socket, addr = in_interface)
z.bind (out_socket, addr = out_interface)
msg_out = z.init_msg_data (string_msg, type)
start = datetime.now ()
for i in range (0, roundtrip_count): for i in range (0, roundtrip_count):
z.send (out_socket, msg_out, True) msg = s.recv ()
list = z.receive (in_socket, True) assert len (msg) == message_size
msg_in = list [1] s.send (msg)
assert len(msg_in) == message_size
end = datetime.now ()
delta = end - start time.sleep (1)
delta_us = delta.seconds * 1000000 + delta.microseconds
print 'Your average latency is', delta_us / roundtrip_count, ' [us]'
if __name__ == "__main__": if __name__ == "__main__":
main () main ()
...@@ -23,46 +23,42 @@ import libpyzmq ...@@ -23,46 +23,42 @@ import libpyzmq
def main (): def main ():
if len (sys.argv) != 4: if len (sys.argv) != 4:
print ('usage: py_local_thr <in_interface> <message-size> ' + print 'usage: local_thr <bind-to> <message-size> <message-count>'
'<message-count>')
sys.exit (1) sys.exit (1)
try: try:
bind_to = sys.argv [1]
message_size = int (sys.argv [2]) message_size = int (sys.argv [2])
message_count = int (sys.argv [3]) message_count = int (sys.argv [3])
except (ValueError, OverflowError), e: except (ValueError, OverflowError), e:
print 'message-size and message-count must be integers' print 'message-size and message-count must be integers'
sys.exit (1) sys.exit (1)
print "message size:", message_size, "[B]" ctx = libpyzmq.Context (1, 1);
print "message count:", message_count s = libpyzmq.Socket (ctx, libpyzmq.P2P)
s.bind (bind_to)
z = libpyzmq.Zmq () msg = s.recv ()
assert len (msg) == message_size
context = z.context (1,1)
in_socket = z.socket (context, libpyzmq.ZMQ_SUB)
z.connect (in_socketaddr = sys.argv [1])
list = z.receive (in_socket, True)
msg = list [1]
assert len(msg) == message_size
start = datetime.now () start = datetime.now ()
for i in range (1, message_count): for i in range (1, message_count):
list = z.receive (in_socket, True) msg = s.recv ()
msg = list [1] assert len (msg) == message_size
assert len(msg) == message_size
end = datetime.now() end = datetime.now()
delta = end - start elapsed = (end - start).seconds * 1000000 + (end - start).microseconds
delta_us = delta.seconds * 1000000 + delta.microseconds if elapsed == 0:
if delta_us == 0: elapsed = 1
delta_us = 1 throughput = (1000000.0 * float (message_count)) / float (elapsed)
message_thr = (1000000.0 * float (message_count)) / float (delta_us) megabits = float (throughput * message_size * 8) / 1000000
megabit_thr = (message_thr * float (message_size) * 8.0) / 1000000.0;
print "Your average throughput is %.0f [msg/s]" % (message_thr, ) print "message size: %.0f [B]" % (message_size, )
print "Your average throughput is %.2f [Mb/s]" % (megabit_thr, ) print "message count: %.0f" % (message_count, )
print "mean throughput: %.0f [msg/s]" % (throughput, )
print "mean throughput: %.3f [Mb/s]" % (megabits, )
if __name__ == "__main__": if __name__ == "__main__":
main () main ()
...@@ -20,39 +20,40 @@ ...@@ -20,39 +20,40 @@
import sys import sys
from datetime import datetime from datetime import datetime
import libpyzmq import libpyzmq
import time
def main (): def main ():
if len(sys.argv) != 5: if len(sys.argv) != 4:
print ('usage: py_remote_lat <in-interface> ' + print 'usage: remote_lat <connect-to> <roundtrip-count> <message-size>'
'<out-interface> <message-size> <roundtrip-count>')
sys.exit (1) sys.exit (1)
try: try:
message_size = int (sys.argv [3]) connect_to = sys.argv [1]
roundtrip_count = int (sys.argv [4]) message_size = int (sys.argv [2])
roundtrip_count = int (sys.argv [3])
except (ValueError, OverflowError), e: except (ValueError, OverflowError), e:
print 'message-size and message-count must be integers' print 'message-size and message-count must be integers'
sys.exit (1) sys.exit (1)
z = libpyzmq.Zmq () ctx = libpyzmq.Context (1, 1);
s = libpyzmq.Socket (ctx, libpyzmq.REQ)
context = z.context (1,1) s.connect (connect_to)
in_socket = z.socket (context, libpyzmq.ZMQ_SUB) msg = ''.join ([' ' for n in range (0, message_size)])
out_socket = z.socket (context, libpyzmq.ZMQ_PUB)
z.connect (in_socket, addr = in_interface) start = datetime.now ()
z.connect (out_socket, addr = out_interface)
for i in range (0, roundtrip_count): for i in range (0, roundtrip_count):
list = z.receive (in_socket, True) s.send (msg)
message = list [1] msg = s.recv ()
z.send (out_socket, message, True) assert len (msg) == message_size
time.sleep (2) end = datetime.now ()
delta = (end - start).microseconds + 1000000 * (end - start).seconds
latency = delta / roundtrip_count / 2
print "message size: %.0f [B]" % (message_size, )
print "roundtrip count: %.0f" % (roundtrip_count, )
print "mean latency: %.3f [us]" % (latency, )
if __name__ == "__main__": if __name__ == "__main__":
main () main ()
......
...@@ -18,33 +18,32 @@ ...@@ -18,33 +18,32 @@
# #
import sys import sys
from datetime import datetime
import libpyzmq import libpyzmq
import time import time
def main (): def main ():
if len (sys.argv) != 4: if len (sys.argv) != 4:
print 'usage: py_remote_thr <out-interface> <message-size> <message-count>' print 'usage: remote_thr <connect-to> <message-size> <message-count>'
sys.exit (1) sys.exit (1)
try: try:
connect_to = argv [1]
message_size = int (sys.argv [2]) message_size = int (sys.argv [2])
message_count = int (sys.argv [3]) message_count = int (sys.argv [3])
except (ValueError, OverflowError), e: except (ValueError, OverflowError), e:
print 'message-size and message-count must be integers' print 'message-size and message-count must be integers'
sys.exit (1) sys.exit (1)
z = libpyzmq.Zmq () ctx = libpyzmq.Context (1, 1);
context = z.context (1,1); s = libpyzmq.Socket (ctx, libpyzmq.P2P)
out_socket = z.socket (context, libpyzmq.ZMQ_PUB) s.connect (connect_to)
z.bind (out_socket, addr = sys.argv [1])
msg = z.init_msg_data (string_msg, type) msg = ''.join ([' ' for n in range (0, message_size)])
for i in range (0, message_count): for i in range (0, message_count):
z.send (out_socket, msg, True) s.send (msg)
time.sleep (2) time.sleep (10)
if __name__ == "__main__": if __name__ == "__main__":
main () main ()
...@@ -17,622 +17,383 @@ ...@@ -17,622 +17,383 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stddef.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <Python.h> #include <Python.h>
#include <zmq.hpp> #include "../include/zmq.h"
struct pyZMQ struct context_t
{ {
PyObject_HEAD PyObject_HEAD
void *handle;
}; };
void pyZMQ_dealloc (pyZMQ *self) PyObject *context_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
self->ob_type->tp_free ((PyObject*) self);
}
PyObject *pyZMQ_new (PyTypeObject *type, PyObject *args, PyObject *kwdict)
{
pyZMQ *self = (pyZMQ*) type->tp_alloc (type, 0);
return (PyObject*) self;
}
PyObject *pyZMQ_term (PyTypeObject *type, PyObject *args, PyObject *kwdict)
{ {
pyZMQ *self = (pyZMQ*) type->tp_alloc (type, 0); printf ("context_new\n");
context_t *self = (context_t*) type->tp_alloc (type, 0);
static const char *kwlist [] = {"context", NULL}; if (self)
PyObject *context; self->handle = NULL;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&context))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_term ((void *) context);
assert (rc != 0);
return (PyObject*) self; return (PyObject*) self;
} }
int pyZMQ_init (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
return 0;
}
PyObject *pyZMQ_context (pyZMQ *self, PyObject *args, PyObject *kwdict) int context_init (context_t *self, PyObject *args, PyObject *kwdict)
{ {
static const char *kwlist [] = {"app_threads", "io_threads", NULL}; printf ("context_init\n");
int app_threads; int app_threads;
int io_threads; int io_threads;
static const char *kwlist [] = {"app_threads", "io_threads", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "ii", (char**) kwlist, if (!PyArg_ParseTupleAndKeywords (args, kwdict, "ii", (char**) kwlist,
&app_threads, &io_threads)) &app_threads, &io_threads)) {
PyErr_SetString (PyExc_SystemError, PyErr_SetString (PyExc_SystemError, "invalid arguments");
"PyArg_ParseTupleAndKeywords error"); printf ("context_init err1\n");
return -1; // ?
void *context = zmq_init (app_threads, io_threads);
if (context == NULL) {
assert (errno == EINVAL);
PyErr_SetString (PyExc_ValueError, "Invalid argument");
} }
return (PyObject*) context; printf ("app_threads=%d io_threads=%d\n", app_threads, io_threads);
}
PyObject *pyZMQ_msg_init (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
zmq_msg *msg;
int rc = zmq_msg_init (msg);
if (rc == -1) { assert (!self->handle);
assert (rc == ENOMEM); self->handle = zmq_init (app_threads, io_threads);
PyErr_SetString( PyExc_MemoryError, "Out of memory"); if (!self->handle) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
return -1; // ?
printf ("context_init err2\n");
} }
return (PyObject*) msg; printf ("context_init ok\n");
return 0;
} }
void context_dealloc (context_t *self)
PyObject *pyZMQ_msg_init_size (pyZMQ *self, PyObject *args, PyObject *kwdict)
{ {
static const char *kwlist [] = {"size", NULL}; printf ("context_dealloc\n");
if (self->handle) {
zmq_msg *msg; int rc = zmq_term (self->handle);
int size; if (rc != 0)
PyErr_SetString (PyExc_SystemError, strerror (errno));
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "i", (char**) kwlist,
&size))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_msg_init_size (msg, size);
if (rc == -1) {
assert (rc == ENOMEM);
PyErr_SetString( PyExc_ValueError, "Out of memory");
} }
return (PyObject*) msg; self->ob_type->tp_free ((PyObject*) self);
} }
PyObject *pyZMQ_msg_init_data (pyZMQ *self, PyObject *args, PyObject *kwdict) struct socket_t
{ {
static const char *kwlist [] = {"data", "size", "ffn", NULL}; PyObject_HEAD
void *handle;
PyObject *data = PyString_FromStringAndSize (NULL, 0); };
zmq_msg *msg;
PyObject *ffn;
int size;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "SiO", (char**) kwlist,
&data, &size, &ffn))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_msg_init_data (msg, data, size, NULL);
assert (rc == 0);
return (PyObject*) msg;
}
PyObject *pyZMQ_msg_close (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
static const char *kwlist [] = {"msg", NULL}; printf ("socket_new\n");
socket_t *self = (socket_t*) type->tp_alloc (type, 0);
PyObject *msg; if (self)
self->handle = NULL;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&msg))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_msg_close ((zmq_msg *) msg);
assert (rc == 0);
return (PyObject*) self; return (PyObject*) self;
} }
PyObject *pyZMQ_msg_move (pyZMQ *self, PyObject *args, PyObject *kwdict) int socket_init (socket_t *self, PyObject *args, PyObject *kwdict)
{
static const char *kwlist [] = {"src", NULL};
zmq_msg *dest;
PyObject *src;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&src))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_msg_move (dest, (zmq_msg*) src);
assert (rc == 0);
return (PyObject*) dest;
}
PyObject *pyZMQ_msg_copy (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
static const char *kwlist [] = {"src", NULL};
PyObject *dest;
PyObject *src;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&src))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_msg_copy ((zmq_msg*) dest, (zmq_msg*) src);
assert (rc == 0);
return (PyObject*) dest;
}
PyObject *pyZMQ_msg_data (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
static const char *kwlist [] = {"msg", NULL};
PyObject *msg;
PyObject *data = PyString_FromStringAndSize (NULL, 0);
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&msg))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
data = (PyObject *) zmq_msg_data ((zmq_msg *) msg);
return (PyObject*) data;
}
int pyZMQ_msg_size (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
static const char *kwlist [] = {"msg", NULL};
PyObject *msg;
int size;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&msg))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
size = zmq_msg_size ((zmq_msg*) msg);
return size;
}
int pyZMQ_msg_type (pyZMQ *self, PyObject *args, PyObject *kwdict)
{
static const char *kwlist [] = {"msg", NULL};
PyObject *msg;
int type;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist,
&msg))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
type = zmq_msg_type ((zmq_msg*) msg);
return type;
}
PyObject *pyZMQ_socket (pyZMQ *self, PyObject *args, PyObject *kwdict)
{ {
printf ("socket_init\n");
context_t *context;
int socket_type;
static const char *kwlist [] = {"context", "type", NULL}; static const char *kwlist [] = {"context", "type", NULL};
void* context;
int type;
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "Oi", (char**) kwlist, if (!PyArg_ParseTupleAndKeywords (args, kwdict, "Oi", (char**) kwlist,
&context, &type)) &context, &socket_type)) {
PyErr_SetString (PyExc_SystemError, PyErr_SetString (PyExc_SystemError, "invalid arguments");
"PyArg_ParseTupleAndKeywords error"); return NULL;
void *socket = zmq_socket ((void *) context, type);
if (socket == NULL) {
assert (errno == EMFILE || errno == EINVAL);
if (errno == EMFILE)
PyErr_SetString (PyExc_MemoryError, "Too many threads");
else
PyErr_SetString (PyExc_ValueError, "Invalid argument");
} }
// TODO: Check whether 'context' is really a libpyzmq.Context object.
return (PyObject*) socket; assert (!self->handle);
self->handle = zmq_socket (context->handle, socket_type);
if (!self->handle) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
return -1; // ?
}
return 0;
} }
PyObject *pyZMQ_close (pyZMQ *self, PyObject *args, PyObject *kwdict) void socket_dealloc (socket_t *self)
{ {
static const char *kwlist [] = {"socket", NULL}; printf ("socket_dealloc\n");
if (self->handle) {
PyObject* socket; int rc = zmq_close (self->handle);
if (rc != 0)
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist, PyErr_SetString (PyExc_SystemError, strerror (errno));
&socket)) }
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_close ((void *)socket);
assert (rc == 0);
return (PyObject *) self; self->ob_type->tp_free ((PyObject*) self);
} }
PyObject *pyZMQ_setsockopt (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_setsockopt (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
static const char *kwlist [] = {"socket", "option", "optval", NULL};
printf ("setsockopt\n");
PyObject* socket;
int option; int option;
PyObject* optval; PyObject* optval;
int optvallen; static const char *kwlist [] = {"option", "optval", NULL};
int rc; if (!PyArg_ParseTupleAndKeywords (args, kwdict, "iO", (char**) kwlist,
&option, &optval)) {
PyErr_SetString (PyExc_SystemError, "invalid arguments");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "OiO", (char**) kwlist, int rc;
&socket, &option, &optval)) if (PyInt_Check (optval)) {
PyErr_SetString (PyExc_SystemError, int val = PyInt_AsLong (optval);
"PyArg_ParseTupleAndKeywords error"); rc = zmq_setsockopt (self->handle, option, &val, sizeof (int));
}
if (PyInt_Check (optval))
rc = zmq_setsockopt ((void *) socket, option, (void *) optval,
4);
if (PyBool_Check (optval))
rc = zmq_setsockopt ((void *) socket, option, (void *) optval,
1);
if (PyFloat_Check (optval))
rc = zmq_setsockopt ((void *) socket, option, (void *) optval,
4);
if (PyString_Check (optval)) if (PyString_Check (optval))
rc = zmq_setsockopt ((void *) socket, option, (void *) optval, rc = zmq_setsockopt (self->handle, option, PyString_AsString (optval),
PyString_Size (optval)); PyString_Size (optval));
else {
rc = -1;
errno = EINVAL;
}
assert (rc == 0); if (rc != 0) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
return NULL;
}
return (PyObject *) self; Py_INCREF (Py_None);
return Py_None;
} }
PyObject *pyZMQ_bind (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_bind (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
char const *addr = NULL; char const *addr;
PyObject* socket; static const char *kwlist [] = {"addr", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "s", (char**) kwlist,
static const char *kwlist [] = {"socket", "addr", NULL}; &addr)) {
PyErr_SetString (PyExc_SystemError, "invalid arguments");
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "Os", (char**) kwlist, return NULL;
&socket, &addr))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_bind ((void*) socket, addr);
if (rc == -1) {
assert (errno == EINVAL || errno == EADDRINUSE);
if (errno == EINVAL)
PyErr_SetString (PyExc_ValueError, "Invalid argument");
else
PyErr_SetString (PyExc_ValueError, "Address in use");
} }
return (PyObject *) self; int rc = zmq_bind (self->handle, addr);
} if (rc != 0) {
PyObject *pyZMQ_connect (pyZMQ *self, PyObject *args, PyObject *kw) PyErr_SetString (PyExc_SystemError, strerror (errno));
{ return NULL;
char const *addr = NULL;
PyObject* socket;
static const char* kwlist [] = {"socket", "addr", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kw, "Os", (char**) kwlist,
&socket, &addr))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_connect ((void *) socket, addr);
if (rc == -1) {
assert (errno == EINVAL || errno == EADDRINUSE);
if (errno == EINVAL)
PyErr_SetString (PyExc_ValueError, "Invalid argument");
else
PyErr_SetString (PyExc_ValueError, "Address in use");
} }
return (PyObject *) self; Py_INCREF (Py_None);
return Py_None;
} }
PyObject *pyZMQ_flush (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_connect (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
char const *addr;
static const char *kwlist [] = {"addr", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "s", (char**) kwlist,
&addr)) {
PyErr_SetString (PyExc_SystemError, "invalid arguments");
return NULL;
}
static const char *kwlist [] = {"socket", NULL}; int rc = zmq_connect (self->handle, addr);
PyObject *socket; if (rc != 0) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "O", (char**) kwlist, return NULL;
&socket)) }
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_flush ((void*) socket);
assert (rc == 0);
return (PyObject *) self; Py_INCREF (Py_None);
return Py_None;
} }
PyObject *pyZMQ_send (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_send (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
PyObject *msg; PyObject *msg; /* = PyString_FromStringAndSize (NULL, 0); */
PyObject *socket;
int flags = 0; int flags = 0;
static const char *kwlist [] = {"msg", "flags", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "S|i", (char**) kwlist,
&msg, &flags)) {
PyErr_SetString (PyExc_SystemError, "invalid arguments");
return NULL;
}
static const char *kwlist [] = {"socket", "msg", "flags", NULL}; zmq_msg_t data;
int rc = zmq_msg_init_size (&data, PyString_Size (msg));
if (rc != 0) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
return NULL;
}
memcpy (zmq_msg_data (&data), PyString_AsString (msg),
zmq_msg_size (&data));
rc = zmq_send (self->handle, &data, flags);
int rc2 = zmq_msg_close (&data);
assert (rc2 == 0);
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "OOi", (char**) kwlist, if (rc != 0 && errno == EAGAIN)
&socket, &msg, &flags)) return PyBool_FromLong (0);
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_send ((void*) socket, (zmq_msg*) msg, flags); if (rc != 0) {
assert (rc == 0 || (rc == -1 && errno == EAGAIN)); PyErr_SetString (PyExc_SystemError, strerror (errno));
return NULL;
}
return (PyObject *) self; return PyBool_FromLong (1);
} }
PyObject *pyZMQ_receive (pyZMQ *self, PyObject *args, PyObject *kwdict) PyObject *socket_flush (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
zmq_msg *msg; static const char *kwlist [] = {NULL};
zmq_msg_init (msg); if (!PyArg_ParseTupleAndKeywords (args, kwdict, "", (char**) kwlist)) {
PyObject *socket; PyErr_SetString (PyExc_SystemError, "invalid arguments");
return NULL;
int flags = 0; }
static const char *kwlist [] = {"socket", "flags", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwdict, "Oi", (char**) kwlist,
&socket, &flags))
PyErr_SetString (PyExc_SystemError,
"PyArg_ParseTupleAndKeywords error");
int rc = zmq_recv (socket, msg, flags);
assert (rc == 0 || (rc == -1 && errno == EAGAIN));
PyObject *py_message = PyString_FromStringAndSize (NULL, 0);
py_message = (PyObject *) zmq_msg_data (msg);
int py_message_size = zmq_msg_size (msg);
int py_message_type = zmq_msg_type (msg);
zmq_msg_close (msg); int rc = zmq_flush (self->handle);
if (rc != 0) {
PyErr_SetString (PyExc_SystemError, strerror (errno));
return NULL;
}
return Py_BuildValue ("isi", rc, py_message, Py_INCREF (Py_None);
py_message_size, py_message_type); return Py_None;
} }
static PyMethodDef pyZMQ_methods [] = PyObject *socket_recv (socket_t *self, PyObject *args, PyObject *kwdict)
{ {
{ int flags = 0;
"context", static const char *kwlist [] = {"flags", NULL};
(PyCFunction) pyZMQ_context, if (!PyArg_ParseTupleAndKeywords (args, kwdict, "|i", (char**) kwlist,
METH_VARARGS | METH_KEYWORDS, &flags)) {
"context (app_threads, io_threads) -> None\n\n" PyErr_SetString (PyExc_SystemError, "invalid arguments");
"Creates new context\n\n" return NULL;
"app_threads is the number of application threads.\n\n" }
"io_threads is the number of io threads.\n\n"
},
{
"msg_init",
(PyCFunction) pyZMQ_msg_init,
METH_VARARGS | METH_KEYWORDS,
"msg_init () -> None\n\n"
"Creates new message\n\n"
},
{
"msg_init_size",
(PyCFunction) pyZMQ_msg_init_size,
METH_VARARGS | METH_KEYWORDS,
"msg_init_size (size) -> None\n\n"
"Creates new message of a specified size.\n\n"
"size if integer specifying the size of the message to be created.\n\n"
},
{
"msg_init_data",
(PyCFunction) pyZMQ_msg_init_data,
METH_VARARGS | METH_KEYWORDS,
"msg_init_data (data, size, ffn) -> None\n\n"
"Initialises new message with data\n\n"
"data is pointer to the data of the message\n\n"
"size is integer specifying size of data\n\n"
"ffn is function to free alocated data\n\n"
},
{
"msg_close",
(PyCFunction) pyZMQ_msg_close,
METH_VARARGS | METH_KEYWORDS,
"msg_close (msg) -> None\n\n"
"Deletes the message.\n\n"
"msg is the message the be freed\n\n"
},
{
"msg_move",
(PyCFunction) pyZMQ_msg_move,
METH_VARARGS | METH_KEYWORDS,
"msg_move (src) -> dest\n\n"
"Move the content of the message from 'src' to 'dest'.\n\n"
"The content isn't copied, just moved. 'src' is an empty\n\n"
"message after the call. Original content of 'dest' message\n\n"
"is deallocated.\n\n"
}, zmq_msg_t msg;
{ int rc = zmq_msg_init (&msg);
"msg_copy", assert (rc == 0);
(PyCFunction) pyZMQ_msg_copy,
METH_VARARGS | METH_KEYWORDS,
"msg_copy (src) -> dest\n\n"
"Copy the 'src' message to 'dest'. The content isn't copied, \n\n"
"instead reference count is increased. Don't modify the message \n\n"
"data after the call as they are shared between two messages.\n\n"
"Original content of 'dest' message is deallocated.\n\n"
}, rc = zmq_recv (self->handle, &msg, flags);
{
"msg_data",
(PyCFunction) pyZMQ_msg_data,
METH_VARARGS | METH_KEYWORDS,
"msg_data (msg) -> data\n\n"
"Returns pointer to message data.\n\n"
}, if (rc != 0 && errno == EAGAIN) {
{ Py_INCREF (Py_None);
"msg_size", return Py_None;
(PyCFunction) pyZMQ_msg_size, }
METH_VARARGS | METH_KEYWORDS,
"msg_size (msg) -> size\n\n"
"Returns size of a message.\n\n"
}, if (rc != 0) {
{ PyErr_SetString (PyExc_SystemError, "invalid arguments");
"msg_type", return NULL;
(PyCFunction) pyZMQ_msg_type, }
METH_VARARGS | METH_KEYWORDS,
"msg_type (msg) -> type\n\n"
"Returns type of a message.\n\n"
}, PyObject *result = PyString_FromStringAndSize ((char*) zmq_msg_data (&msg),
{ zmq_msg_size (&msg));
"term", rc = zmq_msg_close (&msg);
(PyCFunction) pyZMQ_term, assert (rc == 0);
METH_VARARGS | METH_KEYWORDS, return result;
"term (context) -> None\n\n" }
"Deinitialise 0SOCKETS context including all the open sockets.\n\n"
"Closing sockets after zmq_term has been called will result in\n\n"
"undefined behaviour.\n\n"
}, static PyMethodDef context_methods [] =
{
{ {
"close", NULL
(PyCFunction) pyZMQ_close, }
METH_VARARGS | METH_KEYWORDS, };
"close (socket) -> None\n\n"
"Close the socket.\n\n"
}, static PyTypeObject context_type =
{
PyObject_HEAD_INIT (NULL)
0,
"libpyzmq.Context", /* tp_name */
sizeof (context_t), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) context_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
context_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) context_init, /* tp_init */
0, /* tp_alloc */
context_new, /* tp_new */
};
{ static PyMethodDef socket_methods [] =
"socket", {
(PyCFunction) pyZMQ_socket,
METH_VARARGS | METH_KEYWORDS,
"socket (context, type) -> None\n\n"
"Creates new socket.\n\n"
"'context' is a context_t object.\n"
"'type' is one of 'ZMQ_NOBLOCK', 'ZMQ_NOFLUSH', 'ZMQ_P2P', 'ZMQ_PUB', "
" 'ZMQ_SUB', 'ZMQ_REQ ZMQ_REP'\n"
},
{ {
"setsockopt", "setsockopt",
(PyCFunction) pyZMQ_setsockopt, (PyCFunction) socket_setsockopt,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"setsockopt (socket, option, value) -> None\n\n" "setsockopt (option, optval) -> None\n\n"
"Set socket options."
"Possible options are: 'ZMQ_HWM', 'ZMQ_LWM', 'ZMQ_SWAP', 'ZMQ_MASK', "
"'ZMQ_AFFINITY', 'ZMQ_IDENTITY'."
}, },
{ {
"bind", "bind",
(PyCFunction) pyZMQ_bind, (PyCFunction) socket_bind,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"bind (addr) -> None\n\n" "bind (addr) -> None\n\n"
"Bind socket to specified address."
}, },
{ {
"connect", "connect",
(PyCFunction) pyZMQ_connect, (PyCFunction) socket_connect,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"connect (addr) -> None\n\n" "connect (addr) -> None\n\n"
"connect socket to specified address."
}, },
{ {
"flush", "send",
(PyCFunction) pyZMQ_flush, (PyCFunction) socket_send,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"flush (addr) -> None\n\n" "send (msg, [flags]) -> Bool\n\n"
"flush "
}, },
{ {
"send", "flush",
(PyCFunction) pyZMQ_send, (PyCFunction) socket_flush,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"send (message, flags) -> sent\n\n" "flush () -> None\n\n"
"Send a message to within the socket, "
"returns integer specifying if the message was sent.\n"
"'message' is message to be sent.\n"
"'flags' is integer specifying send options.\n"
}, },
{ {
"receive", "recv",
(PyCFunction) pyZMQ_receive, (PyCFunction) socket_recv,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
"receive (flags) -> (received, message, type)\n\n" "recv ([flags]) -> String\n\n"
"Receive a message."
"'flags' is integer specifying receive options.\n"
"'message' is string storing the message received.\n"
"'type' is type of the message received.\n"
}, },
{ {
NULL NULL
} }
}; };
static const char* pyZMQ_ZMQ_doc = static PyTypeObject socket_type =
"0MQ messaging session\n\n"
"Available functions:\n"
" context\n"
" socket\n"
" setsockopt\n"
" bind\n"
" send\n"
" flush\n"
" receive\n\n";
static PyTypeObject pyZMQType =
{ {
PyObject_HEAD_INIT (NULL) PyObject_HEAD_INIT (NULL)
0, 0,
"libpyzmq.Zmq", /* tp_name (This will appear in the default "libpyzmq.Socket" , /* tp_name */
textual representation of our objects and sizeof (socket_t), /* tp_basicsize */
in some error messages)*/
sizeof (pyZMQ), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
(destructor) pyZMQ_dealloc,/* tp_dealloc */ (destructor) socket_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
...@@ -648,14 +409,14 @@ static PyTypeObject pyZMQType = ...@@ -648,14 +409,14 @@ static PyTypeObject pyZMQType =
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_flags */
(char*) pyZMQ_ZMQ_doc, /* tp_doc */ "", /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
pyZMQ_methods, /* tp_methods */ socket_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
...@@ -663,94 +424,77 @@ static PyTypeObject pyZMQType = ...@@ -663,94 +424,77 @@ static PyTypeObject pyZMQType =
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
(initproc) pyZMQ_init, /* tp_init */ (initproc) socket_init, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
pyZMQ_new, /* tp_new */ socket_new, /* tp_new */
}; };
static PyMethodDef module_methods[] = static PyMethodDef module_methods [] = {{ NULL, NULL, 0, NULL }};
{
{ NULL, NULL, 0, NULL } static const char* libpyzmq_doc =
}; "Python API for 0MQ lightweight messaging kernel.\n"
"For more information see http://www.zeromq.org.\n"
"0MQ is distributed under GNU Lesser General Public License v3.\n";
#ifndef PyMODINIT_FUNC #ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void #define PyMODINIT_FUNC void
#endif #endif
static const char* pyZMQ_doc = PyMODINIT_FUNC initlibpyzmq ()
"0MQ Python Module\n\n"
"Constructor:\n"
" z = libpyzmq.Zmq ()\n"
"Available functions:\n"
" context\n"
" socket\n"
" setsockopt\n"
" bind\n"
" send\n"
" flush\n"
" receive\n"
"\n"
"For more information see http://www.zeromq.org.\n"
"\n"
"0MQ is distributed under GNU Lesser General Public License v3\n";
PyMODINIT_FUNC initlibpyzmq (void)
{ {
if (PyType_Ready (&pyZMQType) < 0) if (PyType_Ready (&context_type) < 0 && PyType_Ready (&socket_type) < 0)
return; return;
PyObject *m = Py_InitModule3 ("libpyzmq", module_methods, PyObject *module = Py_InitModule3 ("libpyzmq", module_methods,
(char*) pyZMQ_doc); libpyzmq_doc);
if (!m) if (!module)
return; return;
Py_INCREF (&pyZMQType); Py_INCREF (&context_type);
Py_INCREF (&socket_type);
PyModule_AddObject (module, "Context", (PyObject*) &context_type);
PyModule_AddObject (module, "Socket", (PyObject*) &socket_type);
PyModule_AddObject (m, "Zmq", (PyObject*) &pyZMQType); PyObject *dict = PyModule_GetDict (module);
assert (dict);
PyObject *d = PyModule_GetDict (m); PyObject *t;
t = PyInt_FromLong (ZMQ_NOBLOCK);
PyDict_SetItemString (dict, "NOBLOCK", t);
PyObject *t = PyInt_FromLong (ZMQ_NOBLOCK);
PyDict_SetItemString (d, "ZMQ_NOBLOCK", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_NOFLUSH); t = PyInt_FromLong (ZMQ_NOFLUSH);
PyDict_SetItemString (d, "ZMQ_NOFLUSH", t); PyDict_SetItemString (dict, "NOFLUSH", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_P2P); t = PyInt_FromLong (ZMQ_P2P);
PyDict_SetItemString (d, "ZMQ_P2P", t); PyDict_SetItemString (dict, "P2P", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_PUB); t = PyInt_FromLong (ZMQ_PUB);
PyDict_SetItemString (d, "ZMQ_PUB", t); PyDict_SetItemString (dict, "PUB", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_SUB); t = PyInt_FromLong (ZMQ_SUB);
PyDict_SetItemString (d, "ZMQ_SUB", t); PyDict_SetItemString (dict, "SUB", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_REQ); t = PyInt_FromLong (ZMQ_REQ);
PyDict_SetItemString (d, "ZMQ_REQ", t); PyDict_SetItemString (dict, "REQ", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_REP); t = PyInt_FromLong (ZMQ_REP);
PyDict_SetItemString (d, "ZMQ_REP", t); PyDict_SetItemString (dict, "REP", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_HWM); t = PyInt_FromLong (ZMQ_HWM);
PyDict_SetItemString (d, "ZMQ_HWM", t); PyDict_SetItemString (dict, "HWM", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_LWM); t = PyInt_FromLong (ZMQ_LWM);
PyDict_SetItemString (d, "ZMQ_LWM", t); PyDict_SetItemString (dict, "LWM", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_SWAP); t = PyInt_FromLong (ZMQ_SWAP);
PyDict_SetItemString (d, "ZMQ_SWAP", t); PyDict_SetItemString (dict, "SWAP", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_MASK); t = PyInt_FromLong (ZMQ_MASK);
PyDict_SetItemString (d, "ZMQ_MASK", t); PyDict_SetItemString (dict, "MASK", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_AFFINITY); t = PyInt_FromLong (ZMQ_AFFINITY);
PyDict_SetItemString (d, "ZMQ_AFFINITY", t); PyDict_SetItemString (dict, "AFFINITY", t);
Py_DECREF (t); Py_DECREF (t);
t = PyInt_FromLong (ZMQ_IDENTITY); t = PyInt_FromLong (ZMQ_IDENTITY);
PyDict_SetItemString (d, "ZMQ_IDENTITY", t); PyDict_SetItemString (dict, "IDENTITY", t);
Py_DECREF (t); Py_DECREF (t);
} }
...@@ -25,6 +25,8 @@ namespace zmq ...@@ -25,6 +25,8 @@ namespace zmq
struct i_endpoint struct i_endpoint
{ {
virtual void attach_inpipe (class reader_t *pipe_) = 0;
virtual void attach_outpipe (class writer_t *pipe_) = 0;
virtual void revive (class reader_t *pipe_) = 0; virtual void revive (class reader_t *pipe_) = 0;
virtual void detach_inpipe (class reader_t *pipe_) = 0; virtual void detach_inpipe (class reader_t *pipe_) = 0;
virtual void detach_outpipe (class writer_t *pipe_) = 0; virtual void detach_outpipe (class writer_t *pipe_) = 0;
......
...@@ -43,21 +43,6 @@ zmq::session_t::~session_t () ...@@ -43,21 +43,6 @@ zmq::session_t::~session_t ()
out_pipe->term (); out_pipe->term ();
} }
void zmq::session_t::set_inbound_pipe (reader_t *pipe_)
{
zmq_assert (!in_pipe);
in_pipe = pipe_;
active = true;
in_pipe->set_endpoint (this);
}
void zmq::session_t::set_outbound_pipe (writer_t *pipe_)
{
zmq_assert (!out_pipe);
out_pipe = pipe_;
out_pipe->set_endpoint (this);
}
bool zmq::session_t::read (::zmq_msg_t *msg_) bool zmq::session_t::read (::zmq_msg_t *msg_)
{ {
if (!active) if (!active)
...@@ -90,6 +75,20 @@ void zmq::session_t::detach () ...@@ -90,6 +75,20 @@ void zmq::session_t::detach ()
// term (); // term ();
} }
void zmq::session_t::attach_inpipe (reader_t *pipe_)
{
zmq_assert (!in_pipe);
in_pipe = pipe_;
active = true;
in_pipe->set_endpoint (this);
}
void zmq::session_t::attach_outpipe (writer_t *pipe_)
{
zmq_assert (!out_pipe);
out_pipe = pipe_;
out_pipe->set_endpoint (this);
}
void zmq::session_t::revive (reader_t *pipe_) void zmq::session_t::revive (reader_t *pipe_)
{ {
zmq_assert (in_pipe == pipe_); zmq_assert (in_pipe == pipe_);
......
...@@ -37,13 +37,6 @@ namespace zmq ...@@ -37,13 +37,6 @@ namespace zmq
session_t (object_t *parent_, socket_base_t *owner_, const char *name_, session_t (object_t *parent_, socket_base_t *owner_, const char *name_,
const options_t &options_); const options_t &options_);
void set_inbound_pipe (class reader_t *pipe_);
void set_outbound_pipe (class writer_t *pipe_);
private:
~session_t ();
// i_inout interface implementation. // i_inout interface implementation.
bool read (::zmq_msg_t *msg_); bool read (::zmq_msg_t *msg_);
bool write (::zmq_msg_t *msg_); bool write (::zmq_msg_t *msg_);
...@@ -51,10 +44,16 @@ namespace zmq ...@@ -51,10 +44,16 @@ namespace zmq
void detach (); void detach ();
// i_endpoint interface implementation. // i_endpoint interface implementation.
void attach_inpipe (class reader_t *pipe_);
void attach_outpipe (class writer_t *pipe_);
void revive (class reader_t *pipe_); void revive (class reader_t *pipe_);
void detach_inpipe (class reader_t *pipe_); void detach_inpipe (class reader_t *pipe_);
void detach_outpipe (class writer_t *pipe_); void detach_outpipe (class writer_t *pipe_);
private:
~session_t ();
// Handlers for incoming commands. // Handlers for incoming commands.
void process_plug (); void process_plug ();
void process_unplug (); void process_unplug ();
......
...@@ -173,7 +173,7 @@ int zmq::socket_base_t::connect (const char *addr_) ...@@ -173,7 +173,7 @@ int zmq::socket_base_t::connect (const char *addr_)
pipe_t *in_pipe = new pipe_t (this, session, options.hwm, options.lwm); pipe_t *in_pipe = new pipe_t (this, session, options.hwm, options.lwm);
zmq_assert (in_pipe); zmq_assert (in_pipe);
in_pipe->reader.set_endpoint (this); in_pipe->reader.set_endpoint (this);
session->set_outbound_pipe (&in_pipe->writer); session->attach_outpipe (&in_pipe->writer);
in_pipes.push_back (&in_pipe->reader); in_pipes.push_back (&in_pipe->reader);
in_pipes.back ()->set_index (active); in_pipes.back ()->set_index (active);
in_pipes [active]->set_index (in_pipes.size () - 1); in_pipes [active]->set_index (in_pipes.size () - 1);
...@@ -184,7 +184,7 @@ int zmq::socket_base_t::connect (const char *addr_) ...@@ -184,7 +184,7 @@ int zmq::socket_base_t::connect (const char *addr_)
pipe_t *out_pipe = new pipe_t (session, this, options.hwm, options.lwm); pipe_t *out_pipe = new pipe_t (session, this, options.hwm, options.lwm);
zmq_assert (out_pipe); zmq_assert (out_pipe);
out_pipe->writer.set_endpoint (this); out_pipe->writer.set_endpoint (this);
session->set_inbound_pipe (&out_pipe->reader); session->attach_inpipe (&out_pipe->reader);
out_pipes.push_back (&out_pipe->writer); out_pipes.push_back (&out_pipe->writer);
// Activate the session. // Activate the session.
...@@ -327,6 +327,22 @@ zmq::session_t *zmq::socket_base_t::find_session (const char *name_) ...@@ -327,6 +327,22 @@ zmq::session_t *zmq::socket_base_t::find_session (const char *name_)
return it->second; return it->second;
} }
void zmq::socket_base_t::attach_inpipe (class reader_t *pipe_)
{
pipe_->set_endpoint (this);
in_pipes.push_back (pipe_);
in_pipes.back ()->set_index (active);
in_pipes [active]->set_index (in_pipes.size () - 1);
std::swap (in_pipes.back (), in_pipes [active]);
active++;
}
void zmq::socket_base_t::attach_outpipe (class writer_t *pipe_)
{
pipe_->set_endpoint (this);
out_pipes.push_back (pipe_);
}
void zmq::socket_base_t::revive (reader_t *pipe_) void zmq::socket_base_t::revive (reader_t *pipe_)
{ {
// Move the pipe to the list of active pipes. // Move the pipe to the list of active pipes.
...@@ -372,15 +388,9 @@ void zmq::socket_base_t::process_bind (owned_t *session_, ...@@ -372,15 +388,9 @@ void zmq::socket_base_t::process_bind (owned_t *session_,
reader_t *in_pipe_, writer_t *out_pipe_) reader_t *in_pipe_, writer_t *out_pipe_)
{ {
zmq_assert (in_pipe_); zmq_assert (in_pipe_);
in_pipe_->set_endpoint (this); attach_inpipe (in_pipe_);
in_pipes.push_back (in_pipe_);
in_pipes.back ()->set_index (active);
in_pipes [active]->set_index (in_pipes.size () - 1);
std::swap (in_pipes.back (), in_pipes [active]);
active++;
zmq_assert (out_pipe_); zmq_assert (out_pipe_);
out_pipe_->set_endpoint (this); attach_outpipe (out_pipe_);
out_pipes.push_back (out_pipe_);
} }
void zmq::socket_base_t::process_term_req (owned_t *object_) void zmq::socket_base_t::process_term_req (owned_t *object_)
......
...@@ -60,6 +60,8 @@ namespace zmq ...@@ -60,6 +60,8 @@ namespace zmq
class session_t *find_session (const char *name_); class session_t *find_session (const char *name_);
// i_endpoint interface implementation. // i_endpoint interface implementation.
void attach_inpipe (class reader_t *pipe_);
void attach_outpipe (class writer_t *pipe_);
void revive (class reader_t *pipe_); void revive (class reader_t *pipe_);
void detach_inpipe (class reader_t *pipe_); void detach_inpipe (class reader_t *pipe_);
void detach_outpipe (class writer_t *pipe_); void detach_outpipe (class writer_t *pipe_);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment