Beispiel #1
0
/**
 * Allocates space for and returns a linked
 * list of all the filters.
 * @arg mgr The manager to list from
 * @arg prefix The prefix to list or NULL
 * @arg head Output, sets to the address of the list header
 * @return 0 on success.
 */
int filtmgr_list_filters(bloom_filtmgr *mgr, char *prefix, bloom_filter_list_head **head) {
    // Allocate the head
    bloom_filter_list_head *h = *head = calloc(1, sizeof(bloom_filter_list_head));

    // Iterate through a callback to append
    int prefix_len = 0;
    if (prefix) {
        prefix_len = strlen(prefix);
        art_iter_prefix(mgr->filter_map, (unsigned char*)prefix, prefix_len, filter_map_list_cb, h);
    } else
        art_iter(mgr->filter_map, filter_map_list_cb, h);

    // Joy... we have to potentially handle the delta updates
    if (mgr->primary_vsn == mgr->vsn) return 0;

    filter_list *current = mgr->delta;
    bloom_filter_wrapper *f;
    while (current) {
        // Check if this is a match (potential prefix)
        if (current->type == CREATE) {
            f = current->filter;
            if (!prefix_len || !strncmp(f->filter->filter_name, prefix, prefix_len)) {
                f = current->filter;
                filter_map_list_cb(h, (unsigned char*)f->filter->filter_name, 0, f);
            }
        }

        // Don't seek past what the primary map incorporates
        if (current->vsn == mgr->primary_vsn + 1)
            break;
        current = current->next;
    }

    return 0;
}
Beispiel #2
0
/**
 * Allocates space for and returns a linked
 * list of all the sets.
 * @arg mgr The manager to list from
 * @arg prefix The prefix to match on or NULL
 * @arg head Output, sets to the address of the list header
 * @return 0 on success.
 */
