Browse code

- improved cleanup of pa, rls and libs - corrected error in watcherinfo authorization

Vaclav Kubart authored on 24/11/2005 15:34:03
Showing 13 changed files
... ...
@@ -2,11 +2,13 @@
2 2
 
3 3
 INCLUDES += -I$(CURDIR)
4 4
 LIBS     += -L$(CURDIR)/cds -L$(CURDIR)/qsa
5
+DEFS     += -Wall
5 6
 
6 7
 ####################################
7 8
 # make rules
8 9
 
9 10
 export LIBS
11
+export DEFS
10 12
 export INCLUDES
11 13
 
12 14
 SUBDIRS=cds xcap presence
13 15
new file mode 100644
... ...
@@ -0,0 +1,57 @@
1
+#include <cds/cds.h>
2
+#include <cds/memory.h>
3
+#include <cds/sync.h>
4
+#include <cds/logger.h>
5
+
6
+typedef struct {
7
+	int init_cnt;
8
+} init_data_t;
9
+
10
+static init_data_t *init = NULL;
11
+
12
+/* these functions are internal and thus are not presented in headers !*/
13
+int reference_counter_initialize();
14
+void reference_counter_cleanup();
15
+	
16
+int cds_initialize()
17
+{
18
+	int res = 0;
19
+
20
+	/* initialization should be called from one process/thread 
21
+	 * it is not synchronized because it is impossible ! */
22
+	if (!init) {
23
+		init = (init_data_t*)cds_malloc(sizeof(init_data_t));
24
+		if (!init) return -1;
25
+		init->init_cnt = 0;
26
+	}
27
+
28
+	if (init->init_cnt > 0) { /* already initialized */
29
+		init->init_cnt++;
30
+		return 0;
31
+	}
32
+	else {
33
+		DEBUG_LOG("cds_initialize(): init the content\n");
34
+		
35
+		/* !!! put the real initialization here !!! */
36
+		res = reference_counter_initialize();
37
+	}
38
+			
39
+	if (res == 0) init->init_cnt++;
40
+	return res;
41
+}
42
+
43
+void cds_cleanup()
44
+{
45
+	if (init) {
46
+		if (--init->init_cnt == 0) {
47
+			DEBUG_LOG("cds_cleanup(): cleaning the content\n");
48
+			
49
+			/* !!! put the real destruction here !!! */
50
+			reference_counter_cleanup();
51
+		
52
+			cds_free(init);
53
+			init = NULL;
54
+		}
55
+	}
56
+}
57
+
0 58
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+#ifndef __CDS_H
2
+#define __CDS_H
3
+
4
+/* declaration of initialization/destruction functions */
5
+
6
+#ifdef __cplusplus
7
+extern "C" {
8
+#endif
9
+	
10
+int cds_initialize();
11
+void cds_cleanup();
12
+
13
+#ifdef __cplusplus
14
+}
15
+#endif
16
+
17
+#endif
... ...
@@ -42,7 +42,7 @@
42 42
 #include "dprint.h"
43 43
 
44 44
 #define ERROR_LOG(a,args...)		LOG(L_ERR,a,##args)
45
-#define DEBUG_LOG(a,args...)		LOG(L_DBG,a,##args)
45
+#define DEBUG_LOG(a,args...)		LOG(L_ERR,a,##args)
46 46
 #define TRACE_LOG(a,args...)		LOG(L_ERR,a,##args)
47 47
 #define WARN_LOG(a,args...)			LOG(L_WARN,a,##args)
48 48
 #define FLUSH_LOG()					do{}while(0)
... ...
@@ -26,6 +26,7 @@
26 26
 #include <stdio.h>
27 27
 #include <cds/msg_queue.h>
28 28
 #include <cds/memory.h>
29
+#include <cds/ref_cntr.h>
29 30
 
30 31
 mq_message_t *create_message_ex(int data_len)
