ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Mysql/Mysql.xs
Revision: 1.14
Committed: Tue Jun 3 13:37:59 2014 UTC (9 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-1_26
Changes since 1.13: +3 -2 lines
Log Message:
1.26

File Contents

# Content
1 #include <errno.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4
5 #include <mysql.h>
6
7 #include "EXTERN.h"
8 #include "perl.h"
9 #include "XSUB.h"
10
11 #if HAVE_EV
12 # include "EVAPI.h"
13 # include "CoroAPI.h"
14 #endif
15
16 #define IN_DESTRUCT PL_dirty
17
18 typedef U16 uint16;
19
20 /* cached function gv's */
21 static CV *readable, *writable;
22 static int use_ev;
23
24 #include "violite.h"
25
26 #define CoMy_MAGIC 0x436f4d79
27
28 typedef struct {
29 #if DESC_IS_PTR
30 char desc[30];
31 const char *old_desc;
32 #endif
33 int magic;
34 SV *corohandle_sv, *corohandle;
35 int bufofs, bufcnt;
36 #if HAVE_EV
37 ev_io rw, ww;
38 #endif
39 char buf[VIO_READ_BUFFER_SIZE];
40 size_t (*old_read)(Vio*, uchar *, size_t);
41 size_t (*old_write)(Vio*, const uchar *, size_t);
42 int (*old_vioclose)(Vio*);
43 } ourdata;
44
45 #if DESC_IS_PTR
46 # define OURDATAPTR (*(ourdata **)&((vio)->desc))
47 #else
48 # define DESC_OFFSET 22
49 # define OURDATAPTR (*((ourdata **)((vio)->desc + DESC_OFFSET)))
50 #endif
51
52 static xlen
53 our_read (Vio *vio, xgptr p, xlen len)
54 {
55 ourdata *our = OURDATAPTR;
56
57 if (!our->bufcnt)
58 {
59 int rd;
60 my_bool dummy;
61
62 vio->vioblocking (vio, 0, &dummy);
63
64 for (;;)
65 {
66 rd = recv (vio->sd, our->buf, sizeof (our->buf), 0);
67
68 if (rd >= 0 || errno != EAGAIN)
69 break;
70
71 #if HAVE_EV
72 if (use_ev)
73 {
74 our->rw.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
75 ev_io_start (EV_DEFAULT_UC, &(our->rw));
76 CORO_SCHEDULE;
77 ev_io_stop (EV_DEFAULT_UC, &(our->rw)); /* avoids races */
78 }
79 else
80 #endif
81 {
82 dSP;
83 PUSHMARK (SP);
84 XPUSHs (our->corohandle);
85 PUTBACK;
86 call_sv ((SV *)readable, G_VOID | G_DISCARD);
87 }
88 }
89
90 if (rd <= 0)
91 return rd;
92
93 our->bufcnt = rd;
94 our->bufofs = 0;
95 }
96
97 if (our->bufcnt < len)
98 len = our->bufcnt;
99
100 memcpy (p, our->buf + our->bufofs, len);
101 our->bufofs += len;
102 our->bufcnt -= len;
103
104 return len;
105 }
106
107 static xlen
108 our_write (Vio *vio, cxgptr p, xlen len)
109 {
110 char *ptr = (char *)p;
111 my_bool dummy;
112
113 vio->vioblocking (vio, 0, &dummy);
114
115 while (len > 0)
116 {
117 int wr = send (vio->sd, ptr, len, 0);
118
119 if (wr > 0)
120 {
121 ptr += wr;
122 len -= wr;
123 }
124 else if (errno == EAGAIN)
125 {
126 ourdata *our = OURDATAPTR;
127
128 #if HAVE_EV
129 if (use_ev)
130 {
131 our->ww.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
132 ev_io_start (EV_DEFAULT_UC, &(our->ww));
133 CORO_SCHEDULE;
134 ev_io_stop (EV_DEFAULT_UC, &(our->ww)); /* avoids races */
135 }
136 else
137 #endif
138 {
139 dSP;
140 PUSHMARK (SP);
141 XPUSHs (our->corohandle);
142 PUTBACK;
143 call_sv ((SV *)writable, G_VOID | G_DISCARD);
144 }
145 }
146 else if (ptr == (char *)p)
147 return -1;
148 else
149 break;
150 }
151
152 return ptr - (char *)p;
153 }
154
155 static int
156 our_close (Vio *vio)
157 {
158 ourdata *our = OURDATAPTR;
159 printf ("close()\n");//D
160
161 if (vio->read != our_read)
162 croak ("vio.read has unexpected content during unpatch - wtf?");
163
164 if (vio->write != our_write)
165 croak ("vio.write has unexpected content during unpatch - wtf?");
166
167 if (vio->vioclose != our_close)
168 croak ("vio.vioclose has unexpected content during unpatch - wtf?");
169
170 #if HAVE_EV
171 if (use_ev)
172 {
173 ev_io_stop (EV_DEFAULT_UC, &(our->rw));
174 ev_io_stop (EV_DEFAULT_UC, &(our->ww));
175 }
176 #endif
177
178 SvREFCNT_dec (our->corohandle);
179 SvREFCNT_dec (our->corohandle_sv);
180
181 #if DESC_IS_PTR
182 vio->desc = our->old_desc;
183 #endif
184
185 vio->vioclose = our->old_vioclose;
186 vio->write = our->old_write;
187 vio->read = our->old_read;
188
189 Safefree (our);
190
191 vio->vioclose (vio);
192 }
193
194 #if HAVE_EV
195 static void
196 iocb (EV_P_ ev_io *w, int revents)
197 {
198 ev_io_stop (EV_A, w);
199 CORO_READY ((SV *)w->data);
200 }
201 #endif
202
203 MODULE = Coro::Mysql PACKAGE = Coro::Mysql
204
205 BOOT:
206 {
207 readable = get_cv ("Coro::Mysql::readable", 0);
208 writable = get_cv ("Coro::Mysql::writable", 0);
209 }
210
211 PROTOTYPES: ENABLE
212
213 void
214 _use_ev ()
215 PPCODE:
216 {
217 static int onceonly;
218
219 if (!onceonly)
220 {
221 onceonly = 1;
222 #if HAVE_EV
223 I_EV_API ("Coro::Mysql");
224 I_CORO_API ("Coro::Mysql");
225 use_ev = 1;
226 #endif
227 }
228
229 XPUSHs (use_ev ? &PL_sv_yes : &PL_sv_no);
230 }
231
232 void
233 _patch (IV sock, int fd, unsigned long client_version, SV *corohandle_sv, SV *corohandle)
234 CODE:
235 {
236 MYSQL *my = (MYSQL *)sock;
237 Vio *vio = my->net.vio;
238 ourdata *our;
239
240 /* matching versions are required but not sufficient */
241 if (client_version != mysql_get_client_version ())
242 croak ("DBD::mysql linked against different libmysqlclient library than Coro::Mysql (%lu vs. %lu).",
243 client_version, mysql_get_client_version ());
244
245 if (fd != my->net.fd)
246 croak ("DBD::mysql fd and libmysql disagree - library mismatch, unsupported transport or API changes?");
247
248 if (fd != vio->sd)
249 croak ("DBD::mysql fd and vio-sd disagree - library mismatch, unsupported transport or API changes?");
250 #if MYSQL_VERSION_ID < 100010 && !defined(MARIADB_BASE_VERSION)
251 if (vio->vioclose != vio_close)
252 croak ("vio.vioclose has unexpected content - library mismatch, unsupported transport or API changes?");
253
254 if (vio->write != vio_write)
255 croak ("vio.write has unexpected content - library mismatch, unsupported transport or API changes?");
256
257 if (vio->read != vio_read
258 && vio->read != vio_read_buff)
259 croak ("vio.read has unexpected content - library mismatch, unsupported transport or API changes?");
260 #endif
261
262 Newz (0, our, 1, ourdata);
263 our->magic = CoMy_MAGIC;
264 our->corohandle_sv = newSVsv (corohandle_sv);
265 our->corohandle = newSVsv (corohandle);
266 #if HAVE_EV
267 if (use_ev)
268 {
269 ev_io_init (&(our->rw), iocb, vio->sd, EV_READ);
270 ev_io_init (&(our->ww), iocb, vio->sd, EV_WRITE);
271 }
272 #endif
273 #if DESC_IS_PTR
274 our->old_desc = vio->desc;
275 strncpy (our->desc, vio->desc, sizeof (our->desc));
276 our->desc [sizeof (our->desc) - 1] = 0;
277 #else
278 vio->desc [DESC_OFFSET - 1] = 0;
279 #endif
280 OURDATAPTR = our;
281
282 our->old_vioclose = vio->vioclose;
283 our->old_write = vio->write;
284 our->old_read = vio->read;
285
286 vio->vioclose = our_close;
287 vio->write = our_write;
288 vio->read = our_read;
289 }
290