2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following disclaimer
16
* in the documentation and/or other materials provided with the
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
23
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
* @brief Drizzle Definitions
42
#include "libdrizzle/common.h"
45
* @addtogroup drizzle_static Static Drizzle Declarations
51
* Names of the verbose levels provided.
53
static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
69
const char *drizzle_version(void)
71
return PACKAGE_VERSION;
74
const char *drizzle_bugreport(void)
76
return PACKAGE_BUGREPORT;
79
const char *drizzle_verbose_name(drizzle_verbose_t verbose)
81
if (verbose >= DRIZZLE_VERBOSE_MAX)
84
return _verbose_name[verbose];
87
drizzle_st *drizzle_create(drizzle_st *drizzle)
90
/* if it is MS windows, invoke WSAStartup */
92
if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
93
printf("Error at WSAStartup()\n");
96
memset(&act, 0, sizeof(act));
98
act.sa_handler = SIG_IGN;
99
sigaction(SIGPIPE, &act, NULL);
104
drizzle= new drizzle_st;
108
drizzle->options= DRIZZLE_ALLOCATED;
111
drizzle->options= DRIZZLE_NONE;
113
/* @todo remove this default free flag with new API. */
114
drizzle->options|= DRIZZLE_FREE_OBJECTS;
115
drizzle->error_code= 0;
116
/* drizzle->options set above */
117
drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
118
drizzle->con_count= 0;
119
drizzle->pfds_size= 0;
120
drizzle->query_count= 0;
121
drizzle->query_new= 0;
122
drizzle->query_running= 0;
123
drizzle->last_errno= 0;
124
drizzle->timeout= -1;
125
drizzle->con_list= NULL;
126
drizzle->context= NULL;
127
drizzle->context_free_fn= NULL;
128
drizzle->event_watch_fn= NULL;
129
drizzle->event_watch_context= NULL;
130
drizzle->log_fn= NULL;
131
drizzle->log_context= NULL;
133
drizzle->query_list= NULL;
134
drizzle->sqlstate[0]= 0;
135
drizzle->last_error[0]= 0;
140
drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
144
drizzle= drizzle_create(drizzle);
148
drizzle->options|= (from->options & ~DRIZZLE_ALLOCATED);
150
for (con= from->con_list; con != NULL; con= con->next)
152
if (drizzle_con_clone(drizzle, NULL, con) == NULL)
154
drizzle_free(drizzle);
162
void drizzle_free(drizzle_st *drizzle)
164
if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
165
drizzle->context_free_fn(drizzle, drizzle->context);
167
if (drizzle->options & DRIZZLE_FREE_OBJECTS)
169
drizzle_con_free_all(drizzle);
170
drizzle_query_free_all(drizzle);
172
else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
174
assert(drizzle->con_list == NULL);
175
assert(drizzle->con_list == NULL);
178
if (drizzle->pfds != NULL)
181
if (drizzle->options & DRIZZLE_ALLOCATED)
184
/* if it is MS windows, invoke WSACleanup() at the end*/
189
const char *drizzle_error(const drizzle_st *drizzle)
191
return (const char *)drizzle->last_error;
194
int drizzle_errno(const drizzle_st *drizzle)
196
return drizzle->last_errno;
199
uint16_t drizzle_error_code(const drizzle_st *drizzle)
201
return drizzle->error_code;
204
const char *drizzle_sqlstate(const drizzle_st *drizzle)
206
return drizzle->sqlstate;
209
int drizzle_options(const drizzle_st *drizzle)
211
return drizzle->options;
214
void drizzle_set_options(drizzle_st *drizzle, int options)
216
drizzle->options= options;
219
void drizzle_add_options(drizzle_st *drizzle, int options)
221
drizzle->options|= options;
224
void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
226
drizzle->options&= ~options;
229
void *drizzle_context(const drizzle_st *drizzle)
231
return drizzle->context;
234
void drizzle_set_context(drizzle_st *drizzle, void *context)
236
drizzle->context= context;
239
void drizzle_set_context_free_fn(drizzle_st *drizzle,
240
drizzle_context_free_fn *function)
242
drizzle->context_free_fn= function;
245
int drizzle_timeout(const drizzle_st *drizzle)
247
return drizzle->timeout;
250
void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
252
drizzle->timeout= timeout;
255
drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
257
return drizzle->verbose;
260
void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
262
drizzle->verbose= verbose;
265
void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
268
drizzle->log_fn= function;
269
drizzle->log_context= context;
272
void drizzle_set_event_watch_fn(drizzle_st *drizzle,
273
drizzle_event_watch_fn *function,
276
drizzle->event_watch_fn= function;
277
drizzle->event_watch_context= context;
280
drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
284
con= new drizzle_con_st;
288
drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
292
con->options= DRIZZLE_CON_ALLOCATED;
297
if (drizzle->con_list != NULL)
298
drizzle->con_list->prev= con;
299
con->next= drizzle->con_list;
301
drizzle->con_list= con;
302
drizzle->con_count++;
304
con->packet_number= 0;
305
con->protocol_version= 0;
306
con->state_current= 0;
309
con->capabilities= DRIZZLE_CAPABILITIES_NONE;
311
con->command= DRIZZLE_COMMAND_SLEEP;
312
con->options|= DRIZZLE_CON_MYSQL;
313
con->socket_type= DRIZZLE_CON_SOCKET_TCP;
314
con->status= DRIZZLE_CON_STATUS_NONE;
315
con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
316
con->result_count= 0;
318
con->backlog= DRIZZLE_DEFAULT_BACKLOG;
321
con->command_offset= 0;
322
con->command_size= 0;
323
con->command_total= 0;
325
con->addrinfo_next= NULL;
326
con->buffer_ptr= con->buffer;
327
con->command_buffer= NULL;
328
con->command_data= NULL;
330
con->context_free_fn= NULL;
331
con->drizzle= drizzle;
332
/* con->next set above */
333
/* con->prev set above */
335
/* con->result doesn't need to be set */
336
con->result_list= NULL;
338
con->socket.tcp.addrinfo= NULL;
339
con->socket.tcp.host= NULL;
340
con->socket.tcp.port= 0;
341
/* con->buffer doesn't need to be set */
344
/* con->scramble_buffer doesn't need to be set */
345
con->server_version[0]= 0;
346
/* con->state_stack doesn't need to be set */
352
drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
353
const drizzle_con_st *from)
355
con= drizzle_con_create(drizzle, con);
359
/* Clear "operational" options such as IO status. */
360
con->options|= (from->options & ~(DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
361
DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
362
DRIZZLE_CON_LISTEN));
363
con->backlog= from->backlog;
364
strcpy(con->db, from->db);
365
strcpy(con->password, from->password);
366
strcpy(con->user, from->user);
368
switch (from->socket_type)
370
case DRIZZLE_CON_SOCKET_TCP:
371
drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
374
case DRIZZLE_CON_SOCKET_UDS:
375
drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
385
void drizzle_con_free(drizzle_con_st *con)
387
if (con->context != NULL && con->context_free_fn != NULL)
388
con->context_free_fn(con, con->context);
390
if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
391
drizzle_result_free_all(con);
392
else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
393
assert(con->result_list == NULL);
396
drizzle_con_close(con);
398
drizzle_con_reset_addrinfo(con);
400
if (con->drizzle->con_list == con)
401
con->drizzle->con_list= con->next;
402
if (con->prev != NULL)
403
con->prev->next= con->next;
404
if (con->next != NULL)
405
con->next->prev= con->prev;
406
con->drizzle->con_count--;
408
if (con->options & DRIZZLE_CON_ALLOCATED)
412
void drizzle_con_free_all(drizzle_st *drizzle)
414
while (drizzle->con_list != NULL)
415
drizzle_con_free(drizzle->con_list);
418
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
424
drizzle_return_t dret;
426
if (drizzle->pfds_size < drizzle->con_count)
428
pfds= (struct pollfd *)realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
431
drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
432
return DRIZZLE_RETURN_MEMORY;
436
drizzle->pfds_size= drizzle->con_count;
442
for (con= drizzle->con_list; con != NULL; con= con->next)
444
if (con->events == 0)
448
pfds[x].events= con->events;
455
drizzle_set_error(drizzle, "drizzle_con_wait",
456
"no active file descriptors");
457
return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
462
drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
465
ret= poll(pfds, x, drizzle->timeout);
467
drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
474
drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
475
drizzle->last_errno= errno;
476
return DRIZZLE_RETURN_ERRNO;
484
drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
485
return DRIZZLE_RETURN_TIMEOUT;
489
for (con= drizzle->con_list; con != NULL; con= con->next)
491
if (con->events == 0)
494
dret= drizzle_con_set_revents(con, pfds[x].revents);
495
if (dret != DRIZZLE_RETURN_OK)
501
return DRIZZLE_RETURN_OK;
504
drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
508
/* We can't keep state between calls since connections may be removed during
509
processing. If this list ever gets big, we may want something faster. */
511
for (con= drizzle->con_list; con != NULL; con= con->next)
513
if (con->options & DRIZZLE_CON_IO_READY)
515
con->options&= ~DRIZZLE_CON_IO_READY;
523
drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
527
/* We can't keep state between calls since connections may be removed during
528
processing. If this list ever gets big, we may want something faster. */
530
for (con= drizzle->con_list; con != NULL; con= con->next)
532
if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
533
(DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
535
con->options&= ~DRIZZLE_CON_IO_READY;
547
drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
548
const char *host, in_port_t port,
549
const char *user, const char *password,
551
drizzle_con_options_t options)
553
con= drizzle_con_create(drizzle, con);
557
drizzle_con_set_tcp(con, host, port);
558
drizzle_con_set_auth(con, user, password);
559
drizzle_con_set_db(con, db);
560
drizzle_con_add_options(con, options);
565
drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
566
const char *uds, const char *user,
567
const char *password, const char *db,
568
drizzle_con_options_t options)
570
con= drizzle_con_create(drizzle, con);
574
drizzle_con_set_uds(con, uds);
575
drizzle_con_set_auth(con, user, password);
576
drizzle_con_set_db(con, db);
577
drizzle_con_add_options(con, options);
586
drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
588
const char *host, in_port_t port,
590
drizzle_con_options_t options)
592
con= drizzle_con_create(drizzle, con);
596
drizzle_con_set_tcp(con, host, port);
597
drizzle_con_set_backlog(con, backlog);
598
drizzle_con_add_options(con, options | DRIZZLE_CON_LISTEN);
603
drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
605
const char *uds, int backlog,
606
drizzle_con_options_t options)
608
con= drizzle_con_create(drizzle, con);
612
drizzle_con_set_uds(con, uds);
613
drizzle_con_set_backlog(con, backlog);
614
drizzle_con_add_options(con, options | DRIZZLE_CON_LISTEN);
619
drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
620
drizzle_return_t *ret_ptr)
622
drizzle_con_st *ready;
627
if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
629
fd= accept(ready->fd, NULL, NULL);
631
con= drizzle_con_create(drizzle, con);
635
*ret_ptr= DRIZZLE_RETURN_MEMORY;
639
*ret_ptr= drizzle_con_set_fd(con, fd);
640
if (*ret_ptr != DRIZZLE_RETURN_OK)
646
if (ready->options & DRIZZLE_CON_MYSQL)
647
drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
649
*ret_ptr= DRIZZLE_RETURN_OK;
653
if (drizzle->options & DRIZZLE_NON_BLOCKING)
655
*ret_ptr= DRIZZLE_RETURN_IO_WAIT;
659
for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
661
if (ready->options & DRIZZLE_CON_LISTEN)
662
drizzle_con_set_events(ready, POLLIN);
665
*ret_ptr= drizzle_con_wait(drizzle);
666
if (*ret_ptr != DRIZZLE_RETURN_OK)
675
void drizzle_set_error(drizzle_st *drizzle, const char *function,
676
const char *format, ...)
680
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
683
size= strlen(function);
684
ptr= (char *)memcpy(log_buffer, function, size);
690
va_start(args, format);
691
size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
694
if (drizzle->log_fn == NULL)
696
if (size >= DRIZZLE_MAX_ERROR_SIZE)
697
size= DRIZZLE_MAX_ERROR_SIZE - 1;
699
memcpy(drizzle->last_error, log_buffer, size + 1);
702
drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
705
void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
706
const char *format, va_list args)
708
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
710
if (drizzle->log_fn == NULL)
712
printf("%5s: ", drizzle_verbose_name(verbose));
713
vprintf(format, args);
718
vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
719
drizzle->log_fn(log_buffer, verbose, drizzle->log_context);