31 32
 {
... ...
@@ -155,6 +156,7 @@ int msg_queue_init(msg_queue_t *q)
155 156
 int msg_queue_init_ex(msg_queue_t *q, int synchronize)
156 157
 {
157 158
 	if (synchronize) cds_mutex_init(&q->q_mutex);
159
+	init_reference_counter(&q->ref);
158 160
 	q->use_mutex = synchronize;
159 161
 	q->first = NULL;
160 162
 	q->last = NULL;
... ...
@@ -181,4 +183,11 @@ void msg_queue_destroy(msg_queue_t *q)
181 183
 	}
182 184
 }
183 185
 
186
+void msg_queue_free(msg_queue_t *q)
187
+{
188
+	if (remove_reference(&q->ref)) {
189
+		msg_queue_destroy(q);
190
+		cds_free(q);
191
+	}
192
+}
184 193
 
... ...
@@ -27,6 +27,11 @@
27 27
 #define __MSG_QUEUE_H
28 28
 
29 29
 #include <cds/sync.h>
30
+#include <cds/ref_cntr.h>
31
+
32
+#ifdef __cplusplus
33
+extern "C" {
34
+#endif
30 35
 
31 36
 typedef void (*destroy_function_f)(void *);
32 37
 
... ...
@@ -43,6 +48,7 @@ typedef struct _mq_message_t {
43 48
 } mq_message_t;
44 49
 
45 50
 typedef struct msg_queue {
51
+	reference_counter_data_t ref;
46 52
 	mq_message_t *first;
47 53
 	mq_message_t *last;
48 54
 	cds_mutex_t q_mutex;
... ...
@@ -82,5 +88,12 @@ int msg_queue_init(msg_queue_t *q);
82 88
 int msg_queue_init_ex(msg_queue_t *q, int synchronize);
83 89
 void msg_queue_destroy(msg_queue_t *q);
84 90
 
91
+/* removes reference to message queue and frees it if no other references exist */
92
+void msg_queue_free(msg_queue_t *q);
93
+
94
+#ifdef __cplusplus
95
+}
96
+#endif
97
+
85 98
 #endif
86 99
 
87 100
new file mode 100644
... ...
@@ -0,0 +1,75 @@
1
+#include <cds/ref_cntr.h>
2
+#include <cds/logger.h>
3
+#include <cds/memory.h>
4
+
5
+/* One global mutex for reference counting may be enough. 
6
+ * If problems try to create pool of precreated mutexes
7
+ * and use them randomly.
8
+ */
9
+static cds_mutex_t *ref_cntr_mutex = NULL;
10
+
11
+/* global functions for initialization and destruction */
12
+
13
+int reference_counter_initialize()
14
+{
15
+	if (!ref_cntr_mutex) {
16
+		ref_cntr_mutex = (cds_mutex_t*)cds_malloc(sizeof(cds_mutex_t));
17
+		if (ref_cntr_mutex) {
18
+			cds_mutex_init(ref_cntr_mutex);
19
+			return 0;
20
+		}
21
+	}
22
+	return -1;
23
+}
24
+
25
+void reference_counter_cleanup()
26
+{
27
+	if (ref_cntr_mutex) {
28
+		cds_mutex_destroy(ref_cntr_mutex);
29
+		cds_free(ref_cntr_mutex);
30
+		ref_cntr_mutex = NULL;
31
+	}
32
+}
33
+
34
+/* -------------------------------------------------------------------- */
35
+
36
+void init_reference_counter(reference_counter_data_t *ref)
37
+{
38
+	if (ref) {
39
+		ref->cntr = 1;
40
+		ref->mutex = ref_cntr_mutex;
41
+	}
42
+}
43
+
44
+void add_reference(reference_counter_data_t *ref)
45
+{
46
+	if (ref) {
47
+		if (ref->mutex) cds_mutex_lock(ref->mutex);
48
+		ref->cntr++;
49
+		if (ref->mutex) cds_mutex_unlock(ref->mutex);
50
+	}
51
+}
52
+
53
+int get_reference_count(reference_counter_data_t *ref)
54
+{
55
+	int res = 0;
56
+	if (ref) {
57
+		if (ref->mutex) cds_mutex_lock(ref->mutex);
58
+		res = ref->cntr;
59
+		if (ref->mutex) cds_mutex_unlock(ref->mutex);
60
+	}
61
+	return res;
62
+}
63
+
64
+int remove_reference(reference_counter_data_t *ref)
65
+{
66
+	int res = 0;
67
+	if (ref) {
68
+		if (ref->mutex) cds_mutex_lock(ref->mutex);
69
+		if (ref->cntr > 0) ref->cntr--;
70
+		if (ref->cntr == 0) res = 1;
71
+		if (ref->mutex) cds_mutex_unlock(ref->mutex);
72
+	}
73
+	return res;
74
+}
75
+
0 76
new file mode 100644
... ...
@@ -0,0 +1,42 @@
1
+#ifndef __REFERENCE_CNTR_H
2
+#define __REFERENCE_CNTR_H
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+#include <cds/sync.h>
9
+	
10
+typedef struct {
11
+	int cntr;
12
+	cds_mutex_t *mutex;
13
+} reference_counter_data_t;
14
+	
15
+/* these functions can be called only by owner of at least one reference */
16
+/* owner is somebody who:
17
+ *    - created a referenced structure
18
+ *    - added a reference
19
+ *    - got a reference by an ovner
20
+ */
21
+
22
+void init_reference_counter(reference_counter_data_t *ref);
23
+void add_reference(reference_counter_data_t *ref);
24
+int get_reference_count(reference_counter_data_t *ref);
25
+
26
+/* returns:
27
+ * 0 if reference removed, but exist other references
28
+ * 1 if removed last refernce and the element SHOULD be freed
29
+ *
30
+ * usage:
31
+ * 
32
+ * some_structure *ss;
33
+ * ...
34
+ * if (remove_reference(&ss->ref)) cds_free(&ss->ref);
35
+ *  */
36
+int remove_reference(reference_counter_data_t *ref);
37
+
38
+#ifdef __cplusplus
39
+}
40
+#endif
41
+
42
+#endif
... ...
@@ -46,12 +46,17 @@ void destroy_domain_maintainer(domain_maintainer_t *dm)
46 46
 	notifier_domain_t *d;
