예제 #1
0
celix_status_t configuration_bind(configuration_impl_pt configuration, bundle_pt bundle, bool *isBind) {

//	printf("[ DEBUG ]: Configuration{PID=%s} - bind(START) \n",configuration->pid);

    char *bundleLocation;

    configuration_lock(configuration);

    /* ----------- BINDING -------------- */

    // (1): it's the configuration already bound?
    if ( configuration->boundBundle == NULL ) { // (1): No

        // (2): it's the configuration located?
        if ( configuration->bundleLocation != NULL ) { //(2): Yes

            if ( bundle_getBundleLocation(bundle, &bundleLocation) != CELIX_SUCCESS) {
                configuration_unlock(configuration);
                return CELIX_ILLEGAL_ARGUMENT;
            }

            // (3): bundle and configuration have the same location?
            if ( strcmp(configuration->bundleLocation, bundleLocation) == 0 ) { // (3): Yes
                // bind up configuration with bundle
                configuration->boundBundle = bundle;
//				printf("[ DEBUG ]: Configuration{PID=%s} - bind (bound with Bundle{%s}) \n",configuration->pid,bundleLocation);
            }
            // (3): No

        } else { // (2): No
            // bind up configuration with bundle
            configuration->boundBundle = bundle;
//			printf("[ DEBUG ]: Configuration{PID=%s}) - bind (not located and now bound with Bundle) \n",configuration->pid);
        }

    }// (1): Yes

    /* ------------ RETURN -------------- */

    bool bind;
    if(configuration->boundBundle == bundle) {
        bind = true;
    } else {
        bind = false;
    }

    /* ------------- END ----------------- */
    configuration_unlock(configuration);

    *isBind = bind;
//	printf("[ DEBUG ]: Configuration{PID=%s} - bind(END) \n",configuration->pid);
    return CELIX_SUCCESS;

}
예제 #2
0
celix_status_t configuration_update(void *handle, properties_pt properties) {

    configuration_impl_pt conf = (configuration_impl_pt)handle;


    celix_status_t status;

    // (1)
    configuration_lock(conf);

    // (2)
    if ( configuration_checkDeleted(conf) != CELIX_SUCCESS ) {
        configuration_unlock(conf);
        return CELIX_ILLEGAL_STATE;
    }
    // (3)
    configuration_updateDictionary(conf, properties);

    // (4)
    status = configurationStore_saveConfiguration(conf->configurationStore, conf->pid, conf->configuration_interface);
    if (status != CELIX_SUCCESS) {
        configuration_unlock(conf);
        return status;
    }

    // (5)
    bool isFactory;
    if (conf->factoryPid == NULL) {
        isFactory = false;
    } else {
        isFactory = true;
    }

    status = configurationAdminFactory_notifyConfigurationUpdated(conf->configurationAdminFactory, conf->configuration_interface, isFactory);
    if (status != CELIX_SUCCESS) {
        configuration_unlock(conf);
        return status;
    }

    // (6)
    status = configurationAdminFactory_dispatchEvent(conf->configurationAdminFactory, CONFIGURATION_EVENT_CM_UPDATED, conf->factoryPid, conf->pid);
    if (status != CELIX_SUCCESS) {
        configuration_unlock(conf);
        return status;
    }

    // (7)
    configuration_unlock(conf);
    return CELIX_SUCCESS;
}
예제 #3
0
static celix_status_t configuration_getPid2(configuration_impl_pt configuration, bool checkDeleted, char **pid) {

    configuration_lock(configuration);

    if ( checkDeleted ) {
        if ( configuration_checkDeleted(configuration) != CELIX_SUCCESS ) {
            configuration_unlock(configuration);
            return CELIX_ILLEGAL_STATE;
        }
    }

    *pid = configuration->pid;

    configuration_unlock(configuration);

    return CELIX_SUCCESS;
}
예제 #4
0
// org.eclipse.equinox.internal.cm modified to fit with org.apache.felix.cm.impl
// change due to ConfigurationStore implementation
celix_status_t configuration_getAllProperties(configuration_impl_pt configuration, properties_pt *properties) {

    celix_status_t status;

    properties_pt copy = NULL;

    // (1) configuration.lock
    configuration_lock(configuration);

    // (2) configuration.deleted ?
    if( configuration->deleted ) {
        *properties = NULL;
        configuration_unlock(configuration);
        return CELIX_SUCCESS;
    }

    // (3) configuration.getProps
    if( configuration_getProperties(configuration, &copy) != CELIX_SUCCESS) {
        configuration_unlock(configuration);
        return CELIX_ILLEGAL_ARGUMENT;
    }

    // (4) configuration.setProperties
    if ( copy == NULL ) { //set all the automatic properties

        copy = properties_create();
        status = configuration_setAutoProperties(configuration, &copy, true);

    } else { // copy != NULL - only set service.bundleLocation

        status = configuration_setBundleLocationProperty(configuration, &copy);

    }

    // (5) return
    if (status == CELIX_SUCCESS) {
        *properties = copy;
    } else {
        *properties = NULL;
    }

    configuration_unlock(configuration);
    return status;

}
예제 #5
0
celix_status_t configuration_setBundleLocation(void *handle, char *bundleLocation) {

    configuration_impl_pt	conf = (configuration_impl_pt)handle;
    configuration_lock(conf);

    if ( configuration_checkDeleted(conf) != CELIX_SUCCESS ) {
        configuration_unlock(conf);
        return CELIX_ILLEGAL_STATE;
    }

    //	TODO configurationAdminFactory.checkConfigurationPermission

    conf->bundleLocation = bundleLocation;
    conf->boundBundle = NULL; // always reset the boundBundle when setBundleLocation is called

    configuration_unlock(conf);

    return CELIX_SUCCESS;
}
예제 #6
0
celix_status_t configuration_setBundleLocationProperty(configuration_impl_pt configuration, properties_pt *properties) {

    char *bundleLocation;

    configuration_lock(configuration);

    if( configuration_getBundleLocation(configuration, &bundleLocation) != CELIX_SUCCESS ) {
        configuration_unlock(configuration);
        return CELIX_ILLEGAL_ARGUMENT;
    }

    if ( bundleLocation != NULL ) {
        properties_set(*properties, (char*)SERVICE_BUNDLELOCATION, bundleLocation);
    }

    configuration_unlock(configuration);

    return CELIX_SUCCESS;

}
예제 #7
0
celix_status_t configuration_getPool(configuration_impl_pt configuration, apr_pool_t **pool) {

    printf("[ DEBUG ]: Configuration{PID=%s} - get Pool \n",configuration->pid);

    configuration_lock(configuration);

    *pool = configuration->pool;

    configuration_unlock(configuration);

    return CELIX_SUCCESS;
}
예제 #8
0
celix_status_t configuration_getBundleLocation2(configuration_impl_pt configuration, bool checkPermission, char **location) {

    celix_status_t status;

    // (1)
    configuration_lock(configuration);

    // (2)
    if( configuration_checkDeleted(configuration) != CELIX_SUCCESS ) {
        configuration_unlock(configuration);
        return CELIX_ILLEGAL_STATE;
    }
    // (3)
    if ( checkPermission ) {

        if ( configurationAdminFactory_checkConfigurationPermission(configuration->configurationAdminFactory) != CELIX_SUCCESS ) {
            return CELIX_ILLEGAL_STATE; // TODO configurationAdmin, not yet implemented
        }
    }

    // (4)
    if ( configuration->bundleLocation ) {
        *location = configuration->bundleLocation;
        configuration_unlock(configuration);
        return CELIX_SUCCESS;
    }

    // (5)
    if ( configuration->boundBundle != NULL ) {
        status = bundle_getBundleLocation(configuration->boundBundle,location);
        configuration_unlock(configuration);
        return status;
    }

    // (6)
    *location = NULL;
    configuration_unlock(configuration);
    return CELIX_SUCCESS;
}
예제 #9
0
static int
on_read_request_process(struct query_state *qstate)
{
	struct cache_read_request *read_request;
	struct cache_read_response *read_response;
	cache_entry	c_entry, neg_c_entry;

	struct agent	*lookup_agent;
	struct common_agent *c_agent;
	int res;

	TRACE_IN(on_read_request_process);
	init_comm_element(&qstate->response, CET_READ_RESPONSE);
	read_response = get_cache_read_response(&qstate->response);
	read_request = get_cache_read_request(&qstate->request);

	qstate->config_entry = configuration_find_entry(
		s_configuration, read_request->entry);
	if (qstate->config_entry == NULL) {
		read_response->error_code = ENOENT;

		LOG_ERR_2("read_request",
			"can't find configuration "
			"entry '%s'. aborting request", read_request->entry);
		goto fin;
	}

	if (qstate->config_entry->enabled == 0) {
		read_response->error_code = EACCES;

		LOG_ERR_2("read_request",
			"configuration entry '%s' is disabled",
			read_request->entry);
		goto fin;
	}

	/*
	 * if we perform lookups by ourselves, then we don't need to separate
	 * cache entries by euid and egid
	 */
	if (qstate->config_entry->perform_actual_lookups != 0)
		memset(read_request->cache_key, 0, qstate->eid_str_length);
	else {
#ifdef NS_NSCD_EID_CHECKING
		if (check_query_eids(qstate) != 0) {
		/* if the lookup is not self-performing, we check for clients euid/egid */
			read_response->error_code = EPERM;
			goto fin;
		}
#endif
	}

	configuration_lock_rdlock(s_configuration);
	c_entry = find_cache_entry(s_cache,
		qstate->config_entry->positive_cache_params.entry_name);
	neg_c_entry = find_cache_entry(s_cache,
		qstate->config_entry->negative_cache_params.entry_name);
	configuration_unlock(s_configuration);
	if ((c_entry != NULL) && (neg_c_entry != NULL)) {
		configuration_lock_entry(qstate->config_entry, CELT_POSITIVE);
		qstate->config_entry->positive_cache_entry = c_entry;
		read_response->error_code = cache_read(c_entry,
			read_request->cache_key,
			read_request->cache_key_size, NULL,
			&read_response->data_size);

		if (read_response->error_code == -2) {
			read_response->data = (char *)malloc(
				read_response->data_size);
			assert(read_response != NULL);
			read_response->error_code = cache_read(c_entry,
				read_request->cache_key,
				read_request->cache_key_size,
				read_response->data,
				&read_response->data_size);
		}
		configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);

		configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
		qstate->config_entry->negative_cache_entry = neg_c_entry;
		if (read_response->error_code == -1) {
			read_response->error_code = cache_read(neg_c_entry,
				read_request->cache_key,
				read_request->cache_key_size, NULL,
				&read_response->data_size);

			if (read_response->error_code == -2) {
				read_response->error_code = 0;
				read_response->data = NULL;
				read_response->data_size = 0;
			}
		}
		configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);

		if ((read_response->error_code == -1) &&
			(qstate->config_entry->perform_actual_lookups != 0)) {
			free(read_response->data);
			read_response->data = NULL;
			read_response->data_size = 0;

			lookup_agent = find_agent(s_agent_table,
				read_request->entry, COMMON_AGENT);

			if ((lookup_agent != NULL) &&
			(lookup_agent->type == COMMON_AGENT)) {
				c_agent = (struct common_agent *)lookup_agent;
				res = c_agent->lookup_func(
					read_request->cache_key +
						qstate->eid_str_length,
					read_request->cache_key_size -
						qstate->eid_str_length,
					&read_response->data,
					&read_response->data_size);

				if (res == NS_SUCCESS) {
					read_response->error_code = 0;
					configuration_lock_entry(
						qstate->config_entry,
						CELT_POSITIVE);
					cache_write(c_entry,
						read_request->cache_key,
						read_request->cache_key_size,
						read_response->data,
						read_response->data_size);
					configuration_unlock_entry(
						qstate->config_entry,
						CELT_POSITIVE);
				} else if ((res == NS_NOTFOUND) ||
					  (res == NS_RETURN)) {
					configuration_lock_entry(
						  qstate->config_entry,
						  CELT_NEGATIVE);
					cache_write(neg_c_entry,
						read_request->cache_key,
						read_request->cache_key_size,
						negative_data,
						sizeof(negative_data));
					configuration_unlock_entry(
						  qstate->config_entry,
						  CELT_NEGATIVE);

					read_response->error_code = 0;
					read_response->data = NULL;
					read_response->data_size = 0;
				}
			}
		}

		if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
		    (qstate->config_entry->common_query_timeout.tv_usec != 0))
			memcpy(&qstate->timeout,
				&qstate->config_entry->common_query_timeout,
				sizeof(struct timeval));
	} else
		read_response->error_code = -1;

