~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/drizzle.c

Added libdrizzle to the tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Drizzle Client & Protocol Library
 
3
 *
 
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
 
5
 * All rights reserved.
 
6
 *
 
7
 * Use and distribution licensed under the BSD license.  See
 
8
 * the COPYING file in this directory for full text.
 
9
 */
 
10
 
 
11
/**
 
12
 * @file
 
13
 * @brief Drizzle Definitions
 
14
 */
 
15
 
 
16
#include "libdrizzle/common.h"
 
17
 
 
18
 
 
19
/**
 
20
 * @addtogroup drizzle_static Static Drizzle Declarations
 
21
 * @ingroup drizzle
 
22
 * @{
 
23
 */
 
24
 
 
25
/**
 
26
 * Names of the verbose levels provided.
 
27
 */
 
28
static const char *_verbose_name[DRIZZLE_VERBOSE_MAX]=
 
29
{
 
30
  "NEVER",
 
31
  "FATAL",
 
32
  "ERROR",
 
33
  "INFO",
 
34
  "DEBUG",
 
35
  "CRAZY"
 
36
};
 
37
 
 
38
/** @} */
 
39
 
 
40
/*
 
41
 * Common Definitions
 
42
 */
 
43
 
 
44
const char *drizzle_version(void)
 
45
{
 
46
  return PACKAGE_VERSION;
 
47
}
 
48
 
 
49
const char *drizzle_bugreport(void)
 
50
{
 
51
  return PACKAGE_BUGREPORT;
 
52
}
 
53
 
 
54
const char *drizzle_verbose_name(drizzle_verbose_t verbose)
 
55
{
 
56
  if (verbose >= DRIZZLE_VERBOSE_MAX)
 
57
    return "UNKNOWN";
 
58
 
 
59
  return _verbose_name[verbose];
 
60
}
 
61
 
 
62
drizzle_st *drizzle_create(drizzle_st *drizzle)
 
63
{
 
64
#if defined(_WIN32)
 
65
  /* if it is MS windows, invoke WSAStartup */
 
66
  WSADATA wsaData;
 
67
  if ( WSAStartup( MAKEWORD(2,2), &wsaData ) != 0 )
 
68
    printf("Error at WSAStartup()\n");
 
69
#endif
 
70
  if (drizzle == NULL)
 
71
  {
 
72
    drizzle= malloc(sizeof(drizzle_st));
 
73
    if (drizzle == NULL)
 
74
      return NULL;
 
75
 
 
76
    drizzle->options= DRIZZLE_ALLOCATED;
 
77
  }
 
78
  else
 
79
    drizzle->options= DRIZZLE_NONE;
 
80
 
 
81
  /* @todo remove this default free flag with new API. */
 
82
  drizzle->options|= DRIZZLE_FREE_OBJECTS;
 
83
  drizzle->error_code= 0;
 
84
  /* drizzle->options set above */
 
85
  drizzle->verbose= DRIZZLE_VERBOSE_NEVER;
 
86
  drizzle->con_count= 0;
 
87
  drizzle->pfds_size= 0;
 
88
  drizzle->query_count= 0;
 
89
  drizzle->query_new= 0;
 
90
  drizzle->query_running= 0;
 
91
  drizzle->last_errno= 0;
 
92
  drizzle->timeout= -1;
 
93
  drizzle->con_list= NULL;
 
94
  drizzle->context= NULL;
 
95
  drizzle->context_free_fn= NULL;
 
96
  drizzle->event_watch_fn= NULL;
 
97
  drizzle->event_watch_context= NULL;
 
98
  drizzle->log_fn= NULL;
 
99
  drizzle->log_context= NULL;
 
100
  drizzle->pfds= NULL;
 
101
  drizzle->query_list= NULL;
 
102
  drizzle->sqlstate[0]= 0;
 
103
  drizzle->last_error[0]= 0;
 
104
 
 
105
  return drizzle;
 
106
}
 
107
 
 
108
drizzle_st *drizzle_clone(drizzle_st *drizzle, const drizzle_st *from)
 