47 47
 	
48 48
 	if (!dm) return;
49
+			
50
+	DEBUG_LOG("destroying domain maintainer\n");
49 51
 
50 52
 	cnt = ptr_vector_size(&dm->registered_domains);
51 53
 	for (i = 0; i < cnt; i++) {
52 54
 		d = ptr_vector_get(&dm->registered_domains, i);
53 55
 		if (!d) continue;
54
-		destroy_notifier_domain(d);
56
+		if (remove_reference(&d->ref)) {
57
+			DEBUG_LOG("freeing domain: \'%.*s\'\n", FMT_STR(d->name));
58
+			destroy_notifier_domain(d);
59
+		}
55 60
 	}
56 61
 	ptr_vector_destroy(&dm->registered_domains);
57 62
 	cds_mutex_destroy(&dm->mutex);
... ...
@@ -77,13 +82,14 @@ static notifier_domain_t *add_domain_nolock(domain_maintainer_t *dm, const str_t
77 82
 	notifier_domain_t *d = create_notifier_domain(name);
78 83
 	
79 84
 	if (d) {
85
+		DEBUG_LOG("created domain: \'%.*s\'\n", FMT_STR(d->name));
80 86
 		ptr_vector_add(&dm->registered_domains, d);
81 87
 		return d;
82 88
 	}
83 89
 	else return NULL;
84 90
 }
85 91
 
