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"
46
* @addtogroup drizzle_static Static Drizzle Declarations
52
* Names of the verbose levels provided.
54
static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
70
const char *drizzle_version(void)
72
return PACKAGE_VERSION;
75
const char *drizzle_bugreport(void)
77
return PACKAGE_BUGREPORT;
80
const char *drizzle_verbose_name(drizzle_verbose_t verbose)
82
if (verbose >= DRIZZLE_VERBOSE_MAX)
85
return _verbose_name[verbose];
88
drizzle_st *drizzle_create(drizzle_st *drizzle)
91
/* if it is MS windows, invoke WSAStartup */
93
if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
94
printf("Error at WSAStartup()\n");
97
memset(&act, 0, sizeof(act));
99
act.sa_handler = SIG_IGN;
100
sigaction(SIGPIPE, &act, NULL);
104
drizzle= malloc(sizeof(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_options_t)~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
drizzle_options_t drizzle_options(const drizzle_st *drizzle)
211
return drizzle->options;
214
void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
216
drizzle->options= options;
219
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t 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= malloc(sizeof(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;
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_options_t)~(
361
DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
362
DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
363
DRIZZLE_CON_LISTEN));
364
con->backlog= from->backlog;
365
strcpy(con->db, from->db);
366
strcpy(con->password, from->password);
367
strcpy(con->user, from->user);
369
switch (from->socket_type)
371
case DRIZZLE_CON_SOCKET_TCP:
372
drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
375
case DRIZZLE_CON_SOCKET_UDS:
376
drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
386
void drizzle_con_free(drizzle_con_st *con)
388
if (con->context != NULL && con->context_free_fn != NULL)
389
con->context_free_fn(con, con->context);
391
if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
392
drizzle_result_free_all(con);
393
else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
394
assert(con->result_list == NULL);
397
drizzle_con_close(con);
399
drizzle_con_reset_addrinfo(con);
401
if (con->drizzle->con_list == con)
402
con->drizzle->con_list= con->next;
403
if (con->prev != NULL)
404
con->prev->next= con->next;
405
if (con->next != NULL)
406
con->next->prev= con->prev;
407
con->drizzle->con_count--;
409
if (con->options & DRIZZLE_CON_ALLOCATED)
413
void drizzle_con_free_all(drizzle_st *drizzle)
415
while (drizzle->con_list != NULL)
416
drizzle_con_free(drizzle->con_list);
419
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
425
drizzle_return_t dret;
427
if (drizzle->pfds_size < drizzle->con_count)
429
pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
432
drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
433
return DRIZZLE_RETURN_MEMORY;
437
drizzle->pfds_size= drizzle->con_count;
443
for (con= drizzle->con_list; con != NULL; con= con->next)
445
if (con->events == 0)
449
pfds[x].events= con->events;
456
drizzle_set_error(drizzle, "drizzle_con_wait",
457
"no active file descriptors");
458
return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
463
drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
466
ret= poll(pfds, x, drizzle->timeout);
468
drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
475
drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
476
drizzle->last_errno= errno;
477
return DRIZZLE_RETURN_ERRNO;
485
drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
486
return DRIZZLE_RETURN_TIMEOUT;
490
for (con= drizzle->con_list; con != NULL; con= con->next)
492
if (con->events == 0)
495
dret= drizzle_con_set_revents(con, pfds[x].revents);
496
if (dret != DRIZZLE_RETURN_OK)
502
return DRIZZLE_RETURN_OK;
505
drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
509
/* We can't keep state between calls since connections may be removed during
510
processing. If this list ever gets big, we may want something faster. */
512
for (con= drizzle->con_list; con != NULL; con= con->next)
514
if (con->options & DRIZZLE_CON_IO_READY)
516
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
524
drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
528
/* We can't keep state between calls since connections may be removed during
529
processing. If this list ever gets big, we may want something faster. */
531
for (con= drizzle->con_list; con != NULL; con= con->next)
533
if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
534
(DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
536
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
548
drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
549
const char *host, in_port_t port,
550
const char *user, const char *password,
552
drizzle_con_options_t options)
554
con= drizzle_con_create(drizzle, con);
558
drizzle_con_set_tcp(con, host, port);
559
drizzle_con_set_auth(con, user, password);
560
drizzle_con_set_db(con, db);
561
drizzle_con_add_options(con, options);
566
drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
567
const char *uds, const char *user,
568
const char *password, const char *db,
569
drizzle_con_options_t options)
571
con= drizzle_con_create(drizzle, con);
575
drizzle_con_set_uds(con, uds);
576
drizzle_con_set_auth(con, user, password);
577
drizzle_con_set_db(con, db);
578
drizzle_con_add_options(con, options);
587
drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
589
const char *host, in_port_t port,
591
drizzle_con_options_t options)
593
con= drizzle_con_create(drizzle, con);
597
drizzle_con_set_tcp(con, host, port);
598
drizzle_con_set_backlog(con, backlog);
599
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
604
drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
606
const char *uds, int backlog,
607
drizzle_con_options_t options)
609
con= drizzle_con_create(drizzle, con);
613
drizzle_con_set_uds(con, uds);
614
drizzle_con_set_backlog(con, backlog);
615
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
620
drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
621
drizzle_return_t *ret_ptr)
623
drizzle_con_st *ready;
628
if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
630
fd= accept(ready->fd, NULL, NULL);
632
con= drizzle_con_create(drizzle, con);
636
*ret_ptr= DRIZZLE_RETURN_MEMORY;
640
*ret_ptr= drizzle_con_set_fd(con, fd);
641
if (*ret_ptr != DRIZZLE_RETURN_OK)
647
if (ready->options & DRIZZLE_CON_MYSQL)
648
drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
650
*ret_ptr= DRIZZLE_RETURN_OK;
654
if (drizzle->options & DRIZZLE_NON_BLOCKING)
656
*ret_ptr= DRIZZLE_RETURN_IO_WAIT;
660
for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
662
if (ready->options & DRIZZLE_CON_LISTEN)
663
drizzle_con_set_events(ready, POLLIN);
666
*ret_ptr= drizzle_con_wait(drizzle);
667
if (*ret_ptr != DRIZZLE_RETURN_OK)
676
void drizzle_set_error(drizzle_st *drizzle, const char *function,
677
const char *format, ...)
681
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
684
size= strlen(function);
685
ptr= memcpy(log_buffer, function, size);
691
va_start(args, format);
692
size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
695
if (drizzle->log_fn == NULL)
697
if (size >= DRIZZLE_MAX_ERROR_SIZE)
698
size= DRIZZLE_MAX_ERROR_SIZE - 1;
700
memcpy(drizzle->last_error, log_buffer, size + 1);
703
drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
706
void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
707
const char *format, va_list args)
709
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
711
if (drizzle->log_fn == NULL)
713
printf("%5s: ", drizzle_verbose_name(verbose));
714
vprintf(format, args);
719
vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
720
drizzle->log_fn(log_buffer, verbose, drizzle->log_context);