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); }
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; }