[Groonga-commit] groonga/groonga [master] Expanded critical section in grn_ja_replace().

Zurück zum Archiv-Index

null+****@clear***** null+****@clear*****
2010年 7月 26日 (月) 22:50:41 JST


Daijiro MORI	2010-07-26 13:50:41 +0000 (Mon, 26 Jul 2010)

  New Revision: 4f4565478e33021714572734d96b4d8a14950937

  Log:
    Expanded critical section in grn_ja_replace().

  Modified files:
    lib/store.c

  Modified: lib/store.c (+43 -18)
===================================================================
--- lib/store.c    2010-07-26 07:57:11 +0000 (e61f5bc)
+++ lib/store.c    2010-07-26 13:50:41 +0000 (f5b6946)
@@ -407,9 +407,7 @@ grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
     uint32_t n;
     EHUGE_DEC(einfo, seg, element_size);
     n = ((element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT);
-    if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
     for (; n--; seg++) { SEGMENTS_OFF(ja, seg); }
-    grn_io_unlock(ja->io);
     return GRN_SUCCESS;
   }
   EINFO_DEC(einfo, seg, pos, element_size);
@@ -425,23 +423,19 @@ grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
     if (!addr) { return GRN_NO_MEMORY_AVAILABLE; }
     aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
     *(uint32_t *)(addr + pos - sizeof(grn_id)) = DELETED|aligned_size;
-    if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
     SEGMENTS_AT(ja, seg) -= (aligned_size + sizeof(grn_id));
     if (SEGMENTS_AT(ja, seg) == SEG_SEQ) {
       /* reuse the segment */
       SEGMENTS_AT(ja, seg) = 0;
     }
-    grn_io_unlock(ja->io);
     GRN_IO_SEG_UNREF(ja->io, seg);
   } else {
     uint32_t lseg = 0, lseg_;
     gseg = &ja->header->garbages[m - JA_W_EINFO];
-    if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
     while ((lseg_ = *gseg)) {
       if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
       GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
       if (!ginfo) {
-        grn_io_unlock(ja->io);
         return GRN_NO_MEMORY_AVAILABLE;
       }
       lseg = lseg_;
@@ -453,7 +447,6 @@ grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
       while (SEGMENTS_AT(ja, i)) {
         if (++i >= JA_N_DSEGMENTS) {
           if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
-          grn_io_unlock(ja->io);
           return GRN_NO_MEMORY_AVAILABLE;
         }
       }
@@ -464,7 +457,6 @@ grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
       GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
       lseg = lseg_;
       if (!ginfo) {
-        grn_io_unlock(ja->io);
         return GRN_NO_MEMORY_AVAILABLE;
       }
       ginfo->head = 0;
@@ -477,7 +469,6 @@ grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
     if (++ginfo->head == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->head = 0; }
     ginfo->nrecs++;
     ja->header->ngarbages[m - JA_W_EINFO]++;
-    grn_io_unlock(ja->io);
     if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
   }
   return GRN_SUCCESS;
@@ -491,30 +482,30 @@ grn_ja_replace(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_ja_einfo *ei)
   lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
   pos = id & JA_M_EINFO_IN_A_SEGMENT;
   pseg = &ja->header->esegs[lseg];
+  if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
   if (*pseg == JA_ESEG_VOID) {
-    if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
     if (*pseg == JA_ESEG_VOID) {
       int i = 0;
       while (SEGMENTS_AT(ja, i)) {
         if (++i >= JA_N_DSEGMENTS) {
-          grn_io_unlock(ja->io);
           ERR(GRN_NOT_ENOUGH_SPACE, "grn_ja file (%s) is full", ja->io->path);
-          return ctx->rc;
+          goto exit;
         }
       }
       SEGMENTS_EINFO_ON(ja, i, lseg);
       *pseg = i;
     }
-    grn_io_unlock(ja->io);
   }
   GRN_IO_SEG_REF(ja->io, *pseg, einfo);
-  if (!einfo) { return GRN_NO_MEMORY_AVAILABLE; }
+  if (!einfo) { goto exit; }
   eback = einfo[pos];
   // smb_wmb();
   GRN_SET_64BIT(&einfo[pos], *ei);
   GRN_IO_SEG_UNREF(ja->io, *pseg);
   grn_ja_free(ctx, ja, &eback);
-  return GRN_SUCCESS;
+exit :
+  grn_io_unlock(ja->io);
+  return ctx->rc;
 }
 
 #define JA_N_GARBAGES_TH 10
@@ -1042,9 +1033,8 @@ grn_ja_defrag_seg(grn_ctx *ctx, grn_ja *ja, uint32_t seg)
   }
   if (*segusage != SEG_SEQ) {
     GRN_LOG(ctx, GRN_LOG_ERROR, "dseges[%d] = %d after defrag", seg, *segusage);
-    return GRN_FILE_CORRUPT;
   }
-  *segusage = 0;
+  // *segusage = 0;
   GRN_IO_SEG_UNREF(ja->io, seg);
   return GRN_SUCCESS;
 }
@@ -1082,7 +1072,7 @@ grn_ja_check(grn_ctx *ctx, grn_ja *ja)
   GRN_OUTPUT_CSTR("max_element_size");
   GRN_OUTPUT_INT64(h->max_element_size);
   GRN_OUTPUT_MAP_CLOSE();
-  GRN_OUTPUT_ARRAY_OPEN("DETAIL", 8);
+  GRN_OUTPUT_ARRAY_OPEN("DETAIL", -1);
   for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
     int dseg = SEGMENTS_AT(ja, seg);
     if (dseg) {
@@ -1093,6 +1083,41 @@ grn_ja_check(grn_ctx *ctx, grn_ja *ja)
       GRN_OUTPUT_INT64((dseg & SEG_MASK)>>28);
       GRN_OUTPUT_CSTR("seg value");
       GRN_OUTPUT_INT64(dseg & ~SEG_MASK);
+      if ((dseg & SEG_MASK) == SEG_SEQ) {
+        byte *v = NULL, *ve;
+        uint32_t element_size, cum = 0, sum = dseg & ~SEG_MASK;
+        //GRN_OUTPUT_CSTR("seg seq");
+        //GRN_OUTPUT_ARRAY_OPEN("SEQ", -1);
+        GRN_IO_SEG_REF(ja->io, seg, v);
+        if (v) {
+          ve = v + JA_SEGMENT_SIZE;
+          while (v < ve && cum < sum) {
+            grn_id id = *((grn_id *)v);
+            // GRN_OUTPUT_MAP_OPEN("ENTRY", -1);
+            // GRN_OUTPUT_CSTR("id");
+            // GRN_OUTPUT_INT64(id);
+            if (id & DELETED) {
+              element_size = (id & ~DELETED);
+            } else {
+              element_size = grn_ja_size(ctx, ja, id);
+              element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
+              cum += sizeof(uint32_t) + element_size;
+            }
+            // GRN_OUTPUT_CSTR("size");
+            // GRN_OUTPUT_INT64(element_size);
+            // GRN_OUTPUT_CSTR("cum");
+            // GRN_OUTPUT_INT64(cum);
+            v += sizeof(uint32_t) + element_size;
+            // GRN_OUTPUT_MAP_CLOSE();
+          }
+          GRN_IO_SEG_UNREF(ja->io, seg);
+        }
+        //GRN_OUTPUT_ARRAY_CLOSE();
+        if (cum != sum) {
+          GRN_OUTPUT_CSTR("cum gap");
+          GRN_OUTPUT_INT64(cum - sum);
+        }
+      }
       GRN_OUTPUT_MAP_CLOSE();
     }
   }




Groonga-commit メーリングリストの案内
Zurück zum Archiv-Index