00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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
00114 drizzle->options|= DRIZZLE_FREE_OBJECTS;
00115 drizzle->error_code= 0;
00116
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
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
00333
00334 con->query= NULL;
00335
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
00342 con->db[0]= 0;
00343 con->password[0]= 0;
00344
00345 con->server_version[0]= 0;
00346
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
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
00510
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
00529
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
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
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
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 }