summaryrefslogtreecommitdiff
path: root/storage/mroonga/vendor/groonga/lib/dat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/dat.cpp')
-rw-r--r--storage/mroonga/vendor/groonga/lib/dat.cpp267
1 files changed, 230 insertions, 37 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/dat.cpp b/storage/mroonga/vendor/groonga/lib/dat.cpp
index 51a84da2af9..51f625f0b3f 100644
--- a/storage/mroonga/vendor/groonga/lib/dat.cpp
+++ b/storage/mroonga/vendor/groonga/lib/dat.cpp
@@ -1,5 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2011-2015 Brazil
+/*
+ Copyright(C) 2011-2017 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -70,7 +71,22 @@ bool
grn_dat_remove_file(grn_ctx *ctx, const char *path)
{
struct stat stat;
- return !::stat(path, &stat) && !grn_unlink(path);
+
+ if (::stat(path, &stat) == -1) {
+ return false;
+ }
+
+ if (grn_unlink(path) == -1) {
+ const char *system_message = grn_strerror(errno);
+ GRN_LOG(ctx, GRN_LOG_WARNING,
+ "[dat][remove-file] failed to remove path: %s: <%s>",
+ system_message, path);
+ return false;
+ }
+
+ GRN_LOG(ctx, GRN_LOG_INFO,
+ "[dat][remove-file] removed: <%s>", path);
+ return true;
}
grn_rc
@@ -115,6 +131,7 @@ grn_dat_init(grn_ctx *, grn_dat *dat)
dat->normalizer = NULL;
GRN_PTR_INIT(&(dat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL);
CRITICAL_SECTION_INIT(dat->lock);
+ dat->is_dirty = GRN_FALSE;
}
void
@@ -126,6 +143,10 @@ grn_dat_fin(grn_ctx *ctx, grn_dat *dat)
dat->old_trie = NULL;
dat->trie = NULL;
if (dat->io) {
+ if (dat->is_dirty) {
+ uint32_t n_dirty_opens;
+ GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), -1, n_dirty_opens);
+ }
grn_io_close(ctx, dat->io);
dat->io = NULL;
}
@@ -188,13 +209,26 @@ grn_dat_open_trie_if_needed(grn_ctx *ctx, grn_dat *dat)
return false;
}
- try {
- new_trie->open(trie_path);
- } catch (const grn::dat::Exception &ex) {
- ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::open failed");
- delete new_trie;
- return false;
+ if (trie_path[0] == '\0') {
+ try {
+ new_trie->create(trie_path);
+ } catch (const grn::dat::Exception &ex) {
+ ERR(grn_dat_translate_error_code(ex.code()),
+ "grn::dat::Trie::create failed: %s",
+ ex.what());
+ delete new_trie;
+ return false;
+ }
+ } else {
+ try {
+ new_trie->open(trie_path);
+ } catch (const grn::dat::Exception &ex) {
+ ERR(grn_dat_translate_error_code(ex.code()),
+ "grn::dat::Trie::open failed: %s",
+ ex.what());
+ delete new_trie;
+ return false;
+ }
}
dat->old_trie = trie;
@@ -212,6 +246,7 @@ grn_dat_open_trie_if_needed(grn_ctx *ctx, grn_dat *dat)
}
bool grn_dat_rebuild_trie(grn_ctx *ctx, grn_dat *dat) {
+ const grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie);
grn::dat::Trie * const new_trie = new (std::nothrow) grn::dat::Trie;
if (!new_trie) {
MERR("new grn::dat::Trie failed");
@@ -219,16 +254,22 @@ bool grn_dat_rebuild_trie(grn_ctx *ctx, grn_dat *dat) {
}
const uint32_t file_id = dat->header->file_id;
- try {
- char trie_path[PATH_MAX];
- grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id + 1);
- const grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie);
- new_trie->create(*trie, trie_path, trie->file_size() * 2);
- } catch (const grn::dat::Exception &ex) {
- ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::open failed");
- delete new_trie;
- return false;
+ char trie_path[PATH_MAX];
+ grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id + 1);
+
+ for (uint64_t file_size = trie->file_size() * 2;; file_size *= 2) {
+ try {
+ new_trie->create(*trie, trie_path, file_size);
+ } catch (const grn::dat::SizeError &) {
+ continue;
+ } catch (const grn::dat::Exception &ex) {
+ ERR(grn_dat_translate_error_code(ex.code()),
+ "grn::dat::Trie::open failed: %s",
+ ex.what());
+ delete new_trie;
+ return false;
+ }
+ break;
}
grn::dat::Trie * const old_trie = static_cast<grn::dat::Trie *>(dat->old_trie);
@@ -278,7 +319,7 @@ grn_dat_create(grn_ctx *ctx, const char *path, uint32_t,
}
}
- grn_dat * const dat = static_cast<grn_dat *>(GRN_MALLOC(sizeof(grn_dat)));
+ grn_dat * const dat = static_cast<grn_dat *>(GRN_CALLOC(sizeof(grn_dat)));
if (!dat) {
return NULL;
}
@@ -426,7 +467,8 @@ grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::search failed");
+ "grn::dat::Trie::search failed: %s",
+ ex.what());
}
return GRN_ID_NIL;
}
@@ -453,7 +495,8 @@ grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key,
new_trie->create(trie_path);
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::create failed");
+ "grn::dat::Trie::create failed: %s",
+ ex.what());
delete new_trie;
return GRN_ID_NIL;
}
@@ -482,7 +525,8 @@ grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key,
return new_trie->get_key(key_pos).id();
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::insert failed");
+ "grn::dat::Trie::insert failed: %s",
+ ex.what());
return GRN_ID_NIL;
}
}
@@ -556,7 +600,8 @@ grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::remove failed");
+ "grn::dat::Trie::remove failed: %s",
+ ex.what());
return ctx->rc;
}
return GRN_SUCCESS;
@@ -584,7 +629,8 @@ grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_siz
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::search failed");
+ "grn::dat::Trie::search failed: %s",
+ ex.what());
return ctx->rc;
}
}
@@ -596,7 +642,8 @@ grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_siz
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::remove failed");
+ "grn::dat::Trie::remove failed: %s",
+ ex.what());
return ctx->rc;
}
return GRN_SUCCESS;
@@ -630,7 +677,8 @@ grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::update failed");
+ "grn::dat::Trie::update failed: %s",
+ ex.what());
return ctx->rc;
}
return GRN_SUCCESS;
@@ -665,7 +713,8 @@ grn_dat_update(grn_ctx *ctx, grn_dat *dat,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::update failed");
+ "grn::dat::Trie::update failed: %s",
+ ex.what());
return ctx->rc;
}
return GRN_SUCCESS;
@@ -785,7 +834,8 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::lcp_search failed");
+ "grn::dat::lcp_search failed: %s",
+ ex.what());
if (str_rest) {
*str_rest = str;
}
@@ -816,7 +866,8 @@ grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat,
return trie->get_key(key_pos).id();
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::PrefixCursor::open failed");
+ "grn::dat::PrefixCursor::open failed: %s",
+ ex.what());
return GRN_ID_NIL;
}
}
@@ -899,7 +950,8 @@ grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::CursorFactory::open failed");
+ "grn::dat::CursorFactory::open failed: %s",
+ ex.what());
GRN_FREE(dc);
return NULL;
}
@@ -925,7 +977,8 @@ grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c)
c->curr_rec = key.is_valid() ? key.id() : GRN_ID_NIL;
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Cursor::next failed");
+ "grn::dat::Cursor::next failed: %s",
+ ex.what());
return GRN_ID_NIL;
}
return c->curr_rec;
@@ -972,7 +1025,8 @@ grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c,
}
} catch (const grn::dat::Exception &ex) {
ERR(grn_dat_translate_error_code(ex.code()),
- "grn::dat::Trie::remove failed");
+ "grn::dat::Trie::remove failed: %s",
+ ex.what());
return GRN_INVALID_ARGUMENT;
}
return GRN_INVALID_ARGUMENT;
@@ -1008,7 +1062,7 @@ grn_dat_truncate(grn_ctx *ctx, grn_dat *dat)
grn::dat::Trie().create(trie_path);
} catch (const grn::dat::Exception &ex) {
const grn_rc error_code = grn_dat_translate_error_code(ex.code());
- ERR(error_code, "grn::dat::Trie::create failed");
+ ERR(error_code, "grn::dat::Trie::create failed: %s", ex.what());
return error_code;
}
++dat->header->file_id;
@@ -1022,14 +1076,17 @@ const char *
_grn_dat_key(grn_ctx *ctx, grn_dat *dat, grn_id id, uint32_t *key_size)
{
if (!grn_dat_open_trie_if_needed(ctx, dat)) {
+ *key_size = 0;
return NULL;
}
const grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie);
if (!trie) {
+ *key_size = 0;
return NULL;
}
const grn::dat::Key &key = trie->ith_key(id);
if (!key.is_valid()) {
+ *key_size = 0;
return NULL;
}
*key_size = key.length();
@@ -1102,7 +1159,7 @@ grn_dat_repair(grn_ctx *ctx, grn_dat *dat)
grn::dat::Trie().repair(*trie, trie_path);
} catch (const grn::dat::Exception &ex) {
const grn_rc error_code = grn_dat_translate_error_code(ex.code());
- ERR(error_code, "grn::dat::Trie::create failed");
+ ERR(error_code, "grn::dat::Trie::create failed: %s", ex.what());
return error_code;
}
++dat->header->file_id;
@@ -1131,9 +1188,9 @@ grn_dat_flush(grn_ctx *ctx, grn_dat *dat)
} catch (const grn::dat::Exception &ex) {
const grn_rc error_code = grn_dat_translate_error_code(ex.code());
if (error_code == GRN_INPUT_OUTPUT_ERROR) {
- SERR("grn::dat::Trie::flush failed");
+ SERR("grn::dat::Trie::flush failed: %s", ex.what());
} else {
- ERR(error_code, "grn::dat::Trie::flush failed");
+ ERR(error_code, "grn::dat::Trie::flush failed: %s", ex.what());
}
return error_code;
}
@@ -1142,4 +1199,140 @@ grn_dat_flush(grn_ctx *ctx, grn_dat *dat)
return GRN_SUCCESS;
}
+grn_rc
+grn_dat_dirty(grn_ctx *ctx, grn_dat *dat)
+{
+ if (!dat->io) {
+ return GRN_SUCCESS;
+ }
+
+ grn_rc rc = GRN_SUCCESS;
+
+ {
+ CriticalSection critical_section(&dat->lock);
+ if (!dat->is_dirty) {
+ uint32_t n_dirty_opens;
+ dat->is_dirty = GRN_TRUE;
+ GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), 1, n_dirty_opens);
+ rc = grn_io_flush(ctx, dat->io);
+ }
+ }
+
+ return rc;
+}
+
+grn_bool
+grn_dat_is_dirty(grn_ctx *ctx, grn_dat *dat)
+{
+ if (!dat->header) {
+ return GRN_FALSE;
+ }
+
+ return dat->header->n_dirty_opens > 0;
+}
+
+grn_rc
+grn_dat_clean(grn_ctx *ctx, grn_dat *dat)
+{
+ grn_rc rc = GRN_SUCCESS;
+
+ if (!dat->io) {
+ return rc;
+ }
+
+ {
+ CriticalSection critical_section(&dat->lock);
+ if (dat->is_dirty) {
+ uint32_t n_dirty_opens;
+ dat->is_dirty = GRN_FALSE;
+ GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), -1, n_dirty_opens);
+ rc = grn_io_flush(ctx, dat->io);
+ }
+ }
+
+ return rc;
+}
+
+grn_rc
+grn_dat_clear_dirty(grn_ctx *ctx, grn_dat *dat)
+{
+ grn_rc rc = GRN_SUCCESS;
+
+ if (!dat->io) {
+ return rc;
+ }
+
+ {
+ CriticalSection critical_section(&dat->lock);
+ dat->is_dirty = GRN_FALSE;
+ dat->header->n_dirty_opens = 0;
+ rc = grn_io_flush(ctx, dat->io);
+ }
+
+ return rc;
+}
+
+grn_bool
+grn_dat_is_corrupt(grn_ctx *ctx, grn_dat *dat)
+{
+ if (!dat->io) {
+ return GRN_FALSE;
+ }
+
+ {
+ CriticalSection critical_section(&dat->lock);
+
+ if (grn_io_is_corrupt(ctx, dat->io)) {
+ return GRN_TRUE;
+ }
+
+ if (dat->header->file_id == 0) {
+ return GRN_FALSE;
+ }
+
+ char trie_path[PATH_MAX];
+ grn_dat_generate_trie_path(grn_io_path(dat->io),
+ trie_path,
+ dat->header->file_id);
+ struct stat stat;
+ if (::stat(trie_path, &stat) != 0) {
+ SERR("[dat][corrupt] used path doesn't exist: <%s>",
+ trie_path);
+ return GRN_TRUE;
+ }
+ }
+
+ return GRN_FALSE;
+}
+
+size_t
+grn_dat_get_disk_usage(grn_ctx *ctx, grn_dat *dat)
+{
+ if (!dat->io) {
+ return 0;
+ }
+
+ {
+ CriticalSection critical_section(&dat->lock);
+ size_t usage;
+
+ usage = grn_io_get_disk_usage(ctx, dat->io);
+
+ if (dat->header->file_id == 0) {
+ return usage;
+ }
+
+ char trie_path[PATH_MAX];
+ grn_dat_generate_trie_path(grn_io_path(dat->io),
+ trie_path,
+ dat->header->file_id);
+ struct stat stat;
+ if (::stat(trie_path, &stat) == 0) {
+ usage += stat.st_size;
+ }
+
+ return usage;
+ }
+}
+
} // extern "C"