[Groonga-commit] groonga/groonga at 0fef6f1 [master] hash: support 4GiB over total key size

Back to archive index

Kouhei Sutou null+****@clear*****
Tue Mar 8 19:26:28 JST 2016


Kouhei Sutou	2016-03-08 19:26:28 +0900 (Tue, 08 Mar 2016)

  New Revision: 0fef6f1d18c6eba3d75cc3fad6630793af787431
  https://github.com/groonga/groonga/commit/0fef6f1d18c6eba3d75cc3fad6630793af787431

  Merged e25859e: Merge pull request #498 from groonga/support-4gib-over-total-key-size-in-hash

  Message:
    hash: support 4GiB over total key size
    
    If you add KEY_LARGE flag to table:
    
        table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText
    
    you can put many keys to the table. By default, 4GiB is the max total
    key size. With KEY_LARGE flag, 1TiB is the max total key size. Because
    4KiB * (2 ** 28 - 1) < 1TiB. ((2 ** 28 - 1) is the max number of records
    in a table.)
    
    It doesn't break backward compatibility. You can use the existing
    database without dump and restore.

  Added files:
    test/command/suite/dump/schema/table/hash/key_large_flag.expected
    test/command/suite/dump/schema/table/hash/key_large_flag.test
    test/command/suite/table_create/key_large/hash_key.expected
    test/command/suite/table_create/key_large/hash_key.test
    test/command/suite/table_create/key_large/patricia_trie.expected
    test/command/suite/table_create/key_large/patricia_trie.test
  Modified files:
    include/groonga/groonga.h
    lib/db.c
    lib/dump.c
    lib/grn_hash.h
    lib/hash.c
    lib/proc/proc_table.c

  Modified: include/groonga/groonga.h (+2 -0)
===================================================================
--- include/groonga/groonga.h    2016-03-08 16:12:16 +0900 (d6cb07f)
+++ include/groonga/groonga.h    2016-03-08 19:26:28 +0900 (147479c)
@@ -335,6 +335,8 @@ typedef uint16_t grn_obj_flags;
 #define GRN_OBJ_UNIT_USERDEF_SECTION   (0x07<<8)
 #define GRN_OBJ_UNIT_USERDEF_POSITION  (0x08<<8)
 
+#define GRN_OBJ_KEY_LARGE              (0x01<<12)
+
 #define GRN_OBJ_NO_SUBREC              (0x00<<13)
 #define GRN_OBJ_WITH_SUBREC            (0x01<<13)
 

  Modified: lib/db.c (+11 -0)
===================================================================
--- lib/db.c    2016-03-08 16:12:16 +0900 (651e06a)
+++ lib/db.c    2016-03-08 19:26:28 +0900 (320611d)
@@ -933,6 +933,17 @@ grn_table_create_validate(grn_ctx *ctx, const char *name, unsigned int name_size
     return ctx->rc;
   }
 
+  if ((flags & GRN_OBJ_KEY_LARGE) &&
+      table_type != GRN_OBJ_TABLE_HASH_KEY) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[table][create] "
+        "large key support is available only for TABLE_HASH_KEY key table: "
+        "<%.*s>(%s)",
+        name_size, name,
+        table_type_name);
+    return ctx->rc;
+  }
+
   return ctx->rc;
 }
 

  Modified: lib/dump.c (+3 -0)
===================================================================
--- lib/dump.c    2016-03-08 16:12:16 +0900 (3d44731)
+++ lib/dump.c    2016-03-08 19:26:28 +0900 (594213c)
@@ -39,6 +39,9 @@ grn_dump_table_create_flags(grn_ctx *ctx,
     GRN_TEXT_PUTS(ctx, buffer, "TABLE_NO_KEY");
     break;
   }
+  if (flags & GRN_OBJ_KEY_LARGE) {
+    GRN_TEXT_PUTS(ctx, buffer, "|KEY_LARGE");
+  }
   if (flags & GRN_OBJ_KEY_WITH_SIS) {
     GRN_TEXT_PUTS(ctx, buffer, "|KEY_WITH_SIS");
   }

  Modified: lib/grn_hash.h (+5 -2)
