null+****@clear*****
null+****@clear*****
2012年 1月 13日 (金) 17:31:29 JST
Susumu Yata 2012-01-13 17:31:29 +0900 (Fri, 13 Jan 2012)
New Revision: 96c4c58e4fca6db3ecfec7611e0638e74a25d083
Log:
implemented a flag for detecting grn_dat corruption.
Modified files:
lib/dat.cpp
lib/dat.h
lib/dat/dat.hpp
lib/dat/header.hpp
lib/dat/trie.cpp
lib/dat/trie.hpp
Modified: lib/dat.cpp (+25 -5)
===================================================================
--- lib/dat.cpp 2012-01-13 11:04:46 +0900 (7544b8d)
+++ lib/dat.cpp 2012-01-13 17:31:29 +0900 (0f99f68)
@@ -83,7 +83,12 @@ grn_rc grn_dat_translate_error_code(grn::dat::ErrorCode error_code) {
return GRN_NO_MEMORY_AVAILABLE;
}
case grn::dat::SIZE_ERROR:
- case grn::dat::UNEXPECTED_ERROR:
+ case grn::dat::UNEXPECTED_ERROR: {
+ return GRN_UNKNOWN_ERROR;
+ }
+ case grn::dat::STATUS_ERROR: {
+ return GRN_FILE_CORRUPT;
+ }
default: {
return GRN_UNKNOWN_ERROR;
}
@@ -501,7 +506,7 @@ 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");
- return GRN_INVALID_ARGUMENT;
+ return ctx->rc;
}
return GRN_SUCCESS;
}
@@ -529,6 +534,7 @@ 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");
+ return ctx->rc;
}
}
@@ -540,7 +546,7 @@ 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");
- return GRN_INVALID_ARGUMENT;
+ return ctx->rc;
}
return GRN_SUCCESS;
}
@@ -572,7 +578,7 @@ 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");
- return GRN_INVALID_ARGUMENT;
+ return ctx->rc;
}
return GRN_SUCCESS;
}
@@ -605,7 +611,7 @@ 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");
- return GRN_INVALID_ARGUMENT;
+ return ctx->rc;
}
return GRN_SUCCESS;
}
@@ -995,4 +1001,18 @@ grn_dat_at(grn_ctx *ctx, grn_dat *dat, grn_id id)
return id;
}
+grn_rc
+grn_dat_clear_status_flags(grn_ctx *ctx, grn_dat *dat)
+{
+ if (!grn_dat_open_trie_if_needed(ctx, dat)) {
+ return ctx->rc;
+ }
+ grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie);
+ if (!trie) {
+ return GRN_INVALID_ARGUMENT;
+ }
+ trie->clear_status_flags();
+ return GRN_SUCCESS;
+}
+
} // extern "C"
Modified: lib/dat.h (+2 -0)
===================================================================
--- lib/dat.h 2012-01-13 11:04:46 +0900 (bb7656e)
+++ lib/dat.h 2012-01-13 17:31:29 +0900 (df9477d)
@@ -76,6 +76,8 @@ const char *_grn_dat_key(grn_ctx *ctx, grn_dat *dat, grn_id id, uint32_t *key_si
grn_id grn_dat_next(grn_ctx *ctx, grn_dat *dat, grn_id id);
grn_id grn_dat_at(grn_ctx *ctx, grn_dat *dat, grn_id id);
+grn_rc grn_dat_clear_status_flags(grn_ctx *ctx, grn_dat *dat);
+
#ifdef __cplusplus
}
#endif
Modified: lib/dat/dat.hpp (+8 -1)
===================================================================
--- lib/dat/dat.hpp 2012-01-13 11:04:46 +0900 (8106a8f)
+++ lib/dat/dat.hpp 2012-01-13 17:31:29 +0900 (1dace8d)
@@ -137,13 +137,19 @@ const UInt32 EXCEPT_UPPER_BOUND = 0x02000;
const UInt32 EXCEPT_EXACT_MATCH = 0x04000;
const UInt32 CURSOR_OPTIONS_MASK = 0xFF000;
+const UInt32 REMOVING_FLAG = 1U << 0;
+const UInt32 INSERTING_FLAG = 1U << 1;
+const UInt32 UPDATING_FLAG = 1U << 2;
+const UInt32 CHANGING_MASK = REMOVING_FLAG | INSERTING_FLAG | UPDATING_FLAG;
+
enum ErrorCode {
PARAM_ERROR = -1,
IO_ERROR = -2,
FORMAT_ERROR = -3,
MEMORY_ERROR = -4,
SIZE_ERROR = -5,
- UNEXPECTED_ERROR = -6
+ UNEXPECTED_ERROR = -6,
+ STATUS_ERROR = -7
};
class Exception : public std::exception {
@@ -213,6 +219,7 @@ typedef Error<FORMAT_ERROR> FormatError;
typedef Error<MEMORY_ERROR> MemoryError;
typedef Error<SIZE_ERROR> SizeError;
typedef Error<UNEXPECTED_ERROR> UnexpectedError;
+typedef Error<STATUS_ERROR> StatusError;
#define GRN_DAT_INT_TO_STR(value) \
#value
Modified: lib/dat/header.hpp (+9 -1)
===================================================================
--- lib/dat/header.hpp 2012-01-13 11:04:46 +0900 (e09fbce)
+++ lib/dat/header.hpp 2012-01-13 17:31:29 +0900 (fe870ba)
@@ -39,6 +39,7 @@ class Header {
next_key_pos_(0),
key_buf_size_(0),
leaders_(),
+ status_flags_(0),
reserved_() {
for (UInt32 i = 0; i <= MAX_BLOCK_LEVEL; ++i) {
leaders_[i] = INVALID_LEADER;
@@ -93,6 +94,9 @@ class Header {
UInt32 key_buf_size() const {
return key_buf_size_;
}
+ UInt32 status_flags() const {
+ return status_flags_;
+ }
UInt32 ith_leader(UInt32 i) const {
GRN_DAT_DEBUG_THROW_IF(i > MAX_BLOCK_LEVEL);
return leaders_[i];
@@ -146,6 +150,9 @@ class Header {
GRN_DAT_DEBUG_THROW_IF(x > MAX_KEY_BUF_SIZE);
key_buf_size_ = x;
}
+ void set_status_flags(UInt32 x) {
+ status_flags_ = x;
+ }
void set_ith_leader(UInt32 i, UInt32 x) {
GRN_DAT_DEBUG_THROW_IF(i > MAX_BLOCK_LEVEL);
GRN_DAT_DEBUG_THROW_IF((x != INVALID_LEADER) && (x >= num_blocks()));
@@ -166,7 +173,8 @@ class Header {
UInt32 next_key_pos_;
UInt32 key_buf_size_;
UInt32 leaders_[MAX_BLOCK_LEVEL + 1];
- UInt32 reserved_[13];
+ UInt32 status_flags_;
+ UInt32 reserved_[12];
};
} // namespace dat
Modified: lib/dat/trie.cpp (+31 -0)
===================================================================
--- lib/dat/trie.cpp 2012-01-13 11:04:46 +0900 (7c93538)
+++ lib/dat/trie.cpp 2012-01-13 17:31:29 +0900 (ebb6b00)
@@ -22,6 +22,28 @@
namespace grn {
namespace dat {
+namespace {
+
+class StatusFlagManager {
+ public:
+ StatusFlagManager(Header *header, UInt32 status_flag)
+ : header_(header), status_flag_(status_flag) {
+ header_->set_status_flags(header_->status_flags() | status_flag_);
+ }
+ ~StatusFlagManager() {
+ header_->set_status_flags(header_->status_flags() & ~status_flag_);
+ }
+
+ private:
+ Header *header_;
+ UInt32 status_flag_;
+
+ // Disallows copy and assignment.
+ StatusFlagManager(const StatusFlagManager &);
+ StatusFlagManager &operator=(const StatusFlagManager &);
+};
+
+} // namespace
Trie::Trie()
: file_(),
@@ -431,6 +453,9 @@ bool Trie::lcp_search_key(const UInt8 *ptr, UInt32 length,
}
bool Trie::remove_key(const UInt8 *ptr, UInt32 length) {
+ GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
+ StatusFlagManager status_flag_manager(header_, REMOVING_FLAG);
+
GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0));
UInt32 node_id = ROOT_NODE_ID;
@@ -455,6 +480,9 @@ bool Trie::remove_key(const UInt8 *ptr, UInt32 length) {
}
bool Trie::insert_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos) {
+ GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
+ StatusFlagManager status_flag_manager(header_, INSERTING_FLAG);
+
GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0));
UInt32 node_id = ROOT_NODE_ID;
@@ -528,6 +556,9 @@ bool Trie::insert_linker(const UInt8 *ptr, UInt32 length,
bool Trie::update_key(const Key &key, const UInt8 *ptr, UInt32 length,
UInt32 *key_pos) {
+ GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0);
+ StatusFlagManager status_flag_manager(header_, UPDATING_FLAG);
+
GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0));
if (!key.is_valid()) {
Modified: lib/dat/trie.hpp (+7 -0)
===================================================================
--- lib/dat/trie.hpp 2012-01-13 11:04:46 +0900 (ab866fd)
+++ lib/dat/trie.hpp 2012-01-13 17:31:29 +0900 (199dac3)
@@ -179,6 +179,13 @@ class Trie {
UInt32 key_buf_size() const {
return header_->key_buf_size();
}
+ UInt32 status_flags() const {
+ return header_->status_flags();
+ }
+
+ void clear_status_flags() {
+ header_->set_status_flags(status_flags() & ~CHANGING_MASK);
+ }
private:
File file_;