86
-notifier_domain_t *find_notifier_domain(domain_maintainer_t *dm, const str_t *name)
92
+/* notifier_domain_t *find_notifier_domain(domain_maintainer_t *dm, const str_t *name)
87 93
 {
88 94
 	notifier_domain_t *d = NULL;
89 95
 	
... ...
@@ -92,7 +98,7 @@ notifier_domain_t *find_notifier_domain(domain_maintainer_t *dm, const str_t *na
92 98
 	d = find_domain_nolock(dm, name);
93 99
 	cds_mutex_unlock(&dm->mutex);
94 100
 	return d;
95
-}
101
+} */
96 102
 
97 103
 notifier_domain_t *register_notifier_domain(domain_maintainer_t *dm, const str_t *name)
98 104
 {
... ...
@@ -103,12 +109,39 @@ notifier_domain_t *register_notifier_domain(domain_maintainer_t *dm, const str_t
103 109
 	cds_mutex_lock(&dm->mutex);
104 110
 	d = find_domain_nolock(dm, name);
105 111
 	if (!d) d = add_domain_nolock(dm, name);
112
+	if (d) {
113
+		add_reference(&d->ref); /* add reference for client */
114
+	}
106 115
 	cds_mutex_unlock(&dm->mutex);
107 116
 	return d;
108 117
 }
109 118
 
119
+static void remove_notifier_domain(domain_maintainer_t *dm, notifier_domain_t *domain)
120
+{
121
+	notifier_domain_t *d = NULL;
122
+	int i, cnt;
123
+	
124
+	cnt = ptr_vector_size(&dm->registered_domains);
125
+	for (i = 0; i < cnt; i++) {
126
+		d = ptr_vector_get(&dm->registered_domains, i);
127
+		if (d == domain) {
128
+			ptr_vector_remove(&dm->registered_domains, i);
129
+			break;
130
+		}
131
+	}
132
+}
133
+
110 134
 void release_notifier_domain(domain_maintainer_t *dm, notifier_domain_t *domain)
111 135
 {
112
-	/* TODO: decrement "domain counter", if 0 => destroy domain */
136
+	if ((!dm) || (!domain)) return;
137
+	
138
+	cds_mutex_lock(&dm->mutex);
139
+	if (remove_reference(&domain->ref)) {
140
+		/* last reference */
141
+		DEBUG_LOG("freeing domain: \'%.*s\'\n", FMT_STR(domain->name));
142
+		remove_notifier_domain(dm, domain);
143
+		destroy_notifier_domain(domain);
144
+	}
145
+	cds_mutex_unlock(&dm->mutex);
113 146
 }
114 147
 
... ...
@@ -43,6 +43,16 @@ notifier_t *register_notifier(
43 43
 	void *user_data);
44 44
 
45 45
 void unregister_notifier(notifier_domain_t *domain, notifier_t *info);
46
+
47
+/** accepts subscription (internaly adds reference to it), thus it can 
48
+ * be handled by notifier which called this function 
49
+ * MUST be called in notifier's subscribe function, otherwise the 
50
+ * subscription can NOT be accepted */
51
+void accept_subscription(subscription_t *s);
52
+
53
+/** releases accepted subscription - MUST be called on all accepted 
54
+ * subscriptions (only on them!) to be freed from memory !*/
55
+void release_subscription(subscription_t *s);
46 56
 	
47 57
 #ifdef __cplusplus
48 58
 }
... ...
@@ -31,6 +31,10 @@
31 31
 #include <presence/notifier.h>
32 32
 #include <presence/subscriber.h>
33 33
 #include <cds/list.h>
34
+#include <cds/cds.h>
35
+
36
+#define lock_subscription_data(s) if (s->mutex) cds_mutex_lock(s->mutex);
37
+#define unlock_subscription_data(s) if (s->mutex) cds_mutex_unlock(s->mutex);
34 38
 
35 39
 static void free_notifier(notifier_t *info);
36 40
 static void free_subscription(subscription_t *s);
... ...
@@ -89,27 +93,27 @@ static notifier_package_t *get_package(notifier_domain_t *d, const str_t *name)
89 93
 	
