Ejemplo n.º 1
0
apr_status_t
server_init_child_stat(dav_rawx_server_conf *conf, apr_pool_t *pool, apr_pool_t *plog)
{
	char buff[256];
	apr_status_t rc;

	DAV_XDEBUG_POOL(plog, 0, "%s()", __FUNCTION__);

	/* Attaches the mutex */
	DAV_DEBUG_POOL(plog, 0, "%s : Attaching the SHM global_mutex at [%s]", __FUNCTION__, conf->shm.path);
	rc = apr_global_mutex_child_init(&(conf->lock.handle), conf->shm.path, pool);
	if (APR_SUCCESS != rc) {
		DAV_ERROR_POOL(plog, 0, "%s : Failed to attach the SHM global_mutex at [%s] rc=%d : %s",
			__FUNCTION__, conf->shm.path, rc, apr_strerror(rc, buff, sizeof(buff)));
		return rc;
	}
	DAV_DEBUG_POOL(plog, 0, "%s : globalmutex attached at [%s]", __FUNCTION__, conf->shm.path);

	/* Atatches the SHM */
	if (!conf->shm.handle) {
		DAV_DEBUG_POOL(plog, 0, "%s : Attaching the SHM segment at [%s]", __FUNCTION__, conf->shm.path);
		rc = apr_shm_attach(&(conf->shm.handle), conf->shm.path, pool);
		if (APR_SUCCESS != rc) {
			DAV_ERROR_POOL(plog, 0, "%s : Failed to attach the SHM segment at [%s] rc=%d : %s",
				__FUNCTION__, conf->shm.path, rc, apr_strerror(rc, buff, sizeof(buff)));
			conf->shm.handle = NULL;
			return rc;
		}
	}
	DAV_DEBUG_POOL(plog, 0, "%s : SHM segment attached at [%s]", __FUNCTION__, conf->shm.path);

	return APR_SUCCESS;
}
Ejemplo n.º 2
0
static const char *
dav_rainx_cmd_gridconfig_sock_timeout(cmd_parms *cmd, void *config, const char *arg1)
{
	dav_rainx_server_conf *conf;
	apr_int64_t socket_timeout;
	char *endstr;
	(void) config;

	DAV_XDEBUG_POOL(cmd->pool, 0, "%s()", __FUNCTION__);

	conf = ap_get_module_config(cmd->server->module_config, &dav_rainx_module);

	socket_timeout = apr_strtoi64(arg1, &endstr, 10);
	if (errno == 0 && *endstr == '\0')
	{
		conf->socket_timeout = socket_timeout;
	}
	else
	{
		DAV_ERROR_POOL(cmd->pool, 0, "Invalid socket timeout, default value will be used");
	}

	DAV_DEBUG_POOL(cmd->pool, 0,
			"Socket timeout for rawx request is %" APR_TIME_T_FMT " microseconds",
			conf->socket_timeout);
	
	return NULL;
}
Ejemplo n.º 3
0
apr_status_t
server_init_master_stat(dav_rawx_server_conf *conf, apr_pool_t *pool, apr_pool_t *plog)
{
	char buff[256];
	apr_status_t rc;

	DAV_XDEBUG_POOL(plog, 0, "%s()", __FUNCTION__);

	/* Try to attach to the already existing SHM segment */
	rc = apr_shm_attach(&(conf->shm.handle), conf->shm.path, pool);
	if (APR_SUCCESS != rc) {
		DAV_DEBUG_POOL(plog, 0, "%s: Failed to attach to SHM segment at [%s]: %s",
				__FUNCTION__, conf->shm.path, apr_strerror(rc, buff, sizeof(buff)));
		conf->shm.handle = NULL;
		return rc;
	}
	DAV_DEBUG_POOL(plog, 0, "%s: Attached to existing SHM segment at [%s]",
			__FUNCTION__, conf->shm.path);

	/* Create a processus lock*/
	rc = apr_global_mutex_create(&(conf->lock.handle), conf->shm.path, APR_LOCK_DEFAULT, pool);
	if (rc != APR_SUCCESS) {
		DAV_ERROR_POOL(plog, 0, "%s : Cannot create a global_mutex at [%s] rc=%d : %s",
			__FUNCTION__, conf->shm.path, rc, apr_strerror(rc, buff, sizeof(buff)));
		(void) apr_shm_destroy(conf->shm.handle);
		conf->shm.handle = NULL;
		return rc;
	}
	DAV_DEBUG_POOL(plog, 0, "%s : globalmutex created at [%s]", __FUNCTION__, conf->shm.path);

	return APR_SUCCESS;
}
Ejemplo n.º 4
0
apr_status_t
server_init_master_stat(dav_rainx_server_conf *conf, apr_pool_t *pool, apr_pool_t *plog)
{
    char buff[256];
    apr_status_t rc;

    DAV_XDEBUG_POOL(plog, 0, "%s()", __FUNCTION__);

    /* Create and attach the segment */
    rc = apr_shm_create(&(conf->shm.handle), sizeof(struct shm_stats_s), conf->shm.path, pool);
    if (APR_SUCCESS != rc) {
        DAV_ERROR_POOL(plog, 0, "%s : Cannot create a SHM segment at [%s] rc=%d : %s",
                       __FUNCTION__, conf->shm.path, rc, apr_strerror(rc, buff, sizeof(buff)));
        conf->shm.handle = NULL;
        return rc;
    }
    DAV_DEBUG_POOL(plog, 0, "%s : SHM segment created at [%s]", __FUNCTION__, conf->shm.path);

    /* Create a processus lock*/
    rc = apr_global_mutex_create(&(conf->lock.handle), conf->lock.path, APR_LOCK_DEFAULT, pool);
    if (rc != APR_SUCCESS) {
        DAV_ERROR_POOL(plog, 0, "%s : Cannot create a global_mutex at [%s] rc=%d : %s",
                       __FUNCTION__, conf->lock.path, rc, apr_strerror(rc, buff, sizeof(buff)));
        (void) apr_shm_destroy(conf->shm.handle);
        conf->shm.handle = NULL;
        return rc;
    }
    DAV_DEBUG_POOL(plog, 0, "%s : globalmutex created at [%s]", __FUNCTION__, conf->lock.path);

    /* Init the SHM */
    void *ptr_counter = apr_shm_baseaddr_get(conf->shm.handle);
    if (ptr_counter) {
        bzero(ptr_counter, sizeof(struct shm_stats_s));
        /* init rrd's */
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_sec));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_duration));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_put_sec));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_put_duration));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_get_sec));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_get_duration));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_del_sec));
        rainx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_del_duration));
    }

    return APR_SUCCESS;
}
Ejemplo n.º 5
0
void
server_master_stat_fini(dav_rawx_server_conf *conf, apr_pool_t *plog)
{
	DAV_XDEBUG_POOL(plog, 0, "%s()", __FUNCTION__);

	if (conf->lock.handle) {
		DAV_DEBUG_POOL(plog, 0, "%s: Destroying the globalmutex at [%s]", __FUNCTION__, conf->shm.path);
		if (APR_SUCCESS != apr_global_mutex_destroy(conf->lock.handle)) {
			DAV_ERROR_POOL(plog, 0, "Failed to destroy the global_mutex");
		}
		conf->lock.handle = NULL;
	}

	if (conf->shm.handle) {
		DAV_DEBUG_POOL(plog, 0, "%s: Detaching the SHM segment at [%s]", __FUNCTION__, conf->shm.path);
		if (APR_SUCCESS != apr_shm_detach(conf->shm.handle)) {
			DAV_ERROR_POOL(plog, 0, "Failed to detach the SHM segment");
		}
		conf->shm.handle = NULL;
	}
}
Ejemplo n.º 6
0
static void
rainx_hook_child_init(apr_pool_t *pchild, server_rec *s)
{
	apr_status_t status;
	dav_rainx_server_conf *conf;
	
	DAV_XDEBUG_POOL(pchild, 0, "%s()", __FUNCTION__);
	conf = ap_get_module_config(s->module_config, &dav_rainx_module);
	conf->cleanup = _stat_cleanup_child;
	
	status = server_init_child_stat(conf, pchild, pchild);
	if (APR_SUCCESS != status)
		DAV_ERROR_POOL(pchild, 0, "Failed to attach the RAWX statistics support");
	
	conf->cleanup = _stat_cleanup_child;
}
Ejemplo n.º 7
0
static apr_status_t
_create_shm_if_needed(char *shm_path, server_rec *server, apr_pool_t *plog)
{
	apr_pool_t *ppool = server->process->pool;
	apr_shm_t *shm = NULL;
	apr_status_t rc;

	// Test if an SHM segment already exists
	apr_pool_userdata_get((void**)&shm, SHM_HANDLE_KEY, ppool);
	if (shm == NULL) {
		DAV_DEBUG_POOL(plog, 0, "%s: Creating SHM segment at [%s]",
				__FUNCTION__, shm_path);
		// Create a new SHM segment
		rc = apr_shm_create(&shm, sizeof(struct shm_stats_s), shm_path, ppool);
		if (rc != APR_SUCCESS) {
			char buff[256];
			DAV_ERROR_POOL(plog, 0, "Failed to create the SHM segment at [%s]: %s",
					shm_path, apr_strerror(rc, buff, sizeof(buff)));
			return rc;
		}
		/* Init the SHM */
		void *ptr_counter = apr_shm_baseaddr_get(shm);
		if (ptr_counter) {
			memset(ptr_counter, 0, sizeof(struct shm_stats_s));
			/* init rrd's */
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_sec));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_duration));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_put_sec));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_put_duration));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_get_sec));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_get_duration));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_req_del_sec));
			rawx_stats_rrd_init(&(((struct shm_stats_s *) ptr_counter)->body.rrd_del_duration));
		}
		// Save the SHM handle in the process' pool, without cleanup callback
		apr_pool_userdata_set(shm, SHM_HANDLE_KEY, NULL, ppool);
		// Register the cleanup callback to be executed BEFORE pool cleanup
		apr_pool_pre_cleanup_register(ppool, shm, _destroy_shm_cb);
	} else {
		DAV_DEBUG_POOL(plog, 0, "%s: Found an already created SHM segment",
				__FUNCTION__);
	}
	return APR_SUCCESS;
}
Ejemplo n.º 8
0
apr_status_t
server_child_stat_fini(dav_rawx_server_conf *conf, apr_pool_t *plog)
{
	char buff[256];
	apr_status_t rc;

	DAV_XDEBUG_POOL(plog, 0, "%s()", __FUNCTION__);

	/* Detaches the segment */
	if (conf->shm.handle) {
		rc = apr_shm_detach(conf->shm.handle);
		if (APR_SUCCESS != rc) {
			DAV_ERROR_POOL(plog, 0, "Failed to detach SHM segment at [%s] rc=%d : %s",
					conf->shm.path, rc, apr_strerror(rc, buff, sizeof(buff)));
			return rc;
		}
		conf->shm.handle = NULL;
	}

	DAV_DEBUG_POOL(plog, 0, "%s: SHM segment at [%s] detached", __FUNCTION__, conf->shm.path);
	return APR_SUCCESS;
}
Ejemplo n.º 9
0
apr_status_t
rainx_http_req(struct req_params_store* rps) {
	const dav_resource* resource = rps->resource;
	char* remote_uri = rps->service_address;
	char* req_type = rps->req_type;
	char* header = rps->header;
	char* data = rps->data_to_send;
	int data_length = rps->data_to_send_size;
	char** reply = &(rps->reply);
	apr_pool_t *local_pool = rps->pool;
	dav_rainx_server_conf *server_conf = resource_get_server_config(resource);

	if (NULL == resource || NULL == remote_uri ||
			NULL == req_type || NULL == server_conf) {
		DAV_ERROR_POOL(local_pool, APR_EINVAL, "One of these params is wrong: "
				"remote_uri=%p, req_type=%p, server_conf=%p"
				" (__FILE__:__LINE__)",
				remote_uri, req_type, server_conf);
		return APR_EINVAL;
	}

	const gboolean is_get = (0 == g_strcmp0(req_type, "GET"));

	/* Isolating Rawx IP and port */
	char *temp_remote_uri = apr_pstrdup(local_pool, remote_uri);
	char* last;
	char* full_remote_url = apr_strtok(temp_remote_uri, "/", &last);
	char* content_hexid = apr_pstrdup(local_pool, remote_uri + strlen(full_remote_url));

	char* remote_ip = NULL;
	char* scope_id = NULL;
	apr_port_t remote_port;
	apr_parse_addr_port(&remote_ip, &scope_id, &remote_port, full_remote_url, local_pool);
	/* ------- */

	/* Preparing the socket */
	apr_socket_t* sock;
	apr_sockaddr_t* sockaddr;
	apr_status_t status;

	if ((status = apr_sockaddr_info_get(&sockaddr, remote_ip, APR_INET, remote_port, 0, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to connect to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_create(&sock, sockaddr->family, SOCK_STREAM, APR_PROTO_TCP, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to create a socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_timeout_set(sock, server_conf->socket_timeout)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to set timeout for the socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_connect(sock, sockaddr)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to establish the connection to the rawx %s", full_remote_url);
		return status;
	}
	/* ------- */

	/* Forging the message */
	char* forged_header = apr_psprintf(local_pool, "%s %s HTTP/1.1\nHost: %s", req_type, content_hexid, full_remote_url);
	if (header)
		forged_header = apr_psprintf(local_pool, "%s\n%s", forged_header, header);
	if (data)
		forged_header = apr_psprintf(local_pool, "%s\nContent-Length: %d\n\n", forged_header, data_length);
	else
		forged_header = apr_psprintf(local_pool, "%s\n\n", forged_header);
	/* ------- */

	/* Sending the message */
	int remaining_to_send = strlen(forged_header);
	char* ptr_start = forged_header;
	apr_size_t send_buffer_size;
	while (remaining_to_send > 0) {
		if (remaining_to_send < REQUEST_BUFFER_SIZE)
			send_buffer_size = (apr_size_t)remaining_to_send;
		else
			send_buffer_size = REQUEST_BUFFER_SIZE;

		if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
            DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
            apr_status_t status_sav = status;
            apr_socket_close(sock);
            return status_sav;
        }

		remaining_to_send -= send_buffer_size;
		ptr_start = ptr_start + send_buffer_size;
	}
	if (NULL != data) {
		remaining_to_send = data_length;
		ptr_start = data;
		while (remaining_to_send > 0) {
			if (remaining_to_send < REQUEST_BUFFER_SIZE)
				send_buffer_size = (apr_size_t)remaining_to_send;
			else
				send_buffer_size = REQUEST_BUFFER_SIZE;

			if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
				DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
				apr_status_t status_sav = status;
				apr_socket_close(sock);
				return status_sav;
			}

			remaining_to_send -= send_buffer_size;
			ptr_start = ptr_start + send_buffer_size;
		}
	}

	if (is_get) {
		/* This avoids a ~5s delay in the communication */
		apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
	}

	DAV_DEBUG_REQ(resource->info->request, 0, "%s request to the rawx %s sent for the content %s", req_type, full_remote_url, content_hexid);
    /* ------ */

	/* Getting the reply */
	char* reply_ptr = *reply;
	apr_size_t total_size;
	if (!is_get)
		total_size = REPLY_BUFFER_SIZE; // PUT or DELETE
	else
		total_size = MAX_REPLY_HEADER_SIZE + data_length; // GET
	apr_size_t reply_size = (apr_size_t)total_size;
	apr_size_t total_replied_size;
	do {
		status = apr_socket_recv(sock, reply_ptr, &reply_size);
		reply_ptr += reply_size;
		total_replied_size = reply_ptr - *reply;
		/* Leave when OK, or error != timeout, or buffer full */
        if (status == APR_EOF || (status == APR_SUCCESS && !is_get) ||
				(reply_size == 0) ||
				total_replied_size >= total_size) {
            break;
		}
		/* Take care of overflows! */
		reply_size = total_size - total_replied_size;
	} while (total_replied_size < total_size);
	/* ------- */

	apr_socket_close(sock);

	return status;
}
Ejemplo n.º 10
0
static int
rainx_hook_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *server)
{
	apr_status_t status;
	server_rec *s;
	server_addr_rec *a;
	dav_rainx_server_conf *conf;
	GError *gerr;

	(void) ptemp;
	DAV_XDEBUG_POOL(plog, 0, "%s(%lx)", __FUNCTION__, (long)server);

	if (__rainx_is_first_call(server)) {
		DAV_DEBUG_POOL(plog, 0, "First call detected");
		return OK;
	}

	DAV_DEBUG_POOL(plog, 0, "Second call detected");

	gerr = NULL;
	conf = ap_get_module_config(server->module_config, &dav_rainx_module);

	/* perform some options consistency checks */
	if (!(conf->headers_scheme & HEADER_SCHEME_V1) &&
			!(conf->headers_scheme & HEADER_SCHEME_V2)) {
		DAV_ERROR_POOL(plog, 0, "You cannot disable both V1 and V2 header scheme");
		return DONE;
	}

	DAV_XDEBUG_POOL(plog, 0, "Checking the docroot XATTR lock for [%s]", conf->docroot);

	/* Runs the configured servers and check they do not serve
	 * the grid docroot with an unauthorized IP:PORT couple */
	for (s = server ; s ; s = s->next) {

		for (a = s->addrs ; a ; a = a->next) {
			char *host = NULL, url[512];

			if (gerr)
				g_clear_error(&gerr);
			if (a->host_port == 0)
				continue;

			host = NULL;
			status = apr_getnameinfo(&host, a->host_addr, NI_NUMERICSERV|NI_NUMERICHOST|NI_NOFQDN);
			if (status != APR_SUCCESS || host == NULL) {
				DAV_ERROR_POOL(plog, 0, "getnameinfo() failed : %d", status);
				continue;
			}

			apr_snprintf(url, sizeof(url), "%s:%d", host, a->host_port);
			DAV_DEBUG_POOL(plog, 0, "xattr-lock : testing addr [%s]", url);
		}
	}
	
	if (gerr)
		g_clear_error(&gerr);

	/* Init the stat support : doing this so late avoids letting orphan
	 * SHM segments in the nature in case of previous errors */
	status = server_init_master_stat(conf, pconf, plog);
	if (APR_SUCCESS != status) {
		DAV_ERROR_POOL(plog, 0, "Failed to init the RAINX statistics support");
		return DONE;
	}
	else {
		/* This will be overwritten by the child_init */
		conf->cleanup = _stat_cleanup_master;
		apr_pool_userdata_set(conf, apr_psprintf(pconf, "RAINX-config-to-be-cleaned-%d", i++),
				_stat_cleanup_to_register, pconf);
	}

	return OK;
}
Ejemplo n.º 11
0
static int
rawx_hook_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp,
		server_rec *server)
{
	apr_status_t status;
	enum lock_state_e state;
	server_rec *s;
	server_addr_rec *a;
	dav_rawx_server_conf *conf;
	GError *gerr;
	int volume_validated = 0;

	(void) ptemp;
	DAV_XDEBUG_POOL(plog, 0, "%s(%lx)", __FUNCTION__, (long)server);

	if (__rawx_is_first_call(server)) {
		DAV_DEBUG_POOL(plog, 0, "First call detected");
		return OK;
	}

	DAV_DEBUG_POOL(plog, 0, "Second call detected");

	gerr = NULL;
	conf = ap_get_module_config(server->module_config, &dav_rawx_module);

	DAV_XDEBUG_POOL(plog, 0, "Checking the docroot XATTR lock for [%s]",
			conf->docroot);

	/* Runs the configured servers and check they do not serve
	 * the grid docroot with an unauthorized IP:PORT couple */
	for (s = server ; s ; s = s->next) {

		for (a = s->addrs ; a ; a = a->next) {
			apr_status_t status2;
			char *host = NULL, url[512];

			if (gerr)
				g_clear_error(&gerr);
			if (a->host_port == 0)
				continue;

			host = NULL;
			status2 = apr_getnameinfo(&host, a->host_addr,
					NI_NUMERICSERV|NI_NUMERICHOST|NI_NOFQDN);
			if (status2 != APR_SUCCESS || host == NULL) {
				DAV_ERROR_POOL(plog, 0, "getnameinfo() failed : %d", status2);
				continue;
			}

			apr_snprintf(url, sizeof(url), "%s:%d", host, a->host_port);
			DAV_DEBUG_POOL(plog, 0, "xattr-lock : testing addr [%s]", url);

			state = rawx_get_volume_lock_state(conf->docroot, conf->ns_name,
					url, &gerr);
			switch (state) {

				case ERROR_LS:
					DAV_ERROR_POOL(plog, 0, "Failed to check the docroot ownership: %s",
							gerror_get_message(gerr));
					goto label_error;

				case NOLOCK_LS:
					if (!rawx_lock_volume(conf->docroot, conf->ns_name, url, 0, &gerr)) {
						DAV_ERROR_POOL(plog, 0, "Failed to grab the docroot ownership: %s",
								gerror_get_message(gerr));
						goto label_error;
					}
					DAV_DEBUG_POOL(plog, 0, "Docroot now owned");
					volume_validated = ~0;
					break;

				case OWN_LS:
					DAV_DEBUG_POOL(plog, 0, "Docroot already owned by the current server");
					if (!rawx_lock_volume(conf->docroot, conf->ns_name, url,
							RAWXLOCK_FLAG_OVERWRITE, &gerr))
						DAV_ERROR_POOL(plog, 0, "Failed to complete the docroot ownership: %s",
							gerror_get_message(gerr));
					volume_validated = ~0;
					break;

				case OTHER_LS:
					DAV_ERROR_POOL(plog, 0, "Another RAWX already used the docroot (see XATTR)"
							" : %s", gerror_get_message(gerr));
					goto label_error;
			}
		}
	}

	if (gerr)
		g_clear_error(&gerr);

	if (!volume_validated) {
		DAV_ERROR_POOL(plog, 0, "No server found, could not validate the RAWX volume. "
			"Did you declare at least one VirtualHost ?");
		goto label_error;
	}

	if (_create_shm_if_needed(conf->shm.path, server, plog) != APR_SUCCESS) {
		DAV_ERROR_POOL(plog, 0, "Failed to init the RAWX statistics support");
		return DONE;
	}

	/* Init the stat support : doing this so late avoids letting orphan
	 * SHM segments in the nature in case of previous errors */
	status = server_init_master_stat(conf, pconf, plog);
	if (APR_SUCCESS != status) {
		DAV_ERROR_POOL(plog, 0, "Failed to init the RAWX statistics support");
		return DONE;
	}
	else {
		/* This will be overwritten by the child_init */
		conf->cleanup = _stat_cleanup_master;
		apr_pool_userdata_set(conf, apr_psprintf(pconf,
				"RAWX-config-to-be-cleaned-%d", i++),
				_stat_cleanup_to_register, pconf);
	}

	return OK;

label_error:
	if (gerr)
		g_clear_error(&gerr);
	return DONE;
}