Exemplo n.º 1
0
element* table_remove(BlockInfo* pRoot, BlockInfo* pBlock) {
  MY_PRINTF("  table remove\n");
  element* pCur = pRoot;
  MY_ASSERT(table_search(pRoot, element_size(pBlock)) != NULL);
  if (pCur == pBlock) {
    //pCur->child
    //pSib
    if (element_child(pCur)) {
      element* pSib = element_sibling(pCur);
      pCur = element_child(pCur);
      element_sibling(pCur) = pSib;
    }
    else {
      pCur = element_sibling(pCur);
    }
  }
  else if (element_size(pCur) == element_size(pBlock)) {
    MY_ASSERT(pCur != pBlock);
    MY_ASSERT(element_child(pCur) != NULL);
    element_child(pCur) = child_remove(element_child(pCur), pBlock);
  }
  else if (element_size(pCur) < element_size(pBlock)) {
    MY_ASSERT(element_sibling(pCur) != NULL);
    element_sibling(pCur) = table_remove(element_sibling(pCur), pBlock);
  }
  else {
    MY_ASSERT(element_size(pCur) > element_size(pBlock));
    MY_ASSERT(0);
  }
  return pCur;
};
Exemplo n.º 2
0
void
table_main(int ac, char **av)
{
	if (!strncmp(*av, "append", strlen(*av))) {
		table_append(ac, av);
	} else if (!strncmp(*av, "remove", strlen(*av))) {
		table_remove(ac, av);
	} else if (!strncmp(*av, "flush", strlen(*av))) {
		table_flush(ac, av);
	} else if (!strncmp(*av, "list", strlen(*av))) {
		table_list(ac, av);
	} else if (!strncmp(*av, "show", strlen(*av))) {
		table_show(ac, av);
	} else if (!strncmp(*av, "type", strlen(*av))) {
		table_create(ac, av);
	} else if (!strncmp(*av, "delete", strlen(*av))) {
		table_delete(ac, av);
	} else if (!strncmp(*av, "test", strlen(*av))) {
		table_test(ac,av);
	} else if (!strncmp(*av, "name", strlen(*av))) {
		table_rename(ac, av);
	} else {
		errx(EX_USAGE, "bad ipfw table command `%s'", *av);
	}
}
Exemplo n.º 3
0
DIRECT_FN STATIC int gnix_av_remove(struct fid_av *av, fi_addr_t *fi_addr,
				    size_t count, uint64_t flags)
{
	struct gnix_fid_av *int_av = NULL;
	int ret = FI_SUCCESS;

	GNIX_TRACE(FI_LOG_AV, "\n");

	if (!av) {
		ret = -FI_EINVAL;
		goto err;
	}

	int_av = container_of(av, struct gnix_fid_av, av_fid);

	if (!int_av) {
		ret = -FI_EINVAL;
		goto err;
	}

	switch (int_av->type) {
	case FI_AV_TABLE:
		ret = table_remove(int_av, fi_addr, count, flags);
		break;
	case FI_AV_MAP:
		ret = map_remove(int_av, fi_addr, count, flags);
		break;
	default:
		ret = -FI_EINVAL;
		break;
	}

err:
	return ret;
}
Exemplo n.º 4
0
int test_remove( void ) {
	ASSERT_TRUE(table_put(&test_table, L"test2", value, NULL));
	ASSERT_TRUE(table_has(&test_table, L"test2"));

	table_remove(&test_table, L"test2", NULL);
	ASSERT_FALSE(table_has(&test_table, L"test2"));
	return 0;
}
Exemplo n.º 5
0
void test_hash(int prime, int table_size, int elems_count) {
  struct HashTableParams params = GET_HASH_PARAMS(&prime, hash_func, 0, int);
  struct HashTable *table = allocate_table(table_size, params);
  for (int i = 0; i != elems_count; ++i) {
    for (int j = 0; j != i; ++j) {
      int value = j * j;
      assert(table_has(table, &value));
      assert(table_insert(table, &value) == 1);
    }

    for (int j = i; j != elems_count; ++j) {
      int value = j * j;
      assert(!table_has(table, &value));
      assert(!table_remove(table, &value));
    }

    int value = i * i;
    assert(!table_insert(table, &value));
  }

  for (int i = 0; i != elems_count; ++i) {
    for (int j = i; j != elems_count; ++j) {
      int value = j * j;
      assert(table_has(table, &value));
    }

    int value = i * i;
    assert(table_remove(table, &value));
    assert(!table_remove(table, &value));

    for (int j = 0; j != i; ++j) {
      int value = j * j;
      assert(!table_has(table, &value));
    }
  }

  deallocate_table(table);
}
Exemplo n.º 6
0
Arquivo: main.c Projeto: bq/qeo-core
void intt_test (void)
{
	int_table	it;
	unsigned	i, j;

	TABLE_INIT (it);
	for (j = 0; j < 10; j++) {
		i = table_add (&it);
		assert (i != 0);
		TABLE_ITEM (it, i) = j + 5;
		printf ("Add: it[%u]=%d\r\n", i, TABLE_ITEM (it, i));
	}
	int_table_dump (&it);
	table_remove (&it, 2);
	printf ("Remove: it[%u]\r\n", 2);
	table_remove (&it, 4);
	printf ("Remove: it[%u]\r\n", 4);
	int_table_dump (&it);

	for (j = 2; j < 12; j++) {
		i = table_add (&it);
		assert (i != 0);
		TABLE_ITEM (it, i) = j;
		printf ("Add: it[%u]=%d\r\n", i, TABLE_ITEM (it, i));
	}
	int_table_dump (&it);
	TABLE_REQUIRE (it, 2, ~0);
	table_reset (&it);
	int_table_dump (&it);
	for (j = 0; j < 5; j++) {
		i = table_add (&it);
		assert (i != 0);
		TABLE_ITEM (it, i) = j + 5;
		printf ("Add: it[%u]=%d\r\n", i, TABLE_ITEM (it, i));
	}
	int_table_dump (&it);
}
Exemplo n.º 7
0
/* FIXME */
void u_command(client c) {
	dstr pkey, skey;
	dlist_t dlist;

	if (dstr_length(c->argv[0]) == 1) {
		add_reply_error(c, "index can't be empty\r\n");
		return;
	}
	pkey = dstr_new(c->argv[0] + 1);
	skey = dstr_new(pkey);
	if (c->argc > 1) {
		int i;

		for (i = 1; i < c->argc; ++i) {
			skey = dstr_cat(skey, ",");
			skey = dstr_cat(skey, c->argv[i]);
		}
	}
	table_rwlock_wrlock(subscribers);
	if ((dlist = table_get_value(subscribers, pkey))) {
		struct kvd *kvd;

		if (NEW(kvd)) {
			dlist_node_t node, node2;

			kvd->key = skey;
			if ((node = dlist_find(dlist, kvd))) {
				FREE(kvd);
				kvd = (struct kvd *)dlist_node_value(node);
				if ((node2 = dlist_find(kvd->u.dlist, c)))
					dlist_remove(kvd->u.dlist, node2);
				if (dlist_length(kvd->u.dlist) == 0) {
					dlist_remove(dlist, node);
					kdfree(kvd);
				}
				if (dlist_length(dlist) == 0) {
					table_remove(subscribers, pkey);
					dlist_free(&dlist);
				}
			} else
				FREE(kvd);
		} else
			add_reply_error(c, "error allocating memory for kvd");
	}
	table_rwlock_unlock(subscribers);
	dstr_free(skey);
	dstr_free(pkey);
	add_reply_string(c, "\r\n", 2);
}
Exemplo n.º 8
0
/* FIXME */
void uall_command(client c) {
	dstr res = get_indices();
	dstr *fields = NULL;
	int nfield = 0, i;

	RTRIM(res);
	fields = dstr_split_len(res, dstr_length(res), ",", 1, &nfield);
	for (i = 1; i < nfield; ++i) {
		dstr pkey = dstr_new(fields[i]);
		dstr skey = dstr_new(pkey);
		dlist_t dlist;

		table_rwlock_wrlock(subscribers);
		if ((dlist = table_get_value(subscribers, pkey))) {
			struct kvd *kvd;

			if (NEW(kvd)) {
				dlist_node_t node, node2;

				kvd->key = skey;
				if ((node = dlist_find(dlist, kvd))) {
					FREE(kvd);
					kvd = (struct kvd *)dlist_node_value(node);
					if ((node2 = dlist_find(kvd->u.dlist, c)))
						dlist_remove(kvd->u.dlist, node2);
					if (dlist_length(kvd->u.dlist) == 0) {
						dlist_remove(dlist, node);
						kdfree(kvd);
					}
					if (dlist_length(dlist) == 0) {
						table_remove(subscribers, pkey);
						dlist_free(&dlist);
					}
				} else
					FREE(kvd);
			} else
				add_reply_error(c, "error allocating memory for kvd");
		}
		table_rwlock_unlock(subscribers);
		dstr_free(skey);
		dstr_free(pkey);
	}
	add_reply_string(c, "\r\n", 2);
	dstr_free(res);
}
Exemplo n.º 9
0
void test_2()
{
  //generate_keys(30, 2);
  int i;
  enum { nNode = 50 };
  int keys[nNode] = {
    0x38, 0x85, 0x37, 0x55, 0x43,
    0x86, 0x78, 0x23, 0x62, 0x57,
    0x24, 0x02, 0x17, 0x34, 0x96,
    0x22, 0x07, 0x89, 0x91, 0x12,
    0x61, 0x05, 0x36, 0x09, 0x41,
    0x00, 0x31, 0x88, 0x94, 0x04,
    0x18, 0x97, 0x68, 0x35, 0x83,
    0x53, 0x93, 0x64, 0x65, 0x03,
    0x58, 0x60, 0x52, 0x15, 0x30,
    0x06, 0x25, 0x32, 0x39, 0x63
  };
  queue q(nNode);
  element* pNode = NULL;
  element* pRoot = NULL;
  //init
  pRoot = element_crt(keys[0]);
  q.push(pRoot);
  //generate data
  for (i = 1; i < nNode;) {
    //add node
    pNode = element_crt(keys[i]);
    q.push(pNode);
    pRoot = table_insert(pRoot, pNode);
    i++;
  }
  //print
  int count = table_printf(pRoot);
  printf("  count %d\n", count);
  //clean
  for (pNode = (element*)q.pop(); pNode != NULL; pNode = (element*)q.pop()) {
    pRoot = table_remove(pRoot, pNode);
    count = table_printf(pRoot);
    printf("  count %d\n", count);
    element_del(pNode);
  }
}
Exemplo n.º 10
0
// Syfte:        Funktionen tar bort tabellen och frigor minne.
// Inparametrar: Pekare till en tabell.
// Returnerar:   Ingenting.
void table_free(Table *table) {
    ArrayTable *t = (ArrayTable*)table;
    TableElement *i = calloc(1,sizeof(TableElement));
    int position;

    // Loopar genom hela arrayen for att ta bort minne.
    // Avslutas nar vi natt slutet, dvs NULL.
    // Tar bort minnesallokering for nycklar, keys, och
    // minnesallokering for varden, value.
    for (position=0;array_hasValue(t->values,position);position++) {
        i=array_inspectValue(t->values,position);
        if(t->keyFree!=NULL)
            t->keyFree(i->key);
        if(t->valueFree!=NULL)
            t->valueFree(i->value);
        table_remove(t,i->key);
    }
    array_free(t->values);
    // Frigor slutligen allokerat minne for tabellen.
    free(t);
}
Exemplo n.º 11
0
//-----------------------------
void test_1()
{
  element arr[] = {
    { 0x100 },
    { 0x200 },
    { 0x300 },
    { 0x300 },
    { 0x400 },
  };
  element* pRoot = &arr[0];
  for (int i = 1; i < (sizeof(arr) / sizeof(arr[0])); i++) {
    pRoot = table_insert(pRoot, &arr[i]);
    printf("insert %d\n", i);
    table_printf(pRoot);
  }

  for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
    pRoot = table_remove(pRoot, &arr[i]);
    printf("remove %d\n", i);
    table_printf(pRoot);
  }
}
Exemplo n.º 12
0
int
main ()
{
    table_t* tablePtr;
    long hash[] = {3, 1, 4, 1, 5, 9, 2, 6, 8, 7, -1};
    long i;

    bool_t status = memory_init(1, 4, 2);
    assert(status);

    puts("Starting...");

    tablePtr = table_alloc(8, NULL);

    for (i = 0; hash[i] >= 0; i++ ) {
        bool_t status = table_insert(tablePtr,
                                     (ulong_t)hash[i],
                                     (void*)&hash[i])
        assert(status);
        printTable(tablePtr);
        puts("");
    }

    for (i = 0; hash[i] >= 0; i++ ) {
        bool_t status = table_remove(tablePtr,
                                     (ulong_t)hash[i],
                                     (void*)&hash[i])
        assert(status);
        printTable(tablePtr);
        puts("");
    }

    table_free(tablePtr);

    puts("Done.");

    return 0;
}
Exemplo n.º 13
0
int
main(int argc, char *argv[])
{
	FILE *fp;
	char buffer[512];
	size_t i, j, r;
	unsigned int d = 0;
	uint64_t s, e, a, ri, si, ai, sr, rg, sg, ag, sd, ng;
	char **t;
	struct ck_ht_stat st;

	r = 20;
	s = 8;
	srand(time(NULL));

	if (argc < 2) {
		ck_error("Usage: ck_ht <dictionary> [<repetitions> <initial size>]\n");
	}

	if (argc >= 3)
		r = atoi(argv[2]);

	if (argc >= 4)
		s = (uint64_t)atoi(argv[3]);

	keys = malloc(sizeof(char *) * keys_capacity);
	assert(keys != NULL);

	fp = fopen(argv[1], "r");
	assert(fp != NULL);

	while (fgets(buffer, sizeof(buffer), fp) != NULL) {
		buffer[strlen(buffer) - 1] = '\0';
		keys[keys_length++] = strdup(buffer);
		assert(keys[keys_length - 1] != NULL);

		if (keys_length == keys_capacity) {
			t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
			assert(t != NULL);
			keys = t;
		}
	}

	t = realloc(keys, sizeof(char *) * keys_length);
	assert(t != NULL);
	keys = t;

	table_init();

	for (i = 0; i < keys_length; i++)
		d += table_insert(keys[i]) == false;
	ck_ht_stat(&ht, &st);

	fprintf(stderr, "# %zu entries stored, %u duplicates, %" PRIu64 " probe.\n",
	    table_count(), d, st.probe_maximum);

	fprintf(stderr, "#    reverse_insertion serial_insertion random_insertion serial_replace reverse_get serial_get random_get serial_remove negative_get\n\n");

	a = 0;
	for (j = 0; j < r; j++) {
		if (table_reset() == false) {
			ck_error("ERROR: Failed to reset hash table.\n");
		}

		s = rdtsc();
		for (i = keys_length; i > 0; i--)
			d += table_insert(keys[i - 1]) == false;
		e = rdtsc();
		a += e - s;
	}
	ri = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		if (table_reset() == false) {
			ck_error("ERROR: Failed to reset hash table.\n");
		}

		s = rdtsc();
		for (i = 0; i < keys_length; i++)
			d += table_insert(keys[i]) == false;
		e = rdtsc();
		a += e - s;
	}
	si = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		keys_shuffle(keys);

		if (table_reset() == false) {
			ck_error("ERROR: Failed to reset hash table.\n");
		}

		s = rdtsc();
		for (i = 0; i < keys_length; i++)
			d += table_insert(keys[i]) == false;
		e = rdtsc();
		a += e - s;
	}
	ai = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		s = rdtsc();
		for (i = 0; i < keys_length; i++)
			table_replace(keys[i]);
		e = rdtsc();
		a += e - s;
	}
	sr = a / (r * keys_length);

	table_reset();
	for (i = 0; i < keys_length; i++)
		table_insert(keys[i]);

	a = 0;
	for (j = 0; j < r; j++) {
		s = rdtsc();
		for (i = keys_length; i > 0; i--) {
			if (table_get(keys[i - 1]) == NULL) {
				ck_error("ERROR: Unexpected NULL value.\n");
			}
		}
		e = rdtsc();
		a += e - s;
	}
	rg = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		s = rdtsc();
		for (i = 0; i < keys_length; i++) {
			if (table_get(keys[i]) == NULL) {
				ck_error("ERROR: Unexpected NULL value.\n");
			}
		}
		e = rdtsc();
		a += e - s;
	}
	sg = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		keys_shuffle(keys);

		s = rdtsc();
		for (i = 0; i < keys_length; i++) {
			if (table_get(keys[i]) == NULL) {
				ck_error("ERROR: Unexpected NULL value.\n");
			}
		}
		e = rdtsc();
		a += e - s;
	}
	ag = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		s = rdtsc();
		for (i = 0; i < keys_length; i++)
			table_remove(keys[i]);
		e = rdtsc();
		a += e - s;

		for (i = 0; i < keys_length; i++)
			table_insert(keys[i]);
	}
	sd = a / (r * keys_length);

	a = 0;
	for (j = 0; j < r; j++) {
		s = rdtsc();
		for (i = 0; i < keys_length; i++) {
			table_get("\x50\x03\x04\x05\x06\x10");
		}
		e = rdtsc();
		a += e - s;
	}
	ng = a / (r * keys_length);

	printf("%zu "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 " "
	    "%" PRIu64 "\n",
	    keys_length, ri, si, ai, sr, rg, sg, ag, sd, ng);

	return 0;
}
Exemplo n.º 14
0
int main() {
    table_t tab = table_new(1024, cmp, dictGenHashFunction);

    table_put(tab, "append", "cmd_append");
    table_put(tab, "bitcount", "cmd_bitcount");
    table_put(tab, "brpop", "cmd_brpop");
    table_put(tab, "brpoplpush", "cmd_brpoplpush");
    table_put(tab, "decr", "cmd_decr");
    table_put(tab, "decrby", "cmd_decrby");
    table_put(tab, "del", "cmd_del");
    table_put(tab, "exists", "cmd_exists");
    table_put(tab, "get", "cmd_get");
    table_put(tab, "getbit", "cmd_getbit");
    table_put(tab, "getrange", "cmd_getrange");
    table_put(tab, "incr", "cmd_incr");
    table_put(tab, "incrby", "cmd_incrby");
    table_put(tab, "keys", "cmd_keys");
    table_put(tab, "lindex", "cmd_lindex");
    table_put(tab, "linsert", "cmd_linsert");
    table_put(tab, "llen", "cmd_llen");
    table_put(tab, "lpop", "cmd_lpop");
    table_put(tab, "lpush", "cmd_lpush");
    table_put(tab, "lpushx", "cmd_lpushx");
    table_put(tab, "lrange", "cmd_lrange");
    table_put(tab, "lrem", "cmd_lrem");
    table_put(tab, "lset", "cmd_lset");
    table_put(tab, "ltrim", "cmd_ltrim");
    table_put(tab, "mget", "cmd_mget");
    table_put(tab, "msetnx", "cmd_msetnx");
    table_put(tab, "randomkey", "cmd_randomkey");
    table_put(tab, "rename", "cmd_rename");
    table_put(tab, "rpop", "cmd_rpop");
    table_put(tab, "rpoplpush", "cmd_rpoplpush");
    table_put(tab, "rpush", "cmd_rpush");
    table_put(tab, "rpushx", "cmd_rpushx");
    table_put(tab, "set", "cmd_set");
    table_put(tab, "setbit", "cmd_setbit");
    table_put(tab, "setrange", "cmd_setrange");
    table_put(tab, "strlen", "cmd_strlen");
    table_put(tab, "type", "cmd_type");

    table_map(tab, apply);
    printf("len = %d\n", table_length(tab));

    char key[32];
    scanf("%s", key);
    printf("%s\n", (char *)table_get(tab, key));

    printf("remove set\n");
    table_remove(tab, "set");

    table_map(tab, apply);
    printf("len = %d\n", table_length(tab));

    scanf("%s", key);
    printf("%s\n", (char *)table_get(tab, key));

    table_free(&tab);

    return 0;
}
Exemplo n.º 15
0
void test_table(void)
{
    int i;
    void* T = table_create(100, NULL, NULL);
    fprintf(stdout, "call function : %s\n", __func__);
    table_object(T);

    fprintf(stdout, "\ntest function - table_insert ===>\n");
    {
        srand((unsigned int)time(0));
        for (i = 0; i < 5; ++i)
        {
            double* d = (double*)malloc(sizeof(double));
            *d = (i + 1) * rand() % 5000 * 0.123;
            fprintf(stdout, "\tinsert {key=>%d,value=>{object=>0x%p,value=>%.3f}}\n", i, d, *d);
            table_insert(T, (const void*)i, d);
        }
        table_for_each(T, table_key_value_show, NULL);
        table_for_each(T, table_key_value_destroy, NULL);
        table_object(T);
        table_clear(T);
    }
    table_object(T);

    fprintf(stdout, "\ntest function - table_remove ===>\n");
    {
        srand((unsigned int)time(0));
        for (i = 0; i < 5; ++i)
        {
            double* d = (double*)malloc(sizeof(double));
            *d = (i + 1) * rand() % 5000 * 0.123;
            fprintf(stdout, "\tinsert {key=>%d,value=>{object=>0x%p,value=>%.3f}}\n", i, d, *d);
            table_insert(T, (const void*)i, d);
        }
        table_for_each(T, table_key_value_show, NULL);
        table_for_each(T, table_key_value_destroy, NULL);
        table_object(T);
        for (i = 0; i < 5; ++i)
            table_remove(T, (const void*)i);
        table_object(T);
        table_clear(T);
    }
    table_object(T);

    fprintf(stdout, "\ntest function - table_get ===>\n");
    {
        double* d;
        srand((unsigned int)time(0));
        for (i = 0; i < 5; ++i)
        {
            d = (double*)malloc(sizeof(double));
            *d = (i + 1) * rand() % 5000 * 0.123;
            fprintf(stdout, "\tinsert {key=>%d,value=>{object=>0x%p,value=>%.3f}}\n", i, d, *d);
            table_insert(T, (const void*)i, d);
        }
        table_object(T);

        d = table_get(T, (const void*)3);
        if (NULL != d)
            fprintf(stdout, "\t{key=>3, value=>0x%p} => %.3f\n", d, *d);

        table_for_each(T, table_key_value_show, NULL);
        table_for_each(T, table_key_value_destroy, NULL);
        table_clear(T);
    }
    table_object(T);

    fprintf(stdout, "\ntest function - table_release ===>\n");
    table_release(&T);
    table_object(T);
}
Exemplo n.º 16
0
/* FIXME */
static void *q_thread(void *data) {
	struct crss *crss = (struct crss *)data;
	char buf[64];
	dstr rid, res = NULL;
	db_iterator_t *it;
	const char *key, *value;
	size_t klen, vlen;

	snprintf(buf, sizeof buf, "%p,", crss->c);
	rid = dstr_new(buf);
	rid = dstr_cat(rid, crss->rid);
	it = db_iterator_create(db, db_ro);
	db_iterator_seek(it, crss->start, dstr_length(crss->start));
	/* seek failed */
	if (!db_iterator_valid(it)) {
		res = dstr_new(crss->rid);
		res = dstr_cat(res, ",1\r\n\r\n");
		pthread_spin_lock(&crss->c->lock);
		if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1)
			xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno));
		pthread_spin_unlock(&crss->c->lock);
		goto end;
	}
	key = db_iterator_key(it, &klen);
	while (memcmp(key, crss->stop, dstr_length(crss->stop)) <= 0) {
		if (crss->cancel)
			break;
		if (!strcmp(crss->match, "") || strstr(key, crss->match)) {
			value = db_iterator_value(it, &vlen);
			res = dstr_new(crss->rid);
			res = dstr_cat(res, ",0,");
			res = dstr_cat_len(res, key, klen);
			res = dstr_cat(res, ",");
			res = dstr_cat_len(res, value, vlen);
			res = dstr_cat(res, "\r\n");
			pthread_spin_lock(&crss->c->lock);
			if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1) {
				xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s",
					crss->c, strerror(errno));
				pthread_spin_unlock(&crss->c->lock);
				goto end;
			}
			pthread_spin_unlock(&crss->c->lock);
			dstr_free(res);
		}
		db_iterator_next(it);
		if (!db_iterator_valid(it) || crss->cancel)
			break;
		key = db_iterator_key(it, &klen);
	}
	res = dstr_new(crss->rid);
	res = dstr_cat(res, ",1\r\n\r\n");
	pthread_spin_lock(&crss->c->lock);
	if (net_try_write(crss->c->fd, res, dstr_length(res), 10, NET_NONBLOCK) == -1)
		xcb_log(XCB_LOG_WARNING, "Writing to client '%p': %s", crss->c, strerror(errno));
	pthread_spin_unlock(&crss->c->lock);

end:
	db_iterator_destroy(&it);
	dstr_free(res);
	table_lock(rids);
	table_remove(rids, rid);
	table_unlock(rids);
	dstr_free(rid);
	client_decr(crss->c);
	dstr_free(crss->rid);
	dstr_free(crss->match);
	dstr_free(crss->start);
	dstr_free(crss->stop);
	FREE(crss);
	return NULL;
}