ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro-Mysql/Mysql.xs
Revision: 1.3
Committed: Sat Jun 20 20:43:44 2009 UTC (15 years ago) by root
Branch: MAIN
Changes since 1.2: +20 -15 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include <sys/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 #define IN_DESTRUCT PL_dirty
12
13 typedef U16 uint16;
14
15 /* cached function gv's */
16 static CV *readable, *writable;
17
18 #include "violite.h"
19
20 #define DESC_OFFSET 22
21
22 #define CoMy_MAGIC 0x436f4d79
23
24 typedef struct {
25 int magic;
26 SV *corosocket;
27 int bufofs, bufcnt;
28 char buf[VIO_READ_BUFFER_SIZE];
29 } ourdata;
30
31 #define OURDATAPTR (*((ourdata **)((vio)->desc + DESC_OFFSET)))
32
33 static int
34 our_read (Vio *vio, gptr p, int len)
35 {
36 ourdata *our = OURDATAPTR;
37
38 if (!our->bufcnt)
39 {
40 int rd;
41 my_bool dummy;
42
43 vio->vioblocking (vio, 0, &dummy);
44
45 for (;;)
46 {
47 rd = recv (vio->sd, our->buf, sizeof (our->buf), 0);
48
49 if (rd >= 0 || errno != EAGAIN)
50 break;
51
52 {
53 dSP;
54 PUSHMARK (SP);
55 XPUSHs (our->corosocket);
56 PUTBACK;
57 call_sv ((SV *)readable, G_VOID | G_DISCARD);
58 }
59 }
60
61 if (rd <= 0)
62 return rd;
63
64 our->bufcnt = rd;
65 our->bufofs = 0;
66 }
67
68 if (our->bufcnt < len)
69 len = our->bufcnt;
70
71 memcpy (p, our->buf + our->bufofs, len);
72 our->bufofs += len;
73 our->bufcnt -= len;
74
75 return len;
76 }
77
78 static int
79 our_write (Vio *vio, const gptr p, int len)
80 {
81 char *ptr = (char *)p;
82 my_bool dummy;
83
84 vio->vioblocking (vio, 0, &dummy);
85
86 while (len > 0)
87 {
88 int wr = send (vio->sd, ptr, len, 0);
89
90 if (wr > 0)
91 {
92 ptr += wr;
93 len -= wr;
94 }
95 else if (errno == EAGAIN)
96 {
97 dSP;
98 PUSHMARK (SP);
99 XPUSHs (OURDATAPTR->corosocket);
100 PUTBACK;
101 call_sv ((SV *)writable, G_VOID | G_DISCARD);
102 }
103 else if (ptr == (char *)p)
104 return -1;
105 else
106 break;
107 }
108
109 return ptr - (char *)p;
110 }
111
112 MODULE = Coro::Mysql PACKAGE = Coro::Mysql
113
114 BOOT:
115 {
116 readable = get_cv ("Coro::Mysql::readable", 0);
117 writable = get_cv ("Coro::Mysql::writable", 0);
118 }
119
120 PROTOTYPES: ENABLE
121
122 void
123 _patch (IV sock, int fd, SV *corosocket)
124 CODE:
125 {
126 MYSQL *my = (MYSQL *)sock;
127 Vio *vio = my->net.vio;
128 ourdata *our;
129
130 if (fd != my->net.fd)
131 croak ("DBD::mysql fd and libmysql disagree - library mismatch, unsupported transport or API changes?");
132
133 if (fd != vio->sd)
134 croak ("DBD::mysql fd and vio-sd disagree - library mismatch, unsupported transport or API changes?");
135
136 if (vio->write != vio_write)
137 croak ("vio.write has unexpected content - library mismatch, unsupported transport or API changes?");
138
139 if (vio->read != vio_read && vio->read != vio_read_buff)
140 croak ("vio.read has unexpected content - library mismatch, unsupported transport or API changes?");
141
142 Newz (0, our, 1, ourdata);
143 our->magic = CoMy_MAGIC;
144 our->corosocket = newSVsv (corosocket);
145
146 vio->desc [DESC_OFFSET - 1] = 0;
147 OURDATAPTR = our;
148
149 vio->write = our_write;
150 vio->read = our_read;
151 }
152
153 void
154 _unpatch (IV sock)
155 CODE:
156 if (IN_DESTRUCT)
157 {
158 /* we currently leak data during global destruction */
159 /* perl makes it extremely hard to do otherwise, though */
160 MYSQL *my = (MYSQL *)sock;
161 Vio *vio = my->net.vio;
162 my_bool dummy;
163
164 if (vio->read != our_read)
165 croak ("vio.read has unexpected content during unpatch - wtf?");
166
167 if (vio->write != our_write)
168 croak ("vio.write has unexpected content during unpatch - wtf?");
169
170 SvREFCNT_dec (OURDATAPTR->corosocket);
171
172 Safefree (OURDATAPTR);
173
174 vio->read = vio_read;
175 vio->write = vio_write;
176 }
177
178
179