===================================================================
--- lib/grn_hash.h    2016-03-08 16:12:16 +0900 (3a0637c)
+++ lib/grn_hash.h    2016-03-08 19:26:28 +0900 (1048252)
@@ -254,7 +254,7 @@ struct _grn_hash {
   uint32_t value_size;\
   grn_id tokenizer;\
   uint32_t curr_rec;\
-  int32_t curr_key;\
+  uint32_t curr_key;\
   uint32_t idx_offset;\
   uint32_t entry_size;\
   uint32_t max_offset;\
@@ -263,7 +263,8 @@ struct _grn_hash {
   uint32_t lock;\
   grn_id normalizer;\
   uint32_t truncated;\
-  uint32_t reserved[14]
+  uint64_t curr_key_large;\
+  uint32_t reserved[12]
 
 struct _grn_hash_header_common {
   GRN_HASH_HEADER_COMMON_FIELDS;
@@ -365,6 +366,8 @@ grn_id grn_array_at(grn_ctx *ctx, grn_array *array, grn_id id);
 
 void grn_hash_check(grn_ctx *ctx, grn_hash *hash);
 
+grn_bool grn_hash_is_large_total_key_size(grn_ctx *ctx, grn_hash *hash);
+
 uint64_t grn_hash_total_key_size(grn_ctx *ctx, grn_hash *hash);
 uint64_t grn_hash_max_total_key_size(grn_ctx *ctx, grn_hash *hash);
 

  Modified: lib/hash.c (+186 -62)
===================================================================
--- lib/hash.c    2016-03-08 16:12:16 +0900 (4b4d3fa)
+++ lib/hash.c    2016-03-08 19:26:28 +0900 (500dd77)
@@ -1,6 +1,6 @@
 /* -*- c-basic-offset: 2 -*- */
 /*
-  Copyright(C) 2009-2015 Brazil
+  Copyright(C) 2009-2016 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -262,7 +262,7 @@ grn_tiny_bitmap_put_and_set(grn_tiny_bitmap *bitmap, grn_id bit_id,
 
 inline static void *
 grn_io_array_at_inline(grn_ctx *ctx, grn_io *io, uint32_t segment_id,
-                       uint32_t offset, int flags)
+                       uint64_t offset, int flags)
 {
   void *ptr;
   GRN_IO_ARRAY_AT(io, segment_id, offset, &flags, ptr);
@@ -1244,9 +1244,13 @@ grn_array_unblock(grn_ctx *ctx, grn_array *array)
     (GRN_HASH_MAX_KEY_SIZE_LARGE - GRN_HASH_MAX_KEY_SIZE_NORMAL)))
 #define GRN_HASH_SEGMENT_SIZE 0x400000
 #define GRN_HASH_KEY_MAX_N_SEGMENTS 0x400
+#define GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE 0x40000
 #define W_OF_KEY_IN_A_SEGMENT 22
 #define GRN_HASH_KEY_MAX_TOTAL_SIZE\
   (((uint64_t)(1) << W_OF_KEY_IN_A_SEGMENT) * GRN_HASH_KEY_MAX_N_SEGMENTS - 1)
+#define GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE\
+  (((uint64_t)(1) << W_OF_KEY_IN_A_SEGMENT) *\
+   GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE - 1)
 #define IDX_MASK_IN_A_SEGMENT 0xfffff
 
 typedef struct {
@@ -1275,6 +1279,17 @@ typedef struct {
   uint16_t flag;
   uint16_t key_size;
   union {
+    uint8_t buf[sizeof(uint64_t)];
+    uint64_t offset;
+  } key;
+  uint8_t value[1];
+} grn_io_hash_entry_large;
+
+typedef struct {
+  uint32_t hash_value;
+  uint16_t flag;
+  uint16_t key_size;
+  union {
     uint8_t buf[sizeof(void *)];
     void *ptr;
   } key;
@@ -1298,6 +1313,7 @@ typedef union {
   grn_plain_hash_entry plain_entry;
   grn_rich_hash_entry rich_entry;
   grn_io_hash_entry io_entry;
+  grn_io_hash_entry_large io_entry_large;
   grn_tiny_hash_entry tiny_entry;
 } grn_hash_entry;
 
@@ -1396,7 +1412,7 @@ grn_hash_idx_at(grn_ctx *ctx, grn_hash *hash, grn_id id)
 }
 
 inline static void *
-grn_io_hash_key_at(grn_ctx *ctx, grn_hash *hash, uint32_t pos)
+grn_io_hash_key_at(grn_ctx *ctx, grn_hash *hash, uint64_t pos)
 {
   return grn_io_array_at_inline(ctx, hash->io, GRN_HASH_KEY_SEGMENT,
                                 pos, GRN_TABLE_ADD);
@@ -1421,10 +1437,20 @@ grn_hash_entry_get_key(grn_ctx *ctx, grn_hash *hash, grn_hash_entry *entry)
 {
   if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
     if (grn_hash_is_io_hash(hash)) {
-      if (entry->io_entry.flag & HASH_IMMEDIATE) {
-        return (char *)entry->io_entry.key.buf;
+      if (grn_hash_is_large_total_key_size(ctx, hash)) {
+        if (entry->io_entry_large.flag & HASH_IMMEDIATE) {
+          return (char *)entry->io_entry_large.key.buf;
+        } else {
+          return (char *)grn_io_hash_key_at(ctx, hash,
+                                            entry->io_entry_large.key.offset);
+        }
       } else {
-        return (char *)grn_io_hash_key_at(ctx, hash, entry->io_entry.key.offset);
+        if (entry->io_entry.flag & HASH_IMMEDIATE) {
+          return (char *)entry->io_entry.key.buf;
+        } else {
+          return (char *)grn_io_hash_key_at(ctx, hash,
+                                            entry->io_entry.key.offset);
+        }
       }
     } else {
       if (entry->tiny_entry.flag & HASH_IMMEDIATE) {
@@ -1443,11 +1469,15 @@ grn_hash_entry_get_key(grn_ctx *ctx, grn_hash *hash, grn_hash_entry *entry)
 }
 
 inline static void *
-grn_hash_entry_get_value(grn_hash *hash, grn_hash_entry *entry)
+grn_hash_entry_get_value(grn_ctx *ctx, grn_hash *hash, grn_hash_entry *entry)
 {
   if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
     if (grn_hash_is_io_hash(hash)) {
-      return entry->io_entry.value;
+      if (grn_hash_is_large_total_key_size(ctx, hash)) {
+        return entry->io_entry_large.value;
+      } else {
+        return entry->io_entry.value;
+      }
     } else {
       return entry->tiny_entry.value;
     }
@@ -1462,15 +1492,34 @@ grn_hash_entry_get_value(grn_hash *hash, grn_hash_entry *entry)
 
 inline static grn_rc
 grn_io_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash,
-                          grn_io_hash_entry *entry,
+                          grn_hash_entry *entry,
                           const void *key, unsigned int key_size)
 {
-  uint32_t key_offset;
-  if (entry->key_size) {
-    key_offset = entry->key.offset;
+  grn_bool is_large_mode;
+  grn_bool key_exist;
+  uint64_t key_offset;
+  grn_io_hash_entry *io_entry = &(entry->io_entry);
+  grn_io_hash_entry_large *io_entry_large = &(entry->io_entry_large);
+
+  is_large_mode = grn_hash_is_large_total_key_size(ctx, hash);
+
+  if (is_large_mode) {
+    key_exist = (io_entry_large->key_size > 0);
+  } else {
+    key_exist = (io_entry->key_size > 0);
+  }
+
+  if (key_exist > 0) {
+    if (is_large_mode) {
+      key_offset = io_entry_large->key.offset;
+    } else {
+      key_offset = io_entry->key.offset;
+    }
   } else {
-    uint32_t segment_id;
+    uint64_t segment_id;
     grn_hash_header_common *header;
+    uint64_t curr_key;
+    uint64_t max_total_size;
 
     header = hash->header.common;
     if (key_size >= GRN_HASH_SEGMENT_SIZE) {
@@ -1484,26 +1533,47 @@ grn_io_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash,
           key_size);
       return ctx->rc;
     }
-    if (key_size > (GRN_HASH_KEY_MAX_TOTAL_SIZE - header->curr_key)) {
+
+    if (is_large_mode) {
+      curr_key = header->curr_key_large;
+      max_total_size = GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE;
+    } else {
+      curr_key = header->curr_key;
+      max_total_size = GRN_HASH_KEY_MAX_TOTAL_SIZE;
+    }
+
+    if (key_size > (max_total_size - curr_key)) {
       char name[GRN_TABLE_MAX_KEY_SIZE];
       int name_size;
       name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE);
       ERR(GRN_NOT_ENOUGH_SPACE,
           "[hash][key][put] total key size is over: <%.*s>: "
-          "max=%" GRN_FMT_INT64U ": current=%u: new key size=%u",
+          "max=%" GRN_FMT_INT64U ": "
+          "current=%" GRN_FMT_INT64U ": "
+          "new key size=%u",
           name_size, name,
-          GRN_HASH_KEY_MAX_TOTAL_SIZE,
-          header->curr_key,
+          max_total_size,
+          curr_key,
           key_size);
       return ctx->rc;
     }
-    key_offset = header->curr_key;
+    key_offset = curr_key;
     segment_id = (key_offset + key_size) >> W_OF_KEY_IN_A_SEGMENT;
     if ((key_offset >> W_OF_KEY_IN_A_SEGMENT) != segment_id) {
-      key_offset = header->curr_key = segment_id << W_OF_KEY_IN_A_SEGMENT;
+      key_offset = segment_id << W_OF_KEY_IN_A_SEGMENT;
+      if (is_large_mode) {
+        header->curr_key_large = key_offset;
+      } else {
+        header->curr_key = key_offset;
+      }
+    }
+    if (is_large_mode) {
+      header->curr_key_large += key_size;
+      io_entry_large->key.offset = key_offset;
+    } else {
+      header->curr_key += key_size;
+      io_entry->key.offset = key_offset;
     }
-    header->curr_key += key_size;
-    entry->key.offset = key_offset;
   }
 
   {
@@ -1514,7 +1584,8 @@ grn_io_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash,
       name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE);
       ERR(GRN_NO_MEMORY_AVAILABLE,
           "[hash][key][put] failed to allocate for new key: <%.*s>: "
-          "new offset:%u key size=%u",
+          "new offset:%" GRN_FMT_INT64U " "
+          "key size:%u",
           name_size, name,
           key_offset,
           key_size);
@@ -1532,20 +1603,35 @@ grn_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash,
 {
   if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
     if (grn_hash_is_io_hash(hash)) {
-      if (key_size <= sizeof(entry->io_entry.key.buf)) {
-        grn_memcpy(entry->io_entry.key.buf, key, key_size);
-        entry->io_entry.flag = HASH_IMMEDIATE;
+      if (grn_hash_is_large_total_key_size(ctx, hash)) {
+        if (key_size <= sizeof(entry->io_entry_large.key.buf)) {
+          grn_memcpy(entry->io_entry_large.key.buf, key, key_size);
+          entry->io_entry_large.flag = HASH_IMMEDIATE;
+        } else {
+          const grn_rc rc =
+            grn_io_hash_entry_put_key(ctx, hash, entry, key, key_size);
+          if (rc) {
+            return rc;
+          }
+          entry->io_entry_large.flag = 0;
+        }
+        entry->io_entry_large.hash_value = hash_value;
+        entry->io_entry_large.key_size = key_size;
       } else {
-        const grn_rc rc =
-            grn_io_hash_entry_put_key(ctx, hash, (grn_io_hash_entry *)entry,
-                                      key, key_size);
-        if (rc) {
-          return rc;
+        if (key_size <= sizeof(entry->io_entry.key.buf)) {
+          grn_memcpy(entry->io_entry.key.buf, key, key_size);
+          entry->io_entry.flag = HASH_IMMEDIATE;
+        } else {
+          const grn_rc rc =
+            grn_io_hash_entry_put_key(ctx, hash, entry, key, key_size);
+          if (rc) {
+            return rc;
+          }
+          entry->io_entry.flag = 0;
         }
-        entry->io_entry.flag = 0;
+        entry->io_entry.hash_value = hash_value;
+        entry->io_entry.key_size = key_size;
       }
-      entry->io_entry.hash_value = hash_value;
-      entry->io_entry.key_size = key_size;
     } else {
       if (key_size <= sizeof(entry->tiny_entry.key.buf)) {
         grn_memcpy(entry->tiny_entry.key.buf, key, key_size);
@@ -1588,12 +1674,22 @@ grn_hash_entry_compare_key(grn_ctx *ctx, grn_hash *hash,
       return GRN_FALSE;
     }
     if (grn_hash_is_io_hash(hash)) {
-      if (entry->io_entry.flag & HASH_IMMEDIATE) {
-        return !memcmp(key, entry->io_entry.key.buf, key_size);
+      if (grn_hash_is_large_total_key_size(ctx, hash)) {
+        if (entry->io_entry_large.flag & HASH_IMMEDIATE) {
+          return !memcmp(key, entry->io_entry_large.key.buf, key_size);
+        } else {
+          const void * const entry_key_ptr =
+              grn_io_hash_key_at(ctx, hash, entry->io_entry_large.key.offset);
+          return !memcmp(key, entry_key_ptr, key_size);
+        }
       } else {
-        const void * const entry_key_ptr =
-            grn_io_hash_key_at(ctx, hash, entry->io_entry.key.offset);
-        return !memcmp(key, entry_key_ptr, key_size);
+        if (entry->io_entry.flag & HASH_IMMEDIATE) {
+          return !memcmp(key, entry->io_entry.key.buf, key_size);
+        } else {
+          const void * const entry_key_ptr =
+              grn_io_hash_key_at(ctx, hash, entry->io_entry.key.offset);
+          return !memcmp(key, entry_key_ptr, key_size);
+        }
       }
     } else {
       if (entry->tiny_entry.flag & HASH_IMMEDIATE) {
@@ -1621,9 +1717,9 @@ get_key(grn_ctx *ctx, grn_hash *hash, entry_str *n)
 }
 
 inline static void *
-get_value(grn_hash *hash, entry_str *n)
+get_value(grn_ctx *ctx, grn_hash *hash, entry_str *n)
 {
-  return grn_hash_entry_get_value(hash, (grn_hash_entry *)n);
+  return grn_hash_entry_get_value(ctx, hash, (grn_hash_entry *)n);
 }
 
 inline static grn_rc
@@ -1661,7 +1757,8 @@ grn_io_hash_calculate_entry_size(uint32_t key_size, uint32_t value_size,
 
 static grn_io *
 grn_io_hash_create_io(grn_ctx *ctx, const char *path,
-                      uint32_t header_size, uint32_t entry_size)
+                      uint32_t header_size, uint32_t entry_size,
+                      uint32_t flags)
 {
   uint32_t w_of_element = 0;
   grn_io_array_spec array_spec[4];
@@ -1671,7 +1768,13 @@ grn_io_hash_create_io(grn_ctx *ctx, const char *path,
   }
 
   array_spec[GRN_HASH_KEY_SEGMENT].w_of_element = 0;
-  array_spec[GRN_HASH_KEY_SEGMENT].max_n_segments = GRN_HASH_KEY_MAX_N_SEGMENTS;
+  if (flags & GRN_OBJ_KEY_LARGE) {
+    array_spec[GRN_HASH_KEY_SEGMENT].max_n_segments =
+      GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE;
+  } else {
+    array_spec[GRN_HASH_KEY_SEGMENT].max_n_segments =
+      GRN_HASH_KEY_MAX_N_SEGMENTS;
+  }
   array_spec[GRN_HASH_ENTRY_SEGMENT].w_of_element = w_of_element;
   array_spec[GRN_HASH_ENTRY_SEGMENT].max_n_segments =
       1U << (30 - (22 - w_of_element));
@@ -1700,7 +1803,7 @@ grn_io_hash_init(grn_ctx *ctx, grn_hash *hash, const char *path,
   }
   entry_size = grn_io_hash_calculate_entry_size(key_size, value_size, flags);
 
-  io = grn_io_hash_create_io(ctx, path, header_size, entry_size);
+  io = grn_io_hash_create_io(ctx, path, header_size, entry_size, flags);
   if (!io) {
     return GRN_NO_MEMORY_AVAILABLE;
   }
@@ -1724,6 +1827,7 @@ grn_io_hash_init(grn_ctx *ctx, grn_hash *hash, const char *path,
   header->key_size = key_size;
   header->curr_rec = 0;
   header->curr_key = 0;
+  header->curr_key_large = 0;
   header->lock = 0;
   header->idx_offset = 0;
   header->value_size = value_size;
@@ -2235,7 +2339,11 @@ grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value,
     garbages[key_size - 1] = *(grn_id *)entry;
     if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
       /* keep entry->io_entry's hash_value, flag, key_size and key. */
-      memset(entry->io_entry.value, 0, header->value_size);
+      if (grn_hash_is_large_total_key_size(ctx, hash)) {
+        memset(entry->io_entry_large.value, 0, header->value_size);
+      } else {
+        memset(entry->io_entry.value, 0, header->value_size);
+      }
     } else {
       memset(entry, 0, header->entry_size);
     }
@@ -2258,7 +2366,7 @@ grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value,
   }
 
   if (value) {
-    *value = grn_hash_entry_get_value(hash, entry);
+    *value = grn_hash_entry_get_value(ctx, hash, entry);
   }
   return entry_id;
 }
