gck: Retrieve attributes in GckEnumerator properly
authorStef Walter <stefw@collabora.co.uk>
Tue, 29 Nov 2011 11:15:03 +0000 (12:15 +0100)
committerStef Walter <stefw@collabora.co.uk>
Tue, 29 Nov 2011 11:15:03 +0000 (12:15 +0100)
 * Previously retrieved attributes only for first enumerator
   iteration.
 * Properly retrieve attributes for objects found, but not
   yet attributes retrieved.

gck/gck-enumerator.c
gck/tests/test-gck-enumerator.c

index 59d1b7b..dc3f2f2 100644 (file)
@@ -99,6 +99,9 @@ struct _GckEnumeratorState {
        /* state_session */
        GckSession *session;
 
+       /* state_find */
+       GQueue *found;
+
        /* state_results */
        GQueue *results;
 };
@@ -126,15 +129,12 @@ static gpointer state_slot           (GckEnumeratorState *args,
 static gpointer state_session        (GckEnumeratorState *args,
                                       gboolean forward);
 
-static gpointer state_authenticated  (GckEnumeratorState *args,
+static gpointer state_find           (GckEnumeratorState *args,
                                       gboolean forward);
 
 static gpointer state_results        (GckEnumeratorState *args,
                                       gboolean forward);
 
-static gpointer state_attributes     (GckEnumeratorState *args,
-                                      gboolean forward);
-
 
 static void
 _gck_enumerator_result_free (gpointer data)
@@ -180,6 +180,13 @@ cleanup_state (GckEnumeratorState *args)
        /* state_session */
        g_assert (!args->session);
 
+       /* state_find */
+       if (args->found) {
+               g_queue_foreach (args->found, (GFunc) _gck_enumerator_result_free, NULL);
+               g_queue_free (args->found);
+               args->found = NULL;
+       }
+
        /* state_results */
        if (args->results) {
                g_queue_foreach (args->results, (GFunc) _gck_enumerator_result_free, NULL);
@@ -373,7 +380,7 @@ state_session (GckEnumeratorState *args, gboolean forward)
                /* Don't want to authenticate? */
                if ((args->session_options & GCK_SESSION_LOGIN_USER) == 0) {
                        _gck_debug ("no authentication necessary, skipping");
-                       return state_authenticated;
+                       return state_find;
                }
 
                /* Compatibility, hook into GckModule signals if no interaction set */
@@ -392,7 +399,7 @@ state_session (GckEnumeratorState *args, gboolean forward)
                        g_message ("couldn't authenticate when enumerating: %s", gck_message_from_rv (rv));
 
                /* We try to proceed anyway with the enumeration */
-               return state_authenticated;
+               return state_find;
 
        /* Session to slot state */
        } else {
@@ -403,7 +410,8 @@ state_session (GckEnumeratorState *args, gboolean forward)
 }
 
 static gpointer
-state_authenticated (GckEnumeratorState *args, gboolean forward)
+state_find (GckEnumeratorState *args,
+            gboolean forward)
 {
        CK_OBJECT_HANDLE objects[128];
        CK_SESSION_HANDLE session;
@@ -422,8 +430,8 @@ state_authenticated (GckEnumeratorState *args, gboolean forward)
        g_assert (args->want_objects > 0);
        g_assert (args->funcs != NULL);
 
-       if (!args->results)
-               args->results = g_queue_new ();
+       if (!args->found)
+               args->found = g_queue_new ();
 
        if (args->match->attributes) {
                attrs = _gck_attributes_commit_out (args->match->attributes, &n_attrs);
@@ -456,7 +464,7 @@ state_authenticated (GckEnumeratorState *args, gboolean forward)
                                result = g_slice_new0 (GckEnumeratorResult);
                                result->handle = objects[i];
                                result->session = g_object_ref (args->session);
-                               g_queue_push_tail (args->results, result);
+                               g_queue_push_tail (args->found, result);
                        }
                }
 
@@ -464,12 +472,12 @@ state_authenticated (GckEnumeratorState *args, gboolean forward)
        }
 
        _gck_debug ("finding objects completed with: %s", _gck_stringize_rv (rv));
-       return state_attributes;
+       return state_results;
 }
 
 static gpointer