int setmgr_list_sets(hlld_setmgr *mgr, char *prefix, hlld_set_list_head **head) {
    // Allocate the head
    hlld_set_list_head *h = *head = calloc(1, sizeof(hlld_set_list_head));

    // Check if we should use the prefix
    int prefix_len = 0;
    if (prefix) {
        prefix_len = strlen(prefix);
        art_iter_prefix(mgr->set_map, prefix, prefix_len, set_map_list_cb, h);
    } else
        art_iter(mgr->set_map, set_map_list_cb, h);

    // Joy... we have to potentially handle the delta updates
    if (mgr->primary_vsn == mgr->vsn) return 0;

    set_list *current = mgr->delta;
    hlld_set_wrapper *s;
    while (current) {
        // Check if this is a match (potential prefix)
        if (current->type == CREATE) {
            s = current->set;
            if (!prefix_len || !strncmp(s->set->set_name, prefix, prefix_len)) {
                s = current->set;
                set_map_list_cb(h, s->set->set_name, 0, s);
            }
        }

        // Don't seek past what the primary set map incorporates
        if (current->vsn == mgr->primary_vsn + 1)
            break;
        current = current->next;
    }

    return 0;
}
Beispiel #3
0
void test_art_long_prefix(void) {
  art_tree t;
  int res = art_tree_init(&t);
  uintptr_t v;
  const char *s;

  fail_unless(res == 0);
  s = "this:key:has:a:long:prefix:3";
  v = 3;
  fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1,
                                 (void *)v));

  s = "this:key:has:a:long:common:prefix:2";
  v = 2;
  fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1,
                                 (void *)v));

  s = "this:key:has:a:long:common:prefix:1";
  v = 1;
  fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1,
                                 (void *)v));

  // Search for the keys
  s = "this:key:has:a:long:common:prefix:1";
  fail_unless(
      1 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1));

  s = "this:key:has:a:long:common:prefix:2";
  fail_unless(
      2 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1));

  s = "this:key:has:a:long:prefix:3";
  fail_unless(
      3 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1));

  {
    const char *expected[] = {
        "this:key:has:a:long:common:prefix:1",
        "this:key:has:a:long:common:prefix:2", "this:key:has:a:long:prefix:3",
    };
    prefix_data p = {0, 3, expected};
    fail_unless(!art_iter_prefix(&t, (unsigned char *)"this:key:has", 12,
                                 test_prefix_cb, &p));
    diag("Count: %d Max: %d", p.count, p.max_count);
    fail_unless(p.count == p.max_count);
  }

  res = art_tree_destroy(&t);
  fail_unless(res == 0);
}
Beispiel #4
0
static ERL_NIF_TERM elibart_prefix_search(ErlNifEnv* env, int argc,
                                          const ERL_NIF_TERM argv[])
{
    art_tree* t;
    ErlNifBinary key;
    callback_data cb_data;

    // extract arguments atr_tree, key
    if (argc != 4)
        return enif_make_badarg(env);
    if(!enif_get_resource(env, argv[0], elibart_RESOURCE, (void**) &t))
        return enif_make_badarg(env);
    if (!enif_inspect_binary(env, argv[1], &key))
        return enif_make_badarg(env);

    cb_data.env = env;
    if(!enif_is_pid(env, argv[3]))
        return mk_error(env, "not_a_pid");

    if(!enif_get_local_pid(env, argv[3], &cb_data.pid))
        return mk_error(env, "not_a_local_pid");

    cb_data.caller_ref = argv[2];
   
    // TODO this should be a worker thread since it's a long opearation (?)
    if (art_iter_prefix(t, key.data, key.size, prefix_cb, &cb_data))
        return mk_error(env, "art_prefix_search");

    ErlNifEnv *msg_env = enif_alloc_env();

    if(msg_env == NULL)
        return mk_error(env, "env_alloc_error");;

    ERL_NIF_TERM caller_ref = enif_make_copy(msg_env, argv[2]);
    ERL_NIF_TERM res = enif_make_tuple2(msg_env, caller_ref, mk_atom(msg_env, "ok"));

    if (!enif_send(env, &cb_data.pid, msg_env, res))
    {
        enif_free(msg_env);

        return mk_error(env, "art_prefix_search");
    }

    enif_free(msg_env);

    return mk_atom(env, "ok");
}
Beispiel #5
0
void test_art_iter_prefix(void) {
  art_tree t;
  int res = art_tree_init(&t);
  const char *s = "api.foo.bar";
  const char *expected2[] = {"abc.123.456", "api",         "api.foe.fum",
                             "api.foo",     "api.foo.bar", "api.foo.baz"};

  fail_unless(res == 0);
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  s = "api.foo.baz";
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  s = "api.foe.fum";
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  s = "abc.123.456";
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  s = "api.foo";
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  s = "api";
  fail_unless(NULL ==
              art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL));

  {
    // Iterate over api
    const char *expected[] = {"api", "api.foe.fum", "api.foo", "api.foo.bar",
                              "api.foo.baz"};
    prefix_data p = {0, 5, expected};
    fail_unless(
        !art_iter_prefix(&t, (unsigned char *)"api", 3, test_prefix_cb, &p));
    diag("Count: %d Max: %d", p.count, p.max_count);
    fail_unless(p.count == p.max_count);
  }

  {
    // Iterate over 'a'
    prefix_data p2 = {0, 6, expected2};
    fail_unless(
        !art_iter_prefix(&t, (unsigned char *)"a", 1, test_prefix_cb, &p2));
    fail_unless(p2.count == p2.max_count);
  }

  {
    // Check a failed iteration
    prefix_data p3 = {0, 0, NULL};
    fail_unless(
        !art_iter_prefix(&t, (unsigned char *)"b", 1, test_prefix_cb, &p3));
    fail_unless(p3.count == 0);
  }

  {
    // Iterate over api.
    const char *expected4[] = {"api.foe.fum", "api.foo", "api.foo.bar",
                               "api.foo.baz"};
    prefix_data p4 = {0, 4, expected4};
    fail_unless(
        !art_iter_prefix(&t, (unsigned char *)"api.", 4, test_prefix_cb, &p4));
    diag("Count: %d Max: %d", p4.count, p4.max_count);
    fail_unless(p4.count == p4.max_count);
  }

  {
    // Iterate over api.foo.ba
    const char *expected5[] = {"api.foo.bar"};
    prefix_data p5 = {0, 1, expected5};
    fail_unless(!art_iter_prefix(&t, (unsigned char *)"api.foo.bar", 11,
                                 test_prefix_cb, &p5));
    diag("Count: %d Max: %d", p5.count, p5.max_count);
    fail_unless(p5.count == p5.max_count);
  }

  // Check a failed iteration on api.end
  {
    prefix_data p6 = {0, 0, NULL};
    fail_unless(!art_iter_prefix(&t, (unsigned char *)"api.end", 7,
                                 test_prefix_cb, &p6));
    fail_unless(p6.count == 0);
  }

  // Iterate over empty prefix
  {
    prefix_data p7 = {0, 6, expected2};
    fail_unless(
        !art_iter_prefix(&t, (unsigned char *)"", 0, test_prefix_cb, &p7));
    fail_unless(p7.count == p7.max_count);
  }

  res = art_tree_destroy(&t);
  fail_unless(res == 0);
}