2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Use and distribution licensed under the BSD license. See
8
* the COPYING.BSD file in the root source directory for full text.
13
* @brief Drizzle Definitions
16
#include "libdrizzle/common.h"
20
* @addtogroup drizzle_static Static Drizzle Declarations
26
* Names of the verbose levels provided.
28
static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
44
const char *drizzle_version(void)
46
return PACKAGE_VERSION;
49
const char *drizzle_bugreport(void)
51
return PACKAGE_BUGREPORT;
54
const char *drizzle_verbose_name(drizzle_verbose_t verbose)
56
if (verbose >= DRIZZLE_VERBOSE_MAX)
59
return _verbose_name[verbose];
62
drizzle_st *drizzle_create(drizzle_st *drizzle)
65
/* if it is MS windows, invoke WSAStartup */
67
if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
68
printf("Error at WSAStartup()\n");
71
memset(&act, 0, sizeof(act));
73
act.sa_handler = SIG_IGN;
74
sigaction(SIGPIPE, &act, NULL);
78
drizzle= malloc(sizeof(drizzle_st));
82
drizzle->options= DRIZZLE_ALLOCATED;
85
drizzle->options= DRIZZLE_NONE;
87
/* @todo remove this default free flag with new API. */
88
drizzle->options|= DRIZZLE_FREE_OBJECTS;
89
drizzle->error_code= 0;
90
/* drizzle->options set above */
91
drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
92
drizzle->con_count= 0;
93
drizzle->pfds_size= 0;
94
drizzle->query_count= 0;
95
drizzle->query_new= 0;
96
drizzle->query_running= 0;
97
drizzle->last_errno= 0;
99
drizzle->con_list= NULL;
100
drizzle->context= NULL;
101
drizzle->context_free_fn= NULL;
102
drizzle->event_watch_fn= NULL;
103
drizzle->event_watch_context= NULL;
104
drizzle->log_fn= NULL;
105
drizzle->log_context= NULL;
107
drizzle->query_list= NULL;
108
drizzle->sqlstate[0]= 0;
109
drizzle->last_error[0]= 0;
114
drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
118
drizzle= drizzle_create(drizzle);
122
drizzle->options|= (from->options & (drizzle_options_t)~DRIZZLE_ALLOCATED);
124
for (con= from->con_list; con != NULL; con= con->next)
126
if (drizzle_con_clone(drizzle, NULL, con) == NULL)
128
drizzle_free(drizzle);
136
void drizzle_free(drizzle_st *drizzle)
138
if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
139
drizzle->context_free_fn(drizzle, drizzle->context);
141
if (drizzle->options & DRIZZLE_FREE_OBJECTS)
143
drizzle_con_free_all(drizzle);
144
drizzle_query_free_all(drizzle);
146
else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
148
assert(drizzle->con_list == NULL);
149
assert(drizzle->con_list == NULL);
152
if (drizzle->pfds != NULL)
155
if (drizzle->options & DRIZZLE_ALLOCATED)
158
/* if it is MS windows, invoke WSACleanup() at the end*/
163
const char *drizzle_error(const drizzle_st *drizzle)
165
return (const char *)drizzle->last_error;
168
int drizzle_errno(const drizzle_st *drizzle)
170
return drizzle->last_errno;
173
uint16_t drizzle_error_code(const drizzle_st *drizzle)
175
return drizzle->error_code;
178
const char *drizzle_sqlstate(const drizzle_st *drizzle)
180
return drizzle->sqlstate;
183
drizzle_options_t drizzle_options(const drizzle_st *drizzle)
185
return drizzle->options;
188
void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
190
drizzle->options= options;
193
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
195
drizzle->options|= options;
198
void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
200
drizzle->options&= ~options;
203
void *drizzle_context(const drizzle_st *drizzle)
205
return drizzle->context;
208
void drizzle_set_context(drizzle_st *drizzle, void *context)
210
drizzle->context= context;
213
void drizzle_set_context_free_fn(drizzle_st *drizzle,
214
drizzle_context_free_fn *function)
216
drizzle->context_free_fn= function;
219
int drizzle_timeout(const drizzle_st *drizzle)
221
return drizzle->timeout;
224
void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
226
drizzle->timeout= timeout;
229
drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
231
return drizzle->verbose;
234
void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
236
drizzle->verbose= verbose;
239
void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
242
drizzle->log_fn= function;
243
drizzle->log_context= context;
246
void drizzle_set_event_watch_fn(drizzle_st *drizzle,
247
drizzle_event_watch_fn *function,
250
drizzle->event_watch_fn= function;
251
drizzle->event_watch_context= context;
254
drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
258
con= malloc(sizeof(drizzle_con_st));
262
drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
266
con->options= DRIZZLE_CON_ALLOCATED;
271
if (drizzle->con_list != NULL)
272
drizzle->con_list->prev= con;
273
con->next= drizzle->con_list;
275
drizzle->con_list= con;
276
drizzle->con_count++;
278
con->packet_number= 0;
279
con->protocol_version= 0;
280
con->state_current= 0;
283
con->capabilities= DRIZZLE_CAPABILITIES_NONE;
286
con->options|= DRIZZLE_CON_MYSQL;
287
con->socket_type= DRIZZLE_CON_SOCKET_TCP;
288
con->status= DRIZZLE_CON_STATUS_NONE;
289
con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
290
con->result_count= 0;
292
con->backlog= DRIZZLE_DEFAULT_BACKLOG;
295
con->command_offset= 0;
296
con->command_size= 0;
297
con->command_total= 0;
299
con->addrinfo_next= NULL;
300
con->buffer_ptr= con->buffer;
301
con->command_buffer= NULL;
302
con->command_data= NULL;
304
con->context_free_fn= NULL;
305
con->drizzle= drizzle;
306
/* con->next set above */
307
/* con->prev set above */
309
/* con->result doesn't need to be set */
310
con->result_list= NULL;
312
con->socket.tcp.addrinfo= NULL;
313
con->socket.tcp.host= NULL;
314
con->socket.tcp.port= 0;
315
/* con->buffer doesn't need to be set */
318
/* con->scramble_buffer doesn't need to be set */
319
con->server_version[0]= 0;
320
/* con->state_stack doesn't need to be set */
326
drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
327
const drizzle_con_st *from)
329
con= drizzle_con_create(drizzle, con);
333
/* Clear "operational" options such as IO status. */
334
con->options|= (from->options & (drizzle_con_options_t)~(
335
DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
336
DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
337
DRIZZLE_CON_LISTEN));
338
con->backlog= from->backlog;
339
strcpy(con->db, from->db);
340
strcpy(con->password, from->password);
341
strcpy(con->user, from->user);
343
switch (from->socket_type)
345
case DRIZZLE_CON_SOCKET_TCP:
346
drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
349
case DRIZZLE_CON_SOCKET_UDS:
350
drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
360
void drizzle_con_free(drizzle_con_st *con)
362
if (con->context != NULL && con->context_free_fn != NULL)
363
con->context_free_fn(con, con->context);
365
if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
366
drizzle_result_free_all(con);
367
else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
368
assert(con->result_list == NULL);
371
drizzle_con_close(con);
373
drizzle_con_reset_addrinfo(con);
375
if (con->drizzle->con_list == con)
376
con->drizzle->con_list= con->next;
377
if (con->prev != NULL)
378
con->prev->next= con->next;
379
if (con->next != NULL)
380
con->next->prev= con->prev;
381
con->drizzle->con_count--;
383
if (con->options & DRIZZLE_CON_ALLOCATED)
387
void drizzle_con_free_all(drizzle_st *drizzle)
389
while (drizzle->con_list != NULL)
390
drizzle_con_free(drizzle->con_list);
393
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
399
drizzle_return_t dret;
401
if (drizzle->pfds_size < drizzle->con_count)
403
pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
406
drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
407
return DRIZZLE_RETURN_MEMORY;
411
drizzle->pfds_size= drizzle->con_count;
417
for (con= drizzle->con_list; con != NULL; con= con->next)
419
if (con->events == 0)
423
pfds[x].events= con->events;
430
drizzle_set_error(drizzle, "drizzle_con_wait",
431
"no active file descriptors");
432
return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
437
drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
440
ret= poll(pfds, x, drizzle->timeout);
442
drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
449
drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
450
drizzle->last_errno= errno;
451
return DRIZZLE_RETURN_ERRNO;
459
drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
460
return DRIZZLE_RETURN_TIMEOUT;
464
for (con= drizzle->con_list; con != NULL; con= con->next)
466
if (con->events == 0)
469
dret= drizzle_con_set_revents(con, pfds[x].revents);
470
if (dret != DRIZZLE_RETURN_OK)
476
return DRIZZLE_RETURN_OK;
479
drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
483
/* We can't keep state between calls since connections may be removed during
484
processing. If this list ever gets big, we may want something faster. */
486
for (con= drizzle->con_list; con != NULL; con= con->next)
488
if (con->options & DRIZZLE_CON_IO_READY)
490
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
498
drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
502
/* We can't keep state between calls since connections may be removed during
503
processing. If this list ever gets big, we may want something faster. */
505
for (con= drizzle->con_list; con != NULL; con= con->next)
507
if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
508
(DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
510
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
522
drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
523
const char *host, in_port_t port,
524
const char *user, const char *password,
526
drizzle_con_options_t options)
528
con= drizzle_con_create(drizzle, con);
532
drizzle_con_set_tcp(con, host, port);
533
drizzle_con_set_auth(con, user, password);
534
drizzle_con_set_db(con, db);
535
drizzle_con_add_options(con, options);
540
drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
541
const char *uds, const char *user,
542
const char *password, const char *db,
543
drizzle_con_options_t options)
545
con= drizzle_con_create(drizzle, con);
549
drizzle_con_set_uds(con, uds);
550
drizzle_con_set_auth(con, user, password);
551
drizzle_con_set_db(con, db);
552
drizzle_con_add_options(con, options);
561
drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
563
const char *host, in_port_t port,
565
drizzle_con_options_t options)
567
con= drizzle_con_create(drizzle, con);
571
drizzle_con_set_tcp(con, host, port);
572
drizzle_con_set_backlog(con, backlog);
573
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
578
drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
580
const char *uds, int backlog,
581
drizzle_con_options_t options)
583
con= drizzle_con_create(drizzle, con);
587
drizzle_con_set_uds(con, uds);
588
drizzle_con_set_backlog(con, backlog);
589
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
594
drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
595
drizzle_return_t *ret_ptr)
597
drizzle_con_st *ready;
602
if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
604
fd= accept(ready->fd, NULL, NULL);
606
con= drizzle_con_create(drizzle, con);
610
*ret_ptr= DRIZZLE_RETURN_MEMORY;
614
*ret_ptr= drizzle_con_set_fd(con, fd);
615
if (*ret_ptr != DRIZZLE_RETURN_OK)
621
if (ready->options & DRIZZLE_CON_MYSQL)
622
drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
624
*ret_ptr= DRIZZLE_RETURN_OK;
628
if (drizzle->options & DRIZZLE_NON_BLOCKING)
630
*ret_ptr= DRIZZLE_RETURN_IO_WAIT;
634
for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
636
if (ready->options & DRIZZLE_CON_LISTEN)
637
drizzle_con_set_events(ready, POLLIN);
640
*ret_ptr= drizzle_con_wait(drizzle);
641
if (*ret_ptr != DRIZZLE_RETURN_OK)
650
void drizzle_set_error(drizzle_st *drizzle, const char *function,
651
const char *format, ...)
655
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
658
size= strlen(function);
659
ptr= memcpy(log_buffer, function, size);
665
va_start(args, format);
666
size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
669
if (drizzle->log_fn == NULL)
671
if (size >= DRIZZLE_MAX_ERROR_SIZE)
672
size= DRIZZLE_MAX_ERROR_SIZE - 1;
674
memcpy(drizzle->last_error, log_buffer, size + 1);
677
drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
680
void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
681
const char *format, va_list args)
683
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
685
if (drizzle->log_fn == NULL)
687
printf("%5s: ", drizzle_verbose_name(verbose));
688
vprintf(format, args);
693
vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
694
drizzle->log_fn(log_buffer, verbose, drizzle->log_context);