fin:
	qstate->kevent_filter = EVFILT_WRITE;
	if (read_response->error_code == 0)
		qstate->kevent_watermark = sizeof(int) + sizeof(size_t);
	else
		qstate->kevent_watermark = sizeof(int);
	qstate->process_func = on_read_response_write1;

	TRACE_OUT(on_read_request_process);
	return (0);
}
예제 #10
0
static int
on_negative_write_request_process(struct query_state *qstate)
{
	struct cache_write_request	*write_request;
	struct cache_write_response	*write_response;
	cache_entry c_entry;

	TRACE_IN(on_negative_write_request_process);
	init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
	write_response = get_cache_write_response(&qstate->response);
	write_request = get_cache_write_request(&qstate->request);

	qstate->config_entry = configuration_find_entry(
		s_configuration, write_request->entry);

	if (qstate->config_entry == NULL) {
		write_response->error_code = ENOENT;

		LOG_ERR_2("negative_write_request",
			"can't find configuration"
			" entry '%s'. aborting request", write_request->entry);
		goto fin;
	}

	if (qstate->config_entry->enabled == 0) {
		write_response->error_code = EACCES;

		LOG_ERR_2("negative_write_request",
			"configuration entry '%s' is disabled",
			write_request->entry);
		goto fin;
	}

	if (qstate->config_entry->perform_actual_lookups != 0) {
		write_response->error_code = EOPNOTSUPP;

		LOG_ERR_2("negative_write_request",
			"entry '%s' performs lookups by itself: "
			"can't write to it", write_request->entry);
		goto fin;
	} else {
#ifdef NS_NSCD_EID_CHECKING
		if (check_query_eids(qstate) != 0) {
			write_response->error_code = EPERM;
			goto fin;
		}
#endif
	}

	configuration_lock_rdlock(s_configuration);
	c_entry = find_cache_entry(s_cache,
		qstate->config_entry->negative_cache_params.entry_name);
	configuration_unlock(s_configuration);
	if (c_entry != NULL) {
		configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
		qstate->config_entry->negative_cache_entry = c_entry;
		write_response->error_code = cache_write(c_entry,
			write_request->cache_key,
			write_request->cache_key_size,
			negative_data,
			sizeof(negative_data));
		configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);

		if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
		    (qstate->config_entry->common_query_timeout.tv_usec != 0))
			memcpy(&qstate->timeout,
				&qstate->config_entry->common_query_timeout,
				sizeof(struct timeval));
	} else
		write_response->error_code = -1;