109
{
 
110
  drizzle_con_st *con;
 
111
 
 
112
  drizzle= drizzle_create(drizzle);
 
113
  if (drizzle == NULL)
 
114
    return NULL;
 
115
 
 
116
  drizzle->options|= (from->options & (drizzle_options_t)~DRIZZLE_ALLOCATED);
 
117
 
 
118
  for (con= from->con_list; con != NULL; con= con->next)
 
119
  {
 
120
    if (drizzle_con_clone(drizzle, NULL, con) == NULL)
 
121
    {
 
122
      drizzle_free(drizzle);
 
123
      return NULL;
 
124
    }
 
125
  }
 
126
 
 
127
  return drizzle;
 
128
}
 
129
 
 
130
void drizzle_free(drizzle_st *drizzle)
 
131
{
 
132
  if (drizzle->context != NULL && drizzle->context_free_fn != NULL)
 
133
    drizzle->context_free_fn(drizzle, drizzle->context);
 
134
 
 
135
  if (drizzle->options & DRIZZLE_FREE_OBJECTS)
 
136
  {
 
137
    drizzle_con_free_all(drizzle);
 
138
    drizzle_query_free_all(drizzle);
 
139
  }
 
140
  else if (drizzle->options & DRIZZLE_ASSERT_DANGLING)
 
141
  {
 
142
    assert(drizzle->con_list == NULL);
 
143
    assert(drizzle->con_list == NULL);
 
144
  }
 
145
 
 
146
  if (drizzle->pfds != NULL)
 
147
    free(drizzle->pfds);
 
148
 
 
149
  if (drizzle->options & DRIZZLE_ALLOCATED)
 
150
    free(drizzle);
 
151
#if defined(_WIN32)
 
152
  /* if it is MS windows, invoke WSACleanup() at the end*/
 
153
  WSACleanup();
 
154
#endif
 
155
}
 
156
 
 
157
const char *drizzle_error(const drizzle_st *drizzle)
 
158
{
 
159
  return (const char *)drizzle->last_error;
 
160
}
 
161
 
 
162
int drizzle_errno(const drizzle_st *drizzle)
 
163
{
 
164
  return drizzle->last_errno;
 
165
}
 
166
 
 
167
uint16_t drizzle_error_code(const drizzle_st *drizzle)
 
168
{
 
169
  return drizzle->error_code;
 
170
}
 
171
 
 
172
const char *drizzle_sqlstate(const drizzle_st *drizzle)
 
173
{
 
174
  return drizzle->sqlstate;
 
175
}
 
176
 
 
177
drizzle_options_t drizzle_options(const drizzle_st *drizzle)
 
178
{
 
179
  return drizzle->options;
 
180
}
 
181
 
 
182
void drizzle_set_options(drizzle_st *drizzle, drizzle_options_t options)
 
183
{
 
184
  drizzle->options= options;
 
185
}
 
186
 
 
187
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
 
188
{
 
189
  drizzle->options|= options;
 
190
}
 
191
 
 
192
void drizzle_remove_options(drizzle_st *drizzle, drizzle_options_t options)
 
193
{
 
194
  drizzle->options&= ~options;
 
195
}
 
196
 
 
197
void *drizzle_context(const drizzle_st *drizzle)
 
198
{
 
199
  return drizzle->context;
 
200
}
 
201
 
 
202
void drizzle_set_context(drizzle_st *drizzle, void *context)
 
203
{
 
204
  drizzle->context= context;
 
205
}
 
206
 
 
207
void drizzle_set_context_free_fn(drizzle_st *drizzle,
 
208
                                 drizzle_context_free_fn *function)
 
209
{
 
210
  drizzle->context_free_fn= function;
 
211
}
 
212
 
 
213
int drizzle_timeout(const drizzle_st *drizzle)
 
214
{
 
215
  return drizzle->timeout;
 
216
}
 
217
 
 
218
void drizzle_set_timeout(drizzle_st *drizzle, int timeout)
 
219
{
 
220
  drizzle->timeout= timeout;
 
221
}
 
222
 
 
223
drizzle_verbose_t drizzle_verbose(const drizzle_st *drizzle)
 
224
{
 
225
  return drizzle->verbose;
 
226
}
 
227
 
 
228
void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
 
229
{
 
230
  drizzle->verbose= verbose;
 
231
}
 
232
 
 
233
void drizzle_set_log_fn(drizzle_st *drizzle, drizzle_log_fn *function,
 
234
                        void *context)
 
235
{
 
236
  drizzle->log_fn= function;
 
237
  drizzle->log_context= context;
 
238
}
 