@@ -2291,7 +2399,7 @@ grn_tiny_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value,
   }
 
   if (value) {
-    *value = grn_hash_entry_get_value(hash, entry);
+    *value = grn_hash_entry_get_value(ctx, hash, entry);
   }
   return entry_id;
 }
@@ -2359,7 +2467,7 @@ grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key,
       if (grn_hash_entry_compare_key(ctx, hash, entry, hash_value,
                                      key, key_size)) {
         if (value) {
-          *value = grn_hash_entry_get_value(hash, entry);
+          *value = grn_hash_entry_get_value(ctx, hash, entry);
         }
         if (added) {
           *added = 0;
@@ -2434,7 +2542,7 @@ grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key,
           if (grn_hash_entry_compare_key(ctx, hash, entry, hash_value,
                                          key, key_size)) {
             if (value) {
-              *value = grn_hash_entry_get_value(hash, entry);
+              *value = grn_hash_entry_get_value(ctx, hash, entry);
             }
             return id;
           }
@@ -2520,7 +2628,7 @@ grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf)
   if (!entry) {
     return 0;
   }
-  value = grn_hash_entry_get_value(hash, entry);
+  value = grn_hash_entry_get_value(ctx, hash, entry);
   if (!value) {
     return 0;
   }
@@ -2542,7 +2650,7 @@ grn_hash_get_value_(grn_ctx *ctx, grn_hash *hash, grn_id id, uint32_t *size)
   if (!entry) {
     return NULL;
   }
-  value = grn_hash_entry_get_value(hash, entry);
+  value = grn_hash_entry_get_value(ctx, hash, entry);
   if (!value) {
     return NULL;
   }
@@ -2568,7 +2676,7 @@ grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id,
   if (bufsize >= key_size) {
     grn_memcpy(keybuf, grn_hash_entry_get_key(ctx, hash, entry), key_size);
   }
-  value = grn_hash_entry_get_value(hash, entry);
+  value = grn_hash_entry_get_value(ctx, hash, entry);
   if (!value) {
     return 0;
   }
@@ -2593,7 +2701,7 @@ _grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id,
   }
   key_size = grn_hash_entry_get_key_size(hash, entry);
   *key = grn_hash_entry_get_key(ctx, hash, entry);
