celix_status_t serviceRegistry_getServiceReferences()

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(&registry->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(&registry->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;
}