├── .gitignore ├── test ├── CMakeLists.txt ├── server.php ├── exmaple │ ├── server.c │ └── client.c └── server.c ├── CMakeLists.txt ├── zeromq.h ├── LICENSE ├── README.md └── zeromq.c /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | cmake_install.cmake 4 | install_manifest.txt 5 | *.a 6 | *.so 7 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(server) 3 | ADD_EXECUTABLE(server server.c) 4 | INCLUDE_DIRECTORIES(/usr/include) 5 | TARGET_LINK_LIBRARIES(server zmq) 6 | #INSTALL(PROGRAMS DESTINATION bin) 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(zeromq) 3 | ADD_LIBRARY(zeromq SHARED zeromq.c) 4 | INCLUDE_DIRECTORIES(/usr/include/mysql) 5 | TARGET_LINK_LIBRARIES(zeromq zmq) 6 | INSTALL(PROGRAMS libzeromq.so DESTINATION /usr/lib64/mysql/plugin/) 7 | -------------------------------------------------------------------------------- /test/server.php: -------------------------------------------------------------------------------- 1 | bind("tcp://127.0.0.1:5555"); 9 | $server->bind("tcp://192.168.2.1:5555"); 10 | 11 | /* Loop receiving and echoing back */ 12 | while ($message = $server->recv()) { 13 | echo "Got message: $message\n"; 14 | /* echo back the message */ 15 | $server->send($message); 16 | } 17 | -------------------------------------------------------------------------------- /zeromq.h: -------------------------------------------------------------------------------- 1 | my_bool zmq_client_init(UDF_INIT *initid, UDF_ARGS *args, char *message); 2 | char *zmq_client(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error); 3 | void zmq_client_deinit(UDF_INIT *initid); 4 | 5 | my_bool zmq_publish_init(UDF_INIT *initid, UDF_ARGS *args, char *message); 6 | char *zmq_publish(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error); 7 | void zmq_publish_deinit(UDF_INIT *initid); 8 | 9 | char* concat(const char* str1, const char* str2) 10 | { 11 | char* res; 12 | asprintf(&res, "%s%s", str1, str2); 13 | return res; 14 | } -------------------------------------------------------------------------------- /test/exmaple/server.c: -------------------------------------------------------------------------------- 1 | // Hello World server 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main (void) 10 | { 11 | // Socket to talk to clients 12 | void *context = zmq_ctx_new (); 13 | void *responder = zmq_socket (context, ZMQ_REP); 14 | int rc = zmq_bind (responder, "tcp://*:5555"); 15 | assert (rc == 0); 16 | 17 | while (1) { 18 | char buffer [10]; 19 | zmq_recv (responder, buffer, 10, 0); 20 | printf ("Received Hello\n"); 21 | sleep (1); // Do some 'work' 22 | zmq_send (responder, "World", 5, 0); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test/exmaple/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main (void) 7 | { 8 | printf ("Connecting to hello world server…\n"); 9 | void *context = zmq_ctx_new (); 10 | void *requester = zmq_socket (context, ZMQ_REQ); 11 | zmq_connect (requester, "tcp://localhost:5555"); 12 | 13 | int request_nbr; 14 | for (request_nbr = 0; request_nbr != 10; request_nbr++) { 15 | char buffer [10]; 16 | printf ("Sending Hello %d…\n", request_nbr); 17 | zmq_send (requester, "Hello", 5, 0); 18 | zmq_recv (requester, buffer, 10, 0); 19 | printf ("Received World %d\n", request_nbr); 20 | } 21 | zmq_close (requester); 22 | zmq_ctx_destroy (context); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /test/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main (int argc,char**argv) 9 | { 10 | // Socket to talk to clients 11 | void *context = zmq_ctx_new (); 12 | void *zmqsocket = zmq_socket (context, ZMQ_REP); 13 | int rc = zmq_bind (zmqsocket, "tcp://*:5555"); 14 | assert (rc == 0); 15 | char *recv; 16 | char *send; 17 | 18 | 19 | while (1) { 20 | 21 | zmq_msg_t buffer={0}; 22 | zmq_msg_init (&buffer); 23 | zmq_msg_recv (&buffer, zmqsocket, 0); 24 | int size = zmq_msg_size (&buffer); 25 | char *string = malloc (size + 1); 26 | memset(string,0,size+1); 27 | memcpy (string, zmq_msg_data (&buffer), size); 28 | if(size > 0){ 29 | asprintf(&recv, "%s", string); 30 | printf ("Received: %s\n", recv); 31 | } 32 | free(string); 33 | zmq_msg_close (&buffer); 34 | 35 | asprintf(&send, "%s OK", recv); 36 | 37 | //zmq_msg_t buffer={0}; 38 | zmq_msg_init_size (&buffer, strlen(send)); 39 | memcpy (zmq_msg_data (&buffer), send, strlen(send)); 40 | 41 | if(zmq_msg_send(&buffer, zmqsocket, 0) == 0){ 42 | printf ("Sent: %s\n", send); 43 | } 44 | 45 | zmq_msg_close (&buffer); 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Neo Chan 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mysql-zmq-plugin 2 | ================ 3 | 4 | [![Join the chat at https://gitter.im/netkiller/mysql-zmq-plugin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/netkiller/mysql-zmq-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | ZeroMQ / ØMQ for MySQL 7 | 8 | http://zeromq.org/event:zeromq-for-mysql 9 | 10 | Build 11 | ----- 12 | # yum install zeromq3-devel 13 | 14 | # cmake . 15 | # make && make install 16 | 17 | Install & uninstall 18 | ------------------- 19 | 20 | drop function zmq_client; 21 | drop function zmq_publish; 22 | 23 | create function zmq_client returns string soname 'libzeromq.so'; 24 | create function zmq_publish returns string soname 'libzeromq.so'; 25 | 26 | mysql> SELECT * FROM `mysql`.`func` LIMIT 1000; 27 | +--------------+-----+--------------+----------+ 28 | | name | ret | dl | type | 29 | +--------------+-----+--------------+----------+ 30 | | image_crc32 | 0 | image.so | function | 31 | | image_rename | 0 | image.so | function | 32 | | image_move | 0 | image.so | function | 33 | | image_remove | 0 | image.so | function | 34 | | image_check | 0 | image.so | function | 35 | | fifo_write | 0 | fifo.so | function | 36 | | fifo_read | 0 | fifo.so | function | 37 | | fifo_remove | 0 | fifo.so | function | 38 | | fifo_create | 0 | fifo.so | function | 39 | | zmq_publish | 0 | libzeromq.so | function | 40 | | zmq_client | 0 | libzeromq.so | function | 41 | +--------------+-----+--------------+----------+ 42 | 11 rows in set (0.00 sec) 43 | 44 | Test 45 | ---- 46 | 47 | ### 编译zeromq server 测试程序 48 | cd test 49 | cmake . 50 | make 51 | ./server 52 | 53 | ### 在mysql终端中运行测试SQL 54 | mysql> select zmq_client('tcp://localhost:5555','Hello world!'); 55 | +---------------------------------------------------+ 56 | | zmq_client('tcp://localhost:5555','Hello world!') | 57 | +---------------------------------------------------+ 58 | | Hello world! OK | 59 | +---------------------------------------------------+ 60 | 1 row in set (0.01 sec) 61 | 62 | mysql> select zmq_client('tcp://localhost:5555',mobile) from demo; 63 | +-------------------------------------------+ 64 | | zmq_client('tcp://localhost:5555',mobile) | 65 | +-------------------------------------------+ 66 | | 13113668891 OK | 67 | | 13113668892 OK | 68 | | 13113668893 OK | 69 | | 13322993040 OK | 70 | | 13588997745 OK | 71 | +-------------------------------------------+ 72 | 5 rows in set (0.03 sec) 73 | 74 | 手工编译 75 | -------- 76 | gcc -O3 -g -I/usr/include/mysql -I/usr/include -fPIC -lm -lz -shared -o libzeromq.so zeromq.c 77 | sudo mv libzeromq.so /usr/lib/mysql/plugin/ 78 | 79 | 80 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/netkiller/mysql-zmq-plugin/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 81 | 82 | -------------------------------------------------------------------------------- /zeromq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Homepage: http://netkiller.github.io/ 3 | Author: netkiller 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "zeromq.h" 13 | 14 | /* ------------------------ zmq_client ----------------------------- */ 15 | 16 | my_bool zmq_client_init(UDF_INIT *initid, UDF_ARGS *args, char *message) 17 | { 18 | if (args->arg_count != 2) 19 | { 20 | strncpy(message, "two arguments must be supplied: zmq_client('socket','message').", MYSQL_ERRMSG_SIZE); 21 | return 1; 22 | } 23 | 24 | args->arg_type[0]= STRING_RESULT; 25 | return 0; 26 | } 27 | 28 | char *zmq_client(UDF_INIT *initid, UDF_ARGS *args, 29 | __attribute__ ((unused)) char *result, 30 | unsigned long *length, 31 | __attribute__ ((unused)) char *is_null, 32 | __attribute__ ((unused)) char *error) 33 | { 34 | 35 | char *text; 36 | int status = -1; 37 | 38 | void *context = zmq_ctx_new (); 39 | void *zmqsocket = zmq_socket (context, ZMQ_REQ); 40 | zmq_connect (zmqsocket, args->args[0]); 41 | 42 | zmq_msg_t buffer={0}; 43 | zmq_msg_init_size (&buffer, strlen(args->args[1])); 44 | memcpy (zmq_msg_data (&buffer), args->args[1], strlen(args->args[1])); 45 | 46 | if(zmq_msg_send(&buffer, zmqsocket, 0) != -1){ 47 | status = 1; 48 | }else{ 49 | text="NULL"; 50 | } 51 | zmq_msg_close (&buffer); 52 | if(status){ 53 | zmq_msg_t buffer={0}; 54 | zmq_msg_init (&buffer); 55 | 56 | zmq_msg_recv (&buffer, zmqsocket, 0); 57 | 58 | int size = zmq_msg_size (&buffer); 59 | char *string = malloc (size + 1); 60 | memset(string,0,size+1); 61 | memcpy (string, zmq_msg_data (&buffer), size); 62 | if(size > 0){ 63 | asprintf(&text, "%s", string); 64 | } 65 | free(string); 66 | zmq_msg_close (&buffer); 67 | } 68 | zmq_close (zmqsocket); 69 | zmq_ctx_destroy (context); 70 | 71 | *length = strlen(text); 72 | return ((char *)text); 73 | } 74 | 75 | void zmq_client_deinit(UDF_INIT *initid) 76 | { 77 | return; 78 | } 79 | 80 | /* ------------------------ zmq_publish ----------------------------- */ 81 | 82 | my_bool zmq_publish_init(UDF_INIT *initid, UDF_ARGS *args, char *message) 83 | { 84 | if (args->arg_count != 2) 85 | { 86 | strncpy(message, "two arguments must be supplied: zmq_publish('socket','message').", MYSQL_ERRMSG_SIZE); 87 | return 1; 88 | } 89 | 90 | args->arg_type[0]= STRING_RESULT; 91 | return 0; 92 | } 93 | 94 | char *zmq_publish(UDF_INIT *initid, UDF_ARGS *args, 95 | __attribute__ ((unused)) char *result, 96 | unsigned long *length, 97 | __attribute__ ((unused)) char *is_null, 98 | __attribute__ ((unused)) char *error) 99 | { 100 | 101 | char *status; 102 | 103 | void *context = zmq_ctx_new (); 104 | void *publisher = zmq_socket (context, ZMQ_PUB); 105 | int rc = zmq_bind (publisher, args->args[0]); 106 | //assert (rc == 0); 107 | // Send message to all subscribers 108 | 109 | zmq_close (publisher); 110 | zmq_ctx_destroy (context); 111 | 112 | /* 等有时间再完善 */ 113 | status = "等有时间再完善"; 114 | 115 | *length = strlen(status); 116 | return ((char *)status); 117 | } 118 | 119 | void zmq_publish_deinit(UDF_INIT *initid) 120 | { 121 | return; 122 | } 123 | --------------------------------------------------------------------------------