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