239
 
 
240
void drizzle_set_event_watch_fn(drizzle_st *drizzle,
 
241
                                drizzle_event_watch_fn *function,
 
242
                                void *context)
 
243
{
 
244
  drizzle->event_watch_fn= function;
 
245
  drizzle->event_watch_context= context;
 
246
}
 
247
 
 
248
drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
 
249
{
 
250
  if (con == NULL)
 
251
  {
 
252
    con= malloc(sizeof(drizzle_con_st));
 
253
    if (con == NULL)
 
254
    {
 
255
      if (drizzle != NULL)
 
256
        drizzle_set_error(drizzle, "drizzle_con_create", "malloc");
 
257
      return NULL;
 
258
    }
 
259
 
 
260
    con->options= DRIZZLE_CON_ALLOCATED;
 
261
  }
 
262
  else
 
263
    con->options= 0;
 
264
 
 
265
  if (drizzle->con_list != NULL)
 
266
    drizzle->con_list->prev= con;
 
267
  con->next= drizzle->con_list;
 
268
  con->prev= NULL;
 
269
  drizzle->con_list= con;
 
270
  drizzle->con_count++;
 
271
 
 
272
  con->packet_number= 0;
 
273
  con->protocol_version= 0;
 
274
  con->state_current= 0;
 
275
  con->events= 0;
 
276
  con->revents= 0;
 
277
  con->capabilities= DRIZZLE_CAPABILITIES_NONE;
 
278
  con->charset= 0;
 
279
  con->command= 0;
 
280
  con->options|= DRIZZLE_CON_MYSQL;
 
281
  con->socket_type= DRIZZLE_CON_SOCKET_TCP;
 
282
  con->status= DRIZZLE_CON_STATUS_NONE;
 
283
  con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
 
284
  con->result_count= 0;
 
285
  con->thread_id= 0;
 
286
  con->backlog= DRIZZLE_DEFAULT_BACKLOG;
 
287
  con->fd= -1;
 
288
  con->buffer_size= 0;
 
289
  con->command_offset= 0;
 
290
  con->command_size= 0;
 
291
  con->command_total= 0;
 
292
  con->packet_size= 0;
 
293
  con->addrinfo_next= NULL;
 
294
  con->buffer_ptr= con->buffer;
 
295
  con->command_buffer= NULL;
 
296
  con->command_data= NULL;
 
297
  con->context= NULL;
 
298
  con->context_free_fn= NULL;
 
299
  con->drizzle= drizzle;
 
300
  /* con->next set above */
 
301
  /* con->prev set above */
 
302
  con->query= NULL;
 
303
  /* con->result doesn't need to be set */
 
304
  con->result_list= NULL;
 
305
  con->scramble= NULL;
 
306
  con->socket.tcp.addrinfo= NULL;
 
307
  con->socket.tcp.host= NULL;
 
308
  con->socket.tcp.port= 0;
 
309
  /* con->buffer doesn't need to be set */
 
310
  con->db[0]= 0;
 
311
  con->password[0]= 0;
 
312
  /* con->scramble_buffer doesn't need to be set */
 
313
  con->server_version[0]= 0;
 
314
  /* con->state_stack doesn't need to be set */
 
315
  con->user[0]= 0;
 
316
 
 
317
  return con;
 
318
}
 
319
 
 
320
drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
 
321
                                  const drizzle_con_st *from)
 
322
{
 
323
  con= drizzle_con_create(drizzle, con);
 
324
  if (con == NULL)
 
325
    return NULL;
 
326
 
 
327
  /* Clear "operational" options such as IO status. */
 
328
  con->options|= (from->options & (drizzle_con_options_t)~(
 
329
                  DRIZZLE_CON_ALLOCATED|DRIZZLE_CON_READY|
 
330
                  DRIZZLE_CON_NO_RESULT_READ|DRIZZLE_CON_IO_READY|
 
331
                  DRIZZLE_CON_LISTEN));
 
332
  con->backlog= from->backlog;
 
333
  strcpy(con->db, from->db);
 
334
  strcpy(con->password, from->password);
 
335
  strcpy(con->user, from->user);
 
336
 
 
337
  switch (from->socket_type)
 
338
  {
 
339
  case DRIZZLE_CON_SOCKET_TCP:
 
340
    drizzle_con_set_tcp(con, from->socket.tcp.host, from->socket.tcp.port);
 
341
    break;
 
342
 
 
343
  case DRIZZLE_CON_SOCKET_UDS:
 
344
    drizzle_con_set_uds(con, from->socket.uds.sockaddr.sun_path);
 
345
    break;
 
346
 
 
347
  default:
 
348
    break;
 
349
  }
 
350
 
 
351
  return con;
 
352
}
 