-state_attributes (GckEnumeratorState *args,
-                  gboolean forward)
+state_results (GckEnumeratorState *args,
+               gboolean forward)
 {
        GckEnumeratorResult *result;
        GckAttributes *attrs;
@@ -477,31 +485,37 @@ state_attributes (GckEnumeratorState *args,
        CK_ULONG n_template;
        CK_SESSION_HANDLE session;
        gint count;
-       GList *l;
-       gint i;
        CK_RV rv;
+       gint i;
 
        g_assert (args->funcs != NULL);
        g_assert (args->object_class != NULL);
-       g_assert (args->results != NULL);
+       g_assert (args->found != NULL);
 
        /* No cleanup, just unwind */
        if (!forward)
-               return state_authenticated;
+               return state_find;
 
-       /* If no request for attributes, just go forward */
-       if (args->object_iface == NULL ||
-           args->object_iface->n_attribute_types == 0)
-               return state_results;
+       if (!args->results)
+               args->results = g_queue_new ();
 
        session = gck_session_get_handle (args->session);
        g_return_val_if_fail (session, NULL);
 
        /* Get the attributes for want_objects */
-       for (count = 0, l = args->results->head;
-            l != NULL && count < args->want_objects;
-            l = g_list_next (l), count++) {
-               result = l->data;
+       for (count = 0; count < args->want_objects; count++) {
+               result = g_queue_pop_head (args->found);
+               if (result == NULL) {
+                       _gck_debug ("wanted %d objects, have %d, looking for more",
+                                   args->want_objects, g_queue_get_length (args->results));
+                       return rewind_state (args, state_slots);
+               }
+
+               /* If no request for attributes, just go forward */
+               if (args->object_iface == NULL || args->object_iface->n_attribute_types == 0) {
+                       g_queue_push_tail (args->results, result);
+                       continue;
+               }
 
                attrs = gck_attributes_new ();
                for (i = 0; i < args->object_iface->n_attribute_types; ++i)
@@ -531,38 +545,18 @@ state_attributes (GckEnumeratorState *args,
                                g_free (string);
                        }
                        result->attrs = attrs;
+                       g_queue_push_tail (args->results, result);
 
                } else {
                        g_message ("couldn't retrieve attributes when enumerating: %s",
                                   gck_message_from_rv (rv));
                        gck_attributes_unref (attrs);
+                       _gck_enumerator_result_free (result);
                }
        }
 
-       return state_results;
-}
-
-static gpointer
-state_results (GckEnumeratorState *args,
-               gboolean forward)
-{
-       g_assert (args->results != NULL);
-       gint length;
-
-       /* No cleanup, just unwind */
-       if (!forward)
-               return state_authenticated;
-
-       length = g_queue_get_length (args->results);
-
-       while (args->want_objects > length) {
-               _gck_debug ("wanted %d objects, have %d, looking for more",
-                           args->want_objects, length);
-               return rewind_state (args, state_slots);
-       }
-
        _gck_debug ("wanted %d objects, returned %d objects",
-                   args->want_objects, length);
+                   args->want_objects, g_queue_get_length (args->results));
 
        /* We got all the results we wanted */
        return NULL;
index f4f66ac..0c8496d 100644 (file)
@@ -407,9 +407,13 @@ typedef struct {
 GType mock_object_get_type (void) G_GNUC_CONST;
 static void mock_object_attributes_init (GckObjectAttributesIface *iface);
 
+#define MOCK_TYPE_OBJECT     (mock_object_get_type())
+#define MOCK_OBJECT(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), MOCK_TYPE_OBJECT, MockObject))
+#define MOCK_IS_OBJECT(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj), MOCK_TYPE_OBJECT))
+
 G_DEFINE_TYPE_WITH_CODE (MockObject, mock_object, GCK_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES,
-                                                mock_object_attributes_init)
+                                                mock_object_attributes_init);
 );
 
 static void
@@ -512,6 +516,35 @@ test_attribute_get (Test *test,
 }
 
 static void
+test_attribute_get_one_at_a_time (Test *test,
+                                  gconstpointer unused)
+{
+       GckUriData *uri_data;
+       GError *error = NULL;
+       GckEnumerator *en;
+       MockObject *mock;
+       GckObject *object;
+
+       uri_data = gck_uri_data_new ();
+       en = _gck_enumerator_new_for_modules (test->modules, 0, uri_data);
+       g_object_set (en, "object-type", mock_object_get_type (), NULL);
+
+       for (;;) {
+               object = gck_enumerator_next (en, NULL, &error);
+               g_assert_no_error (error);
+               if (object == NULL)
+                       break;
+
+               g_assert (G_TYPE_CHECK_INSTANCE_TYPE (object, mock_object_get_type ()));
+               mock = (MockObject *)object;
+               g_assert (mock->attrs != NULL);
+               g_object_unref (object);
+       }
+
+       g_object_unref (en);
+}
+
+static void
 test_chained (Test *test,
               gconstpointer unused)
 {
@@ -571,6 +604,7 @@ main (int argc, char **argv)
        g_test_add ("/gck/enumerator/attribute_match", Test, NULL, setup, test_attribute_match, teardown);
        g_test_add ("/gck/enumerator/token_match", Test, NULL, setup, test_token_match, teardown);
        g_test_add ("/gck/enumerator/attribute_get", Test, NULL, setup, test_attribute_get, teardown);
+       g_test_add ("/gck/enumerator/attribute_get_one_at_a_time", Test, NULL, setup, test_attribute_get_one_at_a_time, teardown);
        g_test_add ("/gck/enumerator/chained", Test, NULL, setup, test_chained, teardown);
 
        return egg_tests_run_with_loop ();