90 94
 static void destroy_package(notifier_package_t *p) 
91 95
 {
92
-	notifier_t *e, *n;
96
+	/* notifier_t *e, *n; */
93 97
 	subscription_t *s, *ns;
94 98
 	
95
-	/* release all subscriptions  */
99
+	/* release all subscriptions ???  */
96 100
 	s = p->first_subscription;
97 101
 	while (s) {
98 102
 		ns = s->next;
99
-		/* unsubscribe(p->domain, s) */
100
-		/* release_subscription(s); */
101
-		free_subscription(s);
103
+		/* CAN NOT be called !!!! : unsubscribe(p->domain, s) */
104
+		release_subscription(s);
102 105
 		s = ns;
103 106
 	}
104 107
 	
105
-	/* release all registered notifiers */
106
-	e = p->first_notifier;
108
+	/* !!! don't release notifiers - its their job !!! */
109
+	/* it may lead to errors there */
110
+	/* e = p->first_notifier;
107 111
 	while (e) {
108 112
 		n = e->next;
109 113
 		free_notifier(e);
110
-		/* maybe: call some notifier callback ? */
111 114
 		e = n;
112
-	}
115
+	} */
116
+	
113 117
 	p->first_notifier = NULL;
114 118
 	p->last_notifier = NULL;
115 119
 	str_free_content(&p->name);
... ...
@@ -170,6 +174,8 @@ notifier_domain_t *create_notifier_domain(const str_t *name)
170 174
 		d->last_package = NULL;
171 175
 		str_dup(&d->name, name);
172 176
 		cds_mutex_init(&d->mutex);
177
+		cds_mutex_init(&d->data_mutex);
178
+		init_reference_counter(&d->ref);
173 179
 	}
174 180
 	return d;
175 181
 }
... ...
@@ -180,6 +186,10 @@ notifier_domain_t *create_notifier_domain(const str_t *name)
180 186
 void destroy_notifier_domain(notifier_domain_t *domain)
181 187
 {
182 188
 	notifier_package_t *p, *n;
189
+
190
+	/* this function is always called only if no only one reference
191
+	 * to domain exists (see domain maintainer), this should mean, that 
192
+	 * all subscribers freed their subscriptions */
183 193
 	
184 194
 	lock_notifier_domain(domain);
185 195
 	
... ...
@@ -197,6 +207,7 @@ void destroy_notifier_domain(notifier_domain_t *domain)
197 207
 	
198 208
 	str_free_content(&domain->name);
199 209
 	cds_mutex_destroy(&domain->mutex);
210
+	cds_mutex_init(&domain->data_mutex);
200 211
 	cds_free(domain);
201 212
 }
202 213
 
... ...
@@ -257,10 +268,13 @@ void unregister_notifier(notifier_domain_t *domain, notifier_t *info)
257 268
 	
258 269
 	p = info->package;
