00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include "common.h"
00017
00027 static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
00028 {
00029 "NEVER",
00030 "FATAL",
00031 "ERROR",
00032 "INFO",
00033 "DEBUG",
00034 "CRAZY"
00035 };
00036
00039
00040
00041
00042
00043 const char *drizzle_version(void)
00044 {
00045 return PACKAGE_VERSION;
00046 }
00047
00048 const char *drizzle_bugreport(void)
00049 {
00050 return PACKAGE_BUGREPORT;
00051 }
00052
00053 const char *drizzle_verbose_name(drizzle_verbose_t verbose)
00054 {
00055 if (verbose >= DRIZZLE_VERBOSE_MAX)
00056 return "UNKNOWN";
00057
00058 return _verbose_name[verbose];
00059 }
00060
00061 drizzle_st *drizzle_create(drizzle_st *drizzle)
00062 {
00063 if (drizzle == NULL)
00064 {
00065 drizzle= malloc(sizeof(drizzle_st));
00066 if (drizzle == NULL)
00067 return NULL;
00068
00069 drizzle->options= DRIZZLE_ALLOCATED;
00070 }
00071 else
00072 drizzle->options= DRIZZLE_NONE;
00073
00074
00075 drizzle->options|= DRIZZLE_FREE_OBJECTS;
00076 drizzle->error_code= 0;
00077
00078 drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
00079 drizzle->con_count= 0;
00080 drizzle->pfds_size= 0;
00081 drizzle->query_count= 0;
00082 drizzle->query_new= 0;
00083 drizzle->query_running= 0;
00084 drizzle->last_errno= 0;
00085 drizzle->timeout= -1;
00086 drizzle->con_list= NULL;
00087 drizzle->context= NULL;
00088 drizzle->context_free_fn= NULL;
00089 drizzle->event_watch_fn= NULL;
00090 drizzle->event_watch_context= NULL;
00091 drizzle->log_fn= NULL;
00092 drizzle->log_context= NULL;
00093 drizzle->pfds= NULL;
00094 drizzle->query_list= NULL;
00095 drizzle->sqlstate[0]= 0;
00096 drizzle->last_error[0]= 0;
00097
00098 return drizzle;
00099 }
00100
00101 drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
00102 {
00103 drizzle_con_st *con;
00104
00105 drizzle= drizzle_create(drizzle);
00106 if (drizzle == NULL)
00107 return NULL;
00108
00109 drizzle->options|= (from->options & (drizzle_options_t)~DRIZZLE_ALLOCATED);
00110
00111 for (con= from->con_list; con != NULL; con= con->next)
00112 {
00113 if (drizzle_con_clone(drizzle, NULL, con) == NULL)
00114 {
00115 drizzle_free(drizzle);
00116 return NULL;
00117 }
00118 }
00119
00120 return drizzle;
00121 }
00122
00123 void drizzle_free(drizzle_st *drizzle)
00124 {
00125 if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
00126 drizzle->context_free_fn(drizzle, drizzle->context);
00127
00128 if (drizzle->options & DRIZZLE_FREE_OBJECTS)
00129 {
00130 drizzle_con_free_all(drizzle);
00131 drizzle_query_free_all(drizzle);
00132 }
00133 else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
00134 {
00135 assert(drizzle->con_list == NULL);
00136 assert(drizzle->con_list == NULL);
00137 }
00138
00139 if (drizzle->pfds != NULL)
00140 free(drizzle->pfds);
00141
00142 if (drizzle->options & DRIZZLE_ALLOCATED)
00143 free(drizzle);
00144 }
00145
00146 const char *drizzle_error(const drizzle_st *drizzle)
00147 {
00148 return (const char *)drizzle->last_error;
00149 }
00150
00151 int drizzle_errno(const drizzle_st *drizzle)
00152 {
00153 return drizzle->last_errno;
00154 }
00155
00156 uint16_t drizzle_error_code(const drizzle_st *drizzle)
00157 {
00158 return drizzle->error_code;
00159 }
00160
00161 const char *drizzle_sqlstate(const drizzle_st *drizzle)
00162 {
00163 return drizzle->sqlstate;
00164 }
00165
00166 drizzle_options_t drizzle_options(const drizzle_st *drizzle)
00167 {
00168 return drizzle->options;
00169 }
00170
00171 void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
00172 {
00173 drizzle->options= options;
00174 }
00175
00176 void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
00177 {
00178 drizzle->options|= options;
00179 }
00180
00181 void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
00182 {
00183 drizzle->options&= ~options;
00184 }
00185
00186 void *drizzle_context(const drizzle_st *drizzle)
00187 {
00188 return drizzle->context;
00189 }
00190
00191 void drizzle_set_context(drizzle_st *drizzle, void *context)
00192 {
00193 drizzle->context= context;
00194 }
00195
00196 void drizzle_set_context_free_fn(drizzle_st *drizzle,
00197 drizzle_context_free_fn *function)
00198 {
00199 drizzle->context_free_fn= function;
00200 }
00201
00202 int drizzle_timeout(const drizzle_st *drizzle)
00203 {
00204 return drizzle->timeout;
00205 }
00206
00207 void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
00208 {
00209 drizzle->timeout= timeout;
00210 }
00211
00212 drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
00213 {
00214 return drizzle->verbose;
00215 }
00216
00217 void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
00218 {
00219 drizzle->verbose= verbose;
00220 }
00221
00222 void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
00223 void *context)
00224 {
00225 drizzle->log_fn= function;
00226 drizzle->log_context= context;
00227 }
00228
00229 void drizzle_set_event_watch_fn(drizzle_st *drizzle,
00230 drizzle_event_watch_fn *function,
00231 void *context)
00232 {
00233 drizzle->event_watch_fn= function;
00234 drizzle->event_watch_context= context;
00235 }
00236
00237 drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
00238 {
00239 if (con == NULL)
00240 {
00241 con= malloc(sizeof(drizzle_con_st));
00242 if (con == NULL)
00243 {
00244 if (drizzle != NULL)
00245 drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
00246 return NULL;
00247 }
00248
00249 con->options= DRIZZLE_CON_ALLOCATED;
00250 }
00251 else
00252 con->options= 0;
00253
00254 if (drizzle->con_list != NULL)
00255 drizzle->con_list->prev= con;
00256 con->next= drizzle->con_list;
00257 con->prev= NULL;
00258 drizzle->con_list= con;
00259 drizzle->con_count++;
00260
00261 con->packet_number= 0;
00262 con->protocol_version= 0;
00263 con->state_current= 0;
00264 con->events= 0;
00265 con->revents= 0;
00266 con->capabilities= DRIZZLE_CAPABILITIES_NONE;
00267 con->charset= 0;
00268 con->command= 0;
00269 con->options|= DRIZZLE_CON_MYSQL;
00270 con->socket_type= DRIZZLE_CON_SOCKET_TCP;
00271 con->status= DRIZZLE_CON_STATUS_NONE;
00272 con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
00273 con->result_count= 0;
00274 con->thread_id= 0;
00275 con->backlog= DRIZZLE_DEFAULT_BACKLOG;
00276 con->fd= -1;
00277 con->buffer_size= 0;
00278 con->command_offset= 0;
00279 con->command_size= 0;
00280 con->command_total= 0;
00281 con->packet_size= 0;
00282 con->addrinfo_next= NULL;
00283 con->buffer_ptr= con->buffer;
00284 con->command_buffer= NULL;
00285 con->command_data= NULL;
00286 con->context= NULL;
00287 con->context_free_fn= NULL;
00288 con->drizzle= drizzle;
00289
00290
00291 con->query= NULL;
00292
00293 con->result_list= NULL;
00294 con->scramble= NULL;
00295 con->socket.tcp.addrinfo= NULL;
00296 con->socket.tcp.host= NULL;
00297 con->socket.tcp.port= 0;
00298
00299 con->db[0]= 0;
00300 con->password[0]= 0;
00301
00302 con->server_version[0]= 0;
00303
00304 con->user[0]= 0;
00305
00306 return con;
00307 }
00308
00309 drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
00310 const drizzle_con_st *from)
00311 {
00312 con= drizzle_con_create(drizzle, con);
00313 if (con == NULL)
00314 return NULL;
00315
00316
00317 con->options|= (from->options & (drizzle_con_options_t)~(
00318 DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
00319 DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
00320 DRIZZLE_CON_LISTEN));
00321 con->backlog= from->backlog;
00322 strcpy(con->db, from->db);
00323 strcpy(con->password, from->password);
00324 strcpy(con->user, from->user);
00325
00326 switch (from->socket_type)
00327 {
00328 case DRIZZLE_CON_SOCKET_TCP:
00329 drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
00330 break;
00331
00332 case DRIZZLE_CON_SOCKET_UDS:
00333 drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
00334 break;
00335
00336 default:
00337 break;
00338 }
00339
00340 return con;
00341 }
00342
00343 void drizzle_con_free(drizzle_con_st *con)
00344 {
00345 if (con->context != NULL && con->context_free_fn != NULL)
00346 con->context_free_fn(con, con->context);
00347
00348 if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
00349 drizzle_result_free_all(con);
00350 else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
00351 assert(con->result_list == NULL);
00352
00353 if (con->fd != -1)
00354 drizzle_con_close(con);
00355
00356 drizzle_con_reset_addrinfo(con);
00357
00358 if (con->drizzle->con_list == con)
00359 con->drizzle->con_list= con->next;
00360 if (con->prev != NULL)
00361 con->prev->next= con->next;
00362 if (con->next != NULL)
00363 con->next->prev= con->prev;
00364 con->drizzle->con_count--;
00365
00366 if (con->options & DRIZZLE_CON_ALLOCATED)
00367 free(con);
00368 }
00369
00370 void drizzle_con_free_all(drizzle_st *drizzle)
00371 {
00372 while (drizzle->con_list != NULL)
00373 drizzle_con_free(drizzle->con_list);
00374 }
00375
00376 drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
00377 {
00378 drizzle_con_st *con;
00379 struct pollfd *pfds;
00380 uint32_t x;
00381 int ret;
00382 drizzle_return_t dret;
00383
00384 if (drizzle->pfds_size < drizzle->con_count)
00385 {
00386 pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
00387 if (pfds == NULL)
00388 {
00389 drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
00390 return DRIZZLE_RETURN_MEMORY;
00391 }
00392
00393 drizzle->pfds= pfds;
00394 drizzle->pfds_size= drizzle->con_count;
00395 }
00396 else
00397 pfds= drizzle->pfds;
00398
00399 x= 0;
00400 for (con= drizzle->con_list; con != NULL; con= con->next)
00401 {
00402 if (con->events == 0)
00403 continue;
00404
00405 pfds[x].fd= con->fd;
00406 pfds[x].events= con->events;
00407 pfds[x].revents= 0;
00408 x++;
00409 }
00410
00411 if (x == 0)
00412 {
00413 drizzle_set_error(drizzle, "drizzle_con_wait",
00414 "no active file descriptors");
00415 return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
00416 }
00417
00418 while (1)
00419 {
00420 drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
00421 drizzle->timeout);
00422
00423 ret= poll(pfds, x, drizzle->timeout);
00424
00425 drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
00426
00427 if (ret == -1)
00428 {
00429 if (errno == EINTR)
00430 continue;
00431
00432 drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
00433 drizzle->last_errno= errno;
00434 return DRIZZLE_RETURN_ERRNO;
00435 }
00436
00437 break;
00438 }
00439
00440 if (ret == 0)
00441 {
00442 drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
00443 return DRIZZLE_RETURN_TIMEOUT;
00444 }
00445
00446 x= 0;
00447 for (con= drizzle->con_list; con != NULL; con= con->next)
00448 {
00449 if (con->events == 0)
00450 continue;
00451
00452 dret= drizzle_con_set_revents(con, pfds[x].revents);
00453 if (dret != DRIZZLE_RETURN_OK)
00454 return dret;
00455
00456 x++;
00457 }
00458
00459 return DRIZZLE_RETURN_OK;
00460 }
00461
00462 drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
00463 {
00464 drizzle_con_st *con;
00465
00466
00467
00468
00469 for (con= drizzle->con_list; con != NULL; con= con->next)
00470 {
00471 if (con->options & DRIZZLE_CON_IO_READY)
00472 {
00473 con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
00474 return con;
00475 }
00476 }
00477
00478 return NULL;
00479 }
00480
00481 drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
00482 {
00483 drizzle_con_st *con;
00484
00485
00486
00487
00488 for (con= drizzle->con_list; con != NULL; con= con->next)
00489 {
00490 if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
00491 (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
00492 {
00493 con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
00494 return con;
00495 }
00496 }
00497
00498 return NULL;
00499 }
00500
00501
00502
00503
00504
00505 drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
00506 const char *host, in_port_t port,
00507 const char *user, const char *password,
00508 const char *db,
00509 drizzle_con_options_t options)
00510 {
00511 con= drizzle_con_create(drizzle, con);
00512 if (con == NULL)
00513 return NULL;
00514
00515 drizzle_con_set_tcp(con, host, port);
00516 drizzle_con_set_auth(con, user, password);
00517 drizzle_con_set_db(con, db);
00518 drizzle_con_add_options(con, options);
00519
00520 return con;
00521 }
00522
00523 drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
00524 const char *uds, const char *user,
00525 const char *password, const char *db,
00526 drizzle_con_options_t options)
00527 {
00528 con= drizzle_con_create(drizzle, con);
00529 if (con == NULL)
00530 return NULL;
00531
00532 drizzle_con_set_uds(con, uds);
00533 drizzle_con_set_auth(con, user, password);
00534 drizzle_con_set_db(con, db);
00535 drizzle_con_add_options(con, options);
00536
00537 return con;
00538 }
00539
00540
00541
00542
00543
00544 drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
00545 drizzle_con_st *con,
00546 const char *host, in_port_t port,
00547 int backlog,
00548 drizzle_con_options_t options)
00549 {
00550 con= drizzle_con_create(drizzle, con);
00551 if (con == NULL)
00552 return NULL;
00553
00554 drizzle_con_set_tcp(con, host, port);
00555 drizzle_con_set_backlog(con, backlog);
00556 drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
00557
00558 return con;
00559 }
00560
00561 drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
00562 drizzle_con_st *con,
00563 const char *uds, int backlog,
00564 drizzle_con_options_t options)
00565 {
00566 con= drizzle_con_create(drizzle, con);
00567 if (con == NULL)
00568 return NULL;
00569
00570 drizzle_con_set_uds(con, uds);
00571 drizzle_con_set_backlog(con, backlog);
00572 drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
00573
00574 return con;
00575 }
00576
00577 drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
00578 drizzle_return_t *ret_ptr)
00579 {
00580 drizzle_con_st *ready;
00581 int fd;
00582
00583 while (1)
00584 {
00585 if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
00586 {
00587 fd= accept(ready->fd, NULL, NULL);
00588
00589 con= drizzle_con_create(drizzle, con);
00590 if (con == NULL)
00591 {
00592 (void)close(fd);
00593 *ret_ptr= DRIZZLE_RETURN_MEMORY;
00594 return NULL;
00595 }
00596
00597 *ret_ptr= drizzle_con_set_fd(con, fd);
00598 if (*ret_ptr != DRIZZLE_RETURN_OK)
00599 {
00600 (void)close(fd);
00601 return NULL;
00602 }
00603
00604 if (ready->options & DRIZZLE_CON_MYSQL)
00605 drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
00606
00607 *ret_ptr= DRIZZLE_RETURN_OK;
00608 return con;
00609 }
00610
00611 if (drizzle->options & DRIZZLE_NON_BLOCKING)
00612 {
00613 *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
00614 return NULL;
00615 }
00616
00617 for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
00618 {
00619 if (ready->options & DRIZZLE_CON_LISTEN)
00620 drizzle_con_set_events(ready, POLLIN);
00621 }
00622
00623 *ret_ptr= drizzle_con_wait(drizzle);
00624 if (*ret_ptr != DRIZZLE_RETURN_OK)
00625 return NULL;
00626 }
00627 }
00628
00629
00630
00631
00632
00633 void drizzle_set_error(drizzle_st *drizzle, const char *function,
00634 const char *format, ...)
00635 {
00636 size_t size;
00637 char *ptr;
00638 char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
00639 va_list args;
00640
00641 size= strlen(function);
00642 ptr= memcpy(log_buffer, function, size);
00643 ptr+= size;
00644 ptr[0]= ':';
00645 size++;
00646 ptr++;
00647
00648 va_start(args, format);
00649 size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
00650 va_end(args);
00651
00652 if (drizzle->log_fn == NULL)
00653 {
00654 if (size >= DRIZZLE_MAX_ERROR_SIZE)
00655 size= DRIZZLE_MAX_ERROR_SIZE - 1;
00656
00657 memcpy(drizzle->last_error, log_buffer, size + 1);
00658 }
00659 else
00660 drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
00661 }
00662
00663 void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
00664 const char *format, va_list args)
00665 {
00666 char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
00667
00668 if (drizzle->log_fn == NULL)
00669 {
00670 printf("%5s: ", drizzle_verbose_name(verbose));
00671 vprintf(format, args);
00672 printf("\n");
00673 }
00674 else
00675 {
00676 vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
00677 drizzle->log_fn(log_buffer, verbose, drizzle->log_context);
00678 }
00679 }