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