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

File Contents

# User Rev Content
1 root 1.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 root 1.3 #define IN_DESTRUCT PL_dirty
12    
13 root 1.1 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 root 1.4 if (!IN_DESTRUCT)
157 root 1.3 {
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 root 1.1
170 root 1.3 SvREFCNT_dec (OURDATAPTR->corosocket);
171 root 1.1
172 root 1.3 Safefree (OURDATAPTR);
173 root 1.2
174 root 1.3 vio->read = vio_read;
175     vio->write = vio_write;
176     }
177 root 1.1
178    
179