[Groonga-commit] groonga/groonga at ed54e84 [master] grn_ja: add grn_ja_reader for fast sequential access

Back to archive index

Susumu Yata null+****@clear*****
Thu Dec 3 17:03:54 JST 2015


Susumu Yata	2015-12-03 17:03:54 +0900 (Thu, 03 Dec 2015)

  New Revision: ed54e8484a01a8b86e2a2bea721a267b9942ad82
  https://github.com/groonga/groonga/commit/ed54e8484a01a8b86e2a2bea721a267b9942ad82

  Message:
    grn_ja: add grn_ja_reader for fast sequential access
    
    GitHub: #441

  Modified files:
    lib/grn_store.h
    lib/store.c

  Modified: lib/grn_store.h (+49 -0)
===================================================================
--- lib/grn_store.h    2015-12-02 17:56:03 +0900 (9e1223e)
+++ lib/grn_store.h    2015-12-03 17:03:54 +0900 (18f004c)
@@ -103,7 +103,56 @@ GRN_API uint32_t grn_ja_size(grn_ctx *ctx, grn_ja *ja, grn_id id);
 void grn_ja_check(grn_ctx *ctx, grn_ja *ja);
 
 /*
+ * grn_ja_reader is designed to improve the performance of sequential access.
+ * FIXME: Compressed values are not supported yet.
+ */
+typedef struct {
+  grn_ja *ja;
+  uint32_t einfo_seg_id;
+  void *einfo_seg_addr;
+  void *einfo;
+  uint32_t body_seg_id;
+  uint32_t body_seg_offset;
+  void *body_seg_addr;
+  grn_id value_id;
+  uint32_t value_size;
+} grn_ja_reader;
 