353
 
 
354
void drizzle_con_free(drizzle_con_st *con)
 
355
{
 
356
  if (con->context != NULL && con->context_free_fn != NULL)
 
357
    con->context_free_fn(con, con->context);
 
358
 
 
359
  if (con->drizzle->options & DRIZZLE_FREE_OBJECTS)
 
360
    drizzle_result_free_all(con);
 
361
  else if (con->drizzle->options & DRIZZLE_ASSERT_DANGLING)
 
362
    assert(con->result_list == NULL);
 
363
 
 
364
  if (con->fd != -1)
 
365
    drizzle_con_close(con);
 
366
 
 
367
  drizzle_con_reset_addrinfo(con);
 
368
 
 
369
  if (con->drizzle->con_list == con)
 
370
    con->drizzle->con_list= con->next;
 
371
  if (con->prev != NULL)
 
372
    con->prev->next= con->next;
 
373
  if (con->next != NULL)
 
374
    con->next->prev= con->prev;
 
375
  con->drizzle->con_count--;
 
376
 
 
377
  if (con->options & DRIZZLE_CON_ALLOCATED)
 
378
    free(con);
 
379
}
 
380
 
 
381
void drizzle_con_free_all(drizzle_st *drizzle)
 
382
{
 
383
  while (drizzle->con_list != NULL)
 
384
    drizzle_con_free(drizzle->con_list);
 
385
}
 
386
 
 
387
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
 
388
{
 
389
  drizzle_con_st *con;
 
390
  struct pollfd *pfds;
 
391
  uint32_t x;
 
392
  int ret;
 
393
  drizzle_return_t dret;
 
394
 
 
395
  if (drizzle->pfds_size < drizzle->con_count)
 
396
  {
 
397
    pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
 
398
    if (pfds == NULL)
 
399
    {
 
400
      drizzle_set_error(drizzle, "drizzle_con_wait", "realloc");
 
401
      return DRIZZLE_RETURN_MEMORY;
 
402
    }
 
403
 
 
404
    drizzle->pfds= pfds;
 
405
    drizzle->pfds_size= drizzle->con_count;
 
406
  }
 
407
  else
 
408
    pfds= drizzle->pfds;
 
409
 
 
410
  x= 0;
 
411
  for (con= drizzle->con_list; con != NULL; con= con->next)
 
412
  {
 
413
    if (con->events == 0)
 
414
      continue;
 
415
 
 
416
    pfds[x].fd= con->fd;
 
417
    pfds[x].events= con->events;
 
418
    pfds[x].revents= 0;
 
419
    x++;
 
420
  }
 
421
 
 
422
  if (x == 0)
 
423
  {
 
424
    drizzle_set_error(drizzle, "drizzle_con_wait",
 
425
                      "no active file descriptors");
 
426
    return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
 
427
  }
 
428
 
 
429
  while (1)
 
430
  {
 
431
    drizzle_log_crazy(drizzle, "poll count=%d timeout=%d", x,
 
432
                      drizzle->timeout);
 
433
 
 
434
    ret= poll(pfds, x, drizzle->timeout);
 
435
 
 
436
    drizzle_log_crazy(drizzle, "poll return=%d errno=%d", ret, errno);
 
437
 
 
438
    if (ret == -1)
 
439
    {
 
440
      if (errno == EINTR)
 
441
        continue;
 
442
 
 
443
      drizzle_set_error(drizzle, "drizzle_con_wait", "poll:%d", errno);
 
444
      drizzle->last_errno= errno;
 
445
      return DRIZZLE_RETURN_ERRNO;
 
446
    }
 
447
 
 
448
    break;
 
449
  }
 
450
 
 
451
  if (ret == 0)
 
452
  {
 
453
    drizzle_set_error(drizzle, "drizzle_con_wait", "timeout reached");
 
454
    return DRIZZLE_RETURN_TIMEOUT;
 
455
  }
 
456
 
 
457
  x= 0;
 
458
  for (con= drizzle->con_list; con != NULL; con= con->next)
 
459
  {
 
460
    if (con->events == 0)
 
461
      continue;
 
462
 
 
463
    dret= drizzle_con_set_revents(con, pfds[x].revents);
 
464
    if (dret != DRIZZLE_RETURN_OK)
 
465
      return dret;
 
466
 
 
467
    x++;
 
468
  }
 
469
 
 
470
  return DRIZZLE_RETURN_OK;
 
471
}
 
