[Groonga-commit] groonga/groonga [master] implemented a flag for detecting grn_dat corruption.

Back to archive index

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_;




Groonga-commit メーリングリストの案内
Back to archive index