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");
72
act.sa_handler = SIG_IGN;
73
sigaction(SIGPIPE, &act, NULL);
77
drizzle= malloc(sizeof(drizzle_st));
81
drizzle->options= DRIZZLE_ALLOCATED;
84
drizzle->options= DRIZZLE_NONE;
86
/* @todo remove this default free flag with new API. */
87
drizzle->options|= DRIZZLE_FREE_OBJECTS;
88
drizzle->error_code= 0;
89
/* drizzle->options set above */
90
drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
91
drizzle->con_count= 0;
92
drizzle->pfds_size= 0;
93
drizzle->query_count= 0;
94
drizzle->query_new= 0;
95
drizzle->query_running= 0;
96
drizzle->last_errno= 0;
98
drizzle->con_list= NULL;
99
drizzle->context= NULL;
100
drizzle->context_free_fn= NULL;
101
drizzle->event_watch_fn= NULL;
102
drizzle->event_watch_context= NULL;
103
drizzle->log_fn= NULL;
104
drizzle->log_context= NULL;
106
drizzle->query_list= NULL;
107
drizzle->sqlstate[0]= 0;
108
drizzle->last_error[0]= 0;
113
drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
117
drizzle= drizzle_create(drizzle);
121
drizzle->options|= (from->options & (drizzle_options_t)~DRIZZLE_ALLOCATED);
123
for (con= from->con_list; con != NULL; con= con->next)
125
if (drizzle_con_clone(drizzle, NULL, con) == NULL)
127
drizzle_free(drizzle);
135
void drizzle_free(drizzle_st *drizzle)
137
if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
138
drizzle->context_free_fn(drizzle, drizzle->context);
140
if (drizzle->options & DRIZZLE_FREE_OBJECTS)
142
drizzle_con_free_all(drizzle);
143
drizzle_query_free_all(drizzle);
145
else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
147
assert(drizzle->con_list == NULL);
148
assert(drizzle->con_list == NULL);
151
if (drizzle->pfds != NULL)
154
if (drizzle->options & DRIZZLE_ALLOCATED)
157
/* if it is MS windows, invoke WSACleanup() at the end*/
162
const char *drizzle_error(const drizzle_st *drizzle)
164
return (const char *)drizzle->last_error;
167
int drizzle_errno(const drizzle_st *drizzle)
169
return drizzle->last_errno;
172
uint16_t drizzle_error_code(const drizzle_st *drizzle)
174
return drizzle->error_code;
177
const char *drizzle_sqlstate(const drizzle_st *drizzle)
179
return drizzle->sqlstate;
182
drizzle_options_t drizzle_options(const drizzle_st *drizzle)
184
return drizzle->options;
187
void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
189
drizzle->options= options;
192
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
194
drizzle->options|= options;
197
void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
199
drizzle->options&= ~options;
202
void *drizzle_context(const drizzle_st *drizzle)
204
return drizzle->context;
207
void drizzle_set_context(drizzle_st *drizzle, void *context)
209
drizzle->context= context;
212
void drizzle_set_context_free_fn(drizzle_st *drizzle,
213
drizzle_context_free_fn *function)
215
drizzle->context_free_fn= function;
218
int drizzle_timeout(const drizzle_st *drizzle)
220
return drizzle->timeout;
223
void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
225
drizzle->timeout= timeout;
228
drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
230
return drizzle->verbose;
233
void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
235
drizzle->verbose= verbose;
238
void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
241
drizzle->log_fn= function;
242
drizzle->log_context= context;
245
void drizzle_set_event_watch_fn(drizzle_st *drizzle,
246
drizzle_event_watch_fn *function,
249
drizzle->event_watch_fn= function;
250
drizzle->event_watch_context= context;
253
drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
257
con= malloc(sizeof(drizzle_con_st));
261
drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
265
con->options= DRIZZLE_CON_ALLOCATED;
270
if (drizzle->con_list != NULL)
271
drizzle->con_list->prev= con;
272
con->next= drizzle->con_list;
274
drizzle->con_list= con;
275
drizzle->con_count++;
277
con->packet_number= 0;
278
con->protocol_version= 0;
279
con->state_current= 0;
282
con->capabilities= DRIZZLE_CAPABILITIES_NONE;
285
con->options|= DRIZZLE_CON_MYSQL;
286
con->socket_type= DRIZZLE_CON_SOCKET_TCP;
287
con->status= DRIZZLE_CON_STATUS_NONE;
288
con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
289
con->result_count= 0;
291
con->backlog= DRIZZLE_DEFAULT_BACKLOG;
294
con->command_offset= 0;
295
con->command_size= 0;
296
con->command_total= 0;
298
con->addrinfo_next= NULL;
299
con->buffer_ptr= con->buffer;
300
con->command_buffer= NULL;
301
con->command_data= NULL;
303
con->context_free_fn= NULL;
304
con->drizzle= drizzle;
305
/* con->next set above */
306
/* con->prev set above */
308
/* con->result doesn't need to be set */
309
con->result_list= NULL;
311
con->socket.tcp.addrinfo= NULL;
312
con->socket.tcp.host= NULL;
313
con->socket.tcp.port= 0;
314
/* con->buffer doesn't need to be set */
317
/* con->scramble_buffer doesn't need to be set */
318
con->server_version[0]= 0;
319
/* con->state_stack doesn't need to be set */
325
drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
326
const drizzle_con_st *from)
328
con= drizzle_con_create(drizzle, con);
332
/* Clear "operational" options such as IO status. */
333
con->options|= (from->options & (drizzle_con_options_t)~(
334
DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
335
DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
336
DRIZZLE_CON_LISTEN));
337
con->backlog= from->backlog;
338
strcpy(con->db, from->db);
339
strcpy(con->password, from->password);
340
strcpy(con->user, from->user);
342
switch (from->socket_type)
344
case DRIZZLE_CON_SOCKET_TCP:
345
drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
348
case DRIZZLE_CON_SOCKET_UDS:
349
drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
359
void drizzle_con_free(drizzle_con_st *con)
361
if (con->context != NULL && con->context_free_fn != NULL)
362
con->context_free_fn(con, con->context);
364
if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
365
drizzle_result_free_all(con);
366
else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
367
assert(con->result_list == NULL);
370
drizzle_con_close(con);
372
drizzle_con_reset_addrinfo(con);
374
if (con->drizzle->con_list == con)
375
con->drizzle->con_list= con->next;
376
if (con->prev != NULL)
377
con->prev->next= con->next;
378
if (con->next != NULL)
379
con->next->prev= con->prev;
380
con->drizzle->con_count--;
382
if (con->options & DRIZZLE_CON_ALLOCATED)
386
void drizzle_con_free_all(drizzle_st *drizzle)
388
while (drizzle->con_list != NULL)
389
drizzle_con_free(drizzle->con_list);
392
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
398
drizzle_return_t dret;
400
if (drizzle->pfds_size < drizzle->con_count)
402
pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
405
drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
406
return DRIZZLE_RETURN_MEMORY;
410
drizzle->pfds_size= drizzle->con_count;
416
for (con= drizzle->con_list; con != NULL; con= con->next)
418
if (con->events == 0)
422
pfds[x].events= con->events;
429
drizzle_set_error(drizzle, "drizzle_con_wait",
430
"no active file descriptors");
431
return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
436
drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
439
ret= poll(pfds, x, drizzle->timeout);
441
drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
448
drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
449
drizzle->last_errno= errno;
450
return DRIZZLE_RETURN_ERRNO;
458
drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
459
return DRIZZLE_RETURN_TIMEOUT;
463
for (con= drizzle->con_list; con != NULL; con= con->next)
465
if (con->events == 0)
468
dret= drizzle_con_set_revents(con, pfds[x].revents);
469
if (dret != DRIZZLE_RETURN_OK)
475
return DRIZZLE_RETURN_OK;
478
drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
482
/* We can't keep state between calls since connections may be removed during
483
processing. If this list ever gets big, we may want something faster. */
485
for (con= drizzle->con_list; con != NULL; con= con->next)
487
if (con->options & DRIZZLE_CON_IO_READY)
489
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
497
drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
501
/* We can't keep state between calls since connections may be removed during
502
processing. If this list ever gets big, we may want something faster. */
504
for (con= drizzle->con_list; con != NULL; con= con->next)
506
if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
507
(DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
509
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
521
drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
522
const char *host, in_port_t port,
523
const char *user, const char *password,
525
drizzle_con_options_t options)
527
con= drizzle_con_create(drizzle, con);
531
drizzle_con_set_tcp(con, host, port);
532
drizzle_con_set_auth(con, user, password);
533
drizzle_con_set_db(con, db);
534
drizzle_con_add_options(con, options);
539
drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
540
const char *uds, const char *user,
541
const char *password, const char *db,
542
drizzle_con_options_t options)
544
con= drizzle_con_create(drizzle, con);
548
drizzle_con_set_uds(con, uds);
549
drizzle_con_set_auth(con, user, password);
550
drizzle_con_set_db(con, db);
551
drizzle_con_add_options(con, options);
560
drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
562
const char *host, in_port_t port,
564
drizzle_con_options_t options)
566
con= drizzle_con_create(drizzle, con);
570
drizzle_con_set_tcp(con, host, port);
571
drizzle_con_set_backlog(con, backlog);
572
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
577
drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
579
const char *uds, int backlog,
580
drizzle_con_options_t options)
582
con= drizzle_con_create(drizzle, con);
586
drizzle_con_set_uds(con, uds);
587
drizzle_con_set_backlog(con, backlog);
588
drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
593
drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
594
drizzle_return_t *ret_ptr)
596
drizzle_con_st *ready;
601
if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
603
fd= accept(ready->fd, NULL, NULL);
605
con= drizzle_con_create(drizzle, con);
609
*ret_ptr= DRIZZLE_RETURN_MEMORY;
613
*ret_ptr= drizzle_con_set_fd(con, fd);
614
if (*ret_ptr != DRIZZLE_RETURN_OK)
620
if (ready->options & DRIZZLE_CON_MYSQL)
621
drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
623
*ret_ptr= DRIZZLE_RETURN_OK;
627
if (drizzle->options & DRIZZLE_NON_BLOCKING)
629
*ret_ptr= DRIZZLE_RETURN_IO_WAIT;
633
for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
635
if (ready->options & DRIZZLE_CON_LISTEN)
636
drizzle_con_set_events(ready, POLLIN);
639
*ret_ptr= drizzle_con_wait(drizzle);
640
if (*ret_ptr != DRIZZLE_RETURN_OK)
649
void drizzle_set_error(drizzle_st *drizzle, const char *function,
650
const char *format, ...)
654
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
657
size= strlen(function);
658
ptr= memcpy(log_buffer, function, size);
664
va_start(args, format);
665
size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
668
if (drizzle->log_fn == NULL)
670
if (size >= DRIZZLE_MAX_ERROR_SIZE)
671
size= DRIZZLE_MAX_ERROR_SIZE - 1;
673
memcpy(drizzle->last_error, log_buffer, size + 1);
676
drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
679
void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
680
const char *format, va_list args)
682
char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
684
if (drizzle->log_fn == NULL)
686
printf("%5s: ", drizzle_verbose_name(verbose));
687
vprintf(format, args);
692
vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
693
drizzle->log_fn(log_buffer, verbose, drizzle->log_context);