+/*
+ * grn_ja_reader_init() initializes a reader.
+ * An initialized reader must be finalized by grn_ja_reader_fin().
+ */
+void grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja);
+
+/* grn_ja_reader_fin() finalizes a reader. */
+void grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader);
+
+/*
+ * grn_ja_reader_open() creates a reader.
+ * A created reader must be destroyed by grn_ja_reader_close().
+ */
+grn_rc grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader);
+
+/* grn_ja_reader_close() destroys a reader. */
+grn_rc grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader);
+
+/*
+ * grn_ja_reader_seek() prepares to access a value specified by `id`.
+ * On success, `reader->value_size` is set.
+ */
+grn_rc grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id);
+
+/* grn_ja_reader_read() reads the current value to `buf`. */
+grn_rc grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf);
+
+/*
+ * grn_ja_reader_pread() reads a part of the current value to `buf`.
+ * If `offset` and `size` are invalid, the behavior is undefined.
+ */
+grn_rc grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader,
+                           size_t offset, size_t size, void *buf);
+
+/*
 typedef struct _grn_vgram_vnode
 {
   struct _grn_vgram_vnode *car;

  Modified: lib/store.c (+187 -0)
===================================================================
--- lib/store.c    2015-12-02 17:56:03 +0900 (d43ebb4)
+++ lib/store.c    2015-12-03 17:03:54 +0900 (acb87e5)
@@ -1574,6 +1574,193 @@ grn_ja_check(grn_ctx *ctx, grn_ja *ja)
   GRN_OUTPUT_ARRAY_CLOSE();
 }
 
+/* grn_ja_reader */
+
+void
+grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja)
+{
+  reader->ja = ja;
+  reader->einfo_seg_id = JA_ESEG_VOID;
+  reader->body_seg_id = JA_ESEG_VOID;
+  reader->body_seg_addr = NULL;
+}
+
+void
+grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader)
+{
+  if (reader->einfo_seg_id != JA_ESEG_VOID) {
+    GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
+  }
+  if (reader->body_seg_addr) {
+    GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
+  }
+}
+
+grn_rc
+grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader)
+{
+  grn_ja_reader *new_reader = GRN_MALLOCN(grn_ja_reader, 1);
+  if (!new_reader) {
+    return GRN_NO_MEMORY_AVAILABLE;
+  }
+  grn_ja_reader_init(ctx, new_reader, ja);
+  *reader = new_reader;
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader)
+{
+  grn_ja_reader_fin(ctx, reader);
+  GRN_FREE(reader);
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
+{
+  grn_ja_einfo *einfo;
+  uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
+  if (seg_id == JA_ESEG_VOID) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if (seg_id != reader->einfo_seg_id) {
+    GRN_IO_SEG_REF(reader->ja->io, seg_id, reader->einfo_seg_addr);
+    if (!reader->einfo_seg_addr) {
+      return GRN_UNKNOWN_ERROR;
+    }
+    if (reader->einfo_seg_id != JA_ESEG_VOID) {
+      GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
+    }
+    reader->einfo_seg_id = seg_id;
+  }
+  einfo = (grn_ja_einfo *)reader->einfo_seg_addr;
+  einfo += id & JA_M_EINFO_IN_A_SEGMENT;
+  reader->einfo = einfo;
+  if (ETINY_P(einfo)) {
+    ETINY_DEC(einfo, reader->value_size);
+  } else {
+    if (EHUGE_P(einfo)) {
+      EHUGE_DEC(einfo, seg_id, reader->value_size);
+    } else {
+      EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->value_size);
+    }
+    if (reader->body_seg_addr) {
+      if (seg_id != reader->body_seg_id) {
+        GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
+        reader->body_seg_addr = NULL;
+      }
+    }
+    reader->body_seg_id = seg_id;
+  }
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
+{
+  grn_io *io = reader->ja->io;
+  grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
+  if (ETINY_P(einfo)) {
+    grn_memcpy(buf, einfo, reader->value_size);
+  } else if (EHUGE_P(einfo)) {
+    char *buf_ptr = (char *)buf;
+    void *seg_addr;
+    uint32_t seg_id = reader->body_seg_id;
+    uint32_t size = reader->value_size;
+    while (size > io->header->segment_size) {
+      GRN_IO_SEG_REF(io, seg_id, seg_addr);
+      if (!seg_addr) {
+        return GRN_UNKNOWN_ERROR;
+      }
+      grn_memcpy(buf_ptr, seg_addr, io->header->segment_size);
+      GRN_IO_SEG_UNREF(io, seg_id);
+      seg_id++;
+      size -= io->header->segment_size;
+      buf_ptr += io->header->segment_size;
+    }
+    GRN_IO_SEG_REF(io, seg_id, seg_addr);
+    if (!seg_addr) {
+      return GRN_UNKNOWN_ERROR;
+    }
+    grn_memcpy(buf_ptr, seg_addr, size);
+    GRN_IO_SEG_UNREF(io, seg_id);
+    seg_id++;
+  } else {
+    if (!reader->body_seg_addr) {
+      GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
+      if (!reader->body_seg_addr) {
+        return GRN_UNKNOWN_ERROR;
+      }
+    }
+    grn_memcpy(buf, (char *)reader->body_seg_addr + reader->body_seg_offset,
+               reader->value_size);
+  }
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader,
+                    size_t offset, size_t size, void *buf)
+{
+  grn_io *io = reader->ja->io;
+  grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
+  if ((offset >= reader->value_size) || !size) {
+    return GRN_SUCCESS;
+  }
+  if (size > (reader->value_size - offset)) {
+    size = reader->value_size - offset;
+  }
+  if (ETINY_P(einfo)) {
+    grn_memcpy(buf, (char *)einfo + offset, size);
+  } else if (EHUGE_P(einfo)) {
+    char *buf_ptr = (char *)buf;
+    void *seg_addr;
+    uint32_t seg_id = reader->body_seg_id;
+    if (offset >= io->header->segment_size) {
+      seg_id += offset / io->header->segment_size;
+      offset %= io->header->segment_size;
+    }
+    GRN_IO_SEG_REF(io, seg_id, seg_addr);
+    if (!seg_addr) {
+      return GRN_UNKNOWN_ERROR;
+    }
+    grn_memcpy(buf_ptr, (char *)seg_addr + offset,
+               io->header->segment_size - offset);
+    GRN_IO_SEG_UNREF(io, seg_id);
+    seg_id++;
+    size -= io->header->segment_size - offset;
+    buf_ptr += io->header->segment_size - offset;
+    while (size > io->header->segment_size) {
+      GRN_IO_SEG_REF(io, seg_id, seg_addr);
+      if (!seg_addr) {
+        return GRN_UNKNOWN_ERROR;
+      }
+      grn_memcpy(buf_ptr, (char *)seg_addr, io->header->segment_size);
+      GRN_IO_SEG_UNREF(io, seg_id);
+      seg_id++;
+      size -= io->header->segment_size;
+      buf_ptr += io->header->segment_size;
+    }
+    GRN_IO_SEG_REF(io, seg_id, seg_addr);
+    if (!seg_addr) {
+      return GRN_UNKNOWN_ERROR;
+    }
+    grn_memcpy(buf_ptr, seg_addr, size);
+    GRN_IO_SEG_UNREF(io, seg_id);
+  } else {
+    if (!reader->body_seg_addr) {
+      GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
+      if (!reader->body_seg_addr) {
+        return GRN_UNKNOWN_ERROR;
+      }
+    }
+    offset += reader->body_seg_offset;
+    grn_memcpy(buf, (char *)reader->body_seg_addr + offset, size);
+  }
+  return GRN_SUCCESS;
+}
+
 /**** vgram ****/
 
 /*
-------------- next part --------------
HTML����������������������������...
다운로드 



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