472
 
 
473
drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
 
474
{
 
475
  drizzle_con_st *con;
 
476
 
 
477
  /* We can't keep state between calls since connections may be removed during
 
478
     processing. If this list ever gets big, we may want something faster. */
 
479
 
 
480
  for (con= drizzle->con_list; con != NULL; con= con->next)
 
481
  {
 
482
    if (con->options & DRIZZLE_CON_IO_READY)
 
483
    {
 
484
      con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
 
485
      return con;
 
486
    }
 
487
  }
 
488
 
 
489
  return NULL;
 
490
}
 
491
 
 
492
drizzle_con_st *drizzle_con_ready_listen(drizzle_st *drizzle)
 
493
{
 
494
  drizzle_con_st *con;
 
495
 
 
496
  /* We can't keep state between calls since connections may be removed during
 
497
     processing. If this list ever gets big, we may want something faster. */
 
498
 
 
499
  for (con= drizzle->con_list; con != NULL; con= con->next)
 
500
  {
 
501
    if ((con->options & (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN)) ==
 
502
        (DRIZZLE_CON_IO_READY | DRIZZLE_CON_LISTEN))
 
503
    {
 
504
      con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
 
505
      return con;
 
506
    }
 
507
  }
 
508
 
 
509
  return NULL;
 
510
}
 
511
 
 
512
/*
 
513
 * Client Definitions
 
514
 */
 
515
 
 
516
drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
 
517
                                    const char *host, in_port_t port,
 
518
                                    const char *user, const char *password,
 
519
                                    const char *db,
 
520
                                    drizzle_con_options_t options)
 
521
{
 
522
  con= drizzle_con_create(drizzle, con);
 
523
  if (con == NULL)
 
524
    return NULL;
 
525
 
 
526
  drizzle_con_set_tcp(con, host, port);
 
527
  drizzle_con_set_auth(con, user, password);
 
528
  drizzle_con_set_db(con, db);
 
529
  drizzle_con_add_options(con, options);
 
530
 
 
531
  return con;
 
532
}
 
533
 
 
534
drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
 
535
                                    const char *uds, const char *user,
 
536
                                    const char *password, const char *db,
 
537
                                    drizzle_con_options_t options)
 
538
{
 
539
  con= drizzle_con_create(drizzle, con);
 
540
  if (con == NULL)
 
541
    return NULL;
 
542
 
 
543
  drizzle_con_set_uds(con, uds);
 
544
  drizzle_con_set_auth(con, user, password);
 
545
  drizzle_con_set_db(con, db);
 
546
  drizzle_con_add_options(con, options);
 
547
 
 
548
  return con;
 
549
}
 
550
 
 
551
/*
 
552
 * Server Definitions
 
553
 */
 
554
 
 
555
drizzle_con_st *drizzle_con_add_tcp_listen(drizzle_st *drizzle,
 
556
                                           drizzle_con_st *con,
 
557
                                           const char *host, in_port_t port,
 
558
                                           int backlog,
 
559
                                           drizzle_con_options_t options)
 
560
{
 
561
  con= drizzle_con_create(drizzle, con);
 
562
  if (con == NULL)
 
563
    return NULL;
 
564
 
 
565
  drizzle_con_set_tcp(con, host, port);
 
566
  drizzle_con_set_backlog(con, backlog);
 
567
  drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
 
568
 
 
569
  return con;
 
570
}
 
571
 
 
572
drizzle_con_st *drizzle_con_add_uds_listen(drizzle_st *drizzle,
 
573
                                           drizzle_con_st *con,
 
574
                                           const char *uds, int backlog,
 
575
                                           drizzle_con_options_t options)
 
