Drizzled Public API Documentation

drizzle.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  *     * Redistributions of source code must retain the above copyright
00012  * notice, this list of conditions and the following disclaimer.
00013  *
00014  *     * Redistributions in binary form must reproduce the above
00015  * copyright notice, this list of conditions and the following disclaimer
00016  * in the documentation and/or other materials provided with the
00017  * distribution.
00018  *
00019  *     * The names of its contributors may not be used to endorse or
00020  * promote products derived from this software without specific prior
00021  * written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  */
00036 
00042 #include "libdrizzle/common.h"
00043 
00053 static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
00054 {
00055   "NEVER",
00056   "FATAL",
00057   "ERROR",
00058   "INFO",
00059   "DEBUG",
00060   "CRAZY"
00061 };
00062 
00065 /*
00066  * Common Definitions
00067  */
00068 
00069 const char *drizzle_version(void)
00070 {
00071   return PACKAGE_VERSION;
00072 }
00073 
00074 const char *drizzle_bugreport(void)
00075 {
00076   return PACKAGE_BUGREPORT;
00077 }
00078 
00079 const char *drizzle_verbose_name(drizzle_verbose_t verbose)
00080 {
00081   if (verbose >= DRIZZLE_VERBOSE_MAX)
00082     return "UNKNOWN";
00083 
00084   return _verbose_name[verbose];
00085 }
00086 
00087 drizzle_st *drizzle_create(drizzle_st *drizzle)
00088 {
00089 #if defined(_WIN32)
00090   /* if it is MS windows, invoke WSAStartup */
00091   WSADATA wsaData;
00092   if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
00093     printf("Error at WSAStartup()\n");
00094 #else
00095   struct sigaction act;
00096   memset(&act, 0, sizeof(act));
00097 
00098   act.sa_handler = SIG_IGN;
00099   sigaction(SIGPIPE, &act, NULL);
00100 #endif
00101 
00102   if (drizzle == NULL)
00103   {
00104     drizzle= malloc(sizeof(drizzle_st));
00105     if (drizzle == NULL)
00106       return NULL;
00107 
00108     drizzle->options= DRIZZLE_ALLOCATED;
00109   }
00110   else
00111     drizzle->options= DRIZZLE_NONE;
00112 
00113   /* @todo remove this default free flag with new API. */
00114   drizzle->options|= DRIZZLE_FREE_OBJECTS;
00115   drizzle->error_code= 0;
00116   /* drizzle->options set above */
00117   drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
00118   drizzle->con_count= 0;
00119   drizzle->pfds_size= 0;
00120   drizzle->query_count= 0;
00121   drizzle->query_new= 0;
00122   drizzle->query_running= 0;
00123   drizzle->last_errno= 0;
00124   drizzle->timeout= -1;
00125   drizzle->con_list= NULL;
00126   drizzle->context= NULL;
00127   drizzle->context_free_fn= NULL;
00128   drizzle->event_watch_fn= NULL;
00129   drizzle->event_watch_context= NULL;
00130   drizzle->log_fn= NULL;
00131   drizzle->log_context= NULL;
00132   drizzle->pfds= NULL;
00133   drizzle->query_list= NULL;
00134   drizzle->sqlstate[0]= 0;
00135   drizzle->last_error[0]= 0;
00136 
00137   return drizzle;
00138 }
00139 
00140 drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
00141 {
00142   drizzle_con_st *con;
00143 
00144   drizzle= drizzle_create(drizzle);
00145   if (drizzle == NULL)
00146     return NULL;
00147 
00148   drizzle->options|= (from->options & (drizzle_options_t)~DRIZZLE_ALLOCATED);
00149 
00150   for (con= from->con_list; con != NULL; con= con->next)
00151   {
00152     if (drizzle_con_clone(drizzle, NULL, con) == NULL)
00153     {
00154       drizzle_free(drizzle);
00155       return NULL;
00156     }
00157   }
00158 
00159   return drizzle;
00160 }
00161 
00162 void drizzle_free(drizzle_st *drizzle)
00163 {
00164   if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
00165     drizzle->context_free_fn(drizzle, drizzle->context);
00166 
00167   if (drizzle->options & DRIZZLE_FREE_OBJECTS)
00168   {
00169     drizzle_con_free_all(drizzle);
00170     drizzle_query_free_all(drizzle);
00171   }
00172   else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
00173   {
00174     assert(drizzle->con_list == NULL);
00175     assert(drizzle->con_list == NULL);
00176   }
00177 
00178   if (drizzle->pfds != NULL)
00179     free(drizzle->pfds);
00180 
00181   if (drizzle->options & DRIZZLE_ALLOCATED)
00182     free(drizzle);
00183 #if defined(_WIN32)
00184   /* if it is MS windows, invoke WSACleanup() at the end*/
00185   WSACleanup();
00186 #endif
00187 }
00188 
00189 const char *drizzle_error(const drizzle_st *drizzle)
00190 {
00191   return (const char *)drizzle->last_error;
00192 }
00193 
00194 int drizzle_errno(const drizzle_st *drizzle)
00195 {
00196   return drizzle->last_errno;
00197 }
00198 
00199 uint16_t drizzle_error_code(const drizzle_st *drizzle)
00200 {
00201   return drizzle->error_code;
00202 }
00203 
00204 const char *drizzle_sqlstate(const drizzle_st *drizzle)
00205 {
00206   return drizzle->sqlstate;
00207 }
00208 
00209 drizzle_options_t drizzle_options(const drizzle_st *drizzle)
00210 {
00211   return drizzle->options;
00212 }
00213 
00214 void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
00215 {
00216   drizzle->options= options;
00217 }
00218 
00219 void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
00220 {
00221   drizzle->options|= options;
00222 }
00223 
00224 void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
00225 {
00226   drizzle->options&= ~options;
00227 }
00228 
00229 void *drizzle_context(const drizzle_st *drizzle)
00230 {
00231   return drizzle->context;
00232 }
00233 
00234 void drizzle_set_context(drizzle_st *drizzle, void *context)
00235 {
00236   drizzle->context= context;
00237 }
00238 
00239 void drizzle_set_context_free_fn(drizzle_st *drizzle,
00240                                  drizzle_context_free_fn *function)
00241 {
00242   drizzle->context_free_fn= function;
00243 }
00244 
00245 int drizzle_timeout(const drizzle_st *drizzle)
00246 {
00247   return drizzle->timeout;
00248 }
00249 
00250 void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
00251 {
00252   drizzle->timeout= timeout;
00253 }
00254 
00255 drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
00256 {
00257   return drizzle->verbose;
00258 }
00259 
00260 void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
00261 {
00262   drizzle->verbose= verbose;
00263 }
00264 
00265 void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
00266                         void *context)
00267 {
00268   drizzle->log_fn= function;
00269   drizzle->log_context= context;
00270 }
00271 
00272 void drizzle_set_event_watch_fn(drizzle_st *drizzle,
00273                                 drizzle_event_watch_fn *function,
00274                                 void *context)
00275 {
00276   drizzle->event_watch_fn= function;
00277   drizzle->event_watch_context= context;
00278 }
00279 
00280 drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
00281 {
00282   if (con == NULL)
00283   {
00284     con= malloc(sizeof(drizzle_con_st));
00285     if (con == NULL)
00286     {
00287       if (drizzle != NULL)
00288         drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
00289       return NULL;
00290     }
00291 
00292     con->options= DRIZZLE_CON_ALLOCATED;
00293   }
00294   else
00295     con->options= 0;
00296 
00297   if (drizzle->con_list != NULL)
00298     drizzle->con_list->prev= con;
00299   con->next= drizzle->con_list;
00300   con->prev= NULL;
00301   drizzle->con_list= con;
00302   drizzle->con_count++;
00303 
00304   con->packet_number= 0;
00305   con->protocol_version= 0;
00306   con->state_current= 0;
00307   con->events= 0;
00308   con->revents= 0;
00309   con->capabilities= DRIZZLE_CAPABILITIES_NONE;
00310   con->charset= 0;
00311   con->command= 0;
00312   con->options|= DRIZZLE_CON_MYSQL;
00313   con->socket_type= DRIZZLE_CON_SOCKET_TCP;
00314   con->status= DRIZZLE_CON_STATUS_NONE;
00315   con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
00316   con->result_count= 0;
00317   con->thread_id= 0;
00318   con->backlog= DRIZZLE_DEFAULT_BACKLOG;
00319   con->fd= -1;
00320   con->buffer_size= 0;
00321   con->command_offset= 0;
00322   con->command_size= 0;
00323   con->command_total= 0;
00324   con->packet_size= 0;
00325   con->addrinfo_next= NULL;
00326   con->buffer_ptr= con->buffer;
00327   con->command_buffer= NULL;
00328   con->command_data= NULL;
00329   con->context= NULL;
00330   con->context_free_fn= NULL;
00331   con->drizzle= drizzle;
00332   /* con->next set above */
00333   /* con->prev set above */
00334   con->query= NULL;
00335   /* con->result doesn't need to be set */
00336   con->result_list= NULL;
00337   con->scramble= NULL;
00338   con->socket.tcp.addrinfo= NULL;
00339   con->socket.tcp.host= NULL;
00340   con->socket.tcp.port= 0;
00341   /* con->buffer doesn't need to be set */
00342   con->db[0]= 0;
00343   con->password[0]= 0;
00344   /* con->scramble_buffer doesn't need to be set */
00345   con->server_version[0]= 0;
00346   /* con->state_stack doesn't need to be set */
00347   con->user[0]= 0;
00348 
00349   return con;
00350 }
00351 
00352 drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
00353                                   const drizzle_con_st *from)
00354 {
00355   con= drizzle_con_create(drizzle, con);
00356   if (con == NULL)
00357     return NULL;
00358 
00359   /* Clear "operational" options such as IO status. */
00360   con->options|= (from->options & (drizzle_con_options_t)~(
00361                   DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
00362                   DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
00363                   DRIZZLE_CON_LISTEN));
00364   con->backlog= from->backlog;
00365   strcpy(con->db, from->db);
00366   strcpy(con->password, from->password);
00367   strcpy(con->user, from->user);
00368 
00369   switch (from->socket_type)
00370   {
00371   case DRIZZLE_CON_SOCKET_TCP:
00372     drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
00373     break;
00374 
00375   case DRIZZLE_CON_SOCKET_UDS:
00376     drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
00377     break;
00378 
00379   default:
00380     break;
00381   }
00382 
00383   return con;
00384 }
00385 
00386 void drizzle_con_free(drizzle_con_st *con)
00387 {
00388   if (con->context != NULL && con->context_free_fn != NULL)
00389     con->context_free_fn(con, con->context);
00390 
00391   if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
00392     drizzle_result_free_all(con);
00393   else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
00394     assert(con->result_list == NULL);
00395 
00396   if (con->fd != -1)
00397     drizzle_con_close(con);
00398 
00399   drizzle_con_reset_addrinfo(con);
00400 
00401   if (con->drizzle->con_list == con)
00402     con->drizzle->con_list= con->next;
00403   if (con->prev != NULL)
00404     con->prev->next= con->next;
00405   if (con->next != NULL)
00406     con->next->prev= con->prev;
00407   con->drizzle->con_count--;
00408 
00409   if (con->options & DRIZZLE_CON_ALLOCATED)
00410     free(con);
00411 }
00412 
00413 void drizzle_con_free_all(drizzle_st *drizzle)
00414 {
00415   while (drizzle->con_list != NULL)
00416     drizzle_con_free(drizzle->con_list);
00417 }
00418 
00419 drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
00420 {
00421   drizzle_con_st *con;
00422   struct pollfd *pfds;
00423   uint32_t x;
00424   int ret;
00425   drizzle_return_t dret;
00426 
00427   if (drizzle->pfds_size < drizzle->con_count)
00428   {
00429     pfds= (struct pollfd *)realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
00430     if (pfds == NULL)
00431     {
00432       drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
00433       return DRIZZLE_RETURN_MEMORY;
00434     }
00435 
00436     drizzle->pfds= pfds;
00437     drizzle->pfds_size= drizzle->con_count;
00438   }
00439   else
00440     pfds= drizzle->pfds;
00441 
00442   x= 0;
00443   for (con= drizzle->con_list; con != NULL; con= con->next)
00444   {
00445     if (con->events == 0)
00446       continue;
00447 
00448     pfds[x].fd= con->fd;
00449     pfds[x].events= con->events;
00450     pfds[x].revents= 0;
00451     x++;
00452   }
00453 
00454   if (x == 0)
00455   {
00456     drizzle_set_error(drizzle, "drizzle_con_wait",
00457                       "no active file descriptors");
00458     return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
00459   }
00460 
00461   while (1)
00462   {
00463     drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
00464                       drizzle->timeout);
00465 
00466     ret= poll(pfds, x, drizzle->timeout);
00467 
00468     drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
00469 
00470     if (ret == -1)
00471     {
00472       if (errno == EINTR)
00473         continue;
00474 
00475       drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
00476       drizzle->last_errno= errno;
00477       return DRIZZLE_RETURN_ERRNO;
00478     }
00479 
00480     break;
00481   }
00482 
00483   if (ret == 0)
00484   {
00485     drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
00486     return DRIZZLE_RETURN_TIMEOUT;
00487   }
00488 
00489   x= 0;
00490   for (con= drizzle->con_list; con != NULL; con= con->next)
00491   {
00492     if (con->events == 0)
00493       continue;
00494 
00495     dret= drizzle_con_set_revents(con, pfds[x].revents);
00496     if (dret != DRIZZLE_RETURN_OK)
00497       return dret;
00498 
00499     x++;
00500   }
00501 
00502   return DRIZZLE_RETURN_OK;
00503 }
00504 
00505 drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
00506 {
00507   drizzle_con_st *con;
00508 
00509   /* We can't keep state between calls since connections may be removed during
00510      processing. If this list ever gets big, we may want something faster. */
00511 
00512   for (con= drizzle->con_list; con != NULL; con= con->next)
00513   {
00514     if (con->options & DRIZZLE_CON_IO_READY)
00515     {
00516       con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
00517       return con;
00518     }
00519   }
00520 
00521   return NULL;
00522 }
00523 
00524 drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
00525 {
00526   drizzle_con_st *con;
00527 
00528   /* We can't keep state between calls since connections may be removed during
00529      processing. If this list ever gets big, we may want something faster. */
00530 
00531   for (con= drizzle->con_list; con != NULL; con= con->next)
00532   {
00533     if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
00534         (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
00535     {
00536       con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
00537       return con;
00538     }
00539   }
00540 
00541   return NULL;
00542 }
00543 
00544 /*
00545  * Client Definitions
00546  */
00547 
00548 drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
00549                                     const char *host, in_port_t port,
00550                                     const char *user, const char *password,
00551                                     const char *db,
00552                                     drizzle_con_options_t options)
00553 {
00554   con= drizzle_con_create(drizzle, con);
00555   if (con == NULL)
00556     return NULL;
00557 
00558   drizzle_con_set_tcp(con, host, port);
00559   drizzle_con_set_auth(con, user, password);
00560   drizzle_con_set_db(con, db);
00561   drizzle_con_add_options(con, options);
00562 
00563   return con;
00564 }
00565 
00566 drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
00567                                     const char *uds, const char *user,
00568                                     const char *password, const char *db,
00569                                     drizzle_con_options_t options)
00570 {
00571   con= drizzle_con_create(drizzle, con);
00572   if (con == NULL)
00573     return NULL;
00574 
00575   drizzle_con_set_uds(con, uds);
00576   drizzle_con_set_auth(con, user, password);
00577   drizzle_con_set_db(con, db);
00578   drizzle_con_add_options(con, options);
00579 
00580   return con;
00581 }
00582 
00583 /*
00584  * Server Definitions
00585  */
00586 
00587 drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
00588                                            drizzle_con_st *con,
00589                                            const char *host, in_port_t port,
00590                                            int backlog,
00591                                            drizzle_con_options_t options)
00592 {
00593   con= drizzle_con_create(drizzle, con);
00594   if (con == NULL)
00595     return NULL;
00596 
00597   drizzle_con_set_tcp(con, host, port);
00598   drizzle_con_set_backlog(con, backlog);
00599   drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
00600 
00601   return con;
00602 }
00603 
00604 drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
00605                                            drizzle_con_st *con,
00606                                            const char *uds, int backlog,
00607                                            drizzle_con_options_t options)
00608 {
00609   con= drizzle_con_create(drizzle, con);
00610   if (con == NULL)
00611     return NULL;
00612 
00613   drizzle_con_set_uds(con, uds);
00614   drizzle_con_set_backlog(con, backlog);
00615   drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
00616 
00617   return con;
00618 }
00619 
00620 drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
00621                                    drizzle_return_t *ret_ptr)
00622 {
00623   drizzle_con_st *ready;
00624   int fd;
00625 
00626   while (1)
00627   {
00628     if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
00629     {
00630       fd= accept(ready->fd, NULL, NULL);
00631 
00632       con= drizzle_con_create(drizzle, con);
00633       if (con == NULL)
00634       {
00635         (void)close(fd);
00636         *ret_ptr= DRIZZLE_RETURN_MEMORY;
00637         return NULL;
00638       }
00639 
00640       *ret_ptr= drizzle_con_set_fd(con, fd);
00641       if (*ret_ptr != DRIZZLE_RETURN_OK)
00642       {
00643         (void)close(fd);
00644         return NULL;
00645       }
00646 
00647       if (ready->options & DRIZZLE_CON_MYSQL)
00648         drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
00649 
00650       *ret_ptr= DRIZZLE_RETURN_OK;
00651       return con;
00652     }
00653 
00654     if (drizzle->options & DRIZZLE_NON_BLOCKING)
00655     {
00656       *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
00657       return NULL;
00658     }
00659 
00660     for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
00661     {
00662       if (ready->options & DRIZZLE_CON_LISTEN)
00663         drizzle_con_set_events(ready, POLLIN);
00664     }
00665 
00666     *ret_ptr= drizzle_con_wait(drizzle);
00667     if (*ret_ptr != DRIZZLE_RETURN_OK)
00668       return NULL;
00669   }
00670 }
00671 
00672 /*
00673  * Local Definitions
00674  */
00675 
00676 void drizzle_set_error(drizzle_st *drizzle, const char *function,
00677                        const char *format, ...)
00678 {
00679   size_t size;
00680   char *ptr;
00681   char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
00682   va_list args;
00683 
00684   size= strlen(function);
00685   ptr= memcpy(log_buffer, function, size);
00686   ptr+= size;
00687   ptr[0]= ':';
00688   size++;
00689   ptr++;
00690 
00691   va_start(args, format);
00692   size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
00693   va_end(args);
00694 
00695   if (drizzle->log_fn == NULL)
00696   {
00697     if (size >= DRIZZLE_MAX_ERROR_SIZE)
00698       size= DRIZZLE_MAX_ERROR_SIZE - 1;
00699 
00700     memcpy(drizzle->last_error, log_buffer, size + 1);
00701   }
00702   else
00703     drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
00704 }
00705 
00706 void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
00707                  const char *format, va_list args)
00708 {
00709   char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
00710 
00711   if (drizzle->log_fn == NULL)
00712   {
00713     printf("%5s: ", drizzle_verbose_name(verbose));
00714     vprintf(format, args);
00715     printf("\n");
00716   }
00717   else
00718   {
00719     vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
00720     drizzle->log_fn(log_buffer, verbose, drizzle->log_context);
00721   }
00722 }