static void
mem_test (void)
{
	EIntervalTree *tree;
	time_t start = 10, end = 50;
	ECalComponent *comp = create_test_component (start, end), *clone_comp;
	const gchar *uid;
	gchar *rid;

	tree = e_intervaltree_new ();

	g_assert (((GObject *) comp)->ref_count == 1);
	e_intervaltree_insert (tree, start, end, comp);
	g_assert (((GObject *) comp)->ref_count == 2);

	e_cal_component_get_uid (comp, &uid);
	rid = e_cal_component_get_recurid_as_string (comp);
	e_intervaltree_remove (tree, uid, rid);
	g_free (rid);
	g_assert (((GObject *) comp)->ref_count == 1);

	e_intervaltree_insert (tree, start, end, comp);
	g_assert (((GObject *) comp)->ref_count == 2);

	clone_comp = e_cal_component_clone (comp);
	e_intervaltree_insert (tree, start, end, clone_comp);

	g_assert (((GObject *) comp)->ref_count == 1);
	g_assert (((GObject *) clone_comp)->ref_count == 2);

	e_intervaltree_destroy (tree);

	g_assert (((GObject *) comp)->ref_count == 1);
	g_assert (((GObject *) clone_comp)->ref_count == 1);

	g_object_unref (comp);
	g_object_unref (clone_comp);
}
/**
 * e_intervaltree_insert:
 * @tree: interval tree
 * @start: start of the interval
 * @end: end of the interval
 * @comp: Component
 * 
 * Since: 2.32
 **/
