mod_netconf: hopefuly "stable" version

- refactoring
- locking strategy revision
diff --git a/src/mod_netconf.c b/src/mod_netconf.c
index 1bc0390..b1c8555 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -106,7 +106,8 @@
 
 module AP_MODULE_DECLARE_DATA netconf_module;
 
-pthread_rwlock_t session_lock; /**< mutex protecting netconf_session_list from multiple access errors */
+pthread_rwlock_t session_lock; /**< mutex protecting netconf_sessions_list from multiple access errors */
+apr_hash_t *netconf_sessions_list = NULL;
 
 volatile int isterminated = 0;
 
@@ -206,6 +207,9 @@
 	if (sid) json_object_object_add(err_reply, "session-id", json_object_new_string(sid));
 }
 
+/**
+ * should be used in locked area
+ */
 void prepare_status_message(server_rec* server, struct session_with_mutex *s, struct nc_session *session)
 {
 	json_object *json_obj = NULL;
@@ -270,7 +274,7 @@
  *
  * \warning Session_key hash is not bound with caller identification. This could be potential security risk.
  */
-static char* netconf_connect(server_rec* server, apr_pool_t* pool, apr_hash_t* conns, const char* host, const char* port, const char* user, const char* pass, struct nc_cpblts * cpblts)
+static char* netconf_connect(server_rec* server, apr_pool_t* pool, const char* host, const char* port, const char* user, const char* pass, struct nc_cpblts * cpblts)
 {
 	struct nc_session* session = NULL;
 	struct session_with_mutex * locked_session;
@@ -308,23 +312,28 @@
 		if (pthread_rwlock_wrlock (&session_lock) != 0) {
 			nc_session_free(session);
 			free (locked_session);
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 			return NULL;
 		}
 		locked_session->notifications = apr_array_make(pool, NOTIFICATION_QUEUE_SIZE, sizeof(notification_t));
 		locked_session->ntfc_subscribed = 0;
 		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "Add connection to the list");
-		apr_hash_set(conns, apr_pstrdup(pool, session_key), APR_HASH_KEY_STRING, (void *) locked_session);
+		apr_hash_set(netconf_sessions_list, apr_pstrdup(pool, session_key), APR_HASH_KEY_STRING, (void *) locked_session);
 		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "Before session_unlock");
 
+		/* lock session */
+		pthread_mutex_lock(&locked_session->lock);
+
+		/* unlock session list */
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
+
 		/* store information about session from hello message for future usage */
 		prepare_status_message(server, locked_session, session);
 
-		/* end of critical section */
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return NULL;
-		}
+		pthread_mutex_unlock(&locked_session->lock);
+
 		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "NETCONF session established");
 		return (session_key);
 	} else {
@@ -334,85 +343,72 @@
 
 }
 
-static int netconf_close(server_rec* server, apr_hash_t* conns, const char* session_key)
+static int close_and_free_session(server_rec *server, struct session_with_mutex *locked_session)
 {
-	struct nc_session *ns = NULL;
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock private lock.");
+	if (pthread_mutex_lock(&locked_session->lock) != 0) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock");
+	}
+	locked_session->ntfc_subscribed = 0;
+	locked_session->closed = 1;
+	nc_session_close(locked_session->session, NC_SESSION_TERM_CLOSED);
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "session closed.");
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock private lock.");
+	if (pthread_mutex_unlock(&locked_session->lock) != 0) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock");
+	}
+
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "closed session, disabled notif(?), wait 2s");
+	usleep(500000); /* let notification thread stop */
+
+	/* session shouldn't be used by now */
+	/** \todo free all notifications from queue */
+	apr_array_clear(locked_session->notifications);
+	pthread_mutex_destroy(&locked_session->lock);
+	if (locked_session->hello_message != NULL) {
+		/** \todo free hello_message */
+		//json_object_put(locked_session->hello_message);
+		locked_session->hello_message = NULL;
+	}
+	nc_session_free(locked_session->session);
+	locked_session->session = NULL;
+	free (locked_session);
+	locked_session = NULL;
+	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "NETCONF session closed, everything cleared.");
+	return (EXIT_SUCCESS);
+}
+
+static int netconf_close(server_rec* server, const char* session_key)
+{
 	struct session_with_mutex * locked_session;
 
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Key in hash to close: %s", session_key);
+
 	/* get exclusive (write) access to sessions_list (conns) */
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock session lock.");
 	if (pthread_rwlock_wrlock (&session_lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock");
 		return EXIT_FAILURE;
 	}
-	locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
-	if (locked_session != NULL) {
-		/** \todo free all notifications from queue */
-		ns = locked_session->session;
-	}
-	if (ns != NULL) {
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock private lock.");
-		if (pthread_mutex_lock(&locked_session->lock) != 0) {
-			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
-		locked_session->ntfc_subscribed = 0;
-		locked_session->closed = 1;
-		nc_session_close (ns, NC_SESSION_TERM_CLOSED);
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "session closed.");
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock private lock.");
-		if (pthread_mutex_unlock(&locked_session->lock) != 0) {
-			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "closed session, disabled notif(?), wait 2s");
-		sleep(2); /* let notification thread stop */
-		/* remove session from the active sessions list */
-		apr_hash_set(conns, session_key, APR_HASH_KEY_STRING, NULL);
-		/* end of critical section */
+	/* get session to close */
+	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
+	/* remove session from the active sessions list -> nobody new can now work with session */
+	apr_hash_set(netconf_sessions_list, session_key, APR_HASH_KEY_STRING, NULL);
 
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock session lock.");
-		if (pthread_rwlock_wrlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
-		/** \todo free all notifications from queue */
-		apr_array_clear(locked_session->notifications);
-		pthread_mutex_destroy(&locked_session->lock);
-		ns = locked_session->session;
-		if (locked_session->hello_message != NULL) {
-			json_object_put(locked_session->hello_message);
-			locked_session->hello_message = NULL;
-		}
-		nc_session_free(ns);
-		ns = NULL;
-		free (locked_session);
-		locked_session = NULL;
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "NETCONF session closed, everything cleared.");
-		return (EXIT_SUCCESS);
+	if (pthread_rwlock_unlock (&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock");
+	}
+
+	if ((locked_session != NULL) && (locked_session->session != NULL)) {
+		return close_and_free_session(server, locked_session);
 	} else {
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to close");
 		return (EXIT_FAILURE);
 	}
 }
 
-static int netconf_op(server_rec* server, apr_hash_t* conns, const char* session_key, nc_rpc* rpc)
+int netconf_op(server_rec* server, const char* session_key, nc_rpc* rpc)
 {
 	struct nc_session *session = NULL;
 	struct session_with_mutex * locked_session;
@@ -429,11 +425,11 @@
 
 	/* get non-exclusive (read) access to sessions_list (conns) */
 	if (pthread_rwlock_rdlock (&session_lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 		return EXIT_FAILURE;
 	}
 	/* get session where send the RPC */
-	locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
+	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	if (locked_session != NULL) {
 		session = locked_session->session;
 	}
@@ -442,11 +438,15 @@
 		if (pthread_mutex_lock(&locked_session->lock) != 0) {
 			/* unlock before returning error */
 			if (pthread_rwlock_unlock (&session_lock) != 0) {
-				ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+				ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 				return EXIT_FAILURE;
 			}
 			return EXIT_FAILURE;
 		}
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		}
+
 		locked_session->last_activity = apr_time_now();
 		/* send the request and get the reply */
 		msgt = nc_session_send_recv(session, rpc, &reply);
@@ -454,17 +454,13 @@
 		/* first release exclusive lock for this session */
 		pthread_mutex_unlock(&locked_session->lock);
 		/* end of critical section */
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return EXIT_FAILURE;
-		}
 
 		/* process the result of the operation */
 		switch (msgt) {
 		case NC_MSG_UNKNOWN:
 			if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
 				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: receiving rpc-reply failed");
-				netconf_close(server, conns, session_key);
+				netconf_close(server, session_key);
 				return (EXIT_FAILURE);
 			}
 			/* no break */
@@ -493,14 +489,14 @@
 	} else {
 		/* release lock on failure */
 		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 		}
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to process.");
 		return (EXIT_FAILURE);
 	}
 }
 
