static long celix_bundleContext_registerServiceWithOptionsInternal()

in libs/framework/src/bundle_context.c [428:496]


static long celix_bundleContext_registerServiceWithOptionsInternal(bundle_context_t *ctx, const celix_service_registration_options_t *opts, bool async) {
    bool valid = opts->serviceName != NULL && strncmp("", opts->serviceName, 1) != 0;
    if (!valid) {
        fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Required serviceName argument is NULL or empty");
        return -1;
    }
    valid = opts->svc != NULL || opts->factory != NULL;
    if (!valid) {
        fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Required svc or factory argument is NULL");
        return -1;
    }

    //set properties
    celix_autoptr(celix_properties_t) props = opts->properties;
    if (props == NULL) {
        props = celix_properties_create();
    }

    if (opts->serviceVersion != NULL && strncmp("", opts->serviceVersion, 1) != 0) {
        celix_autoptr(celix_version_t) version = celix_version_createVersionFromString(opts->serviceVersion);
        if (!version) {
            celix_framework_logTssErrors(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR);
            fw_log(
                ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot parse service version %s", opts->serviceVersion);
            return -1;
        }
        celix_status_t rc =
            celix_properties_assignVersion(props, CELIX_FRAMEWORK_SERVICE_VERSION, celix_steal_ptr(version));
        if (rc != CELIX_SUCCESS) {
            celix_framework_logTssErrors(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR);
            fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot set service version %s", opts->serviceVersion);
            return -1;
        }
    }

    celix_status_t correctionStatus = celix_bundleContext_correctServicePropertiesValueTypes(ctx, props);
    if (correctionStatus != CELIX_SUCCESS) {
        celix_framework_logTssErrors(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR);
        fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot correct service properties value types");
        return -1;
    }

    long svcId;
    if (!async && celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
        /*
         * Note already on event loop, cannot register the service async, because we cannot wait a future event (the
         * service registration) the event loop.
         *
         * So in this case we handle the service registration the "traditional way" and call the sync fw service
         * registrations versions on the event loop thread
         */

        svcId = celix_framework_registerService(ctx->framework, ctx->bundle, opts->serviceName, opts->svc, opts->factory, celix_steal_ptr(props));
    } else {
        void (*asyncCallback)(void *data, long serviceId) = async ? opts->asyncCallback : NULL; //NOTE for not async call do not use the callback.
        svcId = celix_framework_registerServiceAsync(ctx->framework, ctx->bundle, opts->serviceName, opts->svc, opts->factory, celix_steal_ptr(props), opts->asyncData, asyncCallback, NULL, NULL);
        if (!async && svcId >= 0) {
            //note on event loop thread, but in a sync call, so waiting till service registration is concluded
            celix_bundleContext_waitForAsyncRegistration(ctx, svcId);
        }
    }

    if (svcId >= 0) {
        celixThreadRwlock_writeLock(&ctx->lock);
        celix_arrayList_addLong(ctx->svcRegistrations, svcId);
        celixThreadRwlock_unlock(&ctx->lock);
    }
    return svcId;
}