# HG changeset patch
# User Kaitlin Rupert <karupert(a)us.ibm.com>
# Date 1194471308 28800
# Node ID 5959f8f0e5e87540fb7da0bc5a0365388112452b
# Parent 404c4803b1b542676c4d283226a7cc3b7f3ab58d
Add association results filtering.
This adds result filtering so that an association only returns instances that match the
result class specified during the query. Such an example is the following:
HostedService needs to return VSMS and RPCS instances when queried using
CIM_ManagedElement as the result class. However, if CIM_VSMS is specified as the result
class, then only the VSMS instance needs to be returned.
Signed-off-by: Kaitlin Rupert <karupert(a)us.ibm.com>
diff -r 404c4803b1b5 -r 5959f8f0e5e8 std_association.c
--- a/std_association.c Fri Nov 02 15:29:38 2007 -0700
+++ b/std_association.c Wed Nov 07 13:35:08 2007 -0800
@@ -47,6 +47,17 @@ void set_reference(struct std_assoc *ass
(CMPIValue *)&target, CMPI_ref);
}
+static bool match_op(const CMPIBroker *broker,
+ CMPIObjectPath *op,
+ const char *filter_class)
+{
+ if ((filter_class == NULL) ||
+ CMClassPathIsA(broker, op, filter_class, NULL))
+ return true;
+ else
+ return false;
+}
+
static bool match_class(const CMPIBroker *broker,
const char *ns,
const char *test_class,
@@ -58,10 +69,55 @@ static bool match_class(const CMPIBroker
if ((test_class == NULL) ||
(comp_class == NULL) ||
- CMClassPathIsA(broker, rop, comp_class, NULL))
+ match_op(broker, rop, comp_class))
return true;
else
return false;
+}
+
+static CMPIStatus filter_results(struct inst_list *list,
+ char *ns,
+ const char *filter_class,
+ const CMPIBroker *broker)
+{
+ struct inst_list result_list;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *op;
+ int i, c = 0;
+
+ inst_list_init(&result_list);
+
+ for (i = 0; list->list[i] != NULL; i++) {
+ op = CMGetObjectPath(list->list[i], &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullObject(op))
+ goto out;
+
+ s = CMSetNameSpace(op, ns);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ if (!match_op(broker, op, filter_class))
+ continue;
+
+ inst_list_add(&result_list, list->list[i]);
+ c++;
+ }
+
+ inst_list_free(list);
+ if (list->list != NULL) {
+ CU_DEBUG("\tinst_list_free failed.\n");
+ goto out;
+ }
+
+ inst_list_init(list);
+
+ for (i = 0; i <= c; i++)
+ inst_list_add(list, result_list.list[i]);
+
+out:
+ inst_list_free(&result_list);
+
+ return s;
}
static struct std_assoc *
@@ -142,6 +198,20 @@ static CMPIStatus do_assoc(struct std_as
goto out;
} else {
CU_DEBUG("\thandler returned CMPI_RC_OK.\n");
+ }
+
+ if (list.list == NULL) {
+ CU_DEBUG("\tlist is empty.\n");
+ goto out;
+ }
+
+ s = filter_results(&list,
+ NAMESPACE(ref),
+ info->result_class,
+ ctx->brkr);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("\tfilter_results did not return CMPI_RC_OK.\n");
+ goto out;
}
if (list.list == NULL) {
Show replies by date
KR> This adds result filtering so that an association only returns
KR> instances that match the result class specified during the
KR> query. Such an example is the following:
I think this is a good idea. It allows our association handlers to
ignore the result class (if so desired) knowing that std_association
will do the result class filtering before returning to the client.
Handlers could also look at the result_class field in std_assoc_info
to optimize if desired or necessary.
KR> + inst_list_init(&result_list);
KR> +
KR> + for (i = 0; list->list[i] != NULL; i++) {
KR> + op = CMGetObjectPath(list->list[i], &s);
KR> + if ((s.rc != CMPI_RC_OK) || CMIsNullObject(op))
KR> + goto out;
KR> +
KR> + s = CMSetNameSpace(op, ns);
KR> + if (s.rc != CMPI_RC_OK)
KR> + goto out;
KR> +
KR> + if (!match_op(broker, op, filter_class))
KR> + continue;
KR> +
KR> + inst_list_add(&result_list, list->list[i]);
KR> + c++;
KR> + }
KR> +
KR> + inst_list_free(list);
KR> + if (list->list != NULL) {
KR> + CU_DEBUG("\tinst_list_free failed.\n");
KR> + goto out;
KR> + }
KR> +
KR> + inst_list_init(list);
KR> +
KR> + for (i = 0; i <= c; i++)
KR> + inst_list_add(list, result_list.list[i]);
Instead of filling another list, and then copying it back, why not
just make a copy of the incoming list and then copy matching instances
back to the original? Something like this:
struct inst_list tmp_list;
tmp_list = *list;
inst_list_init(list);
for (items in tmp_list) {
if (item is resultclass)
inst_list_add(list, item);
}
inst_list_free(tmp_list);
That should work, and only copy the needed instance pointers once,
instead of running through the list twice.
--
Dan Smith
IBM Linux Technology Center
Open Hypervisor Team
email: danms(a)us.ibm.com
Dan Smith wrote:
Instead of filling another list, and then copying it back, why not
just make a copy of the incoming list and then copy matching instances
back to the original? Something like this:
struct inst_list tmp_list;
tmp_list = *list;
inst_list_init(list);
for (items in tmp_list) {
if (item is resultclass)
inst_list_add(list, item);
}
inst_list_free(tmp_list);
That should work, and only copy the needed instance pointers once,
instead of running through the list twice.
Excellent suggestion! Thanks, this works. Will generate another patch.
--
Kaitlin Rupert
IBM Linux Technology Center
karupert(a)us.ibm.com