-static char* netconf_opdata(server_rec* server, apr_hash_t* conns, const char* session_key, nc_rpc* rpc)
+static char* netconf_opdata(server_rec* server, const char* session_key, nc_rpc* rpc)
 {
 	struct nc_session *session = NULL;
 	struct session_with_mutex * locked_session;
@@ -517,11 +513,11 @@
 
 	/* get non-exclusive (read) access to sessions_list (conns) */
 	if (pthread_rwlock_rdlock (&session_lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 		return NULL;
 	}
 	/* get session where send the RPC */
-	locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
+	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	if (locked_session != NULL) {
 		session = locked_session->session;
 	}
@@ -530,29 +526,26 @@
 		if (pthread_mutex_lock(&locked_session->lock) != 0) {
 			/* unlock before returning error */
 			if (pthread_rwlock_unlock (&session_lock) != 0) {
-				ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-				return NULL;
+				ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 			}
 			return NULL;
 		}
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		locked_session->last_activity = apr_time_now();
 		/* send the request and get the reply */
 		msgt = nc_session_send_recv(session, rpc, &reply);
 
 		/* first release exclusive lock for this session */
 		pthread_mutex_unlock(&locked_session->lock);
-		/* end of critical section */
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return (NULL);
-		}
 
 		/* process the result of the operation */
 		switch (msgt) {
 		case NC_MSG_UNKNOWN:
 			if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
 				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: receiving rpc-reply failed");
-				netconf_close(server, conns, session_key);
+				netconf_close(server, session_key);
 				return (NULL);
 			}
 			/* no break */
@@ -584,14 +577,14 @@
 	} else {
 		/* release lock on failure */
 		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 		}
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to process.");
 		return (NULL);
 	}
 }
 
-static char* netconf_getconfig(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE source, const char* filter)
+static char* netconf_getconfig(server_rec* server, const char* session_key, NC_DATASTORE source, const char* filter)
 {
 	nc_rpc* rpc;
 	struct nc_filter *f = NULL;
@@ -610,12 +603,12 @@
 		return (NULL);
 	}
 
-	data = netconf_opdata(server, conns, session_key, rpc);
+	data = netconf_opdata(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (data);
 }
 
-static char* netconf_getschema(server_rec* server, apr_hash_t* conns, const char* session_key, const char* identifier, const char* version, const char* format)
+static char* netconf_getschema(server_rec* server, const char* session_key, const char* identifier, const char* version, const char* format)
 {
 	nc_rpc* rpc;
 	char* data = NULL;
@@ -627,12 +620,12 @@
 		return (NULL);
 	}
 
-	data = netconf_opdata(server, conns, session_key, rpc);
+	data = netconf_opdata(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (data);
 }
 
-static char* netconf_get(server_rec* server, apr_hash_t* conns, const char* session_key, const char* filter)
+static char* netconf_get(server_rec* server, const char* session_key, const char* filter)
 {
 	nc_rpc* rpc;
 	struct nc_filter *f = NULL;
@@ -651,12 +644,12 @@
 		return (NULL);
 	}
 
-	data = netconf_opdata(server, conns, session_key, rpc);
+	data = netconf_opdata(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (data);
 }
 
-static int netconf_copyconfig(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE source, NC_DATASTORE target, const char* config, const char *url)
+static int netconf_copyconfig(server_rec* server, const char* session_key, NC_DATASTORE source, NC_DATASTORE target, const char* config, const char *url)
 {
 	nc_rpc* rpc;
 	int retval = EXIT_SUCCESS;
@@ -680,12 +673,12 @@
 		return (EXIT_FAILURE);
 	}
 
-	retval = netconf_op(server, conns, session_key, rpc);
+	retval = netconf_op(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (retval);
 }
 
-static int netconf_editconfig(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE target, NC_EDIT_DEFOP_TYPE defop, NC_EDIT_ERROPT_TYPE erropt, NC_EDIT_TESTOPT_TYPE testopt, const char* config)
+static int netconf_editconfig(server_rec* server, const char* session_key, NC_DATASTORE target, NC_EDIT_DEFOP_TYPE defop, NC_EDIT_ERROPT_TYPE erropt, NC_EDIT_TESTOPT_TYPE testopt, const char* config)
 {
 	nc_rpc* rpc;
 	int retval = EXIT_SUCCESS;
@@ -698,12 +691,12 @@
 		return (EXIT_FAILURE);
 	}
 