-  *value = grn_hash_entry_get_value(hash, entry);
+  *value = grn_hash_entry_get_value(ctx, hash, entry);
   return *value ? key_size : 0;
 }
 
@@ -2613,7 +2721,7 @@ grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id,
   if (!entry) {
     return GRN_NO_MEMORY_AVAILABLE;
   }
-  entry_value = grn_hash_entry_get_value(hash, entry);
+  entry_value = grn_hash_entry_get_value(ctx, hash, entry);
   if (!entry_value) {
     return GRN_NO_MEMORY_AVAILABLE;
   }
@@ -2898,7 +3006,7 @@ grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value)
   entry_str *ee;
   if (!c) { return 0; }
   ee = grn_hash_entry_at(ctx, c->hash, c->curr_rec, 0);
-  if (ee && (v = get_value(c->hash, ee))) {
+  if (ee && (v = get_value(ctx, c->hash, ee))) {
     *value = v;
     return c->hash->value_size;
   }
@@ -2917,7 +3025,7 @@ grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c,
     *key_size = (c->hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) ? ee->size : c->hash->key_size;
   }
   if (key) { *key = get_key(ctx, c->hash, ee); }
-  if (value) { *value = get_value(c->hash, ee); }
+  if (value) { *value = get_value(ctx, c->hash, ee); }
   return c->hash->value_size;
 }
 
