ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Mysql/Mysql.xs
(Generate patch)

Comparing Coro-Mysql/Mysql.xs (file contents):
Revision 1.6 by root, Wed Sep 1 16:38:07 2010 UTC vs.
Revision 1.16 by root, Mon Mar 4 05:34:52 2019 UTC

1#include <sys/errno.h> 1#include <errno.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <fcntl.h> 3#include <fcntl.h>
4
5/* mariadb/mysql uses all these reserved macro names, and probably more :( */
6#undef read
7#undef write
8#undef close
4 9
5#include <mysql.h> 10#include <mysql.h>
6 11
7#include "EXTERN.h" 12#include "EXTERN.h"
8#include "perl.h" 13#include "perl.h"
9#include "XSUB.h" 14#include "XSUB.h"
10 15
16#if HAVE_EV
17# include "EVAPI.h"
18# include "CoroAPI.h"
19#endif
20
11#define IN_DESTRUCT PL_dirty 21#define IN_DESTRUCT PL_dirty
12 22
13typedef U16 uint16; 23typedef U16 uint16;
14 24
15/* cached function gv's */ 25/* cached function gv's */
16static CV *readable, *writable; 26static CV *readable, *writable;
27static int use_ev;
17 28
29#if MARIADB_VERSION_ID >= 100300
30
31 typedef unsigned char uchar; /* bug? */
32 #include <ma_pvio.h>
33
34 #define PVIO 1
35 #define VIOPTR MARIADB_PVIO *
36 #define VIOM(vio) (vio)->methods
37 #define vioblocking blocking
38 #define vioclose close
39 #define VIODATA(vio) (vio)->data
40 /* ma_pvio_get_socket would be it, but it's only declared, not defined */
41 #define VIOSD(vio) mysql_get_socket ((vio)->mysql)
42 #define VIO_READ_BUFFER_SIZE PVIO_READ_AHEAD_CACHE_SIZE
43 #define my_to_vio(sock) (sock)->net.pvio
44
45 #define OURDATAPTR ((ourdata *)vio->methods)
46
47 typedef uchar *xgptr;
48 typedef const uchar *cxgptr;
49 typedef size_t xsize_t;
50 typedef ssize_t xssize_t;
51 typedef my_bool xmy_bool;
52
53#else
54
18#include "violite.h" 55 #include "violite.h"
19 56
20#define DESC_OFFSET 22 57 #define PVIO 0
58 #define VIOPTR Vio *
59 #define VIOM(vio) vio
60 #define VIODATA(vio) (vio)->desc
61 #define VIOSD(vio) (vio)->sd
62 #define my_to_vio(sock) (sock)->net.vio
63
64 typedef int xmy_bool;
65
66#endif
21 67
22#define CoMy_MAGIC 0x436f4d79 68#define CoMy_MAGIC 0x436f4d79
23 69
24typedef struct { 70typedef struct {
71#if PVIO
72 /* must be first member */
73 struct st_ma_pvio_methods methods;
74#else
75#if DESC_IS_PTR
76 char desc[30];
77 const char *old_desc;
78#endif
79#endif
25 int magic; 80 int magic;
26 SV *corohandle_sv, *corohandle; 81 SV *corohandle_sv, *corohandle;
27 int bufofs, bufcnt; 82 int bufofs, bufcnt;
83#if HAVE_EV
84 ev_io rw, ww;
85#endif
28 char buf[VIO_READ_BUFFER_SIZE]; 86 char buf[VIO_READ_BUFFER_SIZE];
87#if PVIO
88 struct st_ma_pvio_methods *oldmethods;
89#else
90 xssize_t (*old_read)(VIOPTR, uchar *, size_t);
91 xssize_t (*old_write)(VIOPTR, const uchar *, size_t);
92 xmy_bool (*old_close)(VIOPTR);
93#endif
29} ourdata; 94} ourdata;
30 95
96#ifndef OURDATAPTR
97#if DESC_IS_PTR
98# define OURDATAPTR (*(ourdata **)&((vio)->desc))
99#else
100# define DESC_OFFSET 22
31#define OURDATAPTR (*((ourdata **)((vio)->desc + DESC_OFFSET))) 101# define OURDATAPTR (*((ourdata **)((vio)->desc + DESC_OFFSET)))
102#endif
103#endif
32 104
33static int 105static xssize_t
34our_read (Vio *vio, xgptr p, int len) 106our_read (VIOPTR vio, xgptr p, xsize_t len)
35{ 107{
36 ourdata *our = OURDATAPTR; 108 ourdata *our = OURDATAPTR;
37 109
38 if (!our->bufcnt) 110 if (!our->bufcnt)
39 { 111 {
40 int rd; 112 int rd;
41 my_bool dummy; 113 my_bool dummy;
42 114
43 vio->vioblocking (vio, 0, &dummy); 115 VIOM (vio)->vioblocking (vio, 0, &dummy);
44 116
45 for (;;) 117 for (;;)
46 { 118 {
47 rd = recv (vio->sd, our->buf, sizeof (our->buf), 0); 119 rd = recv (VIOSD (vio), our->buf, sizeof (our->buf), 0);
48 120
49 if (rd >= 0 || errno != EAGAIN) 121 if (rd >= 0 || errno != EAGAIN)
50 break; 122 break;
51 123
124#if HAVE_EV
125 if (use_ev)
52 { 126 {
127 our->rw.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
128 ev_io_start (EV_DEFAULT_UC, &(our->rw));
129 CORO_SCHEDULE;
130 ev_io_stop (EV_DEFAULT_UC, &(our->rw)); /* avoids races */
131 }
132 else
133#endif
134 {
53 dSP; 135 dSP;
54 PUSHMARK (SP); 136 PUSHMARK (SP);
55 XPUSHs (our->corohandle); 137 XPUSHs (our->corohandle);
56 PUTBACK; 138 PUTBACK;
57 call_sv ((SV *)readable, G_VOID | G_DISCARD); 139 call_sv ((SV *)readable, G_VOID | G_DISCARD);
58 } 140 }
59 } 141 }
60 142
61 if (rd <= 0) 143 if (rd <= 0)
62 return rd; 144 return rd;
63 145
73 our->bufcnt -= len; 155 our->bufcnt -= len;
74 156
75 return len; 157 return len;
76} 158}
77 159
78static int 160static xssize_t
79our_write (Vio *vio, const xgptr p, int len) 161our_write (VIOPTR vio, cxgptr p, xsize_t len)
80{ 162{
81 char *ptr = (char *)p; 163 char *ptr = (char *)p;
82 my_bool dummy; 164 my_bool dummy;
83 165
84 vio->vioblocking (vio, 0, &dummy); 166 VIOM (vio)->vioblocking (vio, 0, &dummy);
85 167
86 while (len > 0) 168 while (len > 0)
87 { 169 {
88 int wr = send (vio->sd, ptr, len, 0); 170 int wr = send (VIOSD (vio), ptr, len, 0);
89 171
90 if (wr > 0) 172 if (wr > 0)
91 { 173 {
92 ptr += wr; 174 ptr += wr;
93 len -= wr; 175 len -= wr;
94 } 176 }
95 else if (errno == EAGAIN) 177 else if (errno == EAGAIN)
96 { 178 {
179 ourdata *our = OURDATAPTR;
180
181#if HAVE_EV
182 if (use_ev)
183 {
184 our->ww.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
185 ev_io_start (EV_DEFAULT_UC, &(our->ww));
186 CORO_SCHEDULE;
187 ev_io_stop (EV_DEFAULT_UC, &(our->ww)); /* avoids races */
188 }
189 else
190#endif
191 {
97 dSP; 192 dSP;
98 PUSHMARK (SP); 193 PUSHMARK (SP);
99 XPUSHs (OURDATAPTR->corohandle); 194 XPUSHs (our->corohandle);
100 PUTBACK; 195 PUTBACK;
101 call_sv ((SV *)writable, G_VOID | G_DISCARD); 196 call_sv ((SV *)writable, G_VOID | G_DISCARD);
197 }
102 } 198 }
103 else if (ptr == (char *)p) 199 else if (ptr == (char *)p)
104 return -1; 200 return -1;
105 else 201 else
106 break; 202 break;
107 } 203 }
108 204
109 return ptr - (char *)p; 205 return ptr - (char *)p;
110} 206}
111 207
112static int 208static xmy_bool
113our_close (Vio *vio) 209our_close (VIOPTR vio)
114{ 210{
211 ourdata *our = OURDATAPTR;
212
115 if (vio->read != our_read) 213 if (VIOM (vio)->read != our_read)
116 croak ("vio.read has unexpected content during unpatch - wtf?"); 214 croak ("vio.read has unexpected content during unpatch - wtf?");
117 215
118 if (vio->write != our_write) 216 if (VIOM (vio)->write != our_write)
119 croak ("vio.write has unexpected content during unpatch - wtf?"); 217 croak ("vio.write has unexpected content during unpatch - wtf?");
120 218
121 if (vio->vioclose != our_close) 219 if (VIOM (vio)->vioclose != our_close)
122 croak ("vio.vioclose has unexpected content during unpatch - wtf?"); 220 croak ("vio.vioclose has unexpected content during unpatch - wtf?");
123 221
222#if HAVE_EV
223 if (use_ev)
224 {
225 ev_io_stop (EV_DEFAULT_UC, &(our->rw));
226 ev_io_stop (EV_DEFAULT_UC, &(our->ww));
227 }
228#endif
229
124 SvREFCNT_dec (OURDATAPTR->corohandle); 230 SvREFCNT_dec (our->corohandle);
125 SvREFCNT_dec (OURDATAPTR->corohandle_sv); 231 SvREFCNT_dec (our->corohandle_sv);
126 232
127 Safefree (OURDATAPTR); 233#if DESC_IS_PTR
234 vio->desc = our->old_desc;
235#endif
128 236
129 vio->read = vio_read; 237#if PVIO
130 vio->write = vio_write; 238 vio->methods = our->oldmethods;
239#else
131 vio->vioclose = vio_close; 240 VIOM (vio)->vioclose = our->old_close;
241 VIOM (vio)->write = our->old_write;
242 VIOM (vio)->read = our->old_read;
243#endif
132 244
245 Safefree (our);
246
133 vio->vioclose (vio); 247 VIOM (vio)->vioclose (vio);
134} 248}
249
250#if HAVE_EV
251static void
252iocb (EV_P_ ev_io *w, int revents)
253{
254 ev_io_stop (EV_A, w);
255 CORO_READY ((SV *)w->data);
256}
257#endif
135 258
136MODULE = Coro::Mysql PACKAGE = Coro::Mysql 259MODULE = Coro::Mysql PACKAGE = Coro::Mysql
137 260
138BOOT: 261BOOT:
139{ 262{
142} 265}
143 266
144PROTOTYPES: ENABLE 267PROTOTYPES: ENABLE
145 268
146void 269void
270_use_ev ()
271 PPCODE:
272{
273 static int onceonly;
274
275 if (!onceonly)
276 {
277 onceonly = 1;
278#if HAVE_EV
279 I_EV_API ("Coro::Mysql");
280 I_CORO_API ("Coro::Mysql");
281 use_ev = 1;
282#endif
283 }
284
285 XPUSHs (use_ev ? &PL_sv_yes : &PL_sv_no);
286}
287
288void
147_patch (IV sock, int fd, SV *corohandle_sv, SV *corohandle) 289_patch (IV sock, int fd, unsigned long client_version, SV *corohandle_sv, SV *corohandle)
148 CODE: 290 CODE:
149{ 291{
150 MYSQL *my = (MYSQL *)sock; 292 MYSQL *my = (MYSQL *)sock;
151 Vio *vio = my->net.vio; 293 VIOPTR vio = my_to_vio (my);
152 ourdata *our; 294 ourdata *our;
295
296 /* matching versions are required but not sufficient */
297 if (client_version != mysql_get_client_version ())
298 croak ("DBD::mysql linked against different libmysqlclient library than Coro::Mysql (%lu vs. %lu).",
299 client_version, mysql_get_client_version ());
153 300
154 if (fd != my->net.fd) 301 if (fd != my->net.fd)
155 croak ("DBD::mysql fd and libmysql disagree - library mismatch, unsupported transport or API changes?"); 302 croak ("DBD::mysql fd and libmysql disagree - library mismatch, unsupported transport or API changes?");
156 303
157 if (fd != vio->sd) 304 if (fd != VIOSD (vio))
158 croak ("DBD::mysql fd and vio-sd disagree - library mismatch, unsupported transport or API changes?"); 305 croak ("DBD::mysql fd and vio-sd disagree - library mismatch, unsupported transport or API changes?");
159 306#if MYSQL_VERSION_ID < 100010 && !defined(MARIADB_BASE_VERSION)
160 if (vio->vioclose != vio_close) 307 if (VIOM (vio)->vioclose != vio_close)
308 croak ("vio.vioclose has unexpected content - library mismatch, unsupported transport or API changes?");
309
310 if (VIOM (vio)->write != vio_write)
161 croak ("vio.write has unexpected content - library mismatch, unsupported transport or API changes?"); 311 croak ("vio.write has unexpected content - library mismatch, unsupported transport or API changes?");
162 312
163 if (vio->write != vio_write)
164 croak ("vio.write has unexpected content - library mismatch, unsupported transport or API changes?");
165
166 if (vio->read != vio_read 313 if (VIOM (vio)->read != vio_read
167 && vio->read != vio_read_buff) 314 && VIOM (vio)->read != vio_read_buff)
168 croak ("vio.read has unexpected content - library mismatch, unsupported transport or API changes?"); 315 croak ("vio.read has unexpected content - library mismatch, unsupported transport or API changes?");
316#endif
317#if PVIO
318 if (vio->type != PVIO_TYPE_UNIXSOCKET && vio->type != PVIO_TYPE_SOCKET)
319 croak ("connection type mismatch: Coro::Mysql only supports 'unixsocket' and 'socket' types at this time");
320#endif
169 321
170 Newz (0, our, 1, ourdata); 322 Newz (0, our, 1, ourdata);
171 our->magic = CoMy_MAGIC; 323 our->magic = CoMy_MAGIC;
172 our->corohandle_sv = newSVsv (corohandle_sv); 324 our->corohandle_sv = newSVsv (corohandle_sv);
173 our->corohandle = newSVsv (corohandle); 325 our->corohandle = newSVsv (corohandle);
174 326#if HAVE_EV
327 if (use_ev)
328 {
329 ev_io_init (&(our->rw), iocb, VIOSD (vio), EV_READ);
330 ev_io_init (&(our->ww), iocb, VIOSD (vio), EV_WRITE);
331 }
332#endif
333#if PVIO
334 /* with pvio, we replace methods by our own struct,
335 * both becauase the original might be read-only,
336 * and because we have no private data member, so the
337 * methods pointer includes our data as well
338 */
339 our->methods = *vio->methods;
340 our->oldmethods = vio->methods;
341 vio->methods = &our->methods;
342#else
343 OURDATAPTR = our;
344#if DESC_IS_PTR
345 our->old_desc = vio->desc;
346 strncpy (our->desc, vio->desc, sizeof (our->desc));
347 our->desc [sizeof (our->desc) - 1] = 0;
348#else
175 vio->desc [DESC_OFFSET - 1] = 0; 349 vio->desc [DESC_OFFSET - 1] = 0;
176 OURDATAPTR = our; 350#endif
351 our->old_close = VIOM (vio)->vioclose;
352 our->old_write = VIOM (vio)->write;
353 our->old_read = VIOM (vio)->read;
354#endif
177 355
356 /* with pvio, this patches our own struct */
178 vio->vioclose = our_close; 357 VIOM (vio)->vioclose = our_close;
179 vio->write = our_write; 358 VIOM (vio)->write = our_write;
180 vio->read = our_read; 359 VIOM (vio)->read = our_read;
181} 360}
182 361

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines