示例#1
0
文件: 4s-bind.c 项目: rafl/4store
int main(int argc, char *argv[])
{
  char *password = fsp_argv_password(&argc, argv);

  int flags = 0, many = 0, all = 0;
  int seg = 0; /* deliberately using signed type */
  fs_rid_vector *mrids= NULL, *srids= NULL, *prids= NULL, *orids= NULL;
  fs_rid_vector **result = NULL;

  if (argc < 7) {
    fprintf(stderr, "%s revision %s\n", argv[0], FS_FRONTEND_VER);
    fprintf(stderr, "Usage: %s <kbname> { many | all | seg# } <flags>\n", argv[0]);
    fprintf(stderr, " mrid-file srid-file prid-file orid-file [offset limit]\n");
    fprintf(stderr, "For flags use FS_BIND_... symbols or a numeric value\n");
    fprintf(stderr, "RID files are one RID per line\n");
    exit(1);
  }

  char *kbname = argv[1];

  if (!strcasecmp(argv[2], "many")) {
    many = 1;
  } else if (!strcasecmp(argv[2], "all")) {
    all = 1;
  } else {
    seg = atoi(argv[2]);
  }

  int param = 3;

  flags = strtol(argv[param], NULL, 0);

  if (flags == 0) { /* symbolic flags, hopefully */
    while (param < argc) {
      const int len = sizeof(flag_name) / sizeof(char *);
      int k;
      for (k = 0; k < len; ++k) {
        if (!strcmp(flag_name[k], argv[param])) {
          flags |= flag_value[k];
          break;
        }
      }
      if (k == len) break;
      param ++;
    }
  } else {
    param ++; /* done with the numeric flags then */
  }

  if (argc < param + 4) {
    fprintf(stderr, "Wrong number of arguments\n");
    exit(1);
  }

  mrids = rid_file(argv[param++]);
  srids = rid_file(argv[param++]);
  prids = rid_file(argv[param++]);
  orids = rid_file(argv[param++]);

  int limit, offset;

  if (argc == param ) {
    /* defaults */
    limit = -1;
    offset = -1;
  } else if (argc > param + 2) {
    fprintf(stderr, "Wrong number of arguments\n");
    exit(1);
  } else if (argc < param + 2) {
    fprintf(stderr, "Wrong number of arguments\n");
    exit(1);
  } else {
    offset = atoi(argv[param]);
    limit = atoi(argv[param + 1]);
  }

  fsp_link *link = fsp_open_link(kbname, password, FS_OPEN_HINT_RO);

  if (!link) {
    fs_error (LOG_ERR, "couldn't connect to “%s”", argv[1]);
    exit(2);
  }

  segments = fsp_link_segments(link);

  if (seg < 0 || seg > segments) {
    fs_error (LOG_ERR, "Segment %d out of range (0-%u)", seg, segments);
    exit(1);
  }

  double then = fs_time();
  int ans = 0;

  if (all) {
    ans = fsp_bind_limit_all(link, flags, mrids, srids, prids, orids, &result, offset, limit);
  } else if (many) {
    ans = fsp_bind_limit_many(link, flags, mrids, srids, prids, orids, &result, offset, limit);
  } else {
    ans = fsp_bind_limit(link, seg, flags, mrids, srids, prids, orids, &result, offset, limit);
  }

  double time_binding = fs_time() - then;
  if (ans != 0) exit(1);

  /* print results */

  int cols = 0;
  for (int k = 0; k < 4; ++k) {
    if (flags & (1 << k)) cols++;
  }

  if (!result) {
    printf("NO MATCH found.\n");
  } else if (cols == 0) {
    printf("MATCH found.\n");
  } else if (result[0]) {
    int length = result[0]->length;

    if (flags & FS_BIND_MODEL) printf("-----Model------  ");
    if (flags & FS_BIND_SUBJECT) printf("----Subject-----  ");
    if (flags & FS_BIND_PREDICATE) printf("----Predicate---  ");
    if (flags & FS_BIND_OBJECT) printf("-----Object-----");
    putchar('\n');

    for (int k = 0; k < length; ++k) {
      for (int c = 0; c < cols; ++c) {
        printf("%016llX  ", result[c]->data[k]);
      }
      putchar('\n');
    }
  }

  fprintf(stderr, "bind took %f seconds on client\n", time_binding);

  fs_query_timing times;
  if (all || many) {
    fprintf(stderr, "binding on all or many segments, times in seconds...\n");
    for (int s = 0; s < segments; ++s) {
      fsp_get_query_times(link, s, &times);
      if (times.bind > 0.0f) {
        fprintf(stderr, "%d: %f\n", s, times.bind);
      }
    }
    fputc('\n', stderr);
  } else {
    fsp_get_query_times(link, seg, &times);
    fprintf(stderr, "binding segment %d took %f seconds\n", seg, times.bind);
  }

  fsp_close_link(link);
}
示例#2
0
int fs_bind_cache_wrapper_intl(fs_query_state *qs, fs_query *q, int all,
                int flags, fs_rid_vector *rids[4],
                fs_rid_vector ***result, int offset, int limit)
{
    g_static_mutex_lock(&qs->cache_mutex);
    if (!qs->bind_cache) {
        qs->bind_cache = calloc(CACHE_SIZE, sizeof(struct _fs_bind_cache));
    }
    if (fsp_acl_needs_reload(qs->link))
         fs_acl_load_system_info(qs->link);

    g_static_mutex_unlock(&qs->cache_mutex);

    int slots = 0;
    if (flags & FS_BIND_MODEL) slots++;
    if (flags & FS_BIND_SUBJECT) slots++;
    if (flags & FS_BIND_PREDICATE) slots++;
    if (flags & FS_BIND_OBJECT) slots++;

    /* check for no possible bindings */
    for (int s=0; s<4; s++) {
        if (rids[s]->length == 1 && rids[s]->data[0] == FS_RID_NULL) {
            *result = calloc(slots, sizeof(fs_rid_vector));
            for (int s=0; s<slots; s++) {
                (*result)[s] = fs_rid_vector_new(0);
            }

            return 0;
        }
    }

    int cachable = 0;
    fs_rid cache_hash = 0;
    fs_rid cache_key[4];

    /* only consult the cache for optimasation levels 0-2 */
    if (q && q->opt_level < 3) goto skip_cache;

    if (q && q->qs && q->qs->cache_stats) q->qs->bind_hits++;
    cachable = 1;

    cache_hash += all + flags * 2 + offset * 256 + limit * 32768;
    for (int s=0; s<4; s++) {
        if (rids[s]->length == 1) {
            cache_hash ^= (rids[s]->data[0] + s);
            cache_key[s] = rids[s]->data[0];
        } else if (rids[s]->length == 0) {
            cache_key[s] = 0;
        } else {
           /* bind cache does not cache binds with any
              slot containing multiple values */
            cachable = 0;
            break;
        }
    }
    cache_hash %= (CACHE_SIZE - 1);

    g_static_mutex_lock(&qs->cache_mutex);
    if (cachable && qs->bind_cache[cache_hash].filled) {
        int match = 1;
        if (qs->bind_cache[cache_hash].all != all) match = 0;
        if (qs->bind_cache[cache_hash].flags != flags) match = 0;
        if (qs->bind_cache[cache_hash].offset != offset) match = 0;
        if (qs->bind_cache[cache_hash].limit != limit) match = 0;
        for (int s=0; s<4 && match; s++) {
            if (cache_key[s] != qs->bind_cache[cache_hash].key[s]) {
                match = 0;
            }
        }
        if (match) {
            *result = calloc(slots, sizeof(fs_rid_vector));
            for (int s=0; s<slots; s++) {
                (*result)[s] = fs_rid_vector_copy(qs->bind_cache[cache_hash].res[s]);
            }
            fsp_hit_limits_add(qs->link, qs->bind_cache[cache_hash].limited);
            qs->bind_cache[cache_hash].hits++;

            if (q && q->qs && q->qs->cache_stats) q->qs->bind_cache_success++;
            g_static_mutex_unlock(&qs->cache_mutex);
            return 0;
        }
    }
    g_static_mutex_unlock(&qs->cache_mutex);

    int ret;

    skip_cache:;

    int limited_before = fsp_hit_limits(qs->link);
    if (all) {
        ret = fsp_bind_limit_all(qs->link, flags, rids[0], rids[1], rids[2], rids[3], result, offset, limit);
    } else {
        ret = fsp_bind_limit_many(qs->link, flags, rids[0], rids[1], rids[2], rids[3], result, offset, limit);
    }
    int limited = fsp_hit_limits(qs->link) - limited_before;
    if (ret) {
        fs_error(LOG_ERR, "bind failed in '%s', %d segments gave errors",
                 fsp_kb_name(qs->link), ret);

        exit(1);
    }

    int small = 1;
    for (int s=0; s<slots; s++) {
        if (fs_rid_vector_length((*result)[s]) > 10000) {
            small = 0;
            break;
        }
    }

    if (cachable && small && slots > 0) {
        g_static_mutex_lock(&qs->cache_mutex);
        if (qs->bind_cache[cache_hash].filled == 1) {
          for (int s=0; s<4; s++) {
            fs_rid_vector_free(qs->bind_cache[cache_hash].res[s]);
            qs->bind_cache[cache_hash].res[s] = NULL;
          }
        }
        qs->bind_cache[cache_hash].filled = 1;
        qs->bind_cache[cache_hash].all = all;
        qs->bind_cache[cache_hash].flags = flags;
        qs->bind_cache[cache_hash].offset = offset;
        qs->bind_cache[cache_hash].limit = limit;
        qs->bind_cache[cache_hash].limited = limited;
        for (int s=0; s<4; s++) {
            qs->bind_cache[cache_hash].key[s] = cache_key[s];
            if (s < slots) {
                qs->bind_cache[cache_hash].res[s] = fs_rid_vector_copy((*result)[s]);
            } else {
                qs->bind_cache[cache_hash].res[s] = NULL;
            }
        }
        g_static_mutex_unlock(&qs->cache_mutex);
    }

    return ret;
}