@@ -2941,7 +3049,7 @@ grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c,
 
 #define PREPARE_VAL(e,ep,es) do {\
   if ((arg->flags & GRN_TABLE_SORT_BY_VALUE)) {\
-    ep = ((const uint8_t *)(get_value(hash, (entry_str *)(e))));\
+    ep = ((const uint8_t *)(get_value(ctx, hash, (entry_str *)(e))));\
     es = hash->value_size;\
   } else {\
     ep = ((const uint8_t *)(get_key(ctx, hash, (entry_str *)(e))));\
@@ -3099,7 +3207,7 @@ typedef struct {
   (ep)->v = (arg->flags & GRN_TABLE_SORT_BY_ID)\
     ? (int32_t) id\
     : (*((int32_t *)((byte *)((arg->flags & GRN_TABLE_SORT_BY_VALUE)\
-                              ? get_value(hash, (e))\
+                              ? get_value(ctx, hash, (e))\
                               : get_key(ctx, hash, (e))) + arg->offset)));\
 } while (0)
 
@@ -3306,7 +3414,7 @@ grn_hash_check(grn_ctx *ctx, grn_hash *hash)
     return;
   }
   GRN_OUTPUT_ARRAY_OPEN("RESULT", 1);
-  GRN_OUTPUT_MAP_OPEN("SUMMARY", 25);
+  GRN_OUTPUT_MAP_OPEN("SUMMARY", 26);
   GRN_OUTPUT_CSTR("flags");
   grn_itoh(h->flags, buf, 8);
   GRN_OUTPUT_STR(buf, 8);
