Drizzled Public API Documentation

drizzle.cc
Go to the documentation of this file.
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  * Drizzle Client & Protocol Library
4  *
5  * Copyright (C) 2008 Eric Day (eday@oddments.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following disclaimer
17  * in the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * * The names of its contributors may not be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
43 #include <libdrizzle/common.h>
44 
54 static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
55 {
56  "NEVER",
57  "FATAL",
58  "ERROR",
59  "INFO",
60  "DEBUG",
61  "CRAZY"
62 };
63 
66 /*
67  * Common Definitions
68  */
69 
70 void drizzle_library_init(void)
71 {
72  SSL_library_init();
73 }
74 
75 const char *drizzle_version(void)
76 {
77  return LIBDRIZZLE_VERSION_STRING;
78 }
79 
80 const char *drizzle_bugreport(void)
81 {
82  return PACKAGE_BUGREPORT;
83 }
84 
85 const char *drizzle_verbose_name(drizzle_verbose_t verbose)
86 {
87  if (verbose >= DRIZZLE_VERBOSE_MAX)
88  {
89  return "UNKNOWN";
90  }
91 
92  return _verbose_name[verbose];
93 }
94 
95 drizzle_st *drizzle_create(drizzle_st *drizzle)
96 {
97 #if defined(_WIN32)
98  /* if it is MS windows, invoke WSAStartup */
99  WSADATA wsaData;
100  if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
101  printf("Error at WSAStartup()\n");
102 #else
103  struct sigaction act;
104  memset(&act, 0, sizeof(act));
105 
106  act.sa_handler = SIG_IGN;
107  sigaction(SIGPIPE, &act, NULL);
108 #endif
109 
110  if (drizzle == NULL)
111  {
112  drizzle= new (std::nothrow) drizzle_st;
113  if (drizzle == NULL)
114  {
115  return NULL;
116  }
117 
118  drizzle->options= DRIZZLE_ALLOCATED;
119  }
120  else
121  {
122  drizzle->options= DRIZZLE_NONE;
123  }
124 
125  /* @todo remove this default free flag with new API. */
126  drizzle->options|= DRIZZLE_FREE_OBJECTS;
127  drizzle->error_code= 0;
128  /* drizzle->options set above */
129  drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
130  drizzle->con_count= 0;
131  drizzle->pfds_size= 0;
132  drizzle->query_count= 0;
133  drizzle->query_new= 0;
134  drizzle->query_running= 0;
135  drizzle->last_errno= 0;
136  drizzle->timeout= -1;
137  drizzle->con_list= NULL;
138  drizzle->context= NULL;
139  drizzle->context_free_fn= NULL;
140  drizzle->event_watch_fn= NULL;
141  drizzle->event_watch_context= NULL;
142  drizzle->log_fn= NULL;
143  drizzle->log_context= NULL;
144  drizzle->pfds= NULL;
145  drizzle->query_list= NULL;
146  drizzle->sqlstate[0]= 0;
147  drizzle->last_error[0]= 0;
148 
149  return drizzle;
150 }
151 
152 drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
153 {
154  drizzle= drizzle_create(drizzle);
155  if (drizzle == NULL)
156  {
157  return NULL;
158  }
159 
160  drizzle->options|= (from->options & int(~DRIZZLE_ALLOCATED));
161 
162  for (drizzle_con_st *con= from->con_list; con != NULL; con= con->next)
163  {
164  if (drizzle_con_clone(drizzle, NULL, con) == NULL)
165  {
166  drizzle_free(drizzle);
167  return NULL;
168  }
169  }
170 
171  return drizzle;
172 }
173 
174 void drizzle_free(drizzle_st *drizzle)
175 {
176  if (drizzle == NULL)
177  {
178  return;
179  }
180 
181  if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
182  {
183  drizzle->context_free_fn(drizzle, drizzle->context);
184  }
185 
186  if (drizzle->options & DRIZZLE_FREE_OBJECTS)
187  {
188  drizzle_con_free_all(drizzle);
189  drizzle_query_free_all(drizzle);
190  }
191  else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
192  {
193  assert(drizzle->con_list == NULL);
194  assert(drizzle->query_list == NULL);
195  }
196 
197  free(drizzle->pfds);
198 
199  if (drizzle->options & DRIZZLE_ALLOCATED)
200  {
201  delete drizzle;
202  }
203 #if defined(_WIN32)
204  /* if it is MS windows, invoke WSACleanup() at the end*/
205  WSACleanup();
206 #endif
207 }
208 
209 const char *drizzle_error(const drizzle_st *drizzle)
210 {
211  if (drizzle == NULL)
212  {
213  return NULL;
214  }
215 
216  return (const char *)drizzle->last_error;
217 }
218 
219 int drizzle_errno(const drizzle_st *drizzle)
220 {
221  if (drizzle == NULL)
222  {
223  return 0;
224  }
225 
226  return drizzle->last_errno;
227 }
228 
229 uint16_t drizzle_error_code(const drizzle_st *drizzle)
230 {
231  if (drizzle == NULL)
232  {
233  return 0;
234  }
235 
236  return drizzle->error_code;
237 }
238 
239 const char *drizzle_sqlstate(const drizzle_st *drizzle)
240 {
241  if (drizzle == NULL)
242  {
243  return NULL;
244  }
245 
246  return drizzle->sqlstate;
247 }
248 
249 drizzle_options_t drizzle_options(const drizzle_st *drizzle)
250 {
251  if (drizzle == NULL)
252  {
253  return drizzle_options_t();
254  }
255 
256  return drizzle_options_t(drizzle->options);
257 }
258 
259 void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
260 {
261  if (drizzle == NULL)
262  {
263  return;
264  }
265 
266  drizzle->options= options;
267 }
268 
269 void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
270 {
271  if (drizzle == NULL)
272  {
273  return;
274  }
275 
276  drizzle->options|= options;
277 }
278 
279 void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
280 {
281  if (drizzle == NULL)
282  {
283  return;
284  }
285 
286  drizzle->options&= ~options;
287 }
288 
289 void *drizzle_context(const drizzle_st *drizzle)
290 {
291  if (drizzle == NULL)
292  {
293  return NULL;
294  }
295 
296  return drizzle->context;
297 }
298 
299 void drizzle_set_context(drizzle_st *drizzle, void *context)
300 {
301  if (drizzle == NULL)
302  {
303  return;
304  }
305 
306  drizzle->context= context;
307 }
308 
309 void drizzle_set_context_free_fn(drizzle_st *drizzle,
310  drizzle_context_free_fn *function)
311 {
312  if (drizzle == NULL)
313  {
314  return;
315  }
316 
317  drizzle->context_free_fn= function;
318 }
319 
320 int drizzle_timeout(const drizzle_st *drizzle)
321 {
322  if (drizzle == NULL)
323  {
324  return -1;
325  }
326 
327  return drizzle->timeout;
328 }
329 
330 void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
331 {
332  if (drizzle == NULL)
333  {
334  return;
335  }
336 
337  drizzle->timeout= timeout;
338 }
339 
340 drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
341 {
342  if (drizzle == NULL)
343  {
344  return drizzle_verbose_t();
345  }
346 
347  return drizzle->verbose;
348 }
349 
350 void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
351 {
352  if (drizzle == NULL)
353  {
354  return;
355  }
356 
357  drizzle->verbose= verbose;
358 }
359 
360 void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
361  void *context)
362 {
363  if (drizzle == NULL)
364  {
365  return;
366  }
367 
368  drizzle->log_fn= function;
369  drizzle->log_context= context;
370 }
371 
372 void drizzle_set_event_watch_fn(drizzle_st *drizzle,
373  drizzle_event_watch_fn *function,
374  void *context)
375 {
376  if (drizzle == NULL)
377  {
378  return;
379  }
380 
381  drizzle->event_watch_fn= function;
382  drizzle->event_watch_context= context;
383 }
384 
385 drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
386 {
387  if (drizzle == NULL)
388  {
389  return NULL;
390  }
391 
392  if (con == NULL)
393  {
394  con= new (std::nothrow) drizzle_con_st;
395  if (con == NULL)
396  {
397  if (drizzle != NULL)
398  {
399  drizzle_set_error(drizzle, __func__, "Failed to allocate.");
400  }
401 
402  return NULL;
403  }
404 
405  con->options= DRIZZLE_CON_ALLOCATED;
406  }
407  else
408  {
409  con->options= 0;
410  }
411 
412  if (drizzle->con_list != NULL)
413  {
414  drizzle->con_list->prev= con;
415  }
416  con->next= drizzle->con_list;
417  con->prev= NULL;
418  drizzle->con_list= con;
419  drizzle->con_count++;
420 
421  con->packet_number= 0;
422  con->protocol_version= 0;
423  con->state_current= 0;
424  con->events= 0;
425  con->revents= 0;
426  con->capabilities= DRIZZLE_CAPABILITIES_NONE;
427  con->charset= 0;
428  con->command= drizzle_command_t();
429  con->options|= DRIZZLE_CON_MYSQL;
430  con->socket_type= DRIZZLE_CON_SOCKET_TCP;
431  con->status= DRIZZLE_CON_STATUS_NONE;
432  con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
433  con->result_count= 0;
434  con->thread_id= 0;
435  con->backlog= DRIZZLE_DEFAULT_BACKLOG;
436  con->fd= -1;
437  con->buffer_size= 0;
438  con->command_offset= 0;
439  con->command_size= 0;
440  con->command_total= 0;
441  con->packet_size= 0;
442  con->addrinfo_next= NULL;
443  con->buffer_ptr= con->buffer;
444  con->command_buffer= NULL;
445  con->command_data= NULL;
446  con->context= NULL;
447  con->context_free_fn= NULL;
448  con->drizzle= drizzle;
449  /* con->next set above */
450  /* con->prev set above */
451  con->query= NULL;
452  /* con->result doesn't need to be set */
453  con->result_list= NULL;
454  con->scramble= NULL;
455  con->socket.tcp.addrinfo= NULL;
456  con->socket.tcp.host= NULL;
457  con->socket.tcp.port= 0;
458  /* con->buffer doesn't need to be set */
459  con->db[0]= 0;
460  con->password[0]= 0;
461  /* con->scramble_buffer doesn't need to be set */
462  con->server_version[0]= 0;
463  /* con->state_stack doesn't need to be set */
464  con->user[0]= 0;
465  con->ssl_context= NULL;
466  con->ssl= NULL;
467  con->ssl_state= DRIZZLE_SSL_STATE_NONE;
468 
469  return con;
470 }
471 
472 drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
473  const drizzle_con_st *from)
474 {
475  if (drizzle == NULL)
476  {
477  return NULL;
478  }
479 
480  con= drizzle_con_create(drizzle, con);
481  if (con == NULL)
482  {
483  return NULL;
484  }
485 
486  /* Clear "operational" options such as IO status. */
487  con->options|= (from->options & int(~(
488  DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
489  DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
490  DRIZZLE_CON_LISTEN)));
491  con->backlog= from->backlog;
492  strcpy(con->db, from->db);
493  strcpy(con->password, from->password);
494  strcpy(con->user, from->user);
495 
496  switch (from->socket_type)
497  {
498  case DRIZZLE_CON_SOCKET_TCP:
499  drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
500  break;
501 
502  case DRIZZLE_CON_SOCKET_UDS:
503  drizzle_con_set_uds(con, from->socket.uds.path_buffer);
504  break;
505 
506  default:
507  break;
508  }
509 
510  return con;
511 }
512 
513 void drizzle_con_free(drizzle_con_st *con)
514 {
515  if (con == NULL)
516  {
517  return;
518  }
519 
520  if (con->context != NULL and con->context_free_fn != NULL)
521  {
522  con->context_free_fn(con, con->context);
523  }
524 
525  if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
526  {
527  drizzle_result_free_all(con);
528  }
529  else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
530  {
531  assert(con->result_list == NULL);
532  }
533 
534  if (con->fd != -1)
535  {
536  drizzle_con_close(con);
537  }
538 
540 
541  if (con->drizzle->con_list == con)
542  con->drizzle->con_list= con->next;
543 
544  if (con->prev != NULL)
545  con->prev->next= con->next;
546 
547  if (con->next != NULL)
548  con->next->prev= con->prev;
549 
550  if (con->ssl)
551  SSL_free(con->ssl);
552 
553  if (con->ssl_context)
554  SSL_CTX_free(con->ssl_context);
555 
556  con->drizzle->con_count--;
557 
558  if (con->options & DRIZZLE_CON_ALLOCATED)
559  {
560  delete con;
561  }
562 }
563 
564 void drizzle_con_free_all(drizzle_st *drizzle)
565 {
566  while (drizzle->con_list != NULL)
567  drizzle_con_free(drizzle->con_list);
568 }
569 
570 drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
571 {
572  if (drizzle == NULL)
573  {
574  return DRIZZLE_RETURN_INVALID_ARGUMENT;
575  }
576 
577  struct pollfd *pfds;
578  if (drizzle->pfds_size < drizzle->con_count)
579  {
580  pfds= (struct pollfd *)realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
581  if (pfds == NULL)
582  {
583  drizzle_set_error(drizzle, __func__, "Failed to realloc file descriptors.");
584  return DRIZZLE_RETURN_MEMORY;
585  }
586 
587  drizzle->pfds= pfds;
588  drizzle->pfds_size= drizzle->con_count;
589  }
590  else
591  {
592  pfds= drizzle->pfds;
593  }
594 
595  uint32_t x= 0;
596  for (drizzle_con_st *con= drizzle->con_list; con != NULL; con= con->next)
597  {
598  if (con->events == 0)
599  {
600  continue;
601  }
602 
603  pfds[x].fd= con->fd;
604  pfds[x].events= con->events;
605  pfds[x].revents= 0;
606  x++;
607  }
608 
609  if (x == 0)
610  {
611  drizzle_set_error(drizzle, __func__, "no active file descriptors");
612  return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
613  }
614 
615  int ret;
616  while (1)
617  {
618  drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
619  drizzle->timeout);
620 
621  ret= poll(pfds, x, drizzle->timeout);
622 
623  drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
624 
625  if (ret == -1)
626  {
627  if (errno == EINTR)
628  {
629  continue;
630  }
631 
632  drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
633  drizzle->last_errno= errno;
634  return DRIZZLE_RETURN_ERRNO;
635  }
636 
637  break;
638  }
639 
640  if (ret == 0)
641  {
642  drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
643  return DRIZZLE_RETURN_TIMEOUT;
644  }
645 
646  x= 0;
647  for (drizzle_con_st *con= drizzle->con_list; con != NULL; con= con->next)
648  {
649  if (con->events == 0)
650  {
651  continue;
652  }
653 
654  drizzle_return_t dret= drizzle_con_set_revents(con, pfds[x].revents);
655  if (dret != DRIZZLE_RETURN_OK)
656  {
657  return dret;
658  }
659 
660  x++;
661  }
662 
663  return DRIZZLE_RETURN_OK;
664 }
665 
666 drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
667 {
668  if (drizzle == NULL)
669  {
670  return NULL;
671  }
672 
673  /* We can't keep state between calls since connections may be removed during
674  processing. If this list ever gets big, we may want something faster. */
675 
676  for (drizzle_con_st *con= drizzle->con_list; con != NULL; con= con->next)
677  {
678  if (con->options & DRIZZLE_CON_IO_READY)
679  {
680  con->options&= int(~DRIZZLE_CON_IO_READY);
681  return con;
682  }
683  }
684 
685  return NULL;
686 }
687 
688 drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
689 {
690  if (drizzle == NULL)
691  {
692  return NULL;
693  }
694 
695  /* We can't keep state between calls since connections may be removed during
696  processing. If this list ever gets big, we may want something faster. */
697 
698  for (drizzle_con_st *con= drizzle->con_list; con != NULL; con= con->next)
699  {
700  if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
701  (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
702  {
703  con->options&= int(~DRIZZLE_CON_IO_READY);
704  return con;
705  }
706  }
707 
708  return NULL;
709 }
710 
711 /*
712  * Client Definitions
713  */
714 
715 drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
716  const char *host, in_port_t port,
717  const char *user, const char *password,
718  const char *db,
719  drizzle_con_options_t options)
720 {
721  if (drizzle == NULL)
722  {
723  return NULL;
724  }
725 
726  con= drizzle_con_create(drizzle, con);
727  if (con == NULL)
728  {
729  return NULL;
730  }
731 
732  drizzle_con_set_tcp(con, host, port);
733  drizzle_con_set_auth(con, user, password);
734  drizzle_con_set_db(con, db);
735  drizzle_con_add_options(con, options);
736 
737  return con;
738 }
739 
740 drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
741  const char *uds, const char *user,
742  const char *password, const char *db,
743  drizzle_con_options_t options)
744 {
745  if (drizzle == NULL)
746  {
747  return NULL;
748  }
749 
750  con= drizzle_con_create(drizzle, con);
751  if (con == NULL)
752  {
753  return NULL;
754  }
755 
756  drizzle_con_set_uds(con, uds);
757  drizzle_con_set_auth(con, user, password);
758  drizzle_con_set_db(con, db);
759  drizzle_con_add_options(con, options);
760 
761  return con;
762 }
763 
764 /*
765  * Server Definitions
766  */
767 
768 drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
769  drizzle_con_st *con,
770  const char *host, in_port_t port,
771  int backlog,
772  drizzle_con_options_t options)
773 {
774  if (drizzle == NULL)
775  {
776  return NULL;
777  }
778 
779  con= drizzle_con_create(drizzle, con);
780  if (con == NULL)
781  {
782  return NULL;
783  }
784 
785  drizzle_con_set_tcp(con, host, port);
786  drizzle_con_set_backlog(con, backlog);
787  drizzle_con_add_options(con, drizzle_con_options_t(DRIZZLE_CON_LISTEN | int(options)));
788 
789  return con;
790 }
791 
792 drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
793  drizzle_con_st *con,
794  const char *uds, int backlog,
795  drizzle_con_options_t options)
796 {
797  if (drizzle == NULL)
798  {
799  return NULL;
800  }
801 
802  con= drizzle_con_create(drizzle, con);
803  if (con == NULL)
804  {
805  return NULL;
806  }
807 
808  drizzle_con_set_uds(con, uds);
809  drizzle_con_set_backlog(con, backlog);
810  drizzle_con_add_options(con, drizzle_con_options_t(DRIZZLE_CON_LISTEN | int(options)));
811 
812  return con;
813 }
814 
815 drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
816  drizzle_return_t *ret_ptr)
817 {
818  drizzle_return_t unused_ret;
819  if (ret_ptr == NULL)
820  {
821  ret_ptr= &unused_ret;
822  }
823 
824  if (drizzle == NULL)
825  {
826  return NULL;
827  }
828 
829  while (1)
830  {
831  drizzle_con_st *ready;
832 
833  if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
834  {
835  int fd= accept(ready->fd, NULL, NULL);
836 
837  con= drizzle_con_create(drizzle, con);
838  if (con == NULL)
839  {
840  (void)closesocket(fd);
841  *ret_ptr= DRIZZLE_RETURN_MEMORY;
842  return NULL;
843  }
844 
845  *ret_ptr= drizzle_con_set_fd(con, fd);
846  if (*ret_ptr != DRIZZLE_RETURN_OK)
847  {
848  (void)closesocket(fd);
849  return NULL;
850  }
851 
852  if (ready->options & DRIZZLE_CON_MYSQL)
853  drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
854 
855  *ret_ptr= DRIZZLE_RETURN_OK;
856  return con;
857  }
858 
859  if (drizzle->options & DRIZZLE_NON_BLOCKING)
860  {
861  *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
862  return NULL;
863  }
864 
865  for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
866  {
867  if (ready->options & DRIZZLE_CON_LISTEN)
868  drizzle_con_set_events(ready, POLLIN);
869  }
870 
871  *ret_ptr= drizzle_con_wait(drizzle);
872  if (*ret_ptr != DRIZZLE_RETURN_OK)
873  return NULL;
874  }
875 }
876 
877 /*
878  * Local Definitions
879  */
880 
881 void drizzle_set_error(drizzle_st *drizzle, const char *function,
882  const char *format, ...)
883 {
884  if (drizzle == NULL)
885  {
886  return;
887  }
888 
889  size_t size;
890  int written;
891  char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
892  va_list args;
893 
894  size= strlen(function);
895  char *ptr= (char *)memcpy(log_buffer, function, size);
896  ptr+= size;
897  ptr[0]= ':';
898  size++;
899  ptr++;
900 
901  va_start(args, format);
902  written= vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
903  va_end(args);
904 
905  if (written < 0)
906  {
907  size= DRIZZLE_MAX_ERROR_SIZE;
908  }
909  else
910  {
911  size+= written;
912  }
913 
914  if (size >= DRIZZLE_MAX_ERROR_SIZE)
915  {
916  size= DRIZZLE_MAX_ERROR_SIZE - 1;
917  }
918  log_buffer[size]= 0;
919 
920  if (drizzle->log_fn == NULL)
921  {
922  memcpy(drizzle->last_error, log_buffer, size + 1);
923  }
924  else
925  {
926  drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
927  }
928 }
929 
930 void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
931  const char *format, va_list args)
932 {
933  if (drizzle == NULL)
934  {
935  return;
936  }
937 
938  char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
939 
940  if (drizzle->log_fn == NULL)
941  {
942  printf("%5s: ", drizzle_verbose_name(verbose));
943  vprintf(format, args);
944  printf("\n");
945  }
946  else
947  {
948  vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
949  log_buffer[DRIZZLE_MAX_ERROR_SIZE-1]= 0;
950  drizzle->log_fn(log_buffer, verbose, drizzle->log_context);
951  }
952 }