fin:
	qstate->kevent_filter = EVFILT_WRITE;
	qstate->kevent_watermark = sizeof(int);
	qstate->process_func = on_write_response_write1;

	TRACE_OUT(on_negative_write_request_process);
	return (0);
}
예제 #11
0
// org.eclipse.equinox.internal.cm.ManagedServiceTracker
celix_status_t managedServiceTracker_add(managed_service_tracker_pt tracker, service_reference_pt reference, char *pid, managed_service_service_pt service) {

    celix_status_t status;

    bundle_pt bundle = NULL;
    const char* bundleLocation;

    configuration_pt configuration = NULL;
    properties_pt properties = NULL;

    configurationStore_findConfiguration(tracker->configurationStore, pid, &configuration);

    if (configuration == NULL) {

        if (managedServiceTracker_trackManagedService(tracker, pid, reference, service) == CELIX_SUCCESS) {

            // TODO : this is new code, it hasn't been tested yet

            if (serviceReference_getBundle(reference, &bundle) != CELIX_SUCCESS) {
                return CELIX_ILLEGAL_ARGUMENT;
            }

            if (bundle_getBundleLocation(bundle, &bundleLocation) != CELIX_SUCCESS) {
                return CELIX_ILLEGAL_ARGUMENT;
            }

            // (1) creates a new Configuration for the ManagedService
            if (configurationStore_getConfiguration(tracker->configurationStore, pid, (char*)bundleLocation, &configuration) != CELIX_SUCCESS || configuration == NULL) {
                return CELIX_ILLEGAL_ARGUMENT;
            }

            // (2) bind the Configuration with the ManagedService
            bool dummy;
            if ((configuration_bind(configuration->handle, bundle, &dummy) != CELIX_SUCCESS)) {
                return CELIX_ILLEGAL_ARGUMENT;
            }

            // (3) the new Configuration is persisted and visible for other ConfigAdmin instances
            if (configurationStore_saveConfiguration(tracker->configurationStore, pid, configuration) != CELIX_SUCCESS) {
                return CELIX_ILLEGAL_STATE;
            }

            // End of new code

            // TODO: It must be considered in case of fail if untrack the ManagedService

            return managedServiceTracker_asynchUpdated(tracker, service, NULL);

        } else {
            return CELIX_ILLEGAL_ARGUMENT; // the service was already tracked
        }

    } else {

        configuration_lock(configuration->handle);

        if (managedServiceTracker_trackManagedService(tracker, pid, reference, service) == CELIX_SUCCESS) {

            if (serviceReference_getBundle(reference, &bundle) != CELIX_SUCCESS) {
                configuration_unlock(configuration->handle);
                printf("[ERROR ]: Tracker - Add (Service{PID=%s} Reference - getBundle NULL)", pid);
                return CELIX_ILLEGAL_ARGUMENT;
            }

            // TODO configuration.isDeleted ? - with only using one calling bundle OK

            bool isBind;
            if ((configuration_bind(configuration->handle, bundle, &isBind) == CELIX_SUCCESS) && (isBind == true)) { // config.bind(bundle)

                if (configuration_getProperties(configuration->handle, &properties) != CELIX_SUCCESS) {
                    configuration_unlock(configuration->handle);
                    return CELIX_ILLEGAL_ARGUMENT;
                }

                if (configurationAdminFactory_modifyConfiguration(tracker->configurationAdminfactory, reference, properties) != CELIX_SUCCESS) {
                    configuration_unlock(configuration->handle);
                    return CELIX_ILLEGAL_ARGUMENT;
                }

                status = managedServiceTracker_asynchUpdated(tracker, service, properties);

                configuration_unlock(configuration->handle);

                return status;

            } else {
                configuration_unlock(configuration->handle);
                return CELIX_ILLEGAL_STATE;
            }

        } else {
            configuration_unlock(configuration->handle);
            return CELIX_ILLEGAL_ARGUMENT; // the service was already tracked
        }
    }
}
예제 #12
0
static int
on_mp_write_session_request_process(struct query_state *qstate)
{
	struct cache_mp_write_session_request	*c_mp_ws_request;
	struct cache_mp_write_session_response	*c_mp_ws_response;
	cache_mp_write_session	ws;
	cache_entry	c_entry;
	char	*dec_cache_entry_name;

	TRACE_IN(on_mp_write_session_request_process);
	init_comm_element(&qstate->response, CET_MP_WRITE_SESSION_RESPONSE);
	c_mp_ws_response = get_cache_mp_write_session_response(
		&qstate->response);
	c_mp_ws_request = get_cache_mp_write_session_request(&qstate->request);

	qstate->config_entry = configuration_find_entry(
		s_configuration, c_mp_ws_request->entry);
	if (qstate->config_entry == NULL) {
		c_mp_ws_response->error_code = ENOENT;

		LOG_ERR_2("write_session_request",
			"can't find configuration entry '%s'. "
	    		"aborting request", c_mp_ws_request->entry);
	    	goto fin;
	}

	if (qstate->config_entry->enabled == 0) {
		c_mp_ws_response->error_code = EACCES;

		LOG_ERR_2("write_session_request",
			"configuration entry '%s' is disabled",
			c_mp_ws_request->entry);
		goto fin;
	}

	if (qstate->config_entry->perform_actual_lookups != 0) {
		c_mp_ws_response->error_code = EOPNOTSUPP;

		LOG_ERR_2("write_session_request",
			"entry '%s' performs lookups by itself: "
			"can't write to it", c_mp_ws_request->entry);
		goto fin;
	} else {
#ifdef NS_NSCD_EID_CHECKING
		if (check_query_eids(qstate) != 0) {
			c_mp_ws_response->error_code = EPERM;
			goto fin;
		}
#endif
	}

	/*
	 * All multipart entries are separated by their name decorations.
	 * For one configuration entry there will be a lot of multipart
	 * cache entries - each with its own decorated name.
	 */
	asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str,
		qstate->config_entry->mp_cache_params.cep.entry_name);
	assert(dec_cache_entry_name != NULL);

	configuration_lock_rdlock(s_configuration);
	c_entry = find_cache_entry(s_cache,
		dec_cache_entry_name);
	configuration_unlock(s_configuration);

	if (c_entry == INVALID_CACHE_ENTRY)
		c_entry = register_new_mp_cache_entry(qstate,
			dec_cache_entry_name);

	free(dec_cache_entry_name);

	assert(c_entry != NULL);
	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
	ws = open_cache_mp_write_session(c_entry);
	if (ws == INVALID_CACHE_MP_WRITE_SESSION)
		c_mp_ws_response->error_code = -1;
	else {
		qstate->mdata = ws;
		qstate->destroy_func = on_mp_write_session_destroy;

		if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) ||
		    (qstate->config_entry->mp_query_timeout.tv_usec != 0))
			memcpy(&qstate->timeout,
				&qstate->config_entry->mp_query_timeout,
				sizeof(struct timeval));
	}
	configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART);

