32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
36 #define GRN_CTX_INITIALIZER(enc) \
37 { GRN_SUCCESS, 0, enc, 0, GRN_LOG_NOTICE,\
38 GRN_CTX_FIN, 0, 0, 0, 0, {0}, NULL, NULL, NULL, NULL, NULL }
40 #define GRN_CTX_CLOSED(ctx) ((ctx)->stat == GRN_CTX_FIN)
42 #ifdef USE_EXACT_ALLOC_COUNT
43 #define GRN_ADD_ALLOC_COUNT(count) do { \
45 GRN_ATOMIC_ADD_EX(&alloc_count, count, alloced); \
48 #define GRN_ADD_ALLOC_COUNT(count) do { \
49 alloc_count += count; \
59 int grn_uyield_count = 0;
66 Sleep(seconds * 1000);
76 Sleep((DWORD)(nanoseconds / 1000000));
78 struct timespec interval;
79 interval.tv_sec = (time_t)(nanoseconds / 1000000000);
80 interval.tv_nsec = (long)(nanoseconds % 1000000000);
81 nanosleep(&interval, NULL);
90 #ifdef HAVE_CLOCK_GETTIME
92 if (clock_gettime(CLOCK_REALTIME, &t)) {
93 SERR(
"clock_gettime");
110 if (gettimeofday(&t, NULL)) {
111 SERR(
"gettimeofday");
134 #ifdef HAVE_LOCALTIME_R
137 ltm = localtime_r(&t, &tm);
139 time_t tvsec = (time_t) tv->
tv_sec;
140 ltm = localtime(&tvsec);
142 if (!ltm) {
SERR(
"localtime"); }
144 ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday,
145 ltm->tm_hour, ltm->tm_min, ltm->tm_sec,
155 const char *r1, *r2, *rend = str + str_len;
157 memset(&tm, 0,
sizeof(
struct tm));
159 tm.tm_year = (int)
grn_atoui(str, rend, &r1) - 1900;
160 if ((r1 + 1) >= rend || (*r1 !=
'/' && *r1 !=
'-') ||
163 tm.tm_mon = (int)
grn_atoui(r1, rend, &r1) - 1;
164 if ((r1 + 1) >= rend || (*r1 !=
'/' && *r1 !=
'-') ||
167 tm.tm_mday = (int)
grn_atoui(r1, rend, &r1);
168 if ((r1 + 1) >= rend || *r1 !=
' ' ||
171 tm.tm_hour = (int)
grn_atoui(++r1, rend, &r2);
172 if ((r2 + 1) >= rend || r1 == r2 || *r2 !=
':' ||
173 tm.tm_hour < 0 || tm.tm_hour >= 24) {
177 tm.tm_min = (int)
grn_atoui(r1, rend, &r2);
178 if ((r2 + 1) >= rend || r1 == r2 || *r2 !=
':' ||
179 tm.tm_min < 0 || tm.tm_min >= 60) {
183 tm.tm_sec = (int)
grn_atoui(r1, rend, &r2);
185 tm.tm_sec < 0 || tm.tm_sec > 61 ) {
191 if ((r1 + 1) < rend && *r1 ==
'.') { r1++; }
193 while (r2 < r1 + 6) {
202 #ifdef USE_MEMORY_DEBUG
204 grn_alloc_info_set_backtrace(
char *
buffer,
size_t size)
206 # define N_TRACE_LEVEL 100
207 static void *trace[N_TRACE_LEVEL];
212 n = backtrace(trace, N_TRACE_LEVEL);
213 symbols = backtrace_symbols(trace, n);
215 for (i = 0; i < n; i++) {
218 symbol_length = strlen(symbols[i]);
219 if (symbol_length + 2 > rest) {
222 memcpy(buffer, symbols[i], symbol_length);
223 buffer += symbol_length;
224 rest -= symbol_length;
235 # undef N_TRACE_LEVEL
242 grn_alloc_info *new_alloc_info;
245 if (!ctx->
impl) {
return; }
247 new_alloc_info = malloc(
sizeof(grn_alloc_info));
248 new_alloc_info->address = address;
250 grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace,
251 sizeof(new_alloc_info->alloc_backtrace));
252 new_alloc_info->next = ctx->
impl->alloc_info;
253 ctx->
impl->alloc_info = new_alloc_info;
260 grn_alloc_info *alloc_info;
263 if (!ctx->
impl) {
return; }
265 alloc_info = ctx->
impl->alloc_info;
266 for (; alloc_info; alloc_info = alloc_info->next) {
267 if (alloc_info->address == old_address) {
268 alloc_info->address = new_address;
269 grn_alloc_info_set_backtrace(alloc_info->alloc_backtrace,
270 sizeof(alloc_info->alloc_backtrace));
279 grn_alloc_info *alloc_info;
281 if (!ctx) {
return; }
282 if (!ctx->
impl) {
return; }
284 alloc_info = ctx->
impl->alloc_info;
285 for (; alloc_info; alloc_info = alloc_info->next) {
286 if (alloc_info->freed) {
287 printf(
"address[%d][freed]: %p\n", i, alloc_info->address);
289 printf(
"address[%d][not-freed]: %p:\n%s",
290 i, alloc_info->address, alloc_info->alloc_backtrace);
300 grn_alloc_info *alloc_info;
303 if (!ctx->
impl) {
return; }
306 alloc_info = ctx->
impl->alloc_info;
307 for (; alloc_info; alloc_info = alloc_info->next) {
308 if (alloc_info->address == address) {
309 if (alloc_info->freed) {
311 "double free: (%p):\nalloc backtrace:\n%sfree backtrace:\n%s",
313 alloc_info->alloc_backtrace,
314 alloc_info->free_backtrace);
317 grn_alloc_info_set_backtrace(alloc_info->free_backtrace,
318 sizeof(alloc_info->free_backtrace));
328 grn_alloc_info *alloc_info;
330 if (!ctx) {
return; }
331 if (!ctx->
impl) {
return; }
333 alloc_info = ctx->
impl->alloc_info;
335 grn_alloc_info *current_alloc_info = alloc_info;
336 alloc_info = alloc_info->next;
337 current_alloc_info->next = NULL;
338 free(current_alloc_info);
340 ctx->
impl->alloc_info = NULL;
344 # define grn_alloc_info_add(address)
345 # define grn_alloc_info_change(old_address, new_address)
346 # define grn_alloc_info_check(address)
347 # define grn_alloc_info_dump(ctx)
348 # define grn_alloc_info_free(ctx)
351 #ifdef USE_FAIL_MALLOC
352 int grn_fmalloc_prob = 0;
353 char *grn_fmalloc_func = NULL;
354 char *grn_fmalloc_file = NULL;
355 int grn_fmalloc_line = 0;
358 #define GRN_CTX_SEGMENT_SIZE (1<<22)
359 #define GRN_CTX_SEGMENT_MASK (GRN_CTX_SEGMENT_SIZE - 1)
361 #define GRN_CTX_SEGMENT_WORD (1<<31)
362 #define GRN_CTX_SEGMENT_VLEN (1<<30)
363 #define GRN_CTX_SEGMENT_LIFO (1<<29)
364 #define GRN_CTX_SEGMENT_DIRTY (1<<28)
366 #ifdef USE_DYNAMIC_MALLOC_CHANGE
368 grn_ctx_impl_init_malloc(
grn_ctx *ctx)
370 # ifdef USE_FAIL_MALLOC
371 ctx->
impl->malloc_func = grn_malloc_fail;
372 ctx->
impl->calloc_func = grn_calloc_fail;
373 ctx->
impl->realloc_func = grn_realloc_fail;
374 ctx->
impl->strdup_func = grn_strdup_fail;
391 loader->
table = NULL;
415 grn_loader_init(loader);
418 #define IMPL_SIZE ((sizeof(struct _grn_ctx_impl) + (grn_pagesize - 1)) & ~(grn_pagesize - 1))
420 #ifdef GRN_WITH_MESSAGE_PACK
422 grn_msgpack_buffer_write(
void *data,
const char *buf,
unsigned int len)
430 grn_ctx_impl_init(
grn_ctx *ctx)
438 #ifdef USE_DYNAMIC_MALLOC_CHANGE
439 grn_ctx_impl_init_malloc(ctx);
441 #ifdef USE_MEMORY_DEBUG
442 ctx->
impl->alloc_info = NULL;
447 CRITICAL_SECTION_INIT(ctx->
impl->
lock);
450 CRITICAL_SECTION_FIN(ctx->
impl->
lock);
459 CRITICAL_SECTION_FIN(ctx->
impl->
lock);
475 if (ctx == &grn_gctx) {
481 if (ctx == &grn_gctx) {
511 #ifdef GRN_WITH_MESSAGE_PACK
512 msgpack_packer_init(&ctx->
impl->msgpacker, ctx, grn_msgpack_buffer_write);
534 grn_ctx_impl_clear_n_same_error_mssagges(
grn_ctx *ctx)
567 grn_ctx_impl_clear_n_same_error_mssagges(ctx);
578 if (getenv(
"GRN_CTX_PER_DB") && strcmp(getenv(
"GRN_CTX_PER_DB"),
"yes") == 0) {
589 grn_ctx_impl_init(ctx);
603 ctx->
trace[0] = NULL;
636 grn_ctx_impl_clear_n_same_error_mssagges(ctx);
646 #ifndef USE_MEMORY_DEBUG
661 unsigned int str_len;
706 CRITICAL_SECTION_FIN(ctx->
impl->
lock);
723 grn_ctx_impl_init(ctx);
732 static char *default_logger_path = NULL;
733 static FILE *default_logger_file = NULL;
734 static grn_critical_section default_logger_lock;
738 const char *timestamp,
const char *title,
739 const char *
message,
const char *location,
void *user_data)
741 const char slev[] =
" EACewnid-";
742 if (default_logger_path) {
743 CRITICAL_SECTION_ENTER(default_logger_lock);
744 if (!default_logger_file) {
745 default_logger_file = fopen(default_logger_path,
"a");
747 if (default_logger_file) {
748 if (location && *location) {
749 fprintf(default_logger_file,
"%s|%c|%s %s %s\n",
750 timestamp, *(slev + level), title, message, location);
752 fprintf(default_logger_file,
"%s|%c|%s %s\n", timestamp,
753 *(slev + level), title, message);
755 fflush(default_logger_file);
757 CRITICAL_SECTION_LEAVE(default_logger_lock);
762 default_logger_reopen(
grn_ctx *ctx,
void *user_data)
765 CRITICAL_SECTION_ENTER(default_logger_lock);
766 if (default_logger_file) {
767 fclose(default_logger_file);
768 default_logger_file = NULL;
770 CRITICAL_SECTION_LEAVE(default_logger_lock);
775 default_logger_fin(
grn_ctx *ctx,
void *user_data)
777 CRITICAL_SECTION_ENTER(default_logger_lock);
778 if (default_logger_file) {
779 fclose(default_logger_file);
780 default_logger_file = NULL;
782 CRITICAL_SECTION_LEAVE(default_logger_lock);
790 default_logger_reopen,
807 if (current_logger.
log == default_logger_log) {
821 if (default_logger_path) {
822 free(default_logger_path);
826 default_logger_path =
strdup(path);
828 default_logger_path = NULL;
835 return default_logger_path;
841 if (current_logger.
reopen) {
849 if (current_logger.
fin) {
856 const char *timestamp,
const char *title,
857 const char *
message,
const char *location,
861 info->
func(level, timestamp, title, message, location, info->
func_arg);
875 logger.
log = logger_info_func_wrapper;
878 logger.
log = default_logger_log;
879 logger.
reopen = default_logger_reopen;
880 logger.
fin = default_logger_fin;
893 current_logger = *logger;
895 current_logger = default_logger;
915 return level <= current_logger.
max_level;
918 #define TBUFSIZE GRN_TIMEVAL_STR_SIZE
919 #define MBUFSIZE 0x1000
920 #define LBUFSIZE 0x400
924 const char *file,
int line,
const char *func,
const char *fmt, ...)
926 if (level <= current_logger.
max_level && current_logger.
log) {
939 vsnprintf(mbuf,
MBUFSIZE - 1, fmt, argp);
946 snprintf(lbuf,
LBUFSIZE - 1,
"%d %s:%d %s()", getpid(), file, line, func);
951 current_logger.
log(ctx, level, tbuf,
"", mbuf, lbuf,
959 if (!default_logger_path) {
960 default_logger_path =
strdup(GRN_LOG_PATH);
962 memcpy(¤t_logger, &default_logger,
sizeof(
grn_logger));
963 CRITICAL_SECTION_INIT(default_logger_lock);
970 if (default_logger_path) {
971 free(default_logger_path);
972 default_logger_path = NULL;
974 CRITICAL_SECTION_FIN(default_logger_lock);
978 static char *default_query_logger_path = NULL;
979 static FILE *default_query_logger_file = NULL;
980 static grn_critical_section default_query_logger_lock;
983 default_query_logger_log(
grn_ctx *ctx,
unsigned int flag,
984 const char *timestamp,
const char *info,
985 const char *message,
void *user_data)
987 if (default_query_logger_path) {
988 CRITICAL_SECTION_ENTER(default_query_logger_lock);
989 if (!default_query_logger_file) {
990 default_query_logger_file = fopen(default_query_logger_path,
"a");
992 if (default_query_logger_file) {
993 fprintf(default_query_logger_file,
"%s|%s%s\n", timestamp, info, message);
994 fflush(default_query_logger_file);
996 CRITICAL_SECTION_LEAVE(default_query_logger_lock);
1001 default_query_logger_close(
grn_ctx *ctx,
void *user_data)
1004 "query log will be closed: <%s>", default_query_logger_path);
1005 CRITICAL_SECTION_ENTER(default_query_logger_lock);
1006 if (default_query_logger_file) {
1007 fclose(default_query_logger_file);
1008 default_query_logger_file = NULL;
1010 CRITICAL_SECTION_LEAVE(default_query_logger_lock);
1014 default_query_logger_reopen(
grn_ctx *ctx,
void *user_data)
1016 default_query_logger_close(ctx, user_data);
1017 if (default_query_logger_path) {
1019 "query log is opened: <%s>", default_query_logger_path);
1024 default_query_logger_fin(
grn_ctx *ctx,
void *user_data)
1026 if (default_query_logger_file) {
1027 default_query_logger_close(ctx, user_data);
1034 default_query_logger_log,
1035 default_query_logger_reopen,
1036 default_query_logger_fin
1050 default_query_logger.
flags = flags;
1051 if (current_query_logger.
log == default_query_logger_log) {
1052 current_query_logger.
flags = flags;
1059 return default_query_logger.
flags;
1065 if (default_query_logger_path) {
1066 free(default_query_logger_path);
1070 default_query_logger_path =
strdup(path);
1072 default_query_logger_path = NULL;
1079 return default_query_logger_path;
1085 if (current_query_logger.
reopen) {
1091 grn_query_logger_fin(
grn_ctx *ctx)
1093 if (current_query_logger.
fin) {
1094 current_query_logger.
fin(ctx, current_query_logger.
user_data);
1101 grn_query_logger_fin(ctx);
1103 current_query_logger = *logger;
1105 current_query_logger = default_query_logger;
1113 return current_query_logger.
flags & flag;
1116 #define TIMESTAMP_BUFFER_SIZE TBUFSIZE
1118 #define INFO_BUFFER_SIZE 40
1119 #define MESSAGE_BUFFER_SIZE MBUFSIZE
1123 const char *format, ...)
1129 if (!current_query_logger.
log) {
1135 timestamp[0] =
'\0';
1145 uint64_t elapsed_time;
1158 va_start(args, format);
1164 current_query_logger.
log(ctx, flag, timestamp, info, message,
1169 query_logger_init(
void)
1171 memcpy(¤t_query_logger, &default_query_logger,
sizeof(
grn_query_logger));
1172 CRITICAL_SECTION_INIT(default_query_logger_lock);
1176 query_logger_fin(
grn_ctx *ctx)
1178 grn_query_logger_fin(ctx);
1179 if (default_query_logger_path) {
1180 free(default_query_logger_path);
1182 CRITICAL_SECTION_FIN(default_query_logger_lock);
1194 check_overcommit_memory(
grn_ctx *ctx)
1198 file = fopen(
"/proc/sys/vm/overcommit_memory",
"r");
1199 if (!file) {
return; }
1200 value = fgetc(file);
1203 "vm.overcommit_memory kernel parameter should be 1: <%c>: "
1204 "See INFO level log to resolve this",
1207 "Some processings with vm.overcommit_memory != 1 "
1208 "may break DB under low memory condition.");
1210 "To set vm.overcommit_memory to 1");
1212 "add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and "
1213 "restart your system or");
1215 "run 'sudo /sbin/sysctl vm.overcommit_memory=1' command.");
1221 check_grn_ja_skip_same_value_put(
grn_ctx *ctx)
1223 const char *grn_ja_skip_same_value_put_env;
1225 grn_ja_skip_same_value_put_env = getenv(
"GRN_JA_SKIP_SAME_VALUE_PUT");
1226 if (grn_ja_skip_same_value_put_env &&
1227 strcmp(grn_ja_skip_same_value_put_env,
"yes") == 0) {
1238 query_logger_init();
1254 SERR(
"_SC_PAGESIZE");
1263 if (getenv(
"GRN_DEBUG_PRINT")) {
1264 grn_debug_print = atoi(getenv(
"GRN_DEBUG_PRINT"));
1266 grn_debug_print = 0;
1268 if (getenv(
"GRN_AIO_ENABLED")) {
1269 grn_aio_enabled = atoi(getenv(
"GRN_AIO_ENABLED"));
1271 grn_aio_enabled = 0;
1273 if (grn_aio_enabled) {
1277 #ifdef USE_FAIL_MALLOC
1278 if (getenv(
"GRN_FMALLOC_PROB")) {
1279 grn_fmalloc_prob = strtod(getenv(
"GRN_FMALLOC_PROB"), 0) * RAND_MAX;
1280 if (getenv(
"GRN_FMALLOC_SEED")) {
1281 srand((
unsigned int)atoi(getenv(
"GRN_FMALLOC_SEED")));
1283 srand((
unsigned int)time(NULL));
1286 if (getenv(
"GRN_FMALLOC_FUNC")) {
1287 grn_fmalloc_func = getenv(
"GRN_FMALLOC_FUNC");
1289 if (getenv(
"GRN_FMALLOC_FILE")) {
1290 grn_fmalloc_file = getenv(
"GRN_FMALLOC_FILE");
1292 if (getenv(
"GRN_FMALLOC_LINE")) {
1293 grn_fmalloc_line = atoi(getenv(
"GRN_FMALLOC_LINE"));
1300 grn_ctx_impl_init(ctx);
1325 check_overcommit_memory(ctx);
1326 check_grn_ja_skip_same_value_put(ctx);
1380 static int alloc_count = 0;
1387 for (ctx = grn_gctx.
next; ctx != &grn_gctx; ctx = ctx_) {
1396 query_logger_fin(ctx);
1414 if (!ctx->
impl) { grn_ctx_impl_init(ctx); }
1415 if (!ctx->
impl) {
goto exit; }
1517 get_content_mime_type(
grn_ctx *ctx,
const char *p,
const char *pe)
1525 if (p + 3 == pe && !memcmp(p,
"css", 3)) {
1531 if (p + 3 == pe && !memcmp(p,
"gif", 3)) {
1537 if (p + 4 == pe && !memcmp(p,
"html", 4)) {
1543 if (!memcmp(p,
"js", 2)) {
1547 }
else if (p + 4 == pe && !memcmp(p + 2,
"on", 2)) {
1551 }
else if (p + 3 == pe && !memcmp(p,
"jpg", 3)) {
1556 #ifdef GRN_WITH_MESSAGE_PACK
1558 if (p + 7 == pe && !memcmp(p,
"msgpack", 7)) {
1565 if (p + 3 == pe && !memcmp(p,
"png", 3)) {
1571 if (p + 3 == pe && !memcmp(p,
"txt", 3)) {
1574 }
else if (p + 3 == pe && !memcmp(p,
"tsv", 3)) {
1580 if (p + 3 == pe && !memcmp(p,
"xml", 3)) {
1590 grn_str_get_mime_type(
grn_ctx *ctx,
const char *p,
const char *pe,
1591 const char **key_end,
const char **filename_end)
1593 const char *pd = NULL;
1594 for (; p < pe && *p !=
'?' && *p !=
'#'; p++) {
1595 if (*p ==
'.') { pd = p; }
1599 get_content_mime_type(ctx, pd + 1, p);
1607 get_command_version(
grn_ctx *ctx,
const char *p,
const char *pe)
1618 "unsupported command version is specified: %d: "
1619 "stable command version: %d: "
1620 "available command versions: %d-%d",
1628 #define INDEX_HTML "index.html"
1629 #define OUTPUT_TYPE "output_type"
1630 #define COMMAND_VERSION "command_version"
1631 #define EXPR_MISSING "expr_missing"
1632 #define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1)
1633 #define COMMAND_VERSION_LEN (sizeof(COMMAND_VERSION) - 1)
1635 #define HTTP_QUERY_PAIR_DELIMITER "="
1636 #define HTTP_QUERY_PAIRS_DELIMITERS "&;"
1649 const char *p = path, *e = path + path_len, *v, *key_end, *filename_end;
1654 grn_str_get_mime_type(ctx, v,
GRN_BULK_CURR(&buf), &key_end, &filename_end);
1655 if ((
GRN_TEXT_LEN(&buf) >= 2 && v[0] ==
'd' && v[1] ==
'/') &&
1656 (expr =
grn_ctx_get(ctx, v + 2, key_end - (v + 2))) &&
1657 command_proc_p(expr)) {
1674 if (ctx->
rc) {
goto exit; }
1704 grn_obj buf, *expr = NULL, *val = NULL;
1705 const char *p = str, *e = str + str_len, *v;
1718 if (
GRN_TEXT_LEN(&buf) > 2 && v[0] ==
'-' && v[1] ==
'-') {
1731 if (ctx->
rc) {
goto exit; }
1753 if (expr && command_proc_p(expr)) {
1785 comment_command_p(
const char *command,
unsigned int length)
1789 e = command + length;
1790 for (p = command; p < e; p++) {
1807 if (!ctx) {
return 0; }
1820 sheader.
flags = flags;
1825 ERR(rc,
"grn_com_send failed");
1830 if (comment_command_p(str, str_len)) {
goto output; };
1845 ">",
"%.*s", str_len, str);
1846 if (str_len && *str ==
'/') {
1857 "<",
"rc=%d", ctx->
rc);
1902 ctx->
rc = (int16_t)ntohs(header.
status);
1924 *str_len = tail - head;
1946 if (ctx && ctx->
impl) {
1951 fputc(
'\n', (FILE *)stream);
1952 fflush((FILE *)stream);
1962 if (ctx && ctx->
impl) {
2008 static grn_cache *grn_cache_current = NULL;
2009 static grn_cache *grn_cache_default = NULL;
2027 MUTEX_INIT(cache->
mutex);
2049 MUTEX_FIN(cache->mutex);
2059 grn_cache_current = cache;
2066 return grn_cache_current;
2099 MUTEX_LOCK(cache->
mutex);
2104 MUTEX_UNLOCK(cache->
mutex);
2120 const char *str, uint32_t str_len)
2124 if (!ctx->
impl || !ctx->
impl->
db) {
return obj; }
2125 MUTEX_LOCK(cache->
mutex);
2129 grn_cache_expire_entry(cache, ce);
2146 MUTEX_UNLOCK(cache->
mutex);
2152 const char *str, uint32_t str_len)
2156 MUTEX_LOCK(cache->
mutex);
2160 MUTEX_UNLOCK(cache->
mutex);
2165 const char *str, uint32_t str_len,
grn_obj *value)
2175 MUTEX_LOCK(cache->
mutex);
2176 if ((
id =
grn_hash_add(&grn_gctx, cache->
hash, str, str_len, (
void **)&ce, &added))) {
2198 grn_cache_expire_entry(cache, cache->
prev);
2204 MUTEX_UNLOCK(cache->
mutex);
2213 MUTEX_LOCK(cache->
mutex);
2214 while (ce0 != ce0->
prev && size--) {
2215 grn_cache_expire_entry(cache, ce0->
prev);
2217 MUTEX_UNLOCK(cache->
mutex);
2229 #define ALIGN_SIZE (1<<3)
2230 #define ALIGN_MASK (ALIGN_SIZE-1)
2231 #define GRN_CTX_ALLOC_CLEAR 1
2235 const char* file,
int line,
const char *func)
2238 if (!ctx) {
return res; }
2240 grn_ctx_impl_init(ctx);
2243 CRITICAL_SECTION_ENTER(ctx->
impl->
lock);
2251 if (npages >= (1LL<<32)) {
2252 MERR(
"too long request size=%zu", size);
2255 for (i = 0, mi = ctx->
impl->
segs;; i++, mi++) {
2257 MERR(
"all segments are full");
2260 if (!mi->
map) {
break; }
2264 mi->
nref = (uint32_t) npages;
2269 header[1] = (int32_t) size;
2274 for (i = 0, mi = ctx->
impl->
segs;; i++, mi++) {
2276 MERR(
"all segments are full");
2279 if (!mi->
map) {
break; }
2291 header[1] = (int32_t) size;
2306 CRITICAL_SECTION_LEAVE(ctx->
impl->
lock);
2312 const char* file,
int line,
const char *func)
2319 const char* file,
int line,
const char *func)
2326 const char* file,
int line,
const char *func)
2333 int32_t *header = &((int32_t *)ptr)[-2];
2334 size_t size_ = header[1];
2335 memcpy(res, ptr, size_ > size ? size : size_);
2349 size_t size = strlen(s) + 1;
2350 if ((res =
grn_ctx_alloc(ctx, size, 0, file, line, func))) {
2351 memcpy(res, s, size);
2359 const char* file,
int line,
const char *func)
2361 if (!ctx) {
return; }
2366 CRITICAL_SECTION_ENTER(ctx->
impl->
lock);
2368 int32_t *header = &((int32_t *)ptr)[-2];
2385 int32_t i = header[0];
2388 if (mi->
map != header) {
2415 CRITICAL_SECTION_LEAVE(ctx->
impl->
lock);
2418 #define DB_P(s) ((s) && (s)->header.type == GRN_DB)
2424 if (db && !
DB_P(db)) {
2427 if (!ctx->
impl) { grn_ctx_impl_init(ctx); }
2444 const char* file,
int line,
const char *func)
2446 if (!ctx) {
return NULL; }
2448 grn_ctx_impl_init(ctx);
2456 if (npages >= (1LL<<32)) {
2457 MERR(
"too long request size=%zu", size);
2462 MERR(
"all segments are full");
2466 if (!mi->
map) {
break; }
2469 mi->
nref = (uint32_t) npages;
2478 MERR(
"all segments are full");
2481 if (!(++mi)->map) {
break; }
2489 uint32_t u = mi->
nref;
2499 const char* file,
int line,
const char *func)
2501 if (!ctx) {
return; }
2513 for (; i >= 0; i--, mi--) {
2515 if (done) {
break; }
2517 if (mi->
map == ptr) { done = 1; }
2521 if (mi->
map == ptr) {
2524 if (mi->
map < ptr && ptr < (
void *)((
byte*)mi->
map + mi->
nref)) {
2525 mi->
nref = (uint32_t) ((uintptr_t)ptr - (uintptr_t)mi->
map);
2537 #if USE_DYNAMIC_MALLOC_CHANGE
2539 grn_ctx_get_malloc(
grn_ctx *ctx)
2541 if (!ctx || !ctx->
impl) {
return NULL; }
2542 return ctx->
impl->malloc_func;
2546 grn_ctx_set_malloc(
grn_ctx *ctx, grn_malloc_func malloc_func)
2548 if (!ctx || !ctx->
impl) {
return; }
2549 ctx->
impl->malloc_func = malloc_func;
2553 grn_ctx_get_calloc(
grn_ctx *ctx)
2555 if (!ctx || !ctx->
impl) {
return NULL; }
2556 return ctx->
impl->calloc_func;
2560 grn_ctx_set_calloc(
grn_ctx *ctx, grn_calloc_func calloc_func)
2562 if (!ctx || !ctx->
impl) {
return; }
2563 ctx->
impl->calloc_func = calloc_func;
2567 grn_ctx_get_realloc(
grn_ctx *ctx)
2569 if (!ctx || !ctx->
impl) {
return NULL; }
2570 return ctx->
impl->realloc_func;
2574 grn_ctx_set_realloc(
grn_ctx *ctx, grn_realloc_func realloc_func)
2576 if (!ctx || !ctx->
impl) {
return; }
2577 ctx->
impl->realloc_func = realloc_func;
2581 grn_ctx_get_strdup(
grn_ctx *ctx)
2583 if (!ctx || !ctx->
impl) {
return NULL; }
2584 return ctx->
impl->strdup_func;
2588 grn_ctx_set_strdup(
grn_ctx *ctx, grn_strdup_func strdup_func)
2590 if (!ctx || !ctx->
impl) {
return; }
2591 ctx->
impl->strdup_func = strdup_func;
2595 grn_malloc(
grn_ctx *ctx,
size_t size,
const char* file,
int line,
const char *func)
2597 if (ctx && ctx->
impl && ctx->
impl->malloc_func) {
2598 return ctx->
impl->malloc_func(ctx, size, file, line, func);
2605 grn_calloc(
grn_ctx *ctx,
size_t size,
const char* file,
int line,
const char *func)
2607 if (ctx && ctx->
impl && ctx->
impl->calloc_func) {
2608 return ctx->
impl->calloc_func(ctx, size, file, line, func);
2615 grn_realloc(
grn_ctx *ctx,
void *ptr,
size_t size,
const char* file,
int line,
const char *func)
2617 if (ctx && ctx->
impl && ctx->
impl->realloc_func) {
2618 return ctx->
impl->realloc_func(ctx, ptr, size, file, line, func);
2625 grn_strdup(
grn_ctx *ctx,
const char *
string,
const char* file,
int line,
const char *func)
2627 if (ctx && ctx->
impl && ctx->
impl->strdup_func) {
2628 return ctx->
impl->strdup_func(ctx,
string, file, line, func);
2638 if (!ctx) {
return NULL; }
2640 void *res = malloc(size);
2645 if (!(res = malloc(size))) {
2646 MERR(
"malloc fail (%zu)=%p (%s:%d) <%d>",
2647 size, res, file, line, alloc_count);
2660 if (!ctx) {
return NULL; }
2662 void *res = calloc(size, 1);
2667 if (!(res = calloc(size, 1))) {
2669 (
unsigned long long int)size, res, file, line,
2670 (
unsigned long long int)alloc_count);
2683 if (!ctx) {
return; }
2699 if (!ctx) {
return NULL; }
2701 if (!(res = realloc(ptr, size))) {
2702 if (!(res = realloc(ptr, size))) {
2703 MERR(
"realloc fail (%p,%zu)=%p (%s:%d) <%d>", ptr, size, res, file, line, alloc_count);
2714 if (!ptr) {
return NULL; }
2732 if (!ctx) {
return NULL; }
2738 if (!(res =
strdup(s))) {
2739 MERR(
"strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count);
2746 #ifdef USE_FAIL_MALLOC
2748 grn_fail_malloc_check(
size_t size,
const char *file,
int line,
const char *func)
2750 if ((grn_fmalloc_file && strcmp(file, grn_fmalloc_file)) ||
2751 (grn_fmalloc_line && line != grn_fmalloc_line) ||
2752 (grn_fmalloc_func && strcmp(func, grn_fmalloc_func))) {
2755 if (grn_fmalloc_prob && grn_fmalloc_prob >= rand()) {
2762 grn_malloc_fail(
grn_ctx *ctx,
size_t size,
const char* file,
int line,
const char *func)
2764 if (grn_fail_malloc_check(size, file, line, func)) {
2767 MERR(
"fail_malloc (%d) (%s:%d@%s) <%d>", size, file, line, func, alloc_count);
2773 grn_calloc_fail(
grn_ctx *ctx,
size_t size,
const char* file,
int line,
const char *func)
2775 if (grn_fail_malloc_check(size, file, line, func)) {
2778 MERR(
"fail_calloc (%d) (%s:%d@%s) <%d>", size, file, line, func, alloc_count);
2784 grn_realloc_fail(
grn_ctx *ctx,
void *ptr,
size_t size,
const char* file,
int line,
2787 if (grn_fail_malloc_check(size, file, line, func)) {
2790 MERR(
"fail_realloc (%p,%zu) (%s:%d@%s) <%d>", ptr, size, file, line, func, alloc_count);
2796 grn_strdup_fail(
grn_ctx *ctx,
const char *s,
const char* file,
int line,
const char *func)
2798 if (grn_fail_malloc_check(strlen(s), file, line, func)) {
2801 MERR(
"fail_strdup(%p) (%s:%d@%s) <%d>", s, file, line, func, alloc_count);
2813 va_start(argp, fmt);
2838 #if defined(HAVE_SIGNAL_H) && !defined(WIN32)
2839 static int segv_received = 0;
2841 segv_handler(
int signal_number, siginfo_t *info,
void *
context)
2845 if (segv_received) {
2852 #ifdef HAVE_BACKTRACE
2853 # define N_TRACE_LEVEL 1024
2855 static void *trace[N_TRACE_LEVEL];
2856 int n = backtrace(trace, N_TRACE_LEVEL);
2857 char **symbols = backtrace_symbols(trace, n);
2861 for (i = 0; i < n; i++) {
2879 #if defined(HAVE_SIGNAL_H) && !defined(WIN32)
2881 struct sigaction action;
2883 sigemptyset(&action.sa_mask);
2884 action.sa_sigaction = segv_handler;
2885 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
2887 if (sigaction(SIGSEGV, &action, NULL)) {
2888 SERR(
"failed to set SIGSEGV action");
2895 #if defined(HAVE_SIGNAL_H) && !defined(WIN32)
2896 static struct sigaction old_int_handler;
2898 int_handler(
int signal_number, siginfo_t *info,
void *context)
2901 sigaction(signal_number, &old_int_handler, NULL);
2904 static struct sigaction old_term_handler;
2906 term_handler(
int signal_number, siginfo_t *info,
void *context)
2909 sigaction(signal_number, &old_term_handler, NULL);
2917 #if defined(HAVE_SIGNAL_H) && !defined(WIN32)
2919 struct sigaction action;
2921 sigemptyset(&action.sa_mask);
2922 action.sa_sigaction = int_handler;
2923 action.sa_flags = SA_SIGINFO;
2925 if (sigaction(SIGINT, &action, &old_int_handler)) {
2926 SERR(
"failed to set SIGINT action");
2937 #if defined(HAVE_SIGNAL_H) && !defined(WIN32)
2939 struct sigaction action;
2941 sigemptyset(&action.sa_mask);
2942 action.sa_sigaction = term_handler;
2943 action.sa_flags = SA_SIGINFO;
2945 if (sigaction(SIGTERM, &action, &old_term_handler)) {
2946 SERR(
"failed to set SIGTERM action");