2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to you under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14
* implied. See the License for the specific language governing
15
* permissions and limitations under the License.
23
#include "avro/errors.h"
25
#if defined THREADSAFE && (defined __unix__ || defined __unix)
27
static pthread_key_t error_data_key;
28
static pthread_once_t error_data_key_once = PTHREAD_ONCE_INIT;
30
static void make_error_data_key()
32
pthread_key_create(&error_data_key, free);
36
/* 4K should be enough, right? */
37
#define AVRO_ERROR_SIZE 4096
40
* To support the avro_prefix_error function, we keep two string buffers
41
* around. The AVRO_CURRENT_ERROR points at the buffer that's holding
42
* the current error message. avro_prefix error writes into the other
43
* buffer, and then swaps them.
46
struct avro_error_data_t {
47
char AVRO_ERROR1[AVRO_ERROR_SIZE];
48
char AVRO_ERROR2[AVRO_ERROR_SIZE];
50
char *AVRO_CURRENT_ERROR;
51
char *AVRO_OTHER_ERROR;
55
static struct avro_error_data_t *
56
avro_get_error_data(void)
58
#if defined THREADSAFE && (defined __unix__ || defined __unix)
59
pthread_once(&error_data_key_once, make_error_data_key);
61
struct avro_error_data_t *ERROR_DATA =
62
(struct avro_error_data_t*) pthread_getspecific(error_data_key);
65
ERROR_DATA = (struct avro_error_data_t*) malloc(sizeof(struct avro_error_data_t));
66
pthread_setspecific(error_data_key, ERROR_DATA);
68
ERROR_DATA->AVRO_ERROR1[0] = '\0';
69
ERROR_DATA->AVRO_ERROR2[0] = '\0';
70
ERROR_DATA->AVRO_CURRENT_ERROR = ERROR_DATA->AVRO_ERROR1;
71
ERROR_DATA->AVRO_OTHER_ERROR = ERROR_DATA->AVRO_ERROR2;
76
static struct avro_error_data_t ERROR_DATA = {
77
/* .AVRO_ERROR1 = */ {'\0'},
78
/* .AVRO_ERROR2 = */ {'\0'},
79
/* .AVRO_CURRENT_ERROR = */ ERROR_DATA.AVRO_ERROR1,
80
/* .AVRO_OTHER_ERROR = */ ERROR_DATA.AVRO_ERROR2,
89
avro_set_error(const char *fmt, ...)
93
vsnprintf(avro_get_error_data()->AVRO_CURRENT_ERROR, AVRO_ERROR_SIZE, fmt, args);
95
//fprintf(stderr, "--- %s\n", AVRO_CURRENT_ERROR);
100
avro_prefix_error(const char *fmt, ...)
102
struct avro_error_data_t *ERROR_DATA = avro_get_error_data();
105
* First render the prefix into OTHER_ERROR.
110
int bytes_written = vsnprintf(ERROR_DATA->AVRO_OTHER_ERROR, AVRO_ERROR_SIZE, fmt, args);
114
* Then concatenate the existing error onto the end.
117
if (bytes_written < AVRO_ERROR_SIZE) {
118
strncpy(&ERROR_DATA->AVRO_OTHER_ERROR[bytes_written], ERROR_DATA->AVRO_CURRENT_ERROR,
119
AVRO_ERROR_SIZE - bytes_written);
120
ERROR_DATA->AVRO_OTHER_ERROR[AVRO_ERROR_SIZE-1] = '\0';
124
* Swap the two error pointers.
128
tmp = ERROR_DATA->AVRO_OTHER_ERROR;
129
ERROR_DATA->AVRO_OTHER_ERROR = ERROR_DATA->AVRO_CURRENT_ERROR;
130
ERROR_DATA->AVRO_CURRENT_ERROR = tmp;
131
//fprintf(stderr, "+++ %s\n", AVRO_CURRENT_ERROR);
135
const char *avro_strerror(void)
137
return avro_get_error_data()->AVRO_CURRENT_ERROR;