fin:
	qstate->process_func = on_mp_write_session_response_write1;
	qstate->kevent_watermark = sizeof(int);
	qstate->kevent_filter = EVFILT_WRITE;

	TRACE_OUT(on_mp_write_session_request_process);
	return (0);
}
예제 #13
0
static int
on_mp_read_session_request_process(struct query_state *qstate)
{
	struct cache_mp_read_session_request	*c_mp_rs_request;
	struct cache_mp_read_session_response	*c_mp_rs_response;
	cache_mp_read_session	rs;
	cache_entry	c_entry;
	char	*dec_cache_entry_name;

	char *buffer;
	size_t buffer_size;
	cache_mp_write_session ws;
	struct agent	*lookup_agent;
	struct multipart_agent *mp_agent;
	void *mdata;
	int res;

	TRACE_IN(on_mp_read_session_request_process);
	init_comm_element(&qstate->response, CET_MP_READ_SESSION_RESPONSE);
	c_mp_rs_response = get_cache_mp_read_session_response(
		&qstate->response);
	c_mp_rs_request = get_cache_mp_read_session_request(&qstate->request);

	qstate->config_entry = configuration_find_entry(
		s_configuration, c_mp_rs_request->entry);
	if (qstate->config_entry == NULL) {
		c_mp_rs_response->error_code = ENOENT;

		LOG_ERR_2("read_session_request",
			"can't find configuration entry '%s'."
			" aborting request", c_mp_rs_request->entry);
		goto fin;
	}

	if (qstate->config_entry->enabled == 0) {
		c_mp_rs_response->error_code = EACCES;

		LOG_ERR_2("read_session_request",
			"configuration entry '%s' is disabled",
			c_mp_rs_request->entry);
		goto fin;
	}

	if (qstate->config_entry->perform_actual_lookups != 0)
		dec_cache_entry_name = strdup(
			qstate->config_entry->mp_cache_params.cep.entry_name);
	else {
#ifdef NS_NSCD_EID_CHECKING
		if (check_query_eids(qstate) != 0) {
			c_mp_rs_response->error_code = EPERM;
			goto fin;
		}
#endif

		asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str,
			qstate->config_entry->mp_cache_params.cep.entry_name);
	}

	assert(dec_cache_entry_name != NULL);

	configuration_lock_rdlock(s_configuration);
	c_entry = find_cache_entry(s_cache, dec_cache_entry_name);
	configuration_unlock(s_configuration);

	if ((c_entry == INVALID_CACHE) &&
	   (qstate->config_entry->perform_actual_lookups != 0))
		c_entry = register_new_mp_cache_entry(qstate,
			dec_cache_entry_name);

	free(dec_cache_entry_name);

	if (c_entry != INVALID_CACHE_ENTRY) {
		configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
		rs = open_cache_mp_read_session(c_entry);
		configuration_unlock_entry(qstate->config_entry,
			CELT_MULTIPART);

		if ((rs == INVALID_CACHE_MP_READ_SESSION) &&
		   (qstate->config_entry->perform_actual_lookups != 0)) {
			lookup_agent = find_agent(s_agent_table,
				c_mp_rs_request->entry, MULTIPART_AGENT);

			if ((lookup_agent != NULL) &&
			(lookup_agent->type == MULTIPART_AGENT)) {
				mp_agent = (struct multipart_agent *)
					lookup_agent;
				mdata = mp_agent->mp_init_func();

				/*
				 * Multipart agents read the whole snapshot
				 * of the data at one time.
				 */
				configuration_lock_entry(qstate->config_entry,
					CELT_MULTIPART);
				ws = open_cache_mp_write_session(c_entry);
				configuration_unlock_entry(qstate->config_entry,
					CELT_MULTIPART);
				if (ws != NULL) {
				    do {
					buffer = NULL;
					res = mp_agent->mp_lookup_func(&buffer,
						&buffer_size,
						mdata);

					if ((res & NS_TERMINATE) &&
					   (buffer != NULL)) {
						configuration_lock_entry(
							qstate->config_entry,
						   	CELT_MULTIPART);
						if (cache_mp_write(ws, buffer,
						    buffer_size) != 0) {
							abandon_cache_mp_write_session(ws);
							ws = NULL;
						}
						configuration_unlock_entry(
							qstate->config_entry,
							CELT_MULTIPART);

						free(buffer);
						buffer = NULL;
					} else {
						configuration_lock_entry(
							qstate->config_entry,
							CELT_MULTIPART);
						close_cache_mp_write_session(ws);
						configuration_unlock_entry(
							qstate->config_entry,
							CELT_MULTIPART);

						free(buffer);
						buffer = NULL;
					}
				    } while ((res & NS_TERMINATE) &&
				    	    (ws != NULL));
				}

				configuration_lock_entry(qstate->config_entry,
					CELT_MULTIPART);
				rs = open_cache_mp_read_session(c_entry);
				configuration_unlock_entry(qstate->config_entry,
					CELT_MULTIPART);
			}
		}

		if (rs == INVALID_CACHE_MP_READ_SESSION)
			c_mp_rs_response->error_code = -1;
		else {
		    qstate->mdata = rs;
		    qstate->destroy_func = on_mp_read_session_destroy;

		    configuration_lock_entry(qstate->config_entry,
			CELT_MULTIPART);
		    if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) ||
		    (qstate->config_entry->mp_query_timeout.tv_usec != 0))
			memcpy(&qstate->timeout,
			    &qstate->config_entry->mp_query_timeout,
			    sizeof(struct timeval));
		    configuration_unlock_entry(qstate->config_entry,
			CELT_MULTIPART);
		}
	} else
		c_mp_rs_response->error_code = -1;

fin:
	qstate->process_func = on_mp_read_session_response_write1;
	qstate->kevent_watermark = sizeof(int);
	qstate->kevent_filter = EVFILT_WRITE;

	TRACE_OUT(on_mp_read_session_request_process);
	return (0);
}