-	retval = netconf_op(server, conns, session_key, rpc);
+	retval = netconf_op(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (retval);
 }
 
-static int netconf_killsession(server_rec* server, apr_hash_t* conns, const char* session_key, const char* sid)
+static int netconf_killsession(server_rec* server, const char* session_key, const char* sid)
 {
 	nc_rpc* rpc;
 	int retval = EXIT_SUCCESS;
@@ -715,12 +708,12 @@
 		return (EXIT_FAILURE);
 	}
 
-	retval = netconf_op(server, conns, session_key, rpc);
+	retval = netconf_op(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (retval);
 }
 
-static int netconf_onlytargetop(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE target, nc_rpc* (*op_func)(NC_DATASTORE))
+static int netconf_onlytargetop(server_rec* server, const char* session_key, NC_DATASTORE target, nc_rpc* (*op_func)(NC_DATASTORE))
 {
 	nc_rpc* rpc;
 	int retval = EXIT_SUCCESS;
@@ -732,12 +725,12 @@
 		return (EXIT_FAILURE);
 	}
 
-	retval = netconf_op(server, conns, session_key, rpc);
+	retval = netconf_op(server, session_key, rpc);
 	nc_rpc_free (rpc);
 	return (retval);
 }
 
-static int netconf_deleteconfig(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE target)
+static int netconf_deleteconfig(server_rec* server, const char* session_key, NC_DATASTORE target)
 {
 	nc_rpc *rpc = NULL;
 	if (target != NC_DATASTORE_URL) {
@@ -748,17 +741,17 @@
 		return (EXIT_FAILURE);
 	}
 
-	return netconf_op(server, conns, session_key, rpc);
+	return netconf_op(server, session_key, rpc);
 }
 
-static int netconf_lock(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE target)
+static int netconf_lock(server_rec* server, const char* session_key, NC_DATASTORE target)
 {
-	return (netconf_onlytargetop(server, conns, session_key, target, nc_rpc_lock));
+	return (netconf_onlytargetop(server, session_key, target, nc_rpc_lock));
 }
 
-static int netconf_unlock(server_rec* server, apr_hash_t* conns, const char* session_key, NC_DATASTORE target)
+static int netconf_unlock(server_rec* server, const char* session_key, NC_DATASTORE target)
 {
-	return (netconf_onlytargetop(server, conns, session_key, target, nc_rpc_unlock));
+	return (netconf_onlytargetop(server, session_key, target, nc_rpc_unlock));
 }
 
 /**
@@ -766,9 +759,9 @@
  *         REPLY_DATA: 0, *data != NULL
  *         REPLY_ERROR: 1, *data == NULL
  */
-static int netconf_generic(server_rec* server, apr_hash_t* conns, const char* session_key, const char* content, char** data)
+static int netconf_generic(server_rec* server, const char* session_key, const char* content, char** data)
 {
-	struct nc_session *session = NULL;
+	struct session_with_mutex *session = NULL;
 	nc_reply* reply = NULL;
 	nc_rpc* rpc = NULL;
 	int retval = EXIT_SUCCESS;
@@ -786,19 +779,28 @@
 		*data = NULL;
 	}
 
+	if (pthread_rwlock_rdlock(&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		return EXIT_FAILURE;
+	}
 	/* get session where send the RPC */
-	session = (struct nc_session *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
+	session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	if (session != NULL) {
+		pthread_mutex_lock(&session->lock);
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		/* send the request and get the reply */
-		msgt = nc_session_send_recv(session, rpc, &reply);
-		nc_rpc_free (rpc);
+		msgt = nc_session_send_recv(session->session, rpc, &reply);
+		nc_rpc_free(rpc);
+		pthread_mutex_unlock(&session->lock);
 
 		/* process the result of the operation */
 		switch (msgt) {
 		case NC_MSG_UNKNOWN:
-			if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
+			if (nc_session_get_status(session->session) != NC_SESSION_STATUS_WORKING) {
 				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: receiving rpc-reply failed");
-				netconf_close(server, conns, session_key);
+				netconf_close(server, session_key);
 				return (EXIT_FAILURE);
 			}
 			/* no break */
@@ -835,6 +837,10 @@
 		return (retval);
 	} else {
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to process.");
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			return EXIT_FAILURE;
+		}
 		return (EXIT_FAILURE);
 	}
 }
@@ -975,7 +981,7 @@
 	return reply;
 }
 
-json_object *handle_op_connect(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list)
+json_object *handle_op_connect(server_rec *server, apr_pool_t *pool, json_object *request)
 {
 	const char *host = NULL;
 	const char *port = NULL;
@@ -1008,7 +1014,7 @@
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Cannot connect - insufficient input.");
 		session_key_hash = NULL;
 	} else {
-		session_key_hash = netconf_connect(server, pool, netconf_sessions_list, host, port, user, pass, cpblts);
+		session_key_hash = netconf_connect(server, pool, host, port, user, pass, cpblts);
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "hash: %s", session_key_hash);
 	}
 	if (cpblts != NULL) {
@@ -1038,7 +1044,7 @@
 	return reply;
 }
 