gboolean
e_intervaltree_insert (EIntervalTree *tree,
                       time_t start,
                       time_t end,
                       ECalComponent *comp)
{
	EIntervalTreePrivate *priv;
	EIntervalNode *y;
	EIntervalNode *x;
	EIntervalNode *newNode;
	const gchar *uid;
	gchar *rid;

	g_return_val_if_fail (tree != NULL, FALSE);
	g_return_val_if_fail (comp != NULL, FALSE);
	g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);

	priv = tree->priv;

	g_static_rec_mutex_lock (&priv->mutex);

	e_cal_component_get_uid (comp, &uid);
	rid = e_cal_component_get_recurid_as_string (comp);
	e_intervaltree_remove (tree, uid, rid);

	x = g_new (EIntervalNode, 1);
	x->min = x->start = start;
	x->max = x->end = end;
	x->comp = g_object_ref (comp);

	binary_tree_insert (tree, x);
	newNode = x;
	x->red = TRUE;

	fixup_min_max_fields (tree, x->parent);
	while (x->parent->red)
	{ /* use sentinel instead of checking for root */
		if (x->parent == x->parent->parent->left)
		{
			y = x->parent->parent->right;

			if (y->red)
			{
				x->parent->red = FALSE;
				y->red = FALSE;
				x->parent->parent->red = TRUE;
				x = x->parent->parent;
			}
			else
			{
				if (x == x->parent->right)
				{
					x = x ->parent;
					left_rotate (tree, x);
				}

				x->parent->red = FALSE;
				x->parent->parent->red = TRUE;
				right_rotate (tree, x->parent->parent);
			}
		}
		else
		{ /* case for x->parent == x->parent->parent->right */
			y = x->parent->parent->left;

			if (y->red)
			{
				x->parent->red = FALSE;
				y->red = FALSE;
				x->parent->parent->red = TRUE;
				x = x->parent->parent;
			}
			else
			{
				if (x == x->parent->left)
				{
					x = x->parent;
					right_rotate (tree, x);
				}

				x->parent->red = FALSE;
				x->parent->parent->red = TRUE;
				left_rotate (tree, x->parent->parent);
			}
		}
	}

	priv->root->left->red = FALSE;
	g_hash_table_insert (priv->id_node_hash, component_key (uid, rid), newNode);
	g_free (rid);

	g_static_rec_mutex_unlock (&priv->mutex);

	return TRUE;
}
static void
random_test (void)
{
	/*
	 * outline:
	 * 1. create new tree and empty list of intervals
	 * 2. insert some intervals into tree and list
	 * 3. do various searches, compare results of both structures
	 * 4. delete some intervals 
	 * 5. do various searches, compare results of both structures
	 * 6. free memory
	 */
	gint i, start, end;
	EInterval *interval = NULL;
	EIntervalTree *tree;
	GList *l1, *l2, *next;
	gint num_deleted = 0;

	tree = e_intervaltree_new ();

	for (i = 0; i < NUM_INTERVALS_CLOSED; i++)
	{
		ECalComponent *comp;
		start = g_rand_int_range (myrand, 0, 1000);
		end = g_rand_int_range (myrand, start, 2000);
		comp = create_test_component (start, end);
		if (!comp)
		{
			g_message (G_STRLOC ": error");
			exit (-1);
		}

		interval = g_new (EInterval, 1);
		interval->start = start;
		interval->end = end;
		interval->comp = comp;

		list = g_list_insert (list, interval, -1);

		e_intervaltree_insert (tree, start, end, comp);
	}

	/* insert open ended intervals */
	for (i = 0; i < NUM_INTERVALS_OPEN; i++)
	{
		ECalComponent *comp;
		start = g_rand_int_range (myrand, 0, 1000);
		comp = create_test_component (start, end);
		if (!comp)
		{
			g_message (G_STRLOC ": error");
			exit (-1);
		}

		interval = g_new (EInterval, 1);
		interval->start = start;
		interval->end = _TIME_MAX;
		interval->comp = comp;
		list = g_list_insert (list, interval, -1);

		e_intervaltree_insert (tree, start, interval->end, comp);
		/* g_print ("%d - %d\n", start, interval->end); */
	}

	g_print ("Number of intervals inserted: %d\n", NUM_INTERVALS_CLOSED + NUM_INTERVALS_OPEN);

	for (i = 0; i < NUM_SEARCHES; i++)
	{
		start = g_rand_int_range (myrand, 0, 1000);
		end = g_rand_int_range (myrand, 2000, _TIME_MAX);

		/*
		   g_print ("Search for : %d - %d\n", start, end);
		   */

		l1 = e_intervaltree_search (tree, start, end);

		l2 = search_in_list (list, start, end);

		if (!compare_interval_lists (l2, l1))
		{
			e_intervaltree_dump (tree);
			g_message (G_STRLOC "Error");
			exit (-1);
		}

		/* g_print ("OK\n"); */
		g_list_foreach (l1, (GFunc)g_object_unref, NULL);
		g_list_foreach (l2, (GFunc)unref_comp, NULL);
		g_list_free (l1);
		g_list_free (l2);
	}

	/* open-ended intervals */
	for (i = 0; i < 20; i++)
	{
		start = g_rand_int_range (myrand, 0, 1000);
		end = _TIME_MAX;

		/*
		   g_print ("Search for : %d - %d\n", start, end);
		   */

		l1 = e_intervaltree_search (tree, start, end);

		l2 = search_in_list (list, start, end);

		if (!compare_interval_lists (l2, l1))
		{
			e_intervaltree_dump (tree);
			g_message (G_STRLOC "Error");
			exit (-1);
		}

		/* g_print ("OK\n"); */
		g_list_foreach (l1, (GFunc)g_object_unref, NULL);
		g_list_foreach (l2, (GFunc)unref_comp, NULL);
		g_list_free (l1);
		g_list_free (l2);
	}

	l1 = list;

	while (l1)
	{
		/* perhaps we will delete l1 */
		next = l1->next;

		if (g_rand_double (myrand) < pbality_delete)
		{
			ECalComponent *comp;
			const gchar *uid = NULL;
			gchar *rid;
			interval = (EInterval*) l1->data;
			comp = interval->comp;

			/* delete l1 */
			/*
			   g_print ("Deleting interval %d - %d\n", interval->start,
			   interval->end);
			   */

			rid = e_cal_component_get_recurid_as_string (comp);
			e_cal_component_get_uid (comp, &uid);
			if (!e_intervaltree_remove (tree, uid, rid))
			{
				g_free (rid);
				e_intervaltree_dump (tree);
				g_print ("Deleting interval %d - %d ERROR\n", interval->start,
					 interval->end);
				exit (-1);
			}

			g_free (rid);
			g_object_unref (interval->comp);
			g_free (l1->data);
			list = g_list_delete_link (list, l1);
			num_deleted++;
		}

		l1 = next;
	}

	g_print ("Number of intervals deleted: %d\n", num_deleted);

	for (i = 0; i < NUM_SEARCHES; i++)
	{
		start = g_rand_int_range (myrand, 0, 1000);
		end = g_rand_int_range (myrand, start, 2000);

		/*
		   g_print ("Search for : %d - %d\n", start, end);
		   */

		l1 = e_intervaltree_search (tree, start, end);

		/*
		   g_print ("Results from tree:\n");
		   print_nodes_list (l1);
		 */

		l2 = search_in_list (list, start, end);

		if (!compare_interval_lists (l2, l1))
		{
			g_print ("ERROR!\n\n");
			return;
		}

		g_list_foreach (l1, (GFunc)g_object_unref, NULL);
		g_list_foreach (l2, (GFunc)unref_comp, NULL);
		g_list_free (l1);
		g_list_free (l2);

		/* g_print ("OK\n"); */
	}

	e_intervaltree_destroy (tree);
	g_list_foreach (list, (GFunc)unref_comp, NULL);
	g_list_free (list);
}
Exemple #4
0
static gboolean
put_component_to_store (ECalBackendHttp *cb,
                        ECalComponent *comp)
{
	time_t time_start, time_end;
	ECalBackendHttpPrivate *priv;
	ECalComponent *cache_comp;
	const gchar *uid;
	gchar *rid;

	priv = cb->priv;

	e_cal_component_get_uid (comp, &uid);
	rid = e_cal_component_get_recurid_as_string (comp);
	cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid);
	g_free (rid);

	if (cache_comp) {
		gboolean changed = TRUE;
		struct icaltimetype stamp1, stamp2;

		stamp1 = icaltime_null_time ();
		stamp2 = icaltime_null_time ();

		e_cal_component_get_dtstamp (comp, &stamp1);
		e_cal_component_get_dtstamp (cache_comp, &stamp2);

		changed = (icaltime_is_null_time (stamp1) && !icaltime_is_null_time (stamp2)) ||
			  (!icaltime_is_null_time (stamp1) && icaltime_is_null_time (stamp2)) ||
			  (icaltime_compare (stamp1, stamp2) != 0);

		if (!changed) {
			struct icaltimetype *last_modified1 = NULL, *last_modified2 = NULL;

			e_cal_component_get_last_modified (comp, &last_modified1);
			e_cal_component_get_last_modified (cache_comp, &last_modified2);

			changed = (last_modified1 != NULL && last_modified2 == NULL) ||
				  (last_modified1 == NULL && last_modified2 != NULL) ||
				  (last_modified1 != NULL && last_modified2 != NULL && icaltime_compare (*last_modified1, *last_modified2) != 0);

			if (last_modified1)
				e_cal_component_free_icaltimetype (last_modified1);
			if (last_modified2)
				e_cal_component_free_icaltimetype (last_modified2);

			if (!changed) {
				gint *sequence1 = NULL, *sequence2 = NULL;

				e_cal_component_get_sequence (comp, &sequence1);
				e_cal_component_get_sequence (cache_comp, &sequence2);

				changed = (sequence1 != NULL && sequence2 == NULL) ||
					  (sequence1 == NULL && sequence2 != NULL) ||
					  (sequence1 != NULL && sequence2 != NULL && *sequence1 != *sequence2);

				if (sequence1)
					e_cal_component_free_sequence (sequence1);
				if (sequence2)
					e_cal_component_free_sequence (sequence2);
			}
		}

		g_object_unref (cache_comp);

		if (!changed)
			return FALSE;
	}

	e_cal_util_get_component_occur_times (
		comp, &time_start, &time_end,
		resolve_tzid, cb, icaltimezone_get_utc_timezone (),
		e_cal_backend_get_kind (E_CAL_BACKEND (cb)));

	e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);

	return TRUE;
}