Browse code

changed QSA - prepared for internal subscription parameters and reduced memory allocations

Vaclav Kubart authored on 11/04/2006 15:48:24
Showing 7 changed files
... ...
@@ -1,3 +1,7 @@
1
+2006-04-11
2
+	* reduced memory allocations in QSA
3
+	* prepared for parameters to QSA subscriptions
4
+
1 5
 2006-04-10
2 6
 	* changed QSA - corrected content-type propagation
3 7
 
... ...
@@ -51,13 +51,13 @@ void unregister_notifier(notifier_domain_t *domain, notifier_t *info);
51 51
  *
52 52
  * Note: only for asynchonously processed subscriptions (synchronous 
53 53
  * don't need it) */
54
-void accept_subscription(subscription_t *s);
54
+void accept_subscription(qsa_subscription_t *s);
55 55
 
56 56
 /** releases accepted subscription - MUST be called on all accepted 
57 57
  * subscriptions (only on them!) to be freed from memory !
58 58
  * Note: only for asynchonously processed subscriptions (synchronous 
59 59
  * don't need it) */
60
-void release_subscription(subscription_t *s);
60
+void release_subscription(qsa_subscription_t *s);
61 61
 
62 62
 /** This structure is sent via message queue
63 63
  * to client. It must contain all information
... ...
@@ -72,7 +72,7 @@ typedef enum {
72 72
 
73 73
 typedef struct {
74 74
 	/* replacement for record_id, package, ... it is much more efficient */
75
-	subscription_t *subscription; 
75
+	qsa_subscription_t *subscription; 
76 76
 	qsa_content_type_t *content_type;
77 77
 	void *data;
78 78
 	int data_len;
... ...
@@ -83,12 +83,24 @@ typedef struct {
83 83
 void free_client_notify_info_content(client_notify_info_t *info);
84 84
 
85 85
 /* notifications SHOULD be sent through this method */
86
-int notify_subscriber(subscription_t *s, 
86
+int notify_subscriber(qsa_subscription_t *s, 
87 87
 		notifier_t *n,
88 88
 		qsa_content_type_t *content_type, 
89 89
 		void *data, 
90 90
 		qsa_subscription_status_t status);
91 91
 
92
+/* this can be called in notifier and the returned value is valid
93
+ * before finishes "unsubscribe" processing */
94
+str_t *get_subscriber_id(qsa_subscription_t *s);
95
+
96
+/* this can be called in notifier and the returned value is valid
97
+ * before finishes "unsubscribe" processing */
98
+str_t *get_record_id(qsa_subscription_t *s);
99
+
100
+/* this can be called in notifier and the returned value is valid
101
+ * before finishes "unsubscribe" processing */
102
+void *get_subscriber_data(qsa_subscription_t *s);
103
+
92 104
 #ifdef __cplusplus
93 105
 }
94 106
 #endif
... ...
@@ -36,19 +36,19 @@
36 36
 /*#define lock_subscription_data(s) if (s->mutex) cds_mutex_lock(s->mutex);
37 37
 #define unlock_subscription_data(s) if (s->mutex) cds_mutex_unlock(s->mutex);*/
38 38
 
39
-static void lock_subscription_data(subscription_t *s)
39
+static void lock_subscription_data(qsa_subscription_t *s)
40 40
 {
41 41
 	/* is function due to debugging */
42 42
 	if (s->mutex) cds_mutex_lock(s->mutex);
43 43
 }
44 44
 
45
-static void unlock_subscription_data(subscription_t *s) {
45
+static void unlock_subscription_data(qsa_subscription_t *s) {
46 46
 	/* is function due to debugging */
47 47
 	if (s->mutex) cds_mutex_unlock(s->mutex);
48 48
 }
49 49
 
50 50
 static void free_notifier(notifier_t *info);
51
-static void free_subscription(subscription_t *s);
51
+static void free_subscription(qsa_subscription_t *s);
52 52
 
53 53
 /* -------- package functions -------- */
54 54
 
... ...
@@ -109,7 +109,7 @@ static notifier_package_t *get_package(notifier_domain_t *d, const str_t *name)
109 109
 static void destroy_package(notifier_package_t *p) 
110 110
 {
111 111
 	/* notifier_t *e, *n; */
112
-	subscription_t *s, *ns;
112
+	qsa_subscription_t *s, *ns;
113 113
 	
114 114
 	/* release all subscriptions ???  */
115 115
 	s = p->first_subscription;
... ...
@@ -203,15 +203,13 @@ static void free_notifier(notifier_t *info)
203 203
 	cds_free(info);
204 204
 }
205 205
 
206
-static void free_subscription(subscription_t *s)
206
+static void free_subscription(qsa_subscription_t *s)
207 207
 {
208
-	DEBUG_LOG("freeing subscription to %.*s\n", FMT_STR(s->record_id));
209
-	str_free_content(&s->record_id);
210
-	str_free_content(&s->subscriber_id);
208
+	DEBUG_LOG("freeing subscription to %p\n", s);
211 209
 	cds_free(s);
212 210
 }
213 211
 
214
-/*static void add_server_subscription(notifier_t *n, subscription_t *s)
212
+/*static void add_server_subscription(notifier_t *n, qsa_subscription_t *s)
215 213
 {
216 214
 	server_subscription_t server_s;
217 215
 	
... ...
@@ -223,7 +221,7 @@ static void free_subscription(subscription_t *s)
223 221
 	else ERROR_LOG("subscription not accepted by notifier %p\n", n);
224 222
 }
225 223
 			
226
-static void remove_notifier_from_subscription(subscription_t *s, notifier_t *n)
224
+static void remove_notifier_from_subscription(qsa_subscription_t *s, notifier_t *n)
227 225
 {
228 226
 	int cnt,i;
229 227
 
... ...
@@ -314,7 +312,7 @@ notifier_t *register_notifier(
314 312
 {
315 313
 	notifier_t *info;
316 314
 	notifier_package_t *p;
317
-	subscription_t *s;
315
+	qsa_subscription_t *s;
318 316
 
319 317
 	lock_notifier_domain(domain);
320 318
 	p = get_package(domain, package);
... ...
@@ -362,7 +360,7 @@ void unregister_notifier(notifier_domain_t *domain, notifier_t *info)
362 360
 		/* accepted subscriptions MUST be removed by the notifier 
363 361
 		 * how to solve this ? */
364 362
 		
365
-		/* subscription_t *s;
363
+		/* qsa_subscription_t *s;
366 364
 		s = p->first_subscription;
367 365
 		while (s) {
368 366
 			CAN NOT be called !!!!! info->unsubscribe(info, s);
... ...
@@ -380,28 +378,24 @@ void unregister_notifier(notifier_domain_t *domain, notifier_t *info)
380 378
 
381 379
 /* If a notifier publishing watched state registeres after subscibe
382 380
  * call, it receives the subscription automaticaly too! */
383
-subscription_t *subscribe(notifier_domain_t *domain, 
381
+qsa_subscription_t *subscribe(notifier_domain_t *domain, 
384 382
 		str_t *package,
385
-		str_t *record_id,
386
-		str_t *subscriber_id,
387
-		msg_queue_t *dst,
388
-		void *subscriber_data)
383
+		qsa_subscription_data_t *data)
389 384
 {
390
-	subscription_t *s;
385
+	qsa_subscription_t *s;
391 386
 	notifier_t *e;
392 387
 	notifier_package_t *p;
393 388
 	int cnt = 0;
394
-	int res;
395 389
 
396 390
 	lock_notifier_domain(domain);
397 391
 	p = get_package(domain, package);
398 392
 	if (!p) {
399
-		ERROR_LOG("can't find package for subscription\n");
393
+		ERROR_LOG("can't find/add package for subscription\n");
400 394
 		unlock_notifier_domain(domain);
401 395
 		return NULL;
402 396
 	}
403 397
 	
404
-	s = cds_malloc(sizeof(subscription_t));
398
+	s = cds_malloc(sizeof(qsa_subscription_t));
405 399
 	if (!s) {
406 400
 		ERROR_LOG("can't allocate memory\n");
407 401
 		unlock_notifier_domain(domain);
... ...
@@ -409,20 +403,9 @@ subscription_t *subscribe(notifier_domain_t *domain,
409 403
 	}
410 404
 
411 405
 	s->package = p;
412
-	s->dst = dst;
413 406
 	s->mutex = &domain->data_mutex;
414
-	s->subscriber_data = subscriber_data;
415
-	res = str_dup(&s->record_id, record_id);
416
-	if (res == 0) res = str_dup(&s->subscriber_id, subscriber_id);
417
-	else str_clear(&s->subscriber_id);
418
-	if (res != 0) {
419
-		str_free_content(&s->record_id);
420
-		str_free_content(&s->subscriber_id);
421
-		cds_free(s);
422
-		ERROR_LOG("can't allocate memory\n");
423
-		unlock_notifier_domain(domain);
424
-		return NULL;
425
-	}
407
+	s->data = data;
408
+	s->allow_notifications = 1;
426 409
 	init_reference_counter(&s->ref);
427 410
 
428 411
 	DOUBLE_LINKED_LIST_ADD(p->first_subscription, p->last_subscription, s);
... ...
@@ -447,27 +430,27 @@ subscription_t *subscribe(notifier_domain_t *domain,
447 430
 	return s;
448 431
 }
449 432
 	
450
-void release_subscription(subscription_t *s)
433
+void release_subscription(qsa_subscription_t *s)
451 434
 {
452 435
 	if (!s) return;
453 436
 	if (remove_reference(&s->ref)) free_subscription(s);
454 437
 }
455 438
 
456
-void accept_subscription(subscription_t *s)
439
+void accept_subscription(qsa_subscription_t *s)
457 440
 {
458 441
 	if (!s) return;
459 442
 	add_reference(&s->ref);
460 443
 }
461 444
 
462 445
 /** Destroys an existing subscription - can be called ONLY by client !!! */
463
-void unsubscribe(notifier_domain_t *domain, subscription_t *s)
446
+void unsubscribe(notifier_domain_t *domain, qsa_subscription_t *s)
464 447
 {
465 448
 	notifier_package_t *p;
466 449
 	notifier_t *e;
467 450
 
468 451
 	/* mark subscription as un-notifyable */
469 452
 	lock_subscription_data(s);
470
-	s->dst = NULL;
453
+	s->allow_notifications = 0;
471 454
 	unlock_subscription_data(s);
472 455
 
473 456
 	lock_notifier_domain(domain);
... ...
@@ -489,14 +472,19 @@ void unsubscribe(notifier_domain_t *domain, subscription_t *s)
489 472
 	
490 473
 	unlock_notifier_domain(domain);
491 474
 	
475
+	/* mark subscription data as invalid */
476
+	lock_subscription_data(s);
477
+	s->data = NULL;
478
+	unlock_subscription_data(s);
479
+	
492 480
 	/* remove clients reference (dont give references to client?) */
493 481
 	remove_reference(&s->ref);
494 482
 	
495 483
 	release_subscription(s); 
496 484
 }
497 485
 
498
-/* void notify_subscriber(subscription_t *s, mq_message_t *msg) */
499
-int notify_subscriber(subscription_t *s, 
486
+/* void notify_subscriber(qsa_subscription_t *s, mq_message_t *msg) */
487
+int notify_subscriber(qsa_subscription_t *s, 
500 488
 		notifier_t *n,
501 489
 		qsa_content_type_t *content_type, 
502 490
 		void *data, 
... ...
@@ -535,9 +523,11 @@ int notify_subscriber(subscription_t *s,
535 523
 		info->status = status;
536 524
 		
537 525
 		lock_subscription_data(s);
538
-		if (s->dst) {
539
-			if (push_message(s->dst, msg) < 0) ok = 0;
540
-			else sent = 1;
526
+		if ((s->allow_notifications) && (s->data)) {
527
+			if (s->data->dst) {
528
+				if (push_message(s->data->dst, msg) < 0) ok = 0;
529
+				else sent = 1;
530
+			}
541 531
 		}
542 532
 		unlock_subscription_data(s);
543 533
 	}
... ...
@@ -565,3 +555,35 @@ void free_client_notify_info_content(client_notify_info_t *info)
565 555
 	else ERR("BUG: content-type not given! Possible memory leaks!\n");
566 556
 }
567 557
 
558
+/* this can be called in notifier and the returned value is valid
559
+ * before finishes "unsubscribe" processing */
560
+str_t *get_subscriber_id(qsa_subscription_t *s)
561
+{
562
+	if (!s) return NULL;
563
+	if (!s->data) return NULL;
564
+	return &s->data->subscriber_id;
565
+}
566
+
567
+/* this can be called in notifier and the returned value is valid
568
+ * before finishes "unsubscribe" processing */
569
+str_t *get_record_id(qsa_subscription_t *s)
570
+{
571
+	if (!s) return NULL;
572
+	if (!s->data) return NULL;
573
+	return &s->data->record_id;
574
+}
575
+
576
+/* this can be called in notifier and the returned value is valid
577
+ * before finishes "unsubscribe" processing */
578
+void *get_subscriber_data(qsa_subscription_t *s)
579
+{
580
+	if (!s) return NULL;
581
+	if (!s->data) return NULL;
582
+	return s->data->subscriber_data;
583
+}
584
+
585
+void clear_subscription_data(qsa_subscription_data_t *data)
586
+{
587
+	if (data) memset(data, 0, sizeof(*data));
588
+}
589
+
... ...
@@ -29,15 +29,15 @@
29 29
 #include <cds/sstr.h>
30 30
 #include <cds/ptr_vector.h>
31 31
 #include <cds/sync.h>
32
-#include <cds/msg_queue.h>
33
-#include <cds/ref_cntr.h>
32
+
33
+#include <presence/qsa_params.h>
34 34
 
35 35
 #ifdef __cplusplus
36 36
 extern "C" {
37 37
 #endif
38 38
 
39
-struct _subscription_t;
40
-typedef struct _subscription_t subscription_t;
39
+struct _qsa_subscription_t;
40
+typedef struct _qsa_subscription_t qsa_subscription_t;
41 41
 struct _notifier_package_t;
42 42
 typedef struct _notifier_package_t notifier_package_t;
43 43
 struct _notifier_t;
... ...
@@ -45,26 +45,35 @@ typedef struct _notifier_t notifier_t;
45 45
 struct _notifier_domain_t;
46 46
 typedef struct _notifier_domain_t notifier_domain_t;
47 47
 
48
-/* typedef void (*client_notify_func)(client_notify_info_t *info); */
48
+/* data hold by subscriber for the time of subscription duration 
49
+ * (from subscribe to unsubscribe; after calling unsubscribe can
50
+ * be destroyed contents of them) */
51
+typedef struct _qsa_subscription_data_t {
52
+	msg_queue_t *dst;
53
+	str_t record_id;
54
+	str_t subscriber_id;
55
+	qsa_subscription_params_t *first_param;
56
+	void *subscriber_data;
57
+} qsa_subscription_data_t;
49 58
 
50 59
 /** Internal structure holding informations about
51 60
  * created client subscriptions.
52 61
  */
53
-struct _subscription_t {
62
+struct _qsa_subscription_t {
54 63
 	/* client_notify_func notify; */
55 64
 	cds_mutex_t *mutex;
56
-	msg_queue_t *dst;
57
-	str_t record_id;
58
-	str_t subscriber_id;
59 65
 	notifier_package_t *package;
60
-	void *subscriber_data;
61
-	struct _subscription_t *prev, *next;
66
+	int allow_notifications;
67
+	qsa_subscription_data_t *data;
68
+	struct _qsa_subscription_t *prev, *next;
62 69
 	reference_counter_data_t ref;
63 70
 };
64 71
 
65
-typedef int (*server_subscribe_func)(notifier_t *n, subscription_t *subscription);
72
+/* typedef void (*client_notify_func)(client_notify_info_t *info); */
73
+
74
+typedef int (*server_subscribe_func)(notifier_t *n, qsa_subscription_t *subscription);
66 75
 
67
-typedef void (*server_unsubscribe_func)(notifier_t *n, subscription_t *subscription);
76
+typedef void (*server_unsubscribe_func)(notifier_t *n, qsa_subscription_t *subscription);
68 77
 
69 78
 typedef struct _qsa_content_type_t {
70 79
 	struct _qsa_content_type_t *next, *prev;
... ...
@@ -87,7 +96,7 @@ struct _notifier_package_t {
87 96
 	/* maybe: serialize and deserialize methods */
88 97
 	notifier_domain_t *domain;
89 98
 	notifier_t *first_notifier, *last_notifier; /* notifiers are linked in theirs package! */
90
-	subscription_t *first_subscription, *last_subscription;
99
+	qsa_subscription_t *first_subscription, *last_subscription;
91 100
 	notifier_package_t *next, *prev;
92 101
 };
93 102
 
94 103
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+#include <presence/qsa_params.h>
2
+
0 3
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+#ifndef __QSA_PARAMS_H
2
+#define __QSA_PARAMS_H
3
+
4
+#include <cds/sstr.h>
5
+#include <cds/ptr_vector.h>
6
+#include <cds/msg_queue.h>
7
+#include <cds/ref_cntr.h>
8
+
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+	
13
+typedef struct _qsa_subscription_params_t {
14
+	str_t name;
15
+	str_t value; /* whatever */
16
+	char buf[1];
17
+} qsa_subscription_params_t;
18
+
19
+#ifdef __cplusplus
20
+}
21
+#endif
22
+	
23
+#endif
... ...
@@ -36,20 +36,19 @@ extern "C" {
36 36
 
37 37
 /* If a notifier publishing watched state registeres after subscibe
38 38
  * call, it receives the subscription automaticaly too! */
39
-/*subscription_t *subscribe(notifier_domain_t *domain, 
40
-		subscription_t *params);*/
41
-subscription_t *subscribe(notifier_domain_t *domain, 
39
+/*qsa_subscription_t *subscribe(notifier_domain_t *domain, 
40
+		qsa_subscription_t *params);*/
41
+qsa_subscription_t *subscribe(notifier_domain_t *domain, 
42 42
 		str_t *package,
43
-		str_t *record_id,
44
-		str_t *subscriber_id,
45
-		msg_queue_t *dst,
46
-		void *subscriber_data);
43
+		qsa_subscription_data_t *data);
47 44
 
48 45
 /** Destroys an existing subscription */
49
-void unsubscribe(notifier_domain_t *domain, subscription_t *s);
46
+void unsubscribe(notifier_domain_t *domain, qsa_subscription_t *s);
50 47
 
51
-void set_subscriber_data(subscription_t *s, void *data);
52
-void *get_subscriber_data(subscription_t *s);
48
+void set_subscriber_data(qsa_subscription_t *s, void *data);
49
+void *get_subscriber_data(qsa_subscription_t *s);
50
+
51
+void clear_subscription_data(qsa_subscription_data_t *data);
53 52
 	
54 53
 #ifdef __cplusplus
55 54
 }