static void
cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpatialIndexQueryFunc func, void *data)
{
	cpFloat dim = hash->celldim;
	int idx = hash_func(floor_int(point.x/dim), floor_int(point.y/dim), hash->numcells);  // Fix by ShiftZ
	
	query_helper(hash, &hash->table[idx], &point, func, data);
	hash->stamp++;
}
static void
test_query (TestInfo      *test_info,
            gconstpointer  context)
{
	GError *error = NULL;
	gchar *data_filename;
	gchar *query_filename;
	gchar *results_filename;
	gchar *prefix, *data_prefix, *test_prefix;

	prefix = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-data", NULL);
	data_prefix = g_build_filename (prefix, test_info->data, NULL);
	test_prefix = g_build_filename (prefix, test_info->test_name, NULL);
	g_free (prefix);

	tracker_db_journal_set_rotating (FALSE, G_MAXSIZE, NULL);

	/* initialization */
	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
	                           NULL,
	                           NULL,
	                           FALSE,
	                           FALSE,
	                           100,
	                           100,
	                           NULL,
	                           NULL,
	                           NULL,
	                           NULL);

	/* load data set */
	data_filename = g_strconcat (data_prefix, ".ttl", NULL);
	tracker_turtle_reader_load (data_filename, &error);
	g_assert_no_error (error);

	query_filename = g_strconcat (test_prefix, ".rq", NULL);
	results_filename = g_strconcat (test_prefix, ".out", NULL);

	g_free (data_prefix);
	g_free (test_prefix);

	query_helper (query_filename, results_filename);

	/* cleanup */

	g_free (data_filename);
	g_free (query_filename);
	g_free (results_filename);

	tracker_data_manager_shutdown ();
}
// Hashset iterator func used with cpSpaceHashQueryRehash().
static void
queryRehash_helper(cpHandle *hand, queryRehashContext *context)
{
	cpSpaceHash *hash = context->hash;
	cpSpatialIndexQueryFunc func = context->func;
	void *data = context->data;

	cpFloat dim = hash->celldim;
	int n = hash->numcells;

	void *obj = hand->obj;
	cpBB bb = hash->spatialIndex.bbfunc(obj);

	int l = floor_int(bb.l/dim);
	int r = floor_int(bb.r/dim);
	int b = floor_int(bb.b/dim);
	int t = floor_int(bb.t/dim);
	
	cpSpaceHashBin **table = hash->table;

	for(int i=l; i<=r; i++){
		for(int j=b; j<=t; j++){
			int idx = hash_func(i,j,n);
			cpSpaceHashBin *bin = table[idx];
			
			if(containsHandle(bin, hand)) continue;
			
			cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()
			query_helper(hash, &bin, obj, func, data);
			
			cpSpaceHashBin *newBin = getEmptyBin(hash);
			newBin->handle = hand;
			newBin->next = bin;
			table[idx] = newBin;
		}
	}
	
	// Increment the stamp for each object hashed.
	hash->stamp++;
}
static void
cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
{
	// Get the dimensions in cell coordinates.
	cpFloat dim = hash->celldim;
	int l = floor_int(bb.l/dim);  // Fix by ShiftZ
	int r = floor_int(bb.r/dim);
	int b = floor_int(bb.b/dim);
	int t = floor_int(bb.t/dim);
	
	int n = hash->numcells;
	cpSpaceHashBin **table = hash->table;
	
	// Iterate over the cells and query them.
	for(int i=l; i<=r; i++){
		for(int j=b; j<=t; j++){
			query_helper(hash, &table[hash_func(i,j,n)], obj, func, data);
		}
	}
	
	hash->stamp++;
}
static void
test_ontology_change (void)
{
    gchar *ontology_file;
    GFile *file2;
    gchar *prefix, *build_prefix;
    gchar *ontology_dir;
    guint i;
    GError *error = NULL;
    gchar *test_schemas[5] = { NULL, NULL, NULL, NULL, NULL };

    delete_db (TRUE);

    prefix = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-data", NULL);
    build_prefix = g_build_path (G_DIR_SEPARATOR_S, TOP_BUILDDIR, "tests", "libtracker-data", NULL);

    test_schemas[0] = g_build_path (G_DIR_SEPARATOR_S, prefix, "ontologies", "20-dc", NULL);
    test_schemas[1] = g_build_path (G_DIR_SEPARATOR_S, prefix, "ontologies", "31-nao", NULL);
    test_schemas[2] = g_build_path (G_DIR_SEPARATOR_S, prefix, "ontologies", "90-tracker", NULL);
    test_schemas[3] = g_build_path (G_DIR_SEPARATOR_S, build_prefix, "change", "ontologies", "99-example", NULL);

    ontology_file = g_build_path (G_DIR_SEPARATOR_S, build_prefix, "change", "ontologies", "99-example.ontology", NULL);

    file2 = g_file_new_for_path (ontology_file);

    g_file_delete (file2, NULL, NULL);

    ontology_dir = g_build_path (G_DIR_SEPARATOR_S, build_prefix, "change", "ontologies", NULL);
    g_mkdir_with_parents (ontology_dir, 0777);
    g_free (ontology_dir);

    for (i = 0; changes[i].ontology; i++) {
        GFile *file1;
        gchar *queries = NULL;
        gchar *source = g_build_path (G_DIR_SEPARATOR_S, prefix, "change", "source", changes[i].ontology, NULL);
        gchar *update = g_build_path (G_DIR_SEPARATOR_S, prefix, "change", "updates", changes[i].update, NULL);
        gchar *from, *to;

        file1 = g_file_new_for_path (source);

        from = g_file_get_path (file1);
        to = g_file_get_path (file2);
        g_debug ("copy %s to %s", from, to);
        g_free (from);
        g_free (to);

        g_file_copy (file1, file2, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);

        g_assert_no_error (error);
        g_chmod (ontology_file, 0666);

        tracker_data_manager_init (0, (const gchar **) test_schemas,
                                   NULL, FALSE, FALSE,
                                   100, 100, NULL, NULL, NULL, &error);

        g_assert_no_error (error);

        if (g_file_get_contents (update, &queries, NULL, NULL)) {
            gchar *query = strtok (queries, "\n");
            while (query) {

                tracker_data_update_sparql (query, &error);

                g_assert_no_error (error);
                query = strtok (NULL, "\n");
            }
            g_free (queries);
        }

        g_free (update);
        g_free (source);
        g_object_unref (file1);


        if (changes[i].test_name) {
            gchar *query_filename;
            gchar *results_filename;
            gchar *test_prefix;

            test_prefix = g_build_filename (prefix, changes[i].test_name, NULL);
            query_filename = g_strconcat (test_prefix, ".rq", NULL);
            results_filename = g_strconcat (test_prefix, ".out", NULL);

            query_helper (query_filename, results_filename);

            g_free (test_prefix);
            g_free (query_filename);
            g_free (results_filename);
        }

        tracker_data_manager_shutdown ();
    }

    delete_db (FALSE);

    tracker_data_manager_init (0, (const gchar **) test_schemas,
                               NULL, TRUE, FALSE,
                               100, 100, NULL, NULL, NULL, &error);

    g_assert_no_error (error);

    for (i = 0; change_tests[i].test_name != NULL; i++) {
        gchar *query_filename;
        gchar *results_filename;
        gchar *test_prefix;

        test_prefix = g_build_filename (prefix, change_tests[i].test_name, NULL);
        query_filename = g_strconcat (test_prefix, ".rq", NULL);
        results_filename = g_strconcat (test_prefix, ".out", NULL);

        query_helper (query_filename, results_filename);

        g_free (test_prefix);
        g_free (query_filename);
        g_free (results_filename);
    }

    tracker_data_manager_shutdown ();

    g_file_delete (file2, NULL, NULL);

    g_object_unref (file2);
    g_free (test_schemas[0]);
    g_free (test_schemas[1]);
    g_free (test_schemas[2]);
    g_free (build_prefix);
    g_free (prefix);
}