X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsrvtarget.c;h=232da5a345d100aa33e136b1090e69a5570115f7;hb=2e5bd8cf47f9e1559ccc44823a2f321b8ff8c1ea;hp=2e3ee90523c702f205fa70aa43e0405dfac57471;hpb=a28215fa909ef315e596ebd0b41132730aef909d;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsrvtarget.c b/gio/gsrvtarget.c index 2e3ee90..232da5a 100644 --- a/gio/gsrvtarget.c +++ b/gio/gsrvtarget.c @@ -15,9 +15,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . */ #include "config.h" @@ -29,7 +27,6 @@ #include #include -#include "gioalias.h" /** * SECTION:gsrvtarget @@ -45,12 +42,12 @@ * then connect to whatever host was pointed to by that record. * * You can use g_resolver_lookup_service() or - * g_resolver_lookup_service_async() to find the #GSrvTargets + * g_resolver_lookup_service_async() to find the #GSrvTargets * for a given service. However, if you are simply planning to connect * to the remote service, you can use #GNetworkService's * #GSocketConnectable interface and not need to worry about * #GSrvTarget at all. - **/ + */ struct _GSrvTarget { gchar *hostname; @@ -66,21 +63,8 @@ struct _GSrvTarget { * A single target host/port that a network service is running on. */ -GType -g_srv_target_get_type (void) -{ - static volatile gsize type_volatile = 0; - - if (g_once_init_enter (&type_volatile)) - { - GType type = g_boxed_type_register_static ( - g_intern_static_string ("GSrvTarget"), - (GBoxedCopyFunc) g_srv_target_copy, - (GBoxedFreeFunc) g_srv_target_free); - g_once_init_leave (&type_volatile, type); - } - return type_volatile; -} +G_DEFINE_BOXED_TYPE (GSrvTarget, g_srv_target, + g_srv_target_copy, g_srv_target_free) /** * g_srv_target_new: @@ -91,10 +75,10 @@ g_srv_target_get_type (void) * * Creates a new #GSrvTarget with the given parameters. * - * You should not need to use this; normally #GSrvTargets are + * You should not need to use this; normally #GSrvTargets are * created by #GResolver. * - * Return value: a new #GSrvTarget. + * Returns: a new #GSrvTarget. * * Since: 2.22 */ @@ -120,7 +104,7 @@ g_srv_target_new (const gchar *hostname, * * Copies @target * - * Return value: a copy of @target + * Returns: a copy of @target * * Since: 2.22 */ @@ -155,7 +139,7 @@ g_srv_target_free (GSrvTarget *target) * check if it contains encoded Unicode segments, and use * g_hostname_to_unicode() to convert it if it does.) * - * Return value: @target's hostname + * Returns: @target's hostname * * Since: 2.22 */ @@ -171,7 +155,7 @@ g_srv_target_get_hostname (GSrvTarget *target) * * Gets @target's port * - * Return value: @target's port + * Returns: @target's port * * Since: 2.22 */ @@ -189,7 +173,7 @@ g_srv_target_get_port (GSrvTarget *target) * #GResolver already sorts the targets according to the algorithm in * RFC 2782. * - * Return value: @target's priority + * Returns: @target's priority * * Since: 2.22 */ @@ -207,7 +191,7 @@ g_srv_target_get_priority (GSrvTarget *target) * #GResolver already sorts the targets according to the algorithm in * RFC 2782. * - * Return value: @target's weight + * Returns: @target's weight * * Since: 2.22 */ @@ -217,7 +201,7 @@ g_srv_target_get_weight (GSrvTarget *target) return target->weight; } -gint +static gint compare_target (gconstpointer a, gconstpointer b) { GSrvTarget *ta = (GSrvTarget *)a; @@ -229,34 +213,28 @@ compare_target (gconstpointer a, gconstpointer b) * that all those with weight 0 are placed at the beginning of * the list" */ - if (ta->weight == 0) - return -1; - else if (tb->weight == 0) - return 1; - else - return g_random_int_range (-1, 1); + return ta->weight - tb->weight; } else return ta->priority - tb->priority; } /** - * g_srv_target_list_sort: + * g_srv_target_list_sort: (skip) * @targets: a #GList of #GSrvTarget * * Sorts @targets in place according to the algorithm in RFC 2782. * - * Return value: the head of the sorted list. + * Returns: (transfer full): the head of the sorted list. * * Since: 2.22 - */ + */ GList * g_srv_target_list_sort (GList *targets) { - gint sum, val, priority, weight; - GList *first, *last, *n; + gint sum, num, val, priority, weight; + GList *t, *out, *tail; GSrvTarget *target; - gpointer tmp; if (!targets) return NULL; @@ -275,63 +253,60 @@ g_srv_target_list_sort (GList *targets) } } - /* Sort by priority, and partly by weight */ + /* Sort input list by priority, and put the 0-weight targets first + * in each priority group. Initialize output list to %NULL. + */ targets = g_list_sort (targets, compare_target); + out = tail = NULL; - /* For each group of targets with the same priority, rebalance them - * according to weight. + /* For each group of targets with the same priority, remove them + * from @targets and append them to @out in a valid order. */ - for (first = targets; first; first = last->next) + while (targets) { - /* Skip @first to a non-0-weight target. */ - while (first && ((GSrvTarget *)first->data)->weight == 0) - first = first->next; - if (!first) - break; - - /* Skip @last to the last target of the same priority. */ - priority = ((GSrvTarget *)first->data)->priority; - last = first; - while (last->next && - ((GSrvTarget *)last->next->data)->priority == priority) - last = last->next; - - /* If there's only one non-0 weight target at this priority, - * we can move on to the next priority level. - */ - if (last == first) - continue; - - /* Randomly reorder the non-0 weight targets, giving precedence - * to the ones with higher weight. RFC 2782 describes this in - * terms of assigning a running sum to each target and building - * a new list. We do things slightly differently, but should get - * the same result. + priority = ((GSrvTarget *)targets->data)->priority; + + /* Count the number of targets at this priority level, and + * compute the sum of their weights. */ - for (n = first, sum = 0; n != last->next; n = n->next) - sum += ((GSrvTarget *)n->data)->weight; - while (first != last) + sum = num = 0; + for (t = targets; t; t = t->next) + { + target = (GSrvTarget *)t->data; + if (target->priority != priority) + break; + sum += target->weight; + num++; + } + + /* While there are still targets at this priority level... */ + while (num) { - val = g_random_int_range (0, sum); - for (n = first; n != last; n = n->next) + /* Randomly select from the targets at this priority level, + * giving precedence to the ones with higher weight, + * according to the rules from RFC 2782. + */ + val = g_random_int_range (0, sum + 1); + for (t = targets; ; t = t->next) { - weight = ((GSrvTarget *)n->data)->weight; - if (val < weight) + weight = ((GSrvTarget *)t->data)->weight; + if (weight >= val) break; val -= weight; } - tmp = first->data; - first->data = n->data; - n->data = tmp; + targets = g_list_remove_link (targets, t); + + if (!out) + out = t; + else + tail->next = t; + tail = t; sum -= weight; - first = first->next; + num--; } } - return targets; + return out; } - -#define __G_SRV_TARGET_C__ -#include "gioaliasdef.c"