-json_object *handle_op_get(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_get(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	const char *filter = NULL;
 	const char *data = NULL;
@@ -1048,7 +1054,7 @@
 
 	filter = json_object_get_string(json_object_object_get(request, "filter"));
 
-	if ((data = netconf_get(server, netconf_sessions_list, session_key, filter)) == NULL) {
+	if ((data = netconf_get(server, session_key, filter)) == NULL) {
 		if (err_reply == NULL) {
 			reply = create_error("Get information from device failed.");
 		} else {
@@ -1061,7 +1067,7 @@
 	return reply;
 }
 
-json_object *handle_op_getconfig(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_getconfig(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	NC_DATASTORE ds_type_s = -1;
 	NC_DATASTORE ds_type_t = -1;
@@ -1086,7 +1092,7 @@
 		return create_error("Invalid source repository type requested.");
 	}
 
-	if ((data = netconf_getconfig(server, netconf_sessions_list, session_key, ds_type_s, filter)) == NULL) {
+	if ((data = netconf_getconfig(server, session_key, ds_type_s, filter)) == NULL) {
 		if (err_reply == NULL) {
 			reply = create_error("Get configuration information from device failed.");
 		} else {
@@ -1099,7 +1105,7 @@
 	return reply;
 }
 
-json_object *handle_op_getschema(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_getschema(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	const char *data = NULL;
 	const char *identifier = NULL;
@@ -1116,7 +1122,7 @@
 	format = json_object_get_string(json_object_object_get(request, "format"));
 
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "get-schema(version: %s, format: %s)", version, format);
-	if ((data = netconf_getschema(server, netconf_sessions_list, session_key, identifier, version, format)) == NULL) {
+	if ((data = netconf_getschema(server, session_key, identifier, version, format)) == NULL) {
 		if (err_reply == NULL) {
 			reply = create_error("Get schema failed.");
 		} else {
@@ -1129,7 +1135,7 @@
 	return reply;
 }
 
-json_object *handle_op_editconfig(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_editconfig(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	NC_DATASTORE ds_type_s = -1;
 	NC_DATASTORE ds_type_t = -1;
@@ -1190,7 +1196,7 @@
 		return create_error("Invalid config data parameter.");
 	}
 
-	if (netconf_editconfig(server, netconf_sessions_list, session_key, ds_type_t, defop_type, erropt_type, NC_EDIT_TESTOPT_NOTSET, config) != EXIT_SUCCESS) {
+	if (netconf_editconfig(server, session_key, ds_type_t, defop_type, erropt_type, NC_EDIT_TESTOPT_NOTSET, config) != EXIT_SUCCESS) {
 		if (err_reply == NULL) {
 			reply = create_error("Edit-config failed.");
 		} else {
@@ -1204,7 +1210,7 @@
 	return reply;
 }
 
-json_object *handle_op_copyconfig(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_copyconfig(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	NC_DATASTORE ds_type_s = -1;
 	NC_DATASTORE ds_type_t = -1;
@@ -1239,7 +1245,7 @@
 	if (source == NULL && config == NULL) {
 		reply = create_error("invalid input parameters - one of source and config is required.");
 	} else {
-		if (netconf_copyconfig(server, netconf_sessions_list, session_key, ds_type_s, ds_type_t, config, "") != EXIT_SUCCESS) {
+		if (netconf_copyconfig(server, session_key, ds_type_s, ds_type_t, config, "") != EXIT_SUCCESS) {
 			if (err_reply == NULL) {
 				reply = create_error("Copying of configuration failed.");
 			} else {
@@ -1254,7 +1260,7 @@
 	return reply;
 }
 
-json_object *handle_op_generic(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_generic(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	json_object *reply = NULL;
 	const char *config = NULL;
@@ -1268,7 +1274,7 @@
 		return create_error("Missing content parameter.");
 	}
 
-	if (netconf_generic(server, netconf_sessions_list, session_key, config, &data) != EXIT_SUCCESS) {
+	if (netconf_generic(server, session_key, config, &data) != EXIT_SUCCESS) {
 		if (err_reply == NULL) {
 			reply = create_error("Killing of session failed.");
 		} else {
@@ -1286,12 +1292,12 @@
 	return reply;
 }
 
-json_object *handle_op_disconnect(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_disconnect(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	json_object *reply = NULL;
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: Disconnect session %s", session_key);
 
-	if (netconf_close(server, netconf_sessions_list, session_key) != EXIT_SUCCESS) {
+	if (netconf_close(server, session_key) != EXIT_SUCCESS) {
 		if (err_reply == NULL) {
 			reply = create_error("Invalid session identifier.");
 		} else {
@@ -1305,7 +1311,7 @@
 	return reply;
 }
 
-json_object *handle_op_kill(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_kill(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	json_object *reply = NULL;
 	const char *sid = NULL;
@@ -1318,7 +1324,7 @@
 		return create_error("Missing session-id parameter.");
 	}
 
-	if (netconf_killsession(server, netconf_sessions_list, session_key, sid) != EXIT_SUCCESS) {
+	if (netconf_killsession(server, session_key, sid) != EXIT_SUCCESS) {
 		if (err_reply == NULL) {
 			reply = create_error("Killing of session failed.");
 		} else {
@@ -1332,16 +1338,26 @@
 	return reply;
 }
 
-json_object *handle_op_reloadhello(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_reloadhello(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
+	struct nc_session *temp_session = NULL;
 	struct session_with_mutex * locked_session = NULL;
 	json_object *reply = NULL;
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: get info about session %s", session_key);
 
+	if (pthread_rwlock_rdlock(&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		return NULL;
+	}
+
 	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	if ((locked_session != NULL) && (locked_session->hello_message != NULL)) {
+		pthread_mutex_lock(&locked_session->lock);
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "creating temporal NC session.");
-		struct nc_session *temp_session = nc_session_connect_channel(locked_session->session, NULL);
+		temp_session = nc_session_connect_channel(locked_session->session, NULL);
 		if (temp_session != NULL) {
 			prepare_status_message(server, locked_session, temp_session);
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "closing temporal NC session.");
@@ -1350,7 +1366,11 @@
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Reload hello failed due to channel establishment");
 			reply = create_error("Reload was unsuccessful, connection failed.");
 		}
+		pthread_mutex_unlock(&locked_session->lock);
 	} else {
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		reply = create_error("Invalid session identifier.");
 	}
 
@@ -1360,23 +1380,36 @@
 	return reply;
 }
 
-json_object *handle_op_info(server_rec *server, apr_pool_t *pool, json_object *request, apr_hash_t *netconf_sessions_list, const char *session_key)
+json_object *handle_op_info(server_rec *server, apr_pool_t *pool, json_object *request, const char *session_key)
 {
 	json_object *reply = NULL;
-	struct session_with_mutex * locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
+	struct session_with_mutex * locked_session = NULL;
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: get info about session %s", session_key);
 
+	if (pthread_rwlock_rdlock(&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+	}
+
 	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	if (locked_session != NULL) {
+		pthread_mutex_lock(&locked_session->lock);
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		if (locked_session->hello_message != NULL) {
 			reply = locked_session->hello_message;
 		} else {
 			reply = create_error("Invalid session identifier.");
 		}
+		pthread_mutex_unlock(&locked_session->lock);
 	} else {
+		if (pthread_rwlock_unlock(&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		}
 		reply = create_error("Invalid session identifier.");
 	}
 
+
 	return reply;
 }
 
@@ -1396,7 +1429,6 @@
 	NC_DATASTORE ds_type_s = -1;
 	char *chunked_out_msg = NULL;
 	apr_pool_t * pool = ((struct pass_to_thread*)arg)->pool;
-	apr_hash_t *netconf_sessions_list = ((struct pass_to_thread*)arg)->netconf_sessions_list;
 	server_rec * server = ((struct pass_to_thread*)arg)->server;
 	int client = ((struct pass_to_thread*)arg)->client;
 
@@ -1435,9 +1467,10 @@
 			break;
 		}
 
-
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Get framed message...");
 		buffer = get_framed_message(server, client);
 
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Check read buffer.");
 		if (buffer != NULL) {
 			enum json_tokener_error jerr;
 			request = json_tokener_parse_verbose(buffer, &jerr);
@@ -1469,22 +1502,22 @@
 			/* process required operation */
 			switch (operation) {
 			case MSG_CONNECT:
-				reply = handle_op_connect(server, pool, request, netconf_sessions_list);
+				reply = handle_op_connect(server, pool, request);
 				break;
 			case MSG_GET:
-				reply = handle_op_get(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_get(server, pool, request, session_key);
 				break;
 			case MSG_GETCONFIG:
-				reply = handle_op_getconfig(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_getconfig(server, pool, request, session_key);
 				break;
 			case MSG_GETSCHEMA:
-				reply = handle_op_getschema(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_getschema(server, pool, request, session_key);
 				break;
 			case MSG_EDITCONFIG:
-				reply = handle_op_editconfig(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_editconfig(server, pool, request, session_key);
 				break;
 			case MSG_COPYCONFIG:
-				reply = handle_op_copyconfig(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_copyconfig(server, pool, request, session_key);
 				break;
 
 			case MSG_DELETECONFIG:
@@ -1505,15 +1538,15 @@
 				switch(operation) {
 				case MSG_DELETECONFIG:
 					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: delete-config (session %s)", session_key);
-					status = netconf_deleteconfig(server, netconf_sessions_list, session_key, ds_type_t);
+					status = netconf_deleteconfig(server, session_key, ds_type_t);
 					break;
 				case MSG_LOCK:
 					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: lock (session %s)", session_key);
-					status = netconf_lock(server, netconf_sessions_list, session_key, ds_type_t);
+					status = netconf_lock(server, session_key, ds_type_t);
 					break;
 				case MSG_UNLOCK:
 					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: unlock (session %s)", session_key);
-					status = netconf_unlock(server, netconf_sessions_list, session_key, ds_type_t);
+					status = netconf_unlock(server, session_key, ds_type_t);
 					break;
 				default:
 					status = -1;
@@ -1534,19 +1567,19 @@
 				}
 				break;
 			case MSG_KILL:
-				reply = handle_op_kill(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_kill(server, pool, request, session_key);
 				break;
 			case MSG_DISCONNECT:
-				reply = handle_op_disconnect(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_disconnect(server, pool, request, session_key);
 				break;
 			case MSG_RELOADHELLO:
-				reply = handle_op_reloadhello(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_reloadhello(server, pool, request, session_key);
 				break;
 			case MSG_INFO:
-				reply = handle_op_info(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_info(server, pool, request, session_key);
 				break;
 			case MSG_GENERIC:
-				reply = handle_op_generic(server, pool, request, netconf_sessions_list, session_key);
+				reply = handle_op_generic(server, pool, request, session_key);
 				break;
 			default:
 				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown mod_netconf operation requested (%d)", operation);
@@ -1567,8 +1600,11 @@
 					}
 					break;
 				}
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Send framed reply json object.");
 				send(client, chunked_out_msg, strlen(chunked_out_msg) + 1, 0);
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Clean reply json object.");
 				json_object_put(reply);
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Clean message buffer.");
 				free(chunked_out_msg);
 				chunked_out_msg = NULL;
 				if (buffer != NULL) {
@@ -1597,12 +1633,11 @@
  * \param[in] p  apr pool needed for hash table iterating
  * \param[in] ht  hash table of session_with_mutex structs
  */
-static void close_all_nc_sessions(server_rec* server, apr_pool_t *p, apr_hash_t *ht)
+static void close_all_nc_sessions(server_rec* server, apr_pool_t *p)
 {
 	apr_hash_index_t *hi;
 	void *val = NULL;
 	struct session_with_mutex *swm = NULL;
-	struct nc_session *ns = NULL;
 	const char *hashed_key = NULL;
 	apr_ssize_t hashed_key_length;
 	int ret;
@@ -1612,19 +1647,26 @@
 		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", ret, strerror(ret));
 		return;
 	}
-	for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
+	for (hi = apr_hash_first(p, netconf_sessions_list); hi; hi = apr_hash_next(hi)) {
 		apr_hash_this(hi, (const void **) &hashed_key, &hashed_key_length, &val);
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Closing NETCONF session (%s).", hashed_key);
 		swm = (struct session_with_mutex *) val;
 		if (swm != NULL) {
-			pthread_mutex_lock(&swm->lock);
-			if (swm->session != NULL) {
-				ns = swm->session;
-				nc_session_close(ns, NC_SESSION_TERM_CLOSED);
-				nc_session_free(ns);
-				swm->session = NULL;
-			}
+			//pthread_mutex_lock(&swm->lock);
+			//if (swm->session != NULL) {
+			//	swm->closed = 1;
+			//	ns = swm->session;
+			//	nc_session_close(ns, NC_SESSION_TERM_CLOSED);
+			//	nc_session_free(ns);
+			//	swm->session = NULL;
+			//}
+			//pthread_mutex_unlock(&swm->lock);
+
+			apr_hash_set(netconf_sessions_list, hashed_key, APR_HASH_KEY_STRING, NULL);
 			pthread_mutex_unlock(&swm->lock);
+
+			/* close_and_free_session handles locking on its own */
+			close_and_free_session(server, swm);
 		}
 	}
 	/* get exclusive access to sessions_list (conns) */
@@ -1633,8 +1675,10 @@
 	}
 }
 
-static void check_timeout_and_close(server_rec* server, apr_pool_t *p, apr_hash_t *ht)
+static void check_timeout_and_close(server_rec* server, apr_pool_t *p)
 {
+/** \todo fix locking */
+return;
 	apr_hash_index_t *hi;
 	void *val = NULL;
 	struct nc_session *ns = NULL;
@@ -1649,7 +1693,7 @@
 		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", ret, strerror(ret));
 		return;
 	}
-	for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
+	for (hi = apr_hash_first(p, netconf_sessions_list); hi; hi = apr_hash_next(hi)) {
 		apr_hash_this(hi, (const void **) &hashed_key, &hashed_key_length, &val);
 		swm = (struct session_with_mutex *) val;
 		if (swm == NULL) {
@@ -1662,13 +1706,18 @@
 		pthread_mutex_lock(&swm->lock);
 		if ((current_time - swm->last_activity) > apr_time_from_sec(ACTIVITY_TIMEOUT)) {
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Closing NETCONF session (%s).", hashed_key);
-			nc_session_close(ns, NC_SESSION_TERM_CLOSED);
-			nc_session_free (ns);
-			ns = NULL;
+			//nc_session_close(ns, NC_SESSION_TERM_CLOSED);
+			//nc_session_free (ns);
+			//ns = NULL;
 			/* remove session from the active sessions list */
-			apr_hash_set(ht, hashed_key, APR_HASH_KEY_STRING, NULL);
+			apr_hash_set(netconf_sessions_list, hashed_key, APR_HASH_KEY_STRING, NULL);
+			pthread_mutex_unlock(&swm->lock);
+
+			/* close_and_free_session handles locking on its own */
+			close_and_free_session(server, swm);
+		} else {
+			pthread_mutex_unlock(&swm->lock);
 		}
-		pthread_mutex_unlock(&swm->lock);
 	}
 	/* get exclusive access to sessions_list (conns) */
 	if (pthread_rwlock_unlock (&session_lock) != 0) {
@@ -1693,7 +1742,6 @@
 	unsigned int olds = 0, timediff = 0;
 	socklen_t len;
 	mod_netconf_cfg *cfg;
-	apr_hash_t *netconf_sessions_list;
 	struct pass_to_thread * arg;
 	pthread_t * ptids = calloc (1,sizeof(pthread_t));
 	struct timespec maxtime;
@@ -1747,7 +1795,7 @@
 	netconf_sessions_list = apr_hash_make(pool);
 
 	#ifdef WITH_NOTIFICATIONS
-	if (notification_init(pool, server, netconf_sessions_list) == -1) {
+	if (notification_init(pool, server) == -1) {
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "libwebsockets initialization failed");
 		use_notifications = 0;
 	} else {
@@ -1793,7 +1841,7 @@
 		}
 		#endif
 		if (timediff > ACTIVITY_CHECK_INTERVAL) {
-			check_timeout_and_close(server, pool, netconf_sessions_list);
+			check_timeout_and_close(server, pool);
 		}
 
 		/* open incoming connection if any */
@@ -1860,7 +1908,7 @@
 	#endif
 
 	/* close all NETCONF sessions */
-	close_all_nc_sessions(server, pool, netconf_sessions_list);
+	close_all_nc_sessions(server, pool);
 
 	/* destroy rwlock */
 	pthread_rwlock_destroy(&session_lock);
diff --git a/src/notification-server.c b/src/notification-server.c
index 13648ba..bbf373e 100644
--- a/src/notification-server.c
+++ b/src/notification-server.c
@@ -45,7 +45,6 @@
 #endif
 
 #if defined(TEST_NOTIFICATION_SERVER) || defined(WITH_NOTIFICATIONS)
-static int close_testing;
 static int max_poll_elements;
 
 static struct pollfd *pollfds;
@@ -59,7 +58,7 @@
 	char *session_hash;
 };
 
-static apr_hash_t *netconf_locked_sessions = NULL;
+extern apr_hash_t *netconf_sessions_list;
 static pthread_key_t thread_key;
 
 /*
@@ -366,7 +365,7 @@
 	if (session_key == NULL) {
 		return (NULL);
 	}
-	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_locked_sessions, session_key, APR_HASH_KEY_STRING);
+	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_sessions_list, session_key, APR_HASH_KEY_STRING);
 	return locked_session;
 }
 
@@ -466,7 +465,7 @@
 	}
 	if (pthread_rwlock_wrlock(&session_lock) != 0) {
 		#ifndef TEST_NOTIFICATION_SERVER
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock");
 		#endif
 		return;
 	}
@@ -475,25 +474,25 @@
 	if (target_session == NULL) {
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "no session found last_session_key (%s)", session_hash);
 		if (pthread_rwlock_unlock (&session_lock) != 0) {
-#ifndef TEST_NOTIFICATION_SERVER
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-#endif
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock");
 			return;
 		}
 		return;
 	}
+	if (pthread_mutex_lock(&target_session->lock) != 0) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock");
+	}
+	if (pthread_rwlock_unlock(&session_lock) != 0) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock");
+	}
 
 	t[0] = 0;
 	strftime(t, sizeof(t), "%c", localtime(&eventtime));
 
-	if (pthread_mutex_lock(&target_session->lock) != 0) {
-		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-		return;
-	}
 	if (target_session->notifications == NULL) {
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "target_session->notifications is NULL");
 		if (pthread_mutex_unlock(&target_session->lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 			return;
 		}
 		return;
@@ -505,13 +504,7 @@
 	if (ntf == NULL) {
 		ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Failed to allocate element ");
 		if (pthread_mutex_unlock(&target_session->lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			return;
-		}
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-#ifndef TEST_NOTIFICATION_SERVER
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-#endif
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock");
 			return;
 		}
 		return;
@@ -519,25 +512,10 @@
 	ntf->eventtime = eventtime;
 	ntf->content = strdup(content);
 
-	if (http_server != NULL) {
-		ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, http_server, "added notif to queue %u (%s)", (unsigned int) ntf->eventtime, "notifikace");
-	}
+	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "added notif to queue %u (%s)", (unsigned int) ntf->eventtime, "notifikace");
 
 	if (pthread_mutex_unlock(&target_session->lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			#ifndef TEST_NOTIFICATION_SERVER
-			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			#endif
-			return;
-		}
-		return;
-	}
-	if (pthread_rwlock_unlock (&session_lock) != 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-		#endif
-		return;
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock");
 	}
 }
 
@@ -548,11 +526,7 @@
 void* notification_thread(void* arg)
 {
 	struct ntf_thread_config *config = (struct ntf_thread_config*)arg;
-	#ifndef TEST_NOTIFICATION_SERVER
-	if (http_server != NULL) {
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: in thread for libnetconf notifications");
-	}
-	#endif
+	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: in thread for libnetconf notifications");
 
 	/* store hash identification of netconf session for notifications printing callback */
 	if (pthread_setspecific(thread_key, config->session_hash) != 0) {
@@ -563,12 +537,8 @@
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notifications: dispatching");
 	}
 	ncntf_dispatch_receive(config->session, notification_fileprint);
-	#ifndef TEST_NOTIFICATION_SERVER
-	if (http_server != NULL) {
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: ended thread for libnetconf notifications");
-	}
-	#endif
-	free(config);
+	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: ended thread for libnetconf notifications");
+	//free(config);
 	return (NULL);
 }
 
@@ -584,13 +554,16 @@
 	struct ntf_thread_config *tconfig;
 	struct nc_session *session;
 
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notif_subscribe");
 	if (locked_session == NULL) {
 		if (http_server != NULL) {
 			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: no locked_session was given.");
 		}
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Close notification client");
+		return -1;
 	}
 
+	pthread_mutex_lock(&locked_session->lock);
 	session = locked_session->session;
 
 	start = time(NULL) + start_time;
@@ -599,69 +572,54 @@
 	}
 
 	if (session == NULL) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: NETCONF session not established.");
-		}
-		#endif
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: NETCONF session not established.");
+		return -1;
 	}
 
 	/* check if notifications are allowed on this session */
 	if (nc_session_notif_allowed(session) == 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Notification subscription is not allowed on this session.");
-		}
-		#endif
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Notification subscription is not allowed on this session.");
+		return -1;
 	}
 	/* check times */
 	if (start != -1 && stop != -1 && start > stop) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Subscription start time must be lower than the end time.");
-		}
-		#endif
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Subscription start time must be lower than the end time.");
+		return -1;
 	}
 
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Prepare to execute subscription.");
 	/* create requests */
 	rpc = nc_rpc_subscribe(stream, filter, (start_time == 0)?NULL:&start, (stop_time == 0)?NULL:&stop);
 	nc_filter_free(filter);
 	if (rpc == NULL) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating an rpc request failed.");
-		}
-		#endif
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating an rpc request failed.");
+		return -1;
 	}
 
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Send NC subscribe.");
+	/** \todo replace with sth like netconf_op(http_server, session_hash, rpc) */
 	if (send_recv_process(session, "subscribe", rpc) != 0) {
-		return (EXIT_FAILURE);
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Subscription RPC failed.");
+		return -1;
 	}
 	rpc = NULL; /* just note that rpc is already freed by send_recv_process() */
 	locked_session->ntfc_subscribed = 1;
 
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Create config for notification_thread.");
 	tconfig = malloc(sizeof(struct ntf_thread_config));
 	tconfig->session = session;
 	tconfig->session_hash = strdup(session_hash);
-	if (http_server != NULL) {
-		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating libnetconf notification thread (%s).",
-		tconfig->session_hash);
-	}
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating libnetconf notification thread (%s).", tconfig->session_hash);
 
+	pthread_mutex_unlock(&locked_session->lock);
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Create notification_thread.");
 	if (pthread_create(&thread, NULL, notification_thread, tconfig) != 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating a thread for receiving notifications failed");
-		}
-		#endif
-		return (EXIT_FAILURE);
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating a thread for receiving notifications failed");
+		return -1;
 	}
 	pthread_detach(thread);
-	return (EXIT_SUCCESS);
+	ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Subscription finished.");
+	return 0;
 }
 
 static int callback_notification(struct libwebsocket_context *context,
@@ -671,52 +629,65 @@
 {
 	int n = 0;
 	int m = 0;
-	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING];
+	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 40960 + LWS_SEND_BUFFER_POST_PADDING];
 	unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
 	struct per_session_data__notif_client *pss = (struct per_session_data__notif_client *)user;
 
 	switch (reason) {
 	case LWS_CALLBACK_ESTABLISHED:
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification client connected.");
-		}
-		pss->number = 0;
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification client connected.");
 		break;
 
 	case LWS_CALLBACK_SERVER_WRITEABLE:
 		if (pss->session_key == NULL) {
 			return 0;
 		}
-
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Callback server writeable.");
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "lock session lock.");
+		if (pthread_rwlock_wrlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			return -1;
+		}
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "get session_with_mutex for %s.", pss->session_key);
 		struct session_with_mutex *ls = get_ncsession_from_key(pss->session_key);
 		if (ls == NULL) {
 			if (http_server != NULL) {
 				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: session not found");
 			}
+			if (pthread_rwlock_unlock (&session_lock) != 0) {
+				ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+				return -1;
+			}
 			return -1;
 		}
-		if (pthread_mutex_lock(&ls->lock) != 0) {
-			#ifndef TEST_NOTIFICATION_SERVER
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: cannot lock session");
-			}
-			#endif
+		pthread_mutex_lock(&ls->lock);
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 		}
-		notification_t *notif = NULL;
-		if (ls->notifications == NULL) {
-			#ifndef TEST_NOTIFICATION_SERVER
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: no notifications array");
-			}
-			#endif
-			pthread_mutex_unlock(&ls->lock);
-			return -1;
-		}
-		if (!apr_is_empty_array(ls->notifications)) {
 
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications for session");
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "check for closed session.");
+		if (ls->closed == 1) {
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session key.");
+			if (pthread_rwlock_unlock (&session_lock) != 0) {
+				ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking unlock: %d (%s)", errno, strerror(errno));
+				return -1;
 			}
+			return -1;
+		}
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "lock private lock.");
+		notification_t *notif = NULL;
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "check for uninitialized notification list.");
+		if (ls->notifications == NULL) {
+				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: no notifications array");
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock private lock.");
+			if (pthread_mutex_unlock(&ls->lock) != 0) {
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: cannot unlock session");
+			}
+			return -1;
+		}
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "check for empty notification list.");
+		if (!apr_is_empty_array(ls->notifications)) {
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications for session");
 
 			while ((notif = (notification_t *) apr_array_pop(ls->notifications)) != NULL) {
 				char t[128];
@@ -729,49 +700,36 @@
 
 				const char *msgtext = json_object_to_json_string(notif_json);
 
+				//n = sprintf((char *)p, "{\"eventtime\": \"%s\", \"content\": \"notification\"}", t);
 				n = sprintf((char *)p, "%s", msgtext);
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "ws send %dB in %lu", n, sizeof(buf));
 				m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
+				if (lws_send_pipe_choked(wsi)) {
+					libwebsocket_callback_on_writable(context, wsi);
+					break;
+				}
 
 				json_object_put(notif_json);
 			}
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications done");
-			}
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications done");
 		}
 
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock private lock");
 		if (pthread_mutex_unlock(&ls->lock) != 0) {
-			#ifndef TEST_NOTIFICATION_SERVER
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: cannot unlock session");
-			}
-			#endif
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: cannot unlock session");
 		}
-		//if (http_server != NULL) {
-		//	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: unlocked session lock");
-		//}
-
+		//ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
 
 		if (m < n) {
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "ERROR %d writing to di socket\n", n);
-			}
+			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "ERROR %d writing to di socket.", n);
 
 			return -1;
 		}
-		if (close_testing && pss->number == 50) {
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "close tesing limit, closing\n");
-			}
-			return -1;
-		}
 		break;
 
 	case LWS_CALLBACK_RECEIVE:
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "received: (%s)", (char *)in);
-		}
-		#endif
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Callback receive.");
+		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "received: (%s)", (char *)in);
 		if (pss->session_key == NULL) {
 			char session_key_buf[41];
 			int start = -1;
@@ -791,53 +749,43 @@
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "get session from key (%s)", pss->session_key);
 			struct session_with_mutex *ls = get_ncsession_from_key(pss->session_key);
 			if (ls == NULL) {
-				if (http_server != NULL) {
-					ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: session_key not found (%s)", pss->session_key);
-				}
+				ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: session_key not found (%s)", pss->session_key);
 				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
 				if (pthread_rwlock_unlock (&session_lock) != 0) {
 					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-					return -1;
 				}
 				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Close notification client");
 				return -1;
 			}
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "lock private lock");
+			pthread_mutex_lock(&ls->lock);
+
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
+			if (pthread_rwlock_unlock (&session_lock) != 0) {
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			}
+
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Found session to subscribe notif.");
 			if (ls->closed == 1) {
 				ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "session already closed - handle no notification");
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
-				if (pthread_rwlock_unlock (&session_lock) != 0) {
-					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-					return -1;
-				}
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock private lock");
+				pthread_mutex_unlock(&ls->lock);
 				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Close notification client");
 				return -1;
 			}
 			if (ls->ntfc_subscribed != 0) {
 				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: already subscribed");
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
-				if (pthread_rwlock_unlock (&session_lock) != 0) {
-					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-					return -1;
-				}
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock private lock");
+				pthread_mutex_unlock(&ls->lock);
 				/* do not close client, only do not subscribe again */
 				return 0;
 			}
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: prepare to subscribe stream");
 			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
-			if (pthread_rwlock_unlock (&session_lock) != 0) {
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-				return -1;
-			}
-			//if (pthread_rwlock_rdlock (&session_lock) != 0) {
-			//	ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-			//	return -1;
-			//}
+			pthread_mutex_unlock(&ls->lock);
+
+			/* notif_subscribe locks on its own */
 			return notif_subscribe(ls, pss->session_key, (time_t) start, (time_t) stop);
-			//if (pthread_rwlock_unlock (&session_lock) != 0) {
-			//	ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			//	return -1;
-			//}
 		}
 		if (len < 6)
 			break;
@@ -875,7 +823,7 @@
 		"notification-protocol",
 		callback_notification,
 		sizeof(struct per_session_data__notif_client),
-		80,
+		4000,
 	},
 	{ NULL, NULL, 0, 0 } /* terminator */
 };
@@ -884,7 +832,7 @@
 /**
  * initialization of notification module
  */
-int notification_init(apr_pool_t * pool, server_rec * server, apr_hash_t *conns)
+int notification_init(apr_pool_t * pool, server_rec * server)
 {
 	//char cert_path[1024];
 	//char key_path[1024];
@@ -895,20 +843,14 @@
 	const char *iface = NULL;
 	int debug_level = 7;
 
-	netconf_locked_sessions = conns;
-
 	memset(&info, 0, sizeof info);
 	info.port = NOTIFICATION_SERVER_PORT;
 
 	/* tell the library what debug level to emit and to send it to syslog */
 	lws_set_log_level(debug_level, lwsl_emit_syslog);
 
-	#ifndef TEST_NOTIFICATION_SERVER
-	if (server != NULL) {
-		http_server = server;
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "Initialization of libwebsocket");
-	}
-	#endif
+	http_server = server;
+	ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "Initialization of libwebsocket");
 	//lwsl_notice("libwebsockets test server - "
 	//		"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
 	//					    "licensed under LGPL2.1\n");
@@ -942,11 +884,7 @@
 
 	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notifications: init of pthread_key_create.");
 	if (pthread_key_create(&thread_key, NULL) != 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		if (http_server != NULL) {
-			ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: pthread_key_create failed");
-		}
-		#endif
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: pthread_key_create failed");
 	}
 	return 0;
 }
diff --git a/src/notification_module.h b/src/notification_module.h
index 8861e12..a005dc5 100644
--- a/src/notification_module.h
+++ b/src/notification_module.h
@@ -62,7 +62,7 @@
  * \param conns - apr_hash_t representing the list of netconf connections
  * \return 0 on success
  */
-int notification_init(apr_pool_t * pool, server_rec * server, apr_hash_t *conns);
+int notification_init(apr_pool_t * pool, server_rec * server);
 
 /**
  * \brief Handle method - passes execution into the libwebsocket library