259 270
 	if (p) {
271
+		/* accepted subscriptions MUST be removed by the notifier 
272
+		 * how to solve this ? */
273
+		
260 274
 		/* subscription_t *s;
261 275
 		s = p->first_subscription;
262 276
 		while (s) {
263
-			info->unsubscribe(info, s);
277
+			CAN NOT be called !!!!! info->unsubscribe(info, s);
264 278
 			s = s->next;
265 279
 		}*/
266 280
 
... ...
@@ -303,18 +317,25 @@ subscription_t *subscribe(notifier_domain_t *domain,
303 317
 
304 318
 	s->package = p;
305 319
 	s->dst = dst;
320
+	s->mutex = &domain->data_mutex;
306 321
 	s->subscriber_data = subscriber_data;
307 322
 	str_dup(&s->record_id, record_id);
308 323
 	str_dup(&s->subscriber_id, subscriber_id);
324
+	init_reference_counter(&s->ref);
309 325
 
310 326
 	DOUBLE_LINKED_LIST_ADD(p->first_subscription, p->last_subscription, s);
311 327
 
328
+	/* add a reference for calling subscriber */
329
+	add_reference(&s->ref);
330
+	
312 331
 	/* browse all notifiers in given package and subscribe to them
313 332
 	 * and add them to notifiers list */
314 333
 	cnt = 0;
315 334
 	e = p->first_notifier;
316 335
 	while (e) {
317 336
 		cnt++;
337
+		/* each notifier MUST add its own reference if
338
+		 * it wants to accept the subscription !!! */
318 339
 		e->subscribe(e, s);
319 340
 		e = e->next;
320 341
 	}
... ...
@@ -323,13 +344,30 @@ subscription_t *subscribe(notifier_domain_t *domain,
323 344
 	
324 345
 	return s;
325 346
 }
347
+	
348
+void release_subscription(subscription_t *s)
349
+{
350
+	if (!s) return;
351
+	if (remove_reference(&s->ref)) free_subscription(s);
352
+}
326 353
 
327
-/** Destroys an existing subscription */
354
+void accept_subscription(subscription_t *s)
355
+{
356
+	if (!s) return;
357
+	add_reference(&s->ref);
358
+}
359
+
360
+/** Destroys an existing subscription - can be called ONLY by client !!! */
328 361
 void unsubscribe(notifier_domain_t *domain, subscription_t *s)
329 362
 {
330 363
 	notifier_package_t *p;
331 364
 	notifier_t *e;
332 365
 
366
+	/* mark subscription as un-notifyable */
367
+	lock_subscription_data(s);
368
+	s->dst = NULL;
369
+	unlock_subscription_data(s);
370
+
333 371
 	lock_notifier_domain(domain);
334 372
 	
335 373
 	/* maybe: test if the SUBSCRIBER is subscribed before unsubsc. */
... ...
@@ -349,6 +387,28 @@ void unsubscribe(notifier_domain_t *domain, subscription_t *s)
349 387
 	
350 388
 	unlock_notifier_domain(domain);
351 389
 	
352
-	free_subscription(s);
390
+	/* remove clients reference (dont give references to client?) */
391
+	remove_reference(&s->ref);
392
+	
393
+	release_subscription(s); 
353 394
 }
354 395
 
396
+void notify_subscriber(subscription_t *s, mq_message_t *msg)
397
+{
398
+	int sent = 0;
399
+	
400
+	if (s) {
401
+		lock_subscription_data(s);
402
+		if (s->dst) {
403
+			push_message(s->dst, msg);
404
+			sent = 1;
405
+		}
406
+		else free_message(msg);
407
+		unlock_subscription_data(s);
408
+	}
409
+	
410
+	if (!sent) {
411
+		/* free unsent messages */
412
+		free_message(msg);
413
+	}
414
+}
... ...
@@ -30,6 +30,7 @@
30 30
 #include <cds/ptr_vector.h>
31 31
 #include <cds/sync.h>
32 32
 #include <cds/msg_queue.h>
33
+#include <cds/ref_cntr.h>
33 34
 
34 35
 #include <presence/client_notify_info.h>
35 36
 
... ...
@@ -53,12 +54,14 @@ typedef struct _notifier_domain_t notifier_domain_t;
53 54
  */
54 55
 struct _subscription_t {
55 56
 	/* client_notify_func notify; */
57
+	cds_mutex_t *mutex;
56 58
 	msg_queue_t *dst;
57 59
 	str_t record_id;
58 60
 	str_t subscriber_id;
59 61
 	notifier_package_t *package;
60 62
 	void *subscriber_data;
61 63
 	struct _subscription_t *prev, *next;
64
+	reference_counter_data_t ref;
62 65
 };
63 66
 
64 67
 typedef int (*server_subscribe_func)(notifier_t *n, subscription_t *subscription);
... ...
@@ -85,8 +88,10 @@ struct _notifier_package_t {
85 88
 
86 89
 struct _notifier_domain_t {
87 90
 	cds_mutex_t mutex;
91
+	cds_mutex_t data_mutex; /* mutex for locking standalone subscription data, may be changed to mutex pool */
88 92
 	str_t name;
89 93
 	notifier_package_t *first_package, *last_package;
94
+	reference_counter_data_t ref;
90 95
 };
91 96
 
92 97
 /* -------- Domain initialization/destruction functions -------- */
... ...
@@ -25,43 +25,74 @@
25 25
 
26 26
 #include <presence/qsa.h>
27 27
 #include <cds/logger.h>
28
+#include <cds/cds.h>
28 29
 #include <presence/domain_maintainer.h>
29 30
 
30
-static domain_maintainer_t *dm = NULL;
31
-static int initialized = 0;
31
+typedef struct {
32
+	int init_cnt;
33
+	domain_maintainer_t *dm;
34
+} init_data_t;
35
+
36
+static init_data_t *init = NULL;
32 37
 
33 38
 int qsa_initialize()
34 39
 {
35
-	if (!initialized) {
36
-		dm = create_domain_maintainer();
37
-		if (dm) initialized = 1;
38
-		else {
40
+	int res = 0;
41
+
42
+	cds_initialize();
43
+	
44
+	/* initialization should be called from one process/thread 
45
+	 * it is not synchronized because it is impossible ! */
46
+	if (!init) {
47
+		init = (init_data_t*)cds_malloc(sizeof(init_data_t));
48
+		if (!init) return -1;
49
+		init->init_cnt = 0;
50
+	}
51
+
52
+	if (init->init_cnt > 0) { /* already initialized */
53
+		init->init_cnt++;
54
+		return 0;
55
+	}
56
+	else {
57
+		DEBUG_LOG("qsa_initialize(): init the content\n");
58
+
59
+		/* !!! put the real initialization here !!! */
60
+		init->dm = create_domain_maintainer();
61
+		if (!init->dm) {
39 62
 			ERROR_LOG("qsa_initialize error - can't initialize domain maintainer\n");
40
-			return -1;
63
+			res = -1;
41 64
 		}
42
-		DEBUG_LOG("QSA initialized\n");
43 65
 	}
44
-	return 0;
66
+			
67
+	if (res == 0) init->init_cnt++;
68
+	return res;
45 69
 }
46 70
 
47 71
 void qsa_cleanup() 
48 72
 {
49
-	if (initialized && dm) {
50
-		destroy_domain_maintainer(dm);
51
-		dm = NULL;
52
-		initialized = 0;
73
+	if (init) {
74
+		if (--init->init_cnt == 0) {
75
+			DEBUG_LOG("qsa_cleanup(): cleaning the content\n");
76
+			
77
+			/* !!! put the real destruction here !!! */
78
+			if (init->dm) destroy_domain_maintainer(init->dm);
79
+			
80
+			cds_free(init);
81
+			init = NULL;
82
+		}
53 83
 	}
84
+	cds_cleanup();
54 85
 }
55 86
 
56 87
 notifier_domain_t *qsa_register_domain(const str_t *name)
57 88
 {
58 89
 	notifier_domain_t *d = NULL;
59 90
 
60
-	if (!dm) {
91
+	if (!init) {
61 92
 		ERROR_LOG("qsa_initialize was not called - can't register domain\n");
62 93
 		return NULL;
63 94
 	}
64
-	d = register_notifier_domain(dm, name);
95
+	if (init->dm) d = register_notifier_domain(init->dm, name);
65 96
 	return d;
66 97
 }
67 98
 
... ...
@@ -72,5 +103,6 @@ notifier_domain_t *qsa_get_default_domain()
72 103
 
73 104
 void qsa_release_domain(notifier_domain_t *domain)
74 105
 {
75
-	if (dm) release_notifier_domain(dm, domain);
106
+	if (init) 
107
+		if (init->dm) release_notifier_domain(init->dm, domain);
76 108
 }