@@ -3322,6 +3430,8 @@ grn_hash_check(grn_ctx *ctx, grn_hash *hash)
   GRN_OUTPUT_INT64(h->curr_rec);
   GRN_OUTPUT_CSTR("curr_key");
   GRN_OUTPUT_INT64(h->curr_key);
+  GRN_OUTPUT_CSTR("curr_key_large");
+  GRN_OUTPUT_UINT64(h->curr_key_large);
   GRN_OUTPUT_CSTR("idx_offset");
   GRN_OUTPUT_INT64(h->idx_offset);
   GRN_OUTPUT_CSTR("entry_size");
@@ -3528,7 +3638,7 @@ grn_rhash_group(grn_hash *s, int limit, grn_group_optarg *optarg)
 }
 
 grn_rc
-grn_rhash_subrec_info(grn_hash *s, grn_id rh, int index,
+grn_rhash_subrec_info(grn_ctx *ctx, grn_hash *s, grn_id rh, int index,
                       grn_id *rid, int *section, int *pos, int *score, void **subrec)
 {
   grn_rset_posinfo *pi;
@@ -3542,7 +3652,7 @@ grn_rhash_subrec_info(grn_hash *s, grn_id rh, int index,
     ee = grn_hash_entry_at(ctx, s, rh, 0);
     if (!ee) { return GRN_INVALID_ARGUMENT; }
     pi = (grn_rset_posinfo *)get_key(ctx, s, ee);
-    ri = get_value(s, ee);
+    ri = get_value(ctx, s, ee);
     if (!pi || !ri) { return GRN_INVALID_ARGUMENT; }
   }
   if (index >= ri->n_subrecs) { return GRN_INVALID_ARGUMENT; }
@@ -3590,14 +3700,28 @@ grn_rhash_subrec_info(grn_hash *s, grn_id rh, int index,
 }
 #endif /* USE_GRN_INDEX2 */
 
+grn_bool
+grn_hash_is_large_total_key_size(grn_ctx *ctx, grn_hash *hash)
+{
+  return (hash->header.common->flags & GRN_OBJ_KEY_LARGE) == GRN_OBJ_KEY_LARGE;
+}
+
 uint64_t
 grn_hash_total_key_size(grn_ctx *ctx, grn_hash *hash)
 {
-  return hash->header.common->curr_key;
+  if (grn_hash_is_large_total_key_size(ctx, hash)) {
+    return hash->header.common->curr_key_large;
+  } else {
+    return hash->header.common->curr_key;
+  }
 }
 
 uint64_t
 grn_hash_max_total_key_size(grn_ctx *ctx, grn_hash *hash)
 {
-  return GRN_HASH_KEY_MAX_TOTAL_SIZE;
+  if (grn_hash_is_large_total_key_size(ctx, hash)) {
+    return GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE;
+  } else {
+    return GRN_HASH_KEY_MAX_TOTAL_SIZE;
+  }
 }

  Modified: lib/proc/proc_table.c (+3 -0)
===================================================================
--- lib/proc/proc_table.c    2016-03-08 16:12:16 +0900 (9be68cf)
+++ lib/proc/proc_table.c    2016-03-08 19:26:28 +0900 (0ec3be7)
@@ -52,6 +52,9 @@ command_table_create_parse_flags(grn_ctx *ctx,
     } else if (!memcmp(nptr, "KEY_WITH_SIS", 12)) {
       flags |= GRN_OBJ_KEY_WITH_SIS;
       nptr += 12;
+    } else if (!memcmp(nptr, "KEY_LARGE", 9)) {
+      flags |= GRN_OBJ_KEY_LARGE;
+      nptr += 9;
     } else {
       GRN_PLUGIN_ERROR(ctx,
                        GRN_INVALID_ARGUMENT,

  Added: test/command/suite/dump/schema/table/hash/key_large_flag.expected (+4 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/dump/schema/table/hash/key_large_flag.expected    2016-03-08 19:26:28 +0900 (1b096e3)
@@ -0,0 +1,4 @@
+table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText
+[[0,0.0,0.0],true]
+dump
+table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText

  Added: test/command/suite/dump/schema/table/hash/key_large_flag.test (+3 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/dump/schema/table/hash/key_large_flag.test    2016-03-08 19:26:28 +0900 (c32329b)
@@ -0,0 +1,3 @@
+table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText
+
+dump

  Added: test/command/suite/table_create/key_large/hash_key.expected (+46 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/table_create/key_large/hash_key.expected    2016-03-08 19:26:28 +0900 (9a9e1c3)
@@ -0,0 +1,46 @@
+table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText
+[[0,0.0,0.0],true]
+load --table Users
+[
+{"_key": "Alice"},
+{"_key": "Bob"},
+{"_key": "Charlie"}
+]
+[[0,0.0,0.0],3]
+select Users
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        3
+      ],
+      [
+        [
+          "_id",
+          "UInt32"
+        ],
+        [
+          "_key",
+          "ShortText"
+        ]
+      ],
+      [
+        1,
+        "Alice"
+      ],
+      [
+        2,
+        "Bob"
+      ],
+      [
+        3,
+        "Charlie"
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/table_create/key_large/hash_key.test (+10 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/table_create/key_large/hash_key.test    2016-03-08 19:26:28 +0900 (ec21332)
@@ -0,0 +1,10 @@
+table_create Users TABLE_HASH_KEY|KEY_LARGE ShortText
+
+load --table Users
+[
+{"_key": "Alice"},
+{"_key": "Bob"},
+{"_key": "Charlie"}
+]
+
+select Users

  Added: test/command/suite/table_create/key_large/patricia_trie.expected (+13 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/table_create/key_large/patricia_trie.expected    2016-03-08 19:26:28 +0900 (3f4830e)
@@ -0,0 +1,13 @@
+table_create Users TABLE_PAT_KEY|KEY_LARGE ShortText
+[
+  [
+    [
+      -22,
+      0.0,
+      0.0
+    ],
+    "[table][create] large key support is available only for TABLE_HASH_KEY key table: <Users>(TABLE_PAT_KEY)"
+  ],
+  false
+]
+#|e| [table][create] large key support is available only for TABLE_HASH_KEY key table: <Users>(TABLE_PAT_KEY)

  Added: test/command/suite/table_create/key_large/patricia_trie.test (+1 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/table_create/key_large/patricia_trie.test    2016-03-08 19:26:28 +0900 (6c73481)
@@ -0,0 +1 @@
+table_create Users TABLE_PAT_KEY|KEY_LARGE ShortText
-------------- next part --------------
HTML����������������������������...
Télécharger 



More information about the Groonga-commit mailing list
Back to archive index