in libs/framework/src/service_registry.c [327:410]
celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry,
bundle_pt owner,
const char* serviceName,
filter_pt filter,
celix_array_list_t** out) {
bool matchResult;
celix_autoptr(celix_array_list_t) references = celix_arrayList_create();
celix_autoptr(celix_array_list_t) matchingRegistrations = celix_arrayList_create();
if (!references || !matchingRegistrations) {
fw_log(registry->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot create service references, out of memory");
return CELIX_ENOMEM;
}
celix_status_t status = CELIX_SUCCESS;
celixThreadRwlock_readLock(®istry->lock);
hash_map_iterator_t iterator = hashMapIterator_construct(registry->serviceRegistrations);
while (status == CELIX_SUCCESS && hashMapIterator_hasNext(&iterator)) {
celix_array_list_t* regs = hashMapIterator_nextValue(&iterator);
unsigned int regIdx;
for (regIdx = 0; (regs != NULL) && regIdx < celix_arrayList_size(regs); regIdx++) {
service_registration_pt registration = celix_arrayList_get(regs, regIdx);
celix_properties_t* props = NULL;
status = serviceRegistration_getProperties(registration, &props);
if (status == CELIX_SUCCESS) {
bool matched = false;
matchResult = false;
if (filter != NULL) {
filter_match(filter, props, &matchResult);
}
if ((serviceName == NULL) && ((filter == NULL) || matchResult)) {
matched = true;
} else if (serviceName != NULL) {
const char* className = NULL;
matchResult = false;
serviceRegistration_getServiceName(registration, &className);
if (filter != NULL) {
filter_match(filter, props, &matchResult);
}
if ((strcmp(className, serviceName) == 0) && ((filter == NULL) || matchResult)) {
matched = true;
}
}
if (matched) {
// assert(serviceRegistration_isValid(registration));
serviceRegistration_retain(registration);
celix_arrayList_add(matchingRegistrations, registration);
}
}
}
}
celixThreadRwlock_unlock(®istry->lock);
if (status == CELIX_SUCCESS) {
unsigned int i;
unsigned int size = celix_arrayList_size(matchingRegistrations);
for (i = 0; i < size; i += 1) {
service_registration_pt reg = celix_arrayList_get(matchingRegistrations, i);
service_reference_pt reference = NULL;
celix_status_t subStatus = serviceRegistry_getServiceReference(registry, owner, reg, &reference);
if (subStatus == CELIX_SUCCESS) {
celix_arrayList_add(references, reference);
} else {
status = CELIX_BUNDLE_EXCEPTION;
}
serviceRegistration_release(reg);
}
}
if (status == CELIX_SUCCESS) {
*out = celix_steal_ptr(references);
} else {
// TODO: test this branch using malloc mock
unsigned int size = celix_arrayList_size(references);
for (unsigned int i = 0; i < size; i++) {
serviceReference_release(celix_arrayList_get(references, i), NULL);
}
framework_logIfError(registry->framework->logger, status, NULL, "Cannot get service references");
}
return status;
}