576
{
 
577
  con= drizzle_con_create(drizzle, con);
 
578
  if (con == NULL)
 
579
    return NULL;
 
580
 
 
581
  drizzle_con_set_uds(con, uds);
 
582
  drizzle_con_set_backlog(con, backlog);
 
583
  drizzle_con_add_options(con, DRIZZLE_CON_LISTEN | options);
 
584
 
 
585
  return con;
 
586
}
 
587
 
 
588
drizzle_con_st *drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con,
 
589
                                   drizzle_return_t *ret_ptr)
 
590
{
 
591
  drizzle_con_st *ready;
 
592
  int fd;
 
593
 
 
594
  while (1)
 
595
  {
 
596
    if ((ready= drizzle_con_ready_listen(drizzle)) != NULL)
 
597
    {
 
598
      fd= accept(ready->fd, NULL, NULL);
 
599
 
 
600
      con= drizzle_con_create(drizzle, con);
 
601
      if (con == NULL)
 
602
      {
 
603
        (void)close(fd);
 
604
        *ret_ptr= DRIZZLE_RETURN_MEMORY;
 
605
        return NULL;
 
606
      }
 
607
 
 
608
      *ret_ptr= drizzle_con_set_fd(con, fd);
 
609
      if (*ret_ptr != DRIZZLE_RETURN_OK)
 
610
      {
 
611
        (void)close(fd);
 
612
        return NULL;
 
613
      }
 
614
 
 
615
      if (ready->options & DRIZZLE_CON_MYSQL)
 
616
        drizzle_con_add_options(con, DRIZZLE_CON_MYSQL);
 
617
 
 
618
      *ret_ptr= DRIZZLE_RETURN_OK;
 
619
      return con;
 
620
    }
 
621
 
 
622
    if (drizzle->options & DRIZZLE_NON_BLOCKING)
 
623
    {
 
624
      *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
 
625
      return NULL;
 
626
    }
 
627
 
 
628
    for (ready= drizzle->con_list; ready != NULL; ready= ready->next)
 
629
    {
 
630
      if (ready->options & DRIZZLE_CON_LISTEN)
 
631
        drizzle_con_set_events(ready, POLLIN);
 
632
    }
 
633
 
 
634
    *ret_ptr= drizzle_con_wait(drizzle);
 
635
    if (*ret_ptr != DRIZZLE_RETURN_OK)
 
636
      return NULL;
 
637
  }
 
638
}
 
639
 
 
640
/*
 
641
 * Local Definitions
 
642
 */
 
643
 
 
644
void drizzle_set_error(drizzle_st *drizzle, const char *function,
 
645
                       const char *format, ...)
 
646
{
 
647
  size_t size;
 
648
  char *ptr;
 
649
  char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
 
650
  va_list args;
 
651
 
 
652
  size= strlen(function);
 
653
  ptr= memcpy(log_buffer, function, size);
 
654
  ptr+= size;
 
655
  ptr[0]= ':';
 
656
  size++;
 
657
  ptr++;
 
658
 
 
659
  va_start(args, format);
 
660
  size+= (size_t)vsnprintf(ptr, DRIZZLE_MAX_ERROR_SIZE - size, format, args);
 
661
  va_end(args);
 
662
 
 
663
  if (drizzle->log_fn == NULL)
 
664
  {
 
665
    if (size >= DRIZZLE_MAX_ERROR_SIZE)
 
666
      size= DRIZZLE_MAX_ERROR_SIZE - 1;
 
667
 
 
668
    memcpy(drizzle->last_error, log_buffer, size + 1);
 
669
  }
 
670
  else
 
671
    drizzle->log_fn(log_buffer, DRIZZLE_VERBOSE_ERROR, drizzle->log_context);
 
672
}
 
673
 
 
674
void drizzle_log(drizzle_st *drizzle, drizzle_verbose_t verbose,
 
675
                 const char *format, va_list args)
 
676
{
 
677
  char log_buffer[DRIZZLE_MAX_ERROR_SIZE];
 
678
 
 
679
  if (drizzle->log_fn == NULL)
 
680
  {
 
681
    printf("%5s: ", drizzle_verbose_name(verbose));
 
682
    vprintf(format, args);
 
683
    printf("\n");
 
684
  }
 
685
  else
 
686
  {
 
687
    vsnprintf(log_buffer, DRIZZLE_MAX_ERROR_SIZE, format, args);
 
688
    drizzle->log_fn(log_buffer, verbose, drizzle->